Commit 63cd8feadbc85bed6946532214b5b45469e60ca7
1 parent
c5fbd31d
Exists in
master
and in
1 other branch
WIP - Add Users backed by Devise
Showing
24 changed files
with
381 additions
and
19 deletions
Show diff stats
Gemfile
Gemfile.lock
... | ... | @@ -30,10 +30,14 @@ GEM |
30 | 30 | activesupport (3.0.0.rc) |
31 | 31 | arel (0.4.0) |
32 | 32 | activesupport (>= 3.0.0.beta) |
33 | + bcrypt-ruby (2.1.2) | |
33 | 34 | bson (1.0.4) |
34 | 35 | bson_ext (1.0.4) |
35 | 36 | builder (2.1.2) |
36 | 37 | database_cleaner (0.5.2) |
38 | + devise (1.1.1) | |
39 | + bcrypt-ruby (~> 2.1.2) | |
40 | + warden (~> 0.10.7) | |
37 | 41 | diff-lcs (1.1.2) |
38 | 42 | erubis (2.6.6) |
39 | 43 | abstract (>= 1.0.0) |
... | ... | @@ -41,7 +45,7 @@ GEM |
41 | 45 | factory_girl_rails (1.0) |
42 | 46 | factory_girl (~> 1.3) |
43 | 47 | rails (>= 3.0.0.beta4) |
44 | - haml (3.0.15) | |
48 | + haml (3.0.16) | |
45 | 49 | i18n (0.4.1) |
46 | 50 | libxml-ruby (1.1.4) |
47 | 51 | mail (2.2.5) |
... | ... | @@ -93,6 +97,8 @@ GEM |
93 | 97 | treetop (1.4.8) |
94 | 98 | polyglot (>= 0.3.1) |
95 | 99 | tzinfo (0.3.22) |
100 | + warden (0.10.7) | |
101 | + rack (>= 1.0.0) | |
96 | 102 | webrat (0.7.2.beta.1) |
97 | 103 | nokogiri (>= 1.2.0) |
98 | 104 | rack (>= 1.0) |
... | ... | @@ -105,6 +111,7 @@ PLATFORMS |
105 | 111 | DEPENDENCIES |
106 | 112 | bson_ext |
107 | 113 | database_cleaner (= 0.5.2) |
114 | + devise (= 1.1.1) | |
108 | 115 | factory_girl_rails |
109 | 116 | haml |
110 | 117 | libxml-ruby | ... | ... |
README.md
1 | 1 | Errbit: The open source self-hosted Hoptoad Server |
2 | 2 | ===================================================== |
3 | 3 | |
4 | -WIP | |
4 | +Installation | |
5 | +------------ | |
5 | 6 | |
6 | -TODO: License | |
7 | 7 | \ No newline at end of file |
8 | +1. Install MongoDB | |
9 | +2. Install & Run Bundler | |
10 | +3. Seed DB - rake db:seed | |
8 | 11 | \ No newline at end of file | ... | ... |
app/controllers/application_controller.rb
app/mailers/mailer.rb
... | ... | @@ -0,0 +1,13 @@ |
1 | +class User | |
2 | + include Mongoid::Document | |
3 | + | |
4 | + devise :database_authenticatable, :registerable, | |
5 | + :recoverable, :rememberable, :trackable, | |
6 | + :validatable, :token_authenticatable | |
7 | + | |
8 | + field :name | |
9 | + field :admin, :type => Boolean, :default => false | |
10 | + | |
11 | + validates_presence_of :name | |
12 | + | |
13 | +end | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +%h2 Resend confirmation instructions | |
2 | += form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| | |
3 | + = devise_error_messages! | |
4 | + %p | |
5 | + = f.label :email | |
6 | + %br/ | |
7 | + = f.text_field :email | |
8 | + %p= f.submit "Resend confirmation instructions" | |
9 | += render :partial => "devise/shared/links" | ... | ... |
app/views/devise/mailer/confirmation_instructions.html.haml
0 → 100644
app/views/devise/mailer/reset_password_instructions.html.haml
0 → 100644
... | ... | @@ -0,0 +1,6 @@ |
1 | +%p | |
2 | + Hello #{@resource.email}! | |
3 | +%p Someone has requested a link to change your password, and you can do this through the link below. | |
4 | +%p= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) | |
5 | +%p If you didn't request this, please ignore this email. | |
6 | +%p Your password won't change until you access the link above and create a new one. | ... | ... |
... | ... | @@ -0,0 +1,5 @@ |
1 | +%p | |
2 | + Hello #{@resource.email}! | |
3 | +%p Your account has been locked due to an excessive amount of unsuccessful sign in attempts. | |
4 | +%p Click the link below to unlock your account: | |
5 | +%p= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token) | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +%h2 Change your password | |
2 | += form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| | |
3 | + = devise_error_messages! | |
4 | + = f.hidden_field :reset_password_token | |
5 | + %p | |
6 | + = f.label :password | |
7 | + %br/ | |
8 | + = f.password_field :password | |
9 | + %p | |
10 | + = f.label :password_confirmation | |
11 | + %br/ | |
12 | + = f.password_field :password_confirmation | |
13 | + %p= f.submit "Change my password" | |
14 | += render :partial => "devise/shared/links" | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +%h2 Forgot your password? | |
2 | += form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| | |
3 | + = devise_error_messages! | |
4 | + %p | |
5 | + = f.label :email | |
6 | + %br/ | |
7 | + = f.text_field :email | |
8 | + %p= f.submit "Send me reset password instructions" | |
9 | += render :partial => "devise/shared/links" | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +%h2 | |
2 | + Edit #{resource_name.to_s.humanize} | |
3 | += form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| | |
4 | + = devise_error_messages! | |
5 | + %p | |
6 | + = f.label :email | |
7 | + %br/ | |
8 | + = f.text_field :email | |
9 | + %p | |
10 | + = f.label :password | |
11 | + %i (leave blank if you don't want to change it) | |
12 | + %br/ | |
13 | + = f.password_field :password | |
14 | + %p | |
15 | + = f.label :password_confirmation | |
16 | + %br/ | |
17 | + = f.password_field :password_confirmation | |
18 | + %p | |
19 | + = f.label :current_password | |
20 | + %i (we need your current password to confirm your changes) | |
21 | + %br/ | |
22 | + = f.password_field :current_password | |
23 | + %p= f.submit "Update" | |
24 | +%h3 Cancel my account | |
25 | +%p | |
26 | + Unhappy? #{link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete}. | |
27 | += link_to "Back", :back | ... | ... |
... | ... | @@ -0,0 +1,20 @@ |
1 | +%h2 Sign up | |
2 | += form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| | |
3 | + = devise_error_messages! | |
4 | + %p | |
5 | + = f.label :name | |
6 | + = f.text_field :name | |
7 | + %p | |
8 | + = f.label :email | |
9 | + %br/ | |
10 | + = f.text_field :email | |
11 | + %p | |
12 | + = f.label :password | |
13 | + %br/ | |
14 | + = f.password_field :password | |
15 | + %p | |
16 | + = f.label :password_confirmation | |
17 | + %br/ | |
18 | + = f.password_field :password_confirmation | |
19 | + %p= f.submit "Sign up" | |
20 | += render :partial => "devise/shared/links" | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +%h2 Sign in | |
2 | += form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| | |
3 | + %p | |
4 | + = f.label :email | |
5 | + %br/ | |
6 | + = f.text_field :email | |
7 | + %p | |
8 | + = f.label :password | |
9 | + %br/ | |
10 | + = f.password_field :password | |
11 | + - if devise_mapping.rememberable? | |
12 | + %p | |
13 | + = f.check_box :remember_me | |
14 | + = f.label :remember_me | |
15 | + %p= f.submit "Sign in" | |
16 | += render :partial => "devise/shared/links" | ... | ... |
... | ... | @@ -0,0 +1,15 @@ |
1 | +- if controller_name != 'sessions' | |
2 | + = link_to "Sign in", new_session_path(resource_name) | |
3 | + %br/ | |
4 | +- if devise_mapping.registerable? && controller_name != 'registrations' | |
5 | + = link_to "Sign up", new_registration_path(resource_name) | |
6 | + %br/ | |
7 | +- if devise_mapping.recoverable? && controller_name != 'passwords' | |
8 | + = link_to "Forgot your password?", new_password_path(resource_name) | |
9 | + %br/ | |
10 | +- if devise_mapping.confirmable? && controller_name != 'confirmations' | |
11 | + = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) | |
12 | + %br/ | |
13 | +- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' | |
14 | + = link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) | |
15 | + %br/ | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +%h2 Resend unlock instructions | |
2 | += form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| | |
3 | + = devise_error_messages! | |
4 | + %p | |
5 | + = f.label :email | |
6 | + %br/ | |
7 | + = f.text_field :email | |
8 | + %p= f.submit "Resend unlock instructions" | |
9 | += render :partial => "devise/shared/links" | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +require 'ostruct' | |
2 | + | |
3 | +yaml = File.read(Rails.root.join('config','config.yml')) | |
4 | +config = YAML.load(yaml) | |
5 | + | |
6 | +config.merge!(config.delete(Rails.env)) if config.has_key?(Rails.env) | |
7 | + | |
8 | +Errbit::Config = OpenStruct.new(config) | |
9 | + | |
10 | +# Set config specific values | |
11 | +ActionMailer::Base.default_url_options[:host] = Errbit::Config.host | |
0 | 12 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,142 @@ |
1 | +# Use this hook to configure devise mailer, warden hooks and so forth. The first | |
2 | +# four configuration values can also be set straight in your models. | |
3 | +Devise.setup do |config| | |
4 | + # ==> Mailer Configuration | |
5 | + # Configure the e-mail address which will be shown in DeviseMailer. | |
6 | + config.mailer_sender = Errbit::Config.email_from | |
7 | + | |
8 | + # Configure the class responsible to send e-mails. | |
9 | + # config.mailer = "Devise::Mailer" | |
10 | + | |
11 | + # ==> ORM configuration | |
12 | + # Load and configure the ORM. Supports :active_record (default) and | |
13 | + # :mongoid (bson_ext recommended) by default. Other ORMs may be | |
14 | + # available as additional gems. | |
15 | + require 'devise/orm/mongoid' | |
16 | + | |
17 | + # ==> Configuration for any authentication mechanism | |
18 | + # Configure which keys are used when authenticating an user. By default is | |
19 | + # just :email. You can configure it to use [:username, :subdomain], so for | |
20 | + # authenticating an user, both parameters are required. Remember that those | |
21 | + # parameters are used only when authenticating and not when retrieving from | |
22 | + # session. If you need permissions, you should implement that in a before filter. | |
23 | + # config.authentication_keys = [ :email ] | |
24 | + | |
25 | + # Tell if authentication through request.params is enabled. True by default. | |
26 | + # config.params_authenticatable = true | |
27 | + | |
28 | + # Tell if authentication through HTTP Basic Auth is enabled. True by default. | |
29 | + # config.http_authenticatable = true | |
30 | + | |
31 | + # Set this to true to use Basic Auth for AJAX requests. True by default. | |
32 | + # config.http_authenticatable_on_xhr = true | |
33 | + | |
34 | + # The realm used in Http Basic Authentication | |
35 | + # config.http_authentication_realm = "Application" | |
36 | + | |
37 | + # ==> Configuration for :database_authenticatable | |
38 | + # For bcrypt, this is the cost for hashing the password and defaults to 10. If | |
39 | + # using other encryptors, it sets how many times you want the password re-encrypted. | |
40 | + config.stretches = 10 | |
41 | + | |
42 | + # Define which will be the encryption algorithm. Devise also supports encryptors | |
43 | + # from others authentication tools as :clearance_sha1, :authlogic_sha512 (then | |
44 | + # you should set stretches above to 20 for default behavior) and :restful_authentication_sha1 | |
45 | + # (then you should set stretches to 10, and copy REST_AUTH_SITE_KEY to pepper) | |
46 | + config.encryptor = :bcrypt | |
47 | + | |
48 | + # Setup a pepper to generate the encrypted password. | |
49 | + config.pepper = "425f10f555c1a4718aff3370ef9dd2d97a21622beb0400fde6b52177375ddcbe37a2dac6af9bca835c988e00c32887ee940ba111a78eab48234d8799936d36b9" | |
50 | + | |
51 | + # ==> Configuration for :confirmable | |
52 | + # The time you want to give your user to confirm his account. During this time | |
53 | + # he will be able to access your application without confirming. Default is nil. | |
54 | + # When confirm_within is zero, the user won't be able to sign in without confirming. | |
55 | + # You can use this to let your user access some features of your application | |
56 | + # without confirming the account, but blocking it after a certain period | |
57 | + # (ie 2 days). | |
58 | + # config.confirm_within = 2.days | |
59 | + | |
60 | + # ==> Configuration for :rememberable | |
61 | + # The time the user will be remembered without asking for credentials again. | |
62 | + config.remember_for = 2.weeks | |
63 | + | |
64 | + # If true, a valid remember token can be re-used between multiple browsers. | |
65 | + # config.remember_across_browsers = true | |
66 | + | |
67 | + # If true, extends the user's remember period when remembered via cookie. | |
68 | + # config.extend_remember_period = false | |
69 | + | |
70 | + # ==> Configuration for :validatable | |
71 | + # Range for password length | |
72 | + config.password_length = 6..20 | |
73 | + | |
74 | + # Regex to use to validate the email address | |
75 | + config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i | |
76 | + | |
77 | + # ==> Configuration for :timeoutable | |
78 | + # The time you want to timeout the user session without activity. After this | |
79 | + # time the user will be asked for credentials again. | |
80 | + # config.timeout_in = 10.minutes | |
81 | + | |
82 | + # ==> Configuration for :lockable | |
83 | + # Defines which strategy will be used to lock an account. | |
84 | + # :failed_attempts = Locks an account after a number of failed attempts to sign in. | |
85 | + # :none = No lock strategy. You should handle locking by yourself. | |
86 | + # config.lock_strategy = :failed_attempts | |
87 | + | |
88 | + # Defines which strategy will be used to unlock an account. | |
89 | + # :email = Sends an unlock link to the user email | |
90 | + # :time = Re-enables login after a certain amount of time (see :unlock_in below) | |
91 | + # :both = Enables both strategies | |
92 | + # :none = No unlock strategy. You should handle unlocking by yourself. | |
93 | + # config.unlock_strategy = :both | |
94 | + | |
95 | + # Number of authentication tries before locking an account if lock_strategy | |
96 | + # is failed attempts. | |
97 | + # config.maximum_attempts = 20 | |
98 | + | |
99 | + # Time interval to unlock the account if :time is enabled as unlock_strategy. | |
100 | + # config.unlock_in = 1.hour | |
101 | + | |
102 | + # ==> Configuration for :token_authenticatable | |
103 | + # Defines name of the authentication token params key | |
104 | + config.token_authentication_key = :auth_token | |
105 | + | |
106 | + # ==> Scopes configuration | |
107 | + # Turn scoped views on. Before rendering "sessions/new", it will first check for | |
108 | + # "users/sessions/new". It's turned off by default because it's slower if you | |
109 | + # are using only default views. | |
110 | + # config.scoped_views = true | |
111 | + | |
112 | + # Configure the default scope given to Warden. By default it's the first | |
113 | + # devise role declared in your routes. | |
114 | + # config.default_scope = :user | |
115 | + | |
116 | + # Configure sign_out behavior. | |
117 | + # By default sign_out is scoped (i.e. /users/sign_out affects only :user scope). | |
118 | + # In case of sign_out_all_scopes set to true any logout action will sign out all active scopes. | |
119 | + # config.sign_out_all_scopes = false | |
120 | + | |
121 | + # ==> Navigation configuration | |
122 | + # Lists the formats that should be treated as navigational. Formats like | |
123 | + # :html, should redirect to the sign in page when the user does not have | |
124 | + # access, but formats like :xml or :json, should return 401. | |
125 | + # If you have any extra navigational formats, like :iphone or :mobile, you | |
126 | + # should add them to the navigational formats lists. Default is [:html] | |
127 | + # config.navigational_formats = [:html, :iphone] | |
128 | + | |
129 | + # ==> Warden configuration | |
130 | + # If you want to use other strategies, that are not (yet) supported by Devise, | |
131 | + # you can configure them inside the config.warden block. The example below | |
132 | + # allows you to setup OAuth, using http://github.com/roman/warden_oauth | |
133 | + # | |
134 | + # config.warden do |manager| | |
135 | + # manager.oauth(:twitter) do |twitter| | |
136 | + # twitter.consumer_secret = <YOUR CONSUMER SECRET> | |
137 | + # twitter.consumer_key = <YOUR CONSUMER KEY> | |
138 | + # twitter.options :site => 'http://twitter.com' | |
139 | + # end | |
140 | + # manager.default_strategies(:scope => :user).unshift :twitter_oauth | |
141 | + # end | |
142 | +end | ... | ... |
config/initializers/load_config.rb
... | ... | @@ -0,0 +1,39 @@ |
1 | +en: | |
2 | + errors: | |
3 | + messages: | |
4 | + not_found: "not found" | |
5 | + already_confirmed: "was already confirmed" | |
6 | + not_locked: "was not locked" | |
7 | + | |
8 | + devise: | |
9 | + failure: | |
10 | + unauthenticated: 'You need to sign in or sign up before continuing.' | |
11 | + unconfirmed: 'You have to confirm your account before continuing.' | |
12 | + locked: 'Your account is locked.' | |
13 | + invalid: 'Invalid email or password.' | |
14 | + invalid_token: 'Invalid authentication token.' | |
15 | + timeout: 'Your session expired, please sign in again to continue.' | |
16 | + inactive: 'Your account was not activated yet.' | |
17 | + sessions: | |
18 | + signed_in: 'Signed in successfully.' | |
19 | + signed_out: 'Signed out successfully.' | |
20 | + passwords: | |
21 | + send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' | |
22 | + updated: 'Your password was changed successfully. You are now signed in.' | |
23 | + confirmations: | |
24 | + send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' | |
25 | + confirmed: 'Your account was successfully confirmed. You are now signed in.' | |
26 | + registrations: | |
27 | + signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.' | |
28 | + updated: 'You updated your account successfully.' | |
29 | + destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.' | |
30 | + unlocks: | |
31 | + send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' | |
32 | + unlocked: 'Your account was successfully unlocked. You are now signed in.' | |
33 | + mailer: | |
34 | + confirmation_instructions: | |
35 | + subject: 'Confirmation instructions' | |
36 | + reset_password_instructions: | |
37 | + subject: 'Reset password instructions' | |
38 | + unlock_instructions: | |
39 | + subject: 'Unlock Instructions' | ... | ... |
config/routes.rb
1 | 1 | Errbit::Application.routes.draw do |
2 | 2 | |
3 | + devise_for :users | |
4 | + | |
3 | 5 | # Hoptoad Notifier Routes |
4 | 6 | match '/notifier_api/v2/notices' => 'notices#create' |
5 | 7 | match '/deploys.txt' => 'deploys#create' |
... | ... | @@ -21,6 +23,8 @@ Errbit::Application.routes.draw do |
21 | 23 | end |
22 | 24 | end |
23 | 25 | |
26 | + devise_for :users | |
27 | + | |
24 | 28 | root :to => 'apps#index' |
25 | 29 | |
26 | 30 | end | ... | ... |
db/seeds.rb
1 | -# This file should contain all the record creation needed to seed the database with its default values. | |
2 | -# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). | |
3 | -# | |
4 | -# Examples: | |
5 | -# | |
6 | -# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) | |
7 | -# Mayor.create(:name => 'Daley', :city => cities.first) | |
1 | +# Create an initial Admin User | |
2 | +admin_email = "errbit@#{Errbit::Config.host}" | |
3 | +admin_pass = 'password' | |
4 | + | |
5 | +puts "Creating an initial admin user:" | |
6 | +puts "-- email: #{admin_email}" | |
7 | +puts "-- password: #{admin_pass}" | |
8 | +puts "" | |
9 | +puts "Be sure to change these credentials ASAP!" | |
10 | +User.create!({ | |
11 | + :name => 'Errbit Admin', | |
12 | + :email => admin_email, | |
13 | + :password => admin_pass, | |
14 | + :password_confirmation => admin_pass, | |
15 | + :admin => true | |
16 | +}) | |
8 | 17 | \ No newline at end of file | ... | ... |