ioquatix-account_engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/README +0 -0
  2. data/lib/account_engine/configuration.rb +101 -0
  3. data/lib/account_engine/controller.rb +246 -0
  4. data/lib/account_engine/helper.rb +104 -0
  5. data/lib/account_engine/password.rb +432 -0
  6. data/lib/account_engine/support.rb +12 -0
  7. data/lib/account_engine/user_account/class_methods.rb +63 -0
  8. data/lib/account_engine/user_account.rb +184 -0
  9. data/lib/account_engine.rb +63 -0
  10. data/rails/app/controllers/account_controller.rb +162 -0
  11. data/rails/app/controllers/permissions_controller.rb +90 -0
  12. data/rails/app/controllers/roles_controller.rb +133 -0
  13. data/rails/app/controllers/users_controller.rb +144 -0
  14. data/rails/app/helpers/account_helper.rb +3 -0
  15. data/rails/app/helpers/permissions_helper.rb +3 -0
  16. data/rails/app/helpers/roles_helper.rb +3 -0
  17. data/rails/app/helpers/users_helper.rb +3 -0
  18. data/rails/app/models/permission.rb +129 -0
  19. data/rails/app/models/role.rb +60 -0
  20. data/rails/app/models/user.rb +5 -0
  21. data/rails/app/models/user_notify.rb +75 -0
  22. data/rails/app/views/account/_form.rhtml +8 -0
  23. data/rails/app/views/account/change_password.rhtml +17 -0
  24. data/rails/app/views/account/edit.rhtml +5 -0
  25. data/rails/app/views/account/forgot_password.rhtml +12 -0
  26. data/rails/app/views/account/home.rhtml +3 -0
  27. data/rails/app/views/account/login.rhtml +27 -0
  28. data/rails/app/views/account/logout.rhtml +8 -0
  29. data/rails/app/views/account/signup.rhtml +28 -0
  30. data/rails/app/views/permissions/_form.rhtml +14 -0
  31. data/rails/app/views/permissions/_list.rhtml +38 -0
  32. data/rails/app/views/permissions/edit.rhtml +5 -0
  33. data/rails/app/views/permissions/index.rhtml +3 -0
  34. data/rails/app/views/permissions/new.rhtml +5 -0
  35. data/rails/app/views/roles/_form.rhtml +8 -0
  36. data/rails/app/views/roles/_permissions.rhtml +25 -0
  37. data/rails/app/views/roles/edit.rhtml +5 -0
  38. data/rails/app/views/roles/index.rhtml +34 -0
  39. data/rails/app/views/roles/new.rhtml +5 -0
  40. data/rails/app/views/roles/show.rhtml +20 -0
  41. data/rails/app/views/user_notify/change_password.rhtml +10 -0
  42. data/rails/app/views/user_notify/delete.rhtml +5 -0
  43. data/rails/app/views/user_notify/forgot_password.rhtml +11 -0
  44. data/rails/app/views/user_notify/pending_delete.rhtml +9 -0
  45. data/rails/app/views/user_notify/signup.rhtml +12 -0
  46. data/rails/app/views/users/_form.rhtml +12 -0
  47. data/rails/app/views/users/edit.rhtml +5 -0
  48. data/rails/app/views/users/index.rhtml +38 -0
  49. data/rails/app/views/users/new.rhtml +5 -0
  50. data/rails/app/views/users/roles.rhtml +42 -0
  51. data/rails/app/views/users/show.rhtml +36 -0
  52. data/rails/assets/images/default/omnipotent.png +0 -0
  53. data/rails/assets/images/default/system.png +0 -0
  54. data/rails/assets/images/permissions/create.png +0 -0
  55. data/rails/assets/images/permissions/sync.png +0 -0
  56. data/rails/assets/images/roles/add_permission.png +0 -0
  57. data/rails/assets/images/roles/create.png +0 -0
  58. data/rails/assets/images/roles/edit.png +0 -0
  59. data/rails/assets/images/roles/remove_permission.png +0 -0
  60. data/rails/assets/images/roles/user.png +0 -0
  61. data/rails/assets/images/table_background.png +0 -0
  62. data/rails/assets/images/users/create.png +0 -0
  63. data/rails/assets/images/users/destroy.png +0 -0
  64. data/rails/assets/images/users/edit.png +0 -0
  65. data/rails/assets/images/users/show.png +0 -0
  66. data/rails/assets/javascripts/account_engine.js +166 -0
  67. data/rails/assets/stylesheets/account_engine.css +7 -0
  68. data/rails/assets/stylesheets/check_password.css +10 -0
  69. data/rails/assets/stylesheets/simple.css +168 -0
  70. data/rails/db/migrate/001_initial_schema.rb +49 -0
  71. data/rails/init.rb +21 -0
  72. data/rails/routes.rb +5 -0
  73. data/rails/tasks/account_engine.rake +123 -0
  74. metadata +165 -0
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2006 Samuel Williams <samuel.williams@oriontransfer.co.nz>
2
+ #
3
+ # The GNU General Public License (GPL)
4
+ # Version 2, June 1991
5
+ #
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+
20
+
21
+ require 'account_engine/configuration'
22
+ require 'account_engine/controller'
23
+ require 'account_engine/helper'
24
+ require 'account_engine/user_account'
25
+
26
+ module AccountEngine
27
+ include AccountEngine::Helper
28
+
29
+ # This method will check the Roles in the database against to ensure that there is
30
+ # only ONE omnipotent role.
31
+ def self.check_system_roles
32
+ begin
33
+ if Role.count() > 0
34
+ begin
35
+ omnipotent_roles = Role.find_all_by_omnipotent(true)
36
+ if omnipotent_roles && omnipotent_roles.length != 1
37
+ @warning = "WARNING: You have more than one omnipotent role: " +
38
+ omnipotent_roles.collect { |r| r.name }.join(", ")
39
+ elsif omnipotent_roles == nil
40
+ @warning = "WARNING: You have no omnipotent roles. Please re-run the bootstrap rake task."
41
+ end
42
+ rescue
43
+ @warning = "WARNING: Could not check integrity of system roles. Please check your data."
44
+ end
45
+ else
46
+ raise "skip error" # this will be caught below
47
+ end
48
+ rescue # either Roles.count() == 0, or the Roles table doesn't even exist yet.
49
+ @warning = "Skipping integrity check. You have no system roles set up; once your " +
50
+ "database tables are set up, run rake bootstrap to create the basic roles."
51
+ end
52
+
53
+ if @warning != nil
54
+ RAILS_DEFAULT_LOGGER.warn @warning
55
+ puts @warning
56
+ end
57
+ end
58
+
59
+ # An exception to be raised when the integrity of the authorization system is
60
+ # threatened.
61
+ class SystemProtectionError < Exception
62
+ end
63
+ end
@@ -0,0 +1,162 @@
1
+ class AccountController < ApplicationController
2
+ layout 'admin'
3
+
4
+ # Override this function in your own application to define a custom home action.
5
+ def home
6
+ @user = current_user
7
+
8
+ unless @user
9
+ access_denied
10
+ end
11
+ end
12
+
13
+ # The action used to log a user in. If the user was redirected to the login page
14
+ # by the login_required method, they should be sent back to the page they were
15
+ # trying to access. If not, they will be sent to "/user/home".
16
+ def login
17
+ if current_user
18
+ flash[:notice] = 'You are already logged in!'
19
+ redirect_to :action => 'home'
20
+
21
+ return
22
+ end
23
+
24
+ if request.post?
25
+ if authenticate_user
26
+ flash[:notice] = 'Login successful'
27
+ redirect_to_stored_or_default :action => 'home'
28
+
29
+ return
30
+ else
31
+ flash.now[:login] = 'Login unsuccessful'
32
+ end
33
+ end
34
+
35
+ @login = params[:login]
36
+ end
37
+
38
+ # Register as a new user.
39
+ def signup
40
+ @user = User.new
41
+ end
42
+
43
+ def register
44
+ @user = User.new
45
+
46
+ User.transaction(@user) do
47
+ @user.login = params[:user][:login]
48
+ @user.email = params[:user][:email]
49
+ @user.password = params[:user][:password]
50
+
51
+ if AccountEngine.use_email_notification
52
+ key = @user.generate_security_token
53
+ url = url_for(:action => '', :user_id => @user.id, :key => key)
54
+ @user.save!
55
+ UserNotify.deliver_signup(@user, params[:user][:password], url)
56
+ flash[:notice] << ' Please check your registered email account to verify your account registration and continue with the login.'
57
+ else
58
+ @user.verified = 1
59
+ @user.save!
60
+ end
61
+
62
+ flash[:notice] = 'Signup successful! Please log in.'
63
+ redirect_to :action => 'login', :login => @user.login
64
+ end
65
+ end
66
+
67
+ def logout
68
+ session[:user] = nil
69
+ redirect_to :action => 'login'
70
+ end
71
+
72
+ def change_password
73
+ if request.post?
74
+ current_user.password = params[:password]
75
+
76
+ if user.save
77
+ if AccountEngine.use_email_notification
78
+ UserNotify.deliver_change_password(user, params[:password])
79
+ flash[:notice] = "Updated password emailed to #{@user.email}"
80
+ else
81
+ flash[:notice] = "Password updated."
82
+ end
83
+ else
84
+ flash[:warning] = 'There was a problem saving the password. Please retry.'
85
+ end
86
+
87
+ redirect_back_or_default :action => 'home'
88
+ end
89
+ end
90
+
91
+ def edit
92
+ @user = current_user
93
+ end
94
+
95
+ def update
96
+ @user = current_user
97
+
98
+ @user.email = params[:user][:email]
99
+ @user.login = params[:user][:login]
100
+
101
+ if @user.save
102
+ flash[:message] = 'Details updated'
103
+ redirect_to :action => :home
104
+ else
105
+ render_action :edit
106
+ end
107
+ end
108
+
109
+ def forgot_password
110
+ # Always redirect if logged in
111
+ if user?
112
+ flash[:message] = 'You are currently logged in. You may change your password now.'
113
+ redirect_to :action => 'change_password'
114
+ return
115
+ end
116
+
117
+ if request.post?
118
+ # Email disabled... we are unable to provide the password
119
+ if !AccountEngine.use_email_notification
120
+ flash[:message] = "Please contact the system admin at #{AccountEngine.admin_email} to reset your password."
121
+ redirect_back_or_default :action => 'login'
122
+ return
123
+ end
124
+
125
+ # Handle the :post
126
+ if params[:email].blank?
127
+ flash.now[:warning] = 'Please enter a valid email address.'
128
+ elsif (user = User.find_by_email(params[:email])).nil?
129
+ flash.now[:warning] = "We could not find a user with the email address #{params[:email]}"
130
+ else
131
+ begin
132
+ User.transaction(user) do
133
+ key = user.generate_security_token
134
+ url = url_for(:action => 'change_password', :user_id => user.id, :key => key)
135
+ UserNotify.deliver_forgot_password(user, url)
136
+ flash[:notice] = "Instructions on resetting your password have been emailed to #{params[:email]}"
137
+ end
138
+
139
+ unless user?
140
+ redirect_to :action => 'login'
141
+ return
142
+ end
143
+
144
+ redirect_back_or_default :action => 'home'
145
+ rescue
146
+ logger.warn "Error mailing password to user #{params[:email]}: #{$!}"
147
+ flash.now[:warning] = "Your password could not be emailed to #{params[:email]}"
148
+ end
149
+ end
150
+ end
151
+
152
+ end
153
+
154
+ protected
155
+ def protect?(action)
156
+ if ['login', 'signup', 'forgot_password'].include?(action)
157
+ return false
158
+ else
159
+ return true
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,90 @@
1
+ # The PermissionController provides methods for manipulating Permission
2
+ # objects from the web interface.
3
+ class PermissionsController < ApplicationController
4
+ layout 'admin'
5
+
6
+ def resync
7
+ Permission.sync
8
+ flash[:message] = "Permissions synchronized"
9
+
10
+ redirect_to :back
11
+ end
12
+
13
+ # Displays a paginated list of all Permission objects
14
+ def index
15
+ @permissions = Permission.find :all, :order => 'controller, action'
16
+ end
17
+
18
+ # Displays a single Permission object, by the id given.
19
+ def show
20
+ @permission = find_permission(params[:id])
21
+ end
22
+
23
+ # Creates a new Permission object. Note that this is not the recommended
24
+ # way of creating Permission objects - instead you should use
25
+ # Permission.sync to add them automatically from your application
26
+ def new
27
+ @permission = Permission.new
28
+
29
+ @permission.system = false
30
+ end
31
+
32
+ def create
33
+ @permission = Permission.new params[:permission]
34
+
35
+ if @permission.save
36
+ flash[:notice] = 'Permission was successfully created.'
37
+ redirect_to :action => 'list'
38
+ else
39
+ render_action 'new'
40
+ end
41
+ end
42
+
43
+ # Edits a Permission object
44
+ def edit
45
+ @permission = find_permission(params[:id])
46
+
47
+ if @permission.system?
48
+ flash[:warning] = "Cannot edit system permissions."
49
+ redirect_to :back
50
+ end
51
+ end
52
+
53
+ def update
54
+ @permission = find_permission(params[:id])
55
+
56
+ if @permission.update_attributes(params[:permission])
57
+ flash[:notice] = 'Permission was successfully updated.'
58
+ redirect_to :action => 'list'
59
+ else
60
+ render_action 'edit'
61
+ end
62
+ end
63
+
64
+ # Destroys a Permission Object
65
+ def destroy
66
+ @permission = find_permission(params[:id])
67
+
68
+ if @permission and !@permission.system?
69
+ @permission.destroy
70
+ flash[:notice] = "Permission destroyed"
71
+ else
72
+ flash[:warning] = "Cannot delete system permissions."
73
+ end
74
+
75
+ redirect_to :back
76
+ end
77
+
78
+ protected
79
+ # A helper method to find Permission objects by ID, and insert
80
+ # appropriate error messages into the flash if it couldn't be
81
+ # found.
82
+ def find_permission(id)
83
+ begin
84
+ Permission.find(id)
85
+ rescue
86
+ flash[:message] = "There is no permission with ID ##{id}"
87
+ nil
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,133 @@
1
+ class RolesController < ApplicationController
2
+ layout 'admin'
3
+
4
+ def index
5
+ @content_columns = Role.content_columns
6
+ @roles = Role.paginate :page => params[:page], :order => "name"
7
+ end
8
+
9
+ # Displays a single Role object by given id.
10
+ def show
11
+ @role = find_role(params[:id])
12
+ @actions = @role.permissions_by_controller
13
+
14
+ # Add in all controllers
15
+ Permission.find(:all, :group => 'controller').each do |c|
16
+ @actions[c.controller] ||= []
17
+ end
18
+ end
19
+
20
+ def add_permission
21
+ @role = Role.find params[:id]
22
+ @permission = Permission.find params[:permission]
23
+
24
+ @role.permissions << @permission
25
+
26
+ redirect_to :back
27
+ end
28
+
29
+ def remove_permission
30
+ @role = Role.find params[:id]
31
+ @permission = Permission.find params[:permission]
32
+
33
+ @role.permissions.delete(@permission)
34
+
35
+ redirect_to :back
36
+ end
37
+
38
+ # Creates a new Role object with the given parameters.
39
+ def new
40
+ @role = Role.new
41
+ end
42
+
43
+ def create
44
+ @role = Role.new(params[:role])
45
+ if @role.save
46
+ flash[:notice] = 'Role was successfully created.'
47
+ redirect_to :action => 'list'
48
+ else
49
+ render_action 'new'
50
+ end
51
+ end
52
+
53
+ # Edit a Role object
54
+ def edit
55
+ case request.method
56
+ when :get
57
+ if (@role = find_role(params[:id]))
58
+ # load up the controllers
59
+ @all_permissions = Permission.find(:all)
60
+
61
+ # split it up into controllers
62
+ @all_actions = {}
63
+ @all_permissions.each { |permission|
64
+ @all_actions[permission.controller] ||= []
65
+ @all_actions[permission.controller] << permission
66
+ }
67
+ else
68
+ redirect_back_or_default :action => 'list'
69
+ end
70
+ when :post
71
+ if (@role = find_role(params[:id]))
72
+ # update the action permissions
73
+ permission_keys = params.keys.select { |k| k =~ /^permissions_/ }
74
+ permissions = permission_keys.collect { |k| params[k] }
75
+
76
+ begin
77
+ permissions.collect! { |perm_id| Permission.find(perm_id) }
78
+
79
+ # just wipe them all and re-build
80
+ @role.permissions.clear
81
+
82
+ permissions.each { |perm|
83
+ if !@role.permissions.include?(perm)
84
+ @role.permissions << perm
85
+ end
86
+ }
87
+
88
+ # save the object
89
+ if @role.update_attributes(params[:role])
90
+ flash[:notice] = 'Role was successfully updated.'
91
+ redirect_to :action => 'show', :id => @role
92
+ else
93
+ flash[:message] = 'The role could not be updated.'
94
+ render :action => 'edit'
95
+ end
96
+ rescue ActiveRecord::RecordNotFound => e
97
+ flash[:message] = 'Permission not found!'
98
+ render :action => 'edit'
99
+ end
100
+ else
101
+ redirect_back_or_default :action => 'list'
102
+ end
103
+ end
104
+ end
105
+
106
+ # Destroy a given Role object
107
+ def destroy
108
+ if (@role = find_role(params[:id]))
109
+ begin
110
+ @role.destroy
111
+ flash[:notice] = "Role '#{@role.name}' has been deleted."
112
+ redirect_to :action => 'list'
113
+ rescue AccountEngine::SystemProtectionError => e
114
+ flash[:message] = "Cannot destroy the system role '#{@role.name}'!"
115
+ redirect_to :action => 'list'
116
+ end
117
+ else
118
+ redirect_back_or_default :action => 'list'
119
+ end
120
+ end
121
+
122
+ protected
123
+ # A convenience method to find a Role, and add any errors to the flash if
124
+ # the Role is not found.
125
+ def find_role(id)
126
+ begin
127
+ Role.find(id)
128
+ rescue ActiveRecord::RecordNotFound
129
+ flash[:message] = "There is no role with ID ##{id}"
130
+ nil
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,144 @@
1
+ class UsersController < ApplicationController
2
+ layout 'admin'
3
+
4
+ # Display the details for a given user
5
+ def show
6
+ @user = User.find params[:id]
7
+ end
8
+
9
+ def new
10
+ @user = User.new
11
+ end
12
+
13
+ def create
14
+ @user = User.new(params[:user])
15
+
16
+ if request.post? and @user.save
17
+ redirect_to :action => :roles, :id => @user
18
+ else
19
+ render_action :new
20
+ end
21
+ end
22
+
23
+ def edit
24
+ @user = User.find params[:id]
25
+
26
+ redirect_back_or_default :action => 'list' unless @user
27
+ end
28
+
29
+ def update
30
+ @user = User.find params[:id]
31
+
32
+ attributes = params[:user]
33
+ attributes.delete(:password) if attributes[:password].blank?
34
+
35
+ if @user.update_attributes(attributes)
36
+ redirect_to :action => :list
37
+ else
38
+ render_action :edit
39
+ end
40
+ end
41
+
42
+ # Displays a paginated list of Users
43
+ def index
44
+ @users = User.paginate :page => params[:page], :order => "login"
45
+ end
46
+
47
+ def roles
48
+ @user = User.find params[:id]
49
+ @roles = Role.find(:all)
50
+ end
51
+
52
+ def add_role
53
+ @user = User.find params[:id]
54
+ @role = Role.find params[:role]
55
+
56
+ @user.roles << @role
57
+
58
+ redirect_to :back
59
+ end
60
+
61
+ def remove_role
62
+ @user = User.find params[:id]
63
+ @role = Role.find params[:role]
64
+
65
+ @user.roles.delete(@role)
66
+
67
+ redirect_to :back
68
+ end
69
+
70
+ protected
71
+ def delete
72
+ get_user_to_act_on
73
+ if do_delete_user(@user)
74
+ logout
75
+ else
76
+ redirect_back_or_default :action => 'home'
77
+ end
78
+ end
79
+
80
+ def restore_deleted
81
+ get_user_to_act_on
82
+ @user.deleted = 0
83
+ if not @user.save
84
+ flash.now[:warning] = "The account for #{@user['login']} was not restored. Please try the link again."
85
+ redirect_to :action => 'login'
86
+ else
87
+ redirect_to :action => 'home'
88
+ end
89
+ end
90
+
91
+ protected
92
+ def destroy(user)
93
+ UserNotify.deliver_delete(user) if AccountEngine.use_email_notification
94
+ flash[:notice] = "The account for #{user['login']} was successfully deleted."
95
+ user.destroy()
96
+ end
97
+
98
+
99
+
100
+ # Edit the roles for a given User object.
101
+ # A user typically shouldn't be allowed to edit their own roles, since they could
102
+ # assign themselves as Admins and then do anything. Therefore, keep this method
103
+ # locked down as much as possible.
104
+ def edit_roles
105
+ if (@user = find_user(params[:id]))
106
+ begin
107
+ User.transaction(@user) do
108
+
109
+ roles = params[:user][:roles].collect { |role_id| Role.find(role_id) }
110
+ # add any new roles & remove any missing roles
111
+ roles.each { |role| @user.roles << role if !@user.roles.include?(role) }
112
+ @user.roles.each { |role| @user.roles.delete(role) if !roles.include?(role) }
113
+
114
+ @user.save
115
+ flash[:notice] = "Roles updated for user '#{@user.login}'."
116
+ end
117
+ rescue
118
+ flash[:warning] = 'Roles could not be edited at this time. Please retry.'
119
+ ensure
120
+ redirect_to :back
121
+ end
122
+ else
123
+ redirect_back_or_default :action => 'list'
124
+ end
125
+ end
126
+
127
+ # Change the password of an arbitrary user
128
+ def change_password_for_user
129
+ if (@user = find_user(params[:id]))
130
+ do_change_password_for(@user)
131
+ flash[:notice] = "Password for user '#{@user.login}' has been updated."
132
+ end
133
+ redirect_back_or_default :action => 'list'
134
+ end
135
+
136
+ # Delete an arbitrary user
137
+ def delete_user
138
+ if (@user = find_user(params[:id]))
139
+ do_delete_user(@user)
140
+ flash[:notice] = "User '#{@user.login}' has been deleted."
141
+ end
142
+ redirect_to :action => 'list'
143
+ end
144
+ end
@@ -0,0 +1,3 @@
1
+ module AccountHelper
2
+ include AccountEngine
3
+ end
@@ -0,0 +1,3 @@
1
+ module PermissionsHelper
2
+ include AccountEngine
3
+ end
@@ -0,0 +1,3 @@
1
+ module RolesHelper
2
+ include AccountEngine
3
+ end
@@ -0,0 +1,3 @@
1
+ module UsersHelper
2
+ include AccountEngine
3
+ end