saasy 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +114 -0
- data/Gemfile +26 -0
- data/README.md +118 -0
- data/Rakefile +38 -0
- data/app/controllers/accounts_controller.rb +68 -0
- data/app/controllers/billings_controller.rb +25 -0
- data/app/controllers/invitations_controller.rb +65 -0
- data/app/controllers/memberships_controller.rb +45 -0
- data/app/controllers/plans_controller.rb +24 -0
- data/app/controllers/profiles_controller.rb +19 -0
- data/app/helpers/limits_helper.rb +13 -0
- data/app/mailers/billing_mailer.rb +53 -0
- data/app/mailers/invitation_mailer.rb +18 -0
- data/app/models/invitation.rb +113 -0
- data/app/models/limit.rb +49 -0
- data/app/models/membership.rb +26 -0
- data/app/models/permission.rb +19 -0
- data/app/models/signup.rb +163 -0
- data/app/views/accounts/_account.html.erb +9 -0
- data/app/views/accounts/_blank_slate.html.erb +6 -0
- data/app/views/accounts/_projects.html.erb +12 -0
- data/app/views/accounts/_subnav.html.erb +10 -0
- data/app/views/accounts/edit.html.erb +34 -0
- data/app/views/accounts/index.html.erb +9 -0
- data/app/views/accounts/new.html.erb +36 -0
- data/app/views/billing_mailer/completed_trial.text.erb +13 -0
- data/app/views/billing_mailer/expiring_trial.text.erb +15 -0
- data/app/views/billing_mailer/new_unactivated.text.erb +1 -0
- data/app/views/billing_mailer/problem.html.erb +13 -0
- data/app/views/billing_mailer/problem.text.erb +14 -0
- data/app/views/billing_mailer/receipt.html.erb +41 -0
- data/app/views/billing_mailer/receipt.text.erb +25 -0
- data/app/views/billings/_form.html.erb +8 -0
- data/app/views/billings/edit.html.erb +13 -0
- data/app/views/billings/show.html.erb +29 -0
- data/app/views/invitation_mailer/invitation.text.erb +6 -0
- data/app/views/invitations/new.html.erb +17 -0
- data/app/views/invitations/show.html.erb +22 -0
- data/app/views/layouts/saucy.html.erb +36 -0
- data/app/views/limits/_meter.html.erb +13 -0
- data/app/views/memberships/edit.html.erb +21 -0
- data/app/views/memberships/index.html.erb +17 -0
- data/app/views/plans/_plan.html.erb +32 -0
- data/app/views/plans/_terms.html.erb +15 -0
- data/app/views/plans/edit.html.erb +33 -0
- data/app/views/plans/index.html.erb +12 -0
- data/app/views/profiles/_inputs.html.erb +5 -0
- data/app/views/profiles/edit.html.erb +36 -0
- data/app/views/projects/_form.html.erb +36 -0
- data/app/views/projects/edit.html.erb +22 -0
- data/app/views/projects/index.html.erb +28 -0
- data/app/views/projects/new.html.erb +13 -0
- data/app/views/projects/show.html.erb +0 -0
- data/app/views/shared/_project_dropdown.html.erb +55 -0
- data/app/views/shared/_saucy_javascript.html.erb +33 -0
- data/config/locales/en.yml +37 -0
- data/config/routes.rb +19 -0
- data/features/run_features.feature +83 -0
- data/features/step_definitions/clearance_steps.rb +45 -0
- data/features/step_definitions/rails_steps.rb +73 -0
- data/features/step_definitions/saucy_steps.rb +8 -0
- data/features/support/env.rb +4 -0
- data/features/support/file.rb +11 -0
- data/lib/generators/saucy/base.rb +18 -0
- data/lib/generators/saucy/features/features_generator.rb +91 -0
- data/lib/generators/saucy/features/templates/README +3 -0
- data/lib/generators/saucy/features/templates/factories.rb +71 -0
- data/lib/generators/saucy/features/templates/features/edit_profile.feature +9 -0
- data/lib/generators/saucy/features/templates/features/edit_project_permissions.feature +37 -0
- data/lib/generators/saucy/features/templates/features/edit_user_permissions.feature +47 -0
- data/lib/generators/saucy/features/templates/features/manage_account.feature +35 -0
- data/lib/generators/saucy/features/templates/features/manage_billing.feature +93 -0
- data/lib/generators/saucy/features/templates/features/manage_plan.feature +143 -0
- data/lib/generators/saucy/features/templates/features/manage_projects.feature +139 -0
- data/lib/generators/saucy/features/templates/features/manage_users.feature +142 -0
- data/lib/generators/saucy/features/templates/features/new_account.feature +33 -0
- data/lib/generators/saucy/features/templates/features/project_dropdown.feature +77 -0
- data/lib/generators/saucy/features/templates/features/sign_up.feature +32 -0
- data/lib/generators/saucy/features/templates/features/sign_up_paid.feature +65 -0
- data/lib/generators/saucy/features/templates/features/trial_plans.feature +82 -0
- data/lib/generators/saucy/features/templates/step_definitions/account_steps.rb +30 -0
- data/lib/generators/saucy/features/templates/step_definitions/braintree_steps.rb +25 -0
- data/lib/generators/saucy/features/templates/step_definitions/cron_steps.rb +23 -0
- data/lib/generators/saucy/features/templates/step_definitions/email_steps.rb +40 -0
- data/lib/generators/saucy/features/templates/step_definitions/factory_girl_steps.rb +1 -0
- data/lib/generators/saucy/features/templates/step_definitions/html_steps.rb +51 -0
- data/lib/generators/saucy/features/templates/step_definitions/plan_steps.rb +16 -0
- data/lib/generators/saucy/features/templates/step_definitions/project_steps.rb +4 -0
- data/lib/generators/saucy/features/templates/step_definitions/session_steps.rb +37 -0
- data/lib/generators/saucy/features/templates/step_definitions/user_steps.rb +100 -0
- data/lib/generators/saucy/features/templates/support/braintree.rb +5 -0
- data/lib/generators/saucy/install/install_generator.rb +40 -0
- data/lib/generators/saucy/install/templates/controllers/projects_controller.rb +3 -0
- data/lib/generators/saucy/install/templates/create_saucy_tables.rb +115 -0
- data/lib/generators/saucy/install/templates/models/account.rb +3 -0
- data/lib/generators/saucy/install/templates/models/plan.rb +3 -0
- data/lib/generators/saucy/install/templates/models/project.rb +3 -0
- data/lib/generators/saucy/specs/specs_generator.rb +20 -0
- data/lib/generators/saucy/specs/templates/support/braintree.rb +5 -0
- data/lib/generators/saucy/views/views_generator.rb +23 -0
- data/lib/saucy.rb +10 -0
- data/lib/saucy/account.rb +132 -0
- data/lib/saucy/account_authorization.rb +67 -0
- data/lib/saucy/configuration.rb +29 -0
- data/lib/saucy/engine.rb +35 -0
- data/lib/saucy/fake_braintree.rb +134 -0
- data/lib/saucy/layouts.rb +36 -0
- data/lib/saucy/plan.rb +54 -0
- data/lib/saucy/project.rb +125 -0
- data/lib/saucy/projects_controller.rb +94 -0
- data/lib/saucy/railties/tasks.rake +28 -0
- data/lib/saucy/routing_extensions.rb +121 -0
- data/lib/saucy/subscription.rb +237 -0
- data/lib/saucy/user.rb +30 -0
- data/spec/controllers/accounts_controller_spec.rb +228 -0
- data/spec/controllers/application_controller_spec.rb +32 -0
- data/spec/controllers/invitations_controller_spec.rb +215 -0
- data/spec/controllers/memberships_controller_spec.rb +117 -0
- data/spec/controllers/plans_controller_spec.rb +13 -0
- data/spec/controllers/profiles_controller_spec.rb +48 -0
- data/spec/controllers/projects_controller_spec.rb +216 -0
- data/spec/environment.rb +95 -0
- data/spec/layouts_spec.rb +21 -0
- data/spec/mailers/billing_mailer_spec.rb +68 -0
- data/spec/mailers/invitiation_mailer_spec.rb +19 -0
- data/spec/models/account_spec.rb +218 -0
- data/spec/models/invitation_spec.rb +320 -0
- data/spec/models/limit_spec.rb +70 -0
- data/spec/models/membership_spec.rb +37 -0
- data/spec/models/permission_spec.rb +30 -0
- data/spec/models/plan_spec.rb +81 -0
- data/spec/models/project_spec.rb +223 -0
- data/spec/models/signup_spec.rb +177 -0
- data/spec/models/subscription_spec.rb +481 -0
- data/spec/models/user_spec.rb +72 -0
- data/spec/route_extensions_spec.rb +51 -0
- data/spec/saucy_spec.rb +62 -0
- data/spec/scaffold/config/routes.rb +5 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/authentication_helpers.rb +81 -0
- data/spec/support/authorization_helpers.rb +56 -0
- data/spec/support/braintree.rb +7 -0
- data/spec/support/clearance_matchers.rb +55 -0
- data/spec/support/notifications.rb +57 -0
- data/spec/views/accounts/_account.html.erb_spec.rb +37 -0
- metadata +325 -0
data/CHANGELOG.md
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
0.8.2
|
2
|
+
|
3
|
+
Added a uniqueness validation and database constraint for member_id/project_id on permissions. This prevents somebody from being added to the same project twice, which would display it multiple times in the project index and dropdown. When upgrading, make sure this index is in place:
|
4
|
+
|
5
|
+
remove_index :permissions, :name => [:membership_and_project]
|
6
|
+
add_index :permissions, [:membership_id, :project_id], :name => [:membership_and_project], :unique => true
|
7
|
+
|
8
|
+
You'll need to make sure that no existing duplicates exist before applying the unique index.
|
9
|
+
|
10
|
+
0.8.1
|
11
|
+
|
12
|
+
Fixed a missing translation key.
|
13
|
+
|
14
|
+
0.8.0
|
15
|
+
|
16
|
+
Added a notification for trials that just ended. When upgrading, you'll need to
|
17
|
+
add to add a boolean notified_of_completed_trial column to the accounts table,
|
18
|
+
which should be NOT NULL and default to false. These notifications go out with
|
19
|
+
the daily Saucy jobs.
|
20
|
+
|
21
|
+
0.7.3
|
22
|
+
|
23
|
+
Added a uniqueness constraint for keyword on accounts/projects. When upgrading,
|
24
|
+
projects should ensure that there is a unique index on these columns. The
|
25
|
+
projects index needs to be scoped to an account ID, so that index should be on
|
26
|
+
both columns (account_id and keyword).
|
27
|
+
|
28
|
+
0.7.2
|
29
|
+
|
30
|
+
Don't bother to show the account selection on the project form if the user is only an
|
31
|
+
admin on one account
|
32
|
+
|
33
|
+
0.7.1
|
34
|
+
|
35
|
+
Introduce a project dropdown, include it with:
|
36
|
+
|
37
|
+
render :partial => "shared/project_dropdown"
|
38
|
+
|
39
|
+
Saucy provides the javascript for this dropdown, but not the CSS or the image
|
40
|
+
for the dropdown. The Javascript depends on jQuery.
|
41
|
+
|
42
|
+
Also, adds the ability to move a project to another project that you are an
|
43
|
+
admin on.
|
44
|
+
|
45
|
+
0.7.0
|
46
|
+
|
47
|
+
Split Saucy::Configuration.mailer_sender into support_email_address and manager_email_address.
|
48
|
+
|
49
|
+
0.6.1
|
50
|
+
|
51
|
+
Fix for this known bug in Rails 3.0.7
|
52
|
+
|
53
|
+
https://rails.lighthouseapp.com/projects/8994/tickets/6757-hashfrom_xml-chokes-on-empty-cdata
|
54
|
+
|
55
|
+
0.6.0
|
56
|
+
|
57
|
+
Upgrading to, and making an explicit dependency on Clearance ~> 0.11.0. You can
|
58
|
+
get an overview of the important changes to clearance here:
|
59
|
+
|
60
|
+
https://github.com/thoughtbot/clearance/wiki/upgrading-clearance
|
61
|
+
|
62
|
+
0.5.5
|
63
|
+
|
64
|
+
Fixes for account and project keywords containing special characters, generated by signup
|
65
|
+
|
66
|
+
0.5.4
|
67
|
+
|
68
|
+
Changes from an archive project link to a checkbox on the project form.
|
69
|
+
|
70
|
+
0.5.3
|
71
|
+
|
72
|
+
Removes uniqueness constraint on account names
|
73
|
+
|
74
|
+
0.5.2
|
75
|
+
|
76
|
+
Simplifies the signup process to asking users for just an email and password.
|
77
|
+
Overall this should be seamless upgrade but you may have made other changes in
|
78
|
+
your application which might conflict, just pay attention when you upgrade.
|
79
|
+
|
80
|
+
You'll defintely want to make sure you regerate the saucy features with this upgrade:
|
81
|
+
|
82
|
+
rails g saucy:features
|
83
|
+
|
84
|
+
0.5.1
|
85
|
+
|
86
|
+
Add an index to the archived column for projects
|
87
|
+
|
88
|
+
0.5.0
|
89
|
+
|
90
|
+
Added the ability to archive projects. Archived projects are not included in
|
91
|
+
an accounts `projects_count`.
|
92
|
+
|
93
|
+
To upgrade to this version add the following column to the projects table:
|
94
|
+
|
95
|
+
add_column :projects, :archived, :boolean, :default => false, :null => false
|
96
|
+
add_index :projects, :archived
|
97
|
+
|
98
|
+
This version adds a list of archived projects to the projects index of an
|
99
|
+
account. An introduced headers to these two lists. Archived projects have
|
100
|
+
a "View Project" link, which is how the user can view an archived project.
|
101
|
+
You will probably want to style this list, headers, and link.
|
102
|
+
|
103
|
+
It also adds an Archive/Unarchive link on the project's edit page. You will probably
|
104
|
+
want to style these links.
|
105
|
+
|
106
|
+
It is up to your application to provide any additional logic about what
|
107
|
+
limitations are present for archived projects (for example, not being able to
|
108
|
+
create new comments on them).
|
109
|
+
|
110
|
+
0.4.10
|
111
|
+
|
112
|
+
A user following an invite link who is already signed in and whose email
|
113
|
+
address matches the one in the invite automatically accepts the invite when
|
114
|
+
following the link.
|
data/Gemfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
gem "cucumber"
|
3
|
+
gem "aruba"
|
4
|
+
gem "rake"
|
5
|
+
gem "rspec-rails", :require => false
|
6
|
+
gem "rails", ">= 3.0.3"
|
7
|
+
gem "thin"
|
8
|
+
gem "clearance", "~> 0.11.0"
|
9
|
+
gem "shoulda", :require => false
|
10
|
+
gem "bourne", :require => false
|
11
|
+
gem "sqlite3", :require => false
|
12
|
+
gem "factory_girl", :require => false
|
13
|
+
gem "sinatra"
|
14
|
+
gem "sham_rack"
|
15
|
+
gem "braintree"
|
16
|
+
gem "timecop"
|
17
|
+
|
18
|
+
# used by the rails app in cucumber
|
19
|
+
gem "cucumber-rails", :require => false
|
20
|
+
gem "capybara", :require => false
|
21
|
+
gem "factory_girl_rails", :require => false
|
22
|
+
gem "formtastic", :require => false
|
23
|
+
gem "database_cleaner", :require => false
|
24
|
+
gem "dynamic_form", :require => false
|
25
|
+
gem "launchy", :require => false
|
26
|
+
gem "jquery-rails", :require => false
|
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
Saucy
|
2
|
+
=====
|
3
|
+
|
4
|
+
Saucy is a Rails engine for monthly subscription-style SaaS apps.
|
5
|
+
|
6
|
+
Example scenarios covered by Saucy:
|
7
|
+
|
8
|
+
* I sign up for "Free" plan under new account "thoughtbot"
|
9
|
+
* I am an admin and can be reached at "dan@example.com"
|
10
|
+
* I create a project "Hoptoad"
|
11
|
+
* I upgrade to the "Basic" plan and my credit card is charged
|
12
|
+
* I now have permissions to add users and projects to the "thoughtbot" account
|
13
|
+
* I invite "joe@example.com" to "Hoptoad"
|
14
|
+
* I create a project "Trajectory"
|
15
|
+
* I invite "mike@example.com" to "Trajectory"
|
16
|
+
|
17
|
+
Installation
|
18
|
+
------------
|
19
|
+
|
20
|
+
In your Gemfile:
|
21
|
+
|
22
|
+
gem "saucy"
|
23
|
+
|
24
|
+
After you bundle, run the generator:
|
25
|
+
|
26
|
+
rails generate saucy:install
|
27
|
+
|
28
|
+
You will want to include the `ensure_active_account` `before_filter` in any controller actions that you want to protect if the user is using an past due paid account.
|
29
|
+
|
30
|
+
You will want to customize the from email addresses.
|
31
|
+
|
32
|
+
Support email address for your application:
|
33
|
+
|
34
|
+
Saucy::Configuration.support_email_address = "support@example.com"
|
35
|
+
|
36
|
+
Personalizable emails such as trial expiration notice and activation encouragement are sent from a product manager personal address:
|
37
|
+
|
38
|
+
Saucy::Configuration.manager_email_address = "manager@example.com"
|
39
|
+
|
40
|
+
If you have an account with Braintree with multiple merchant accounts you'll want to configure the merchant account for this application:
|
41
|
+
|
42
|
+
Saucy::Configuration.merchant_account_id = 'your merchant account id'
|
43
|
+
|
44
|
+
In addition, there are a number of strings such as application name, support url, automated emails, etc. that are provided and customized with i18n translations. You can customize these in your app, and you can see what they are by looking at config/locales/en.yml in saucy.
|
45
|
+
|
46
|
+
There is a `saucy:daily` rake task which should be run on a regular basis to send receipts and payment processing problem emails.
|
47
|
+
|
48
|
+
Saucy accounts become "activated" once an initial setup step is complete. This could be creating the first bug for a bug tracker, or setting up a client gem for a server API. Once the application detects that the account is activate, it should set "activated" to true on the account. This will prevent followup emails being sent to users that have already set up their accounts.
|
49
|
+
|
50
|
+
Development environment
|
51
|
+
-----------------------
|
52
|
+
|
53
|
+
Plans need to exist for users to sign up for. In db/seeds.rb:
|
54
|
+
|
55
|
+
%w(free expensive mega-expensive).each do |plan_name|
|
56
|
+
Plan.find_or_create_by_name(plan_name)
|
57
|
+
end
|
58
|
+
|
59
|
+
Then run: rake db:seed
|
60
|
+
|
61
|
+
Test environment
|
62
|
+
----------------
|
63
|
+
|
64
|
+
Generate the Braintree Fake for your specs:
|
65
|
+
|
66
|
+
rails generate saucy:specs
|
67
|
+
|
68
|
+
Generate feature coverage:
|
69
|
+
|
70
|
+
rails generate saucy:features
|
71
|
+
|
72
|
+
To use seed data in your Cucumber, add this to features/support/seed.rb:
|
73
|
+
|
74
|
+
require Rails.root.join('db','seeds')
|
75
|
+
|
76
|
+
Customization
|
77
|
+
-------------
|
78
|
+
|
79
|
+
By default Saucy uses and provides a `saucy.html.erb` layout. To change the
|
80
|
+
layout for a controller inside of saucy, add a line like this to your
|
81
|
+
config/application.rb:
|
82
|
+
|
83
|
+
config.saucy.layouts.accounts.index = "custom"
|
84
|
+
|
85
|
+
In addition to just the normal yield, your layout should yield the following
|
86
|
+
items in order to get everything from saucy views:
|
87
|
+
|
88
|
+
* :header
|
89
|
+
* :subnav
|
90
|
+
|
91
|
+
To extend the ProjectsController:
|
92
|
+
|
93
|
+
class ProjectsController < ApplicationController
|
94
|
+
include Saucy::ProjectsController
|
95
|
+
|
96
|
+
def edit
|
97
|
+
super
|
98
|
+
@deleters = @project.deleters
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
To define additional limit meters, or override existing limit meters, create the
|
103
|
+
partials:
|
104
|
+
|
105
|
+
app/views/limits/_#{limitname}_meter.html.erb
|
106
|
+
|
107
|
+
You can override all the views by generating them into your app and customizing them there:
|
108
|
+
|
109
|
+
rails g saucy:views
|
110
|
+
|
111
|
+
## Gotchas
|
112
|
+
|
113
|
+
Make sure you don't do this in ApplicationController:
|
114
|
+
|
115
|
+
before_filter :authenticate
|
116
|
+
|
117
|
+
Saucy's internal controllers don't skip any before filters.
|
118
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'cucumber/rake/task'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
desc 'Default: run all tests'
|
9
|
+
task :default => [:spec, :cucumber]
|
10
|
+
|
11
|
+
Cucumber::Rake::Task.new(:cucumber) do |t|
|
12
|
+
t.fork = true
|
13
|
+
t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec::Core::RakeTask.new do |t|
|
17
|
+
t.pattern = "spec/**/*_spec.rb"
|
18
|
+
t.rspec_opts = "--format progress"
|
19
|
+
end
|
20
|
+
|
21
|
+
eval("$specification = begin; #{IO.read('saucy.gemspec')}; end")
|
22
|
+
Rake::GemPackageTask.new($specification) do |package|
|
23
|
+
package.need_zip = true
|
24
|
+
package.need_tar = true
|
25
|
+
end
|
26
|
+
|
27
|
+
gem_file = "pkg/#{$specification.name}-#{$specification.version}.gem"
|
28
|
+
|
29
|
+
desc "Build and install the latest gem"
|
30
|
+
task :install => :gem do
|
31
|
+
sh("gem install --local #{gem_file}")
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Build and release the latest gem"
|
35
|
+
task :release => :gem do
|
36
|
+
sh("gem push #{gem_file}")
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class AccountsController < ApplicationController
|
2
|
+
before_filter :authorize, :only => [:index, :edit, :update]
|
3
|
+
before_filter :authorize_admin, :except => [:new, :create, :index]
|
4
|
+
before_filter :ensure_active_account, :only => [:edit, :update]
|
5
|
+
layout Saucy::Layouts.to_proc
|
6
|
+
|
7
|
+
def new
|
8
|
+
@plan = Plan.find(params[:plan_id])
|
9
|
+
@signup = Signup.new
|
10
|
+
Saucy::Configuration.notify("plan_viewed", :request => request,
|
11
|
+
:plan => @plan)
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
@plan = Plan.find(params[:plan_id])
|
16
|
+
@signup = Signup.new(params[:signup])
|
17
|
+
@signup.user = current_user
|
18
|
+
@signup.plan = @plan
|
19
|
+
if @signup.save
|
20
|
+
Saucy::Configuration.notify("account_created", :request => request,
|
21
|
+
:account => @signup.account)
|
22
|
+
flash[:success] = "Account was created."
|
23
|
+
sign_in @signup.user
|
24
|
+
redirect_to new_account_project_path(@signup.account)
|
25
|
+
else
|
26
|
+
render :action => 'new'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def index
|
31
|
+
if current_user.projects.size == 1
|
32
|
+
flash.keep
|
33
|
+
redirect_to project_path(current_user.projects.first)
|
34
|
+
else
|
35
|
+
@accounts = current_user.accounts
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def edit
|
40
|
+
@account = current_account
|
41
|
+
end
|
42
|
+
|
43
|
+
def update
|
44
|
+
@account = current_account
|
45
|
+
if @account.update_attributes(params[:account])
|
46
|
+
flash[:success] = 'Account was updated.'
|
47
|
+
redirect_to edit_profile_url
|
48
|
+
else
|
49
|
+
render :action => :edit
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def destroy
|
54
|
+
current_account.destroy
|
55
|
+
flash[:success] = "Your account has been deleted."
|
56
|
+
redirect_to root_url
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def current_account
|
62
|
+
Account.find_by_keyword!(params[:id])
|
63
|
+
end
|
64
|
+
|
65
|
+
def current_account?
|
66
|
+
params[:id].present?
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class BillingsController < ApplicationController
|
2
|
+
before_filter :authorize_admin, :except => [:show]
|
3
|
+
layout Saucy::Layouts.to_proc
|
4
|
+
|
5
|
+
def show
|
6
|
+
end
|
7
|
+
|
8
|
+
def edit
|
9
|
+
@account = current_account
|
10
|
+
|
11
|
+
@account.cardholder_name = @account.credit_card.cardholder_name
|
12
|
+
@account.billing_email = @account.customer.email
|
13
|
+
@account.expiration_month = @account.credit_card.expiration_month
|
14
|
+
@account.expiration_year = @account.credit_card.expiration_year
|
15
|
+
end
|
16
|
+
|
17
|
+
def update
|
18
|
+
@account = current_account
|
19
|
+
if @account.save_customer_and_subscription!(params[:account])
|
20
|
+
redirect_to account_billing_path(@account), :notice => t('.update.notice', :default => "Billing information updated successfully")
|
21
|
+
else
|
22
|
+
render :edit
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class InvitationsController < ApplicationController
|
2
|
+
before_filter :authorize_admin, :except => [:show, :update]
|
3
|
+
before_filter :ensure_account_within_users_limit, :only => [:new, :create]
|
4
|
+
skip_before_filter :authorize, :only => [:show, :update]
|
5
|
+
layout Saucy::Layouts.to_proc
|
6
|
+
|
7
|
+
def new
|
8
|
+
assign_projects
|
9
|
+
@invitation = Invitation.new
|
10
|
+
render
|
11
|
+
end
|
12
|
+
|
13
|
+
def create
|
14
|
+
@invitation = Invitation.new(params[:invitation])
|
15
|
+
@invitation.account = current_account
|
16
|
+
@invitation.sender = current_user
|
17
|
+
if @invitation.save
|
18
|
+
flash[:success] = "User invited."
|
19
|
+
redirect_to account_memberships_url(current_account)
|
20
|
+
else
|
21
|
+
assign_projects
|
22
|
+
render :action => 'new'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def show
|
27
|
+
with_invitation { render }
|
28
|
+
end
|
29
|
+
|
30
|
+
def update
|
31
|
+
with_invitation do
|
32
|
+
if @invitation.accept(params[:invitation])
|
33
|
+
sign_in @invitation.user
|
34
|
+
redirect_to root_url
|
35
|
+
else
|
36
|
+
render :action => 'show'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def assign_projects
|
44
|
+
@projects = current_account.projects_by_name
|
45
|
+
end
|
46
|
+
|
47
|
+
def with_invitation
|
48
|
+
@invitation = Invitation.find_by_code!(params[:id])
|
49
|
+
if @invitation.used?
|
50
|
+
flash[:error] = t("invitations.show.used",
|
51
|
+
:default => "That invitation has already been used.")
|
52
|
+
redirect_to root_url
|
53
|
+
elsif signed_in? && current_user.email == @invitation.email
|
54
|
+
if @invitation.accept({:existing_user => current_user})
|
55
|
+
redirect_to root_url
|
56
|
+
end
|
57
|
+
else
|
58
|
+
yield
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def ensure_account_within_users_limit
|
63
|
+
ensure_account_within_limit("users")
|
64
|
+
end
|
65
|
+
end
|