oxen_user 0.2.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.
- checksums.yaml +7 -0
- data/.envrc +0 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +7 -0
- data/Guardfile +77 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +10 -0
- data/app/assets/javascripts/oxen_user.js +3 -0
- data/app/assets/javascripts/pw_strength.js.coffee +24 -0
- data/app/assets/javascripts/zxcvbn.js +43 -0
- data/app/controllers/oxen/invitations_controller.rb +66 -0
- data/app/controllers/oxen/users_controller.rb +96 -0
- data/app/helpers/oxen/users_helper.rb +8 -0
- data/app/models/ox_user.rb +89 -0
- data/app/policies/oxen/user_policy.rb +48 -0
- data/app/views/devise/confirmations/new.html.haml +13 -0
- data/app/views/devise/mailer/eksempel +10 -0
- data/app/views/devise/mailer/invitation_instructions.html.erb +1087 -0
- data/app/views/devise/passwords/edit.html.haml +21 -0
- data/app/views/devise/passwords/new.html.haml +10 -0
- data/app/views/devise/registrations/edit.html.haml +51 -0
- data/app/views/devise/registrations/new.html.haml +32 -0
- data/app/views/devise/sessions/new.html.haml +25 -0
- data/app/views/devise/shared/_links.html.haml +24 -0
- data/app/views/devise/unlocks/new.html.haml +13 -0
- data/app/views/oxen/users/_account_user.html.haml +14 -0
- data/app/views/oxen/users/_account_users.html.haml +15 -0
- data/app/views/oxen/users/_form.html.haml +41 -0
- data/app/views/oxen/users/_user_form.html.erb +12 -0
- data/app/views/oxen/users/confirm.html.haml +4 -0
- data/app/views/oxen/users/invitations/_new.html.haml +38 -0
- data/app/views/oxen/users/invitations/create.html.haml +5 -0
- data/app/views/oxen/users/invitations/edit.html.haml +22 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/config/initializers/devise.rb +360 -0
- data/config/initializers/devise_permitted_parameters.rb +17 -0
- data/config/locales/devise.da.yml +58 -0
- data/config/locales/devise.en.yml +61 -0
- data/config/locales/devise_invitable.da.yml +26 -0
- data/config/locales/devise_invitable.en.yml +23 -0
- data/config/routes.rb +51 -0
- data/lib/generators/oxen_user/account_generator.rb +26 -0
- data/lib/generators/oxen_user/templates/user.rb +10 -0
- data/lib/generators/oxen_user/templates/user_permission.rb +14 -0
- data/lib/oxen_user/engine.rb +17 -0
- data/lib/oxen_user/version.rb +3 -0
- data/lib/oxen_user.rb +10 -0
- data/oxen_user.gemspec +57 -0
- metadata +377 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
class Oxen::InvitationsController < Devise::InvitationsController
|
2
|
+
|
3
|
+
#
|
4
|
+
# POST /resource/invitation
|
5
|
+
def create
|
6
|
+
self.resource = invite_resource
|
7
|
+
resource_invited = self.resource.errors.empty?
|
8
|
+
yield resource if block_given?
|
9
|
+
if resource_invited
|
10
|
+
# if is_flashing_format? && self.resource.invitation_sent_at
|
11
|
+
# set_flash_message :notice, :send_instructions, :email => self.resource.email
|
12
|
+
# end
|
13
|
+
flash[:info] = t('.invited')
|
14
|
+
render layout: false, status: 200, locals: { result: true }
|
15
|
+
else
|
16
|
+
flash[:error] = t('.not_invited', error: resource.errors.collect{|v,k| k }.join(', '))
|
17
|
+
render layout: false, status: 401, locals: { result: false, resource: self.resource }
|
18
|
+
#
|
19
|
+
# respond_with resource, :location => after_invite_path_for(current_inviter)
|
20
|
+
# else
|
21
|
+
# respond_with_navigational(resource) { render :new }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# def update
|
27
|
+
# if this
|
28
|
+
# redirect_to root_path
|
29
|
+
# else
|
30
|
+
# super
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# this is called when creating invitation
|
37
|
+
# should return an instance of resource class
|
38
|
+
def invite_resource
|
39
|
+
## skip sending emails on invite
|
40
|
+
resource_class.invite!(resource_params, current_user)
|
41
|
+
# resource_class.invite!(resource_params, current_user) do |u|
|
42
|
+
# # u.skip_invitation = true
|
43
|
+
# end
|
44
|
+
end
|
45
|
+
|
46
|
+
def resource_params
|
47
|
+
params[:user][:role] ||= "user"
|
48
|
+
{email: params[:user][:email], name: params[:user][:name], account_id: params[:user][:account_id], role: params[:user][:role] }
|
49
|
+
|
50
|
+
# {email: params[:user][:email], name: params[:user][:name], account_id: params[:user][:account_id] }
|
51
|
+
# params.permit(user: [:name, :email,:invitation_token, :your_params_here])[:user]
|
52
|
+
end
|
53
|
+
|
54
|
+
# this is called when accepting invitation
|
55
|
+
# should return an instance of resource class
|
56
|
+
def accept_resource
|
57
|
+
resource = resource_class.accept_invitation!(update_resource_params)
|
58
|
+
## Report accepting invitation to analytics
|
59
|
+
# Analytics.report('invite.accept', resource.id)
|
60
|
+
resource
|
61
|
+
end
|
62
|
+
|
63
|
+
# def after_invite_path_for(usr)
|
64
|
+
# end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
class Oxen::UsersController < AbstractResourcesController
|
2
|
+
# before_filter :authenticate_user!
|
3
|
+
# after_action :verify_authorized
|
4
|
+
before_filter :check_user_permissions, only: :create
|
5
|
+
|
6
|
+
def confirm
|
7
|
+
authorize resource
|
8
|
+
if resource.confirm
|
9
|
+
flash[:info] = t('user.confirmed_ok')
|
10
|
+
render :confirm, layout: false, status: 200 and return
|
11
|
+
else
|
12
|
+
flash[:info] = t('user.not_confirmed_ok')
|
13
|
+
render :confirm, layout: false, status: 401 and return
|
14
|
+
end
|
15
|
+
end
|
16
|
+
# def index
|
17
|
+
# @users = User.all
|
18
|
+
# authorize User
|
19
|
+
# end
|
20
|
+
# def index
|
21
|
+
# @resources = policy_scope(User)
|
22
|
+
# authorize User
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# def show
|
26
|
+
# @user = User.find(params[:id])
|
27
|
+
# authorize @user
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# def update
|
31
|
+
# @user = User.find(params[:id])
|
32
|
+
# authorize @user
|
33
|
+
# if @user.update_attributes(secure_params)
|
34
|
+
# redirect_to users_path, :notice => "User updated."
|
35
|
+
# else
|
36
|
+
# redirect_to users_path, :alert => "Unable to update user."
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# def destroy
|
41
|
+
# user = User.find(params[:id])
|
42
|
+
# authorize user
|
43
|
+
# user.destroy
|
44
|
+
# redirect_to users_path, :notice => "User deleted."
|
45
|
+
# end
|
46
|
+
|
47
|
+
def update
|
48
|
+
if params[:user][:password].blank? && params[:user][:password].blank?
|
49
|
+
params[:user].delete :password
|
50
|
+
params[:user].delete :password_confirmation
|
51
|
+
end
|
52
|
+
authorize resource
|
53
|
+
resource.max_role = current_user.role
|
54
|
+
if resource.update_attributes(secure_params)
|
55
|
+
redirect_to users_path, :notice => "User updated."
|
56
|
+
else
|
57
|
+
render :edit, :alert => "Unable to update user."
|
58
|
+
end
|
59
|
+
|
60
|
+
# super
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def resource_params
|
67
|
+
secure_params
|
68
|
+
end
|
69
|
+
|
70
|
+
def secure_params
|
71
|
+
params.require(:user).permit(:role,:name,:email,:active,:account_id, :password, :password_confirmation)
|
72
|
+
end
|
73
|
+
|
74
|
+
def check_user_permissions
|
75
|
+
UserPermission.where(email: params[:user][:email]).count == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
#
|
80
|
+
# build options for fixed action button - implement on each controller to customize
|
81
|
+
# raise an exception
|
82
|
+
def set_fab_button_options
|
83
|
+
opt = { items: {}}
|
84
|
+
case params[:action]
|
85
|
+
when 'nothing'; opt = opt
|
86
|
+
when 'edit'; opt[:items].merge! list: { ajax: 'get', icon: 'list', class: 'blue', url: "/admin/accounts/#{resource.account.id}" },
|
87
|
+
print: { ajax: 'get', icon: 'print', class: 'blue lighten-2', url: "/admin/accounts/#{resource.account.id}/print", browser: 'new' }
|
88
|
+
when 'show'; opt[:items].merge! list: { ajax: 'get', icon: 'list', class: 'blue', url: "/admin/accounts/#{resource.account.id}" },
|
89
|
+
print: { ajax: 'get', icon: 'print', class: 'blue lighten-2', url: "/admin/accounts/#{resource.account.id}/print", browser: 'new' }
|
90
|
+
end
|
91
|
+
|
92
|
+
# = build_print_link(f.object, list: false, print_options: "print_cmd=print_label", button: 'icon-tag', text: 'Udskriv dæk label')
|
93
|
+
@fab_button_options = opt
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class OxUser < AbstractResource #< ActiveRecord::Base
|
2
|
+
self.table_name = 'users'
|
3
|
+
establish_connection ((Rails.env=="development") ? :dev_oxen_tables : :oxen_tables )
|
4
|
+
|
5
|
+
include Roleable
|
6
|
+
|
7
|
+
has_paper_trail
|
8
|
+
|
9
|
+
belongs_to :account, foreign_key: 'account_id'
|
10
|
+
has_many :invitations, :class_name => self.to_s, :as => :invited_by
|
11
|
+
|
12
|
+
# Include default devise modules. Others available are:
|
13
|
+
# :confirmable, :lockable, :timeoutable and :omniauthable, :database_authenticatable
|
14
|
+
# devise :cas_authenticatable
|
15
|
+
devise :invitable, :registerable, :confirmable, :database_authenticatable,
|
16
|
+
:recoverable, :rememberable, :trackable, :validatable, :zxcvbnable #, :cas_authenticatable
|
17
|
+
|
18
|
+
validates :name, presence: true
|
19
|
+
|
20
|
+
# #after_create :create_account
|
21
|
+
#
|
22
|
+
# # belongs_to :account
|
23
|
+
#
|
24
|
+
# # validates :name, presence: true
|
25
|
+
#
|
26
|
+
#
|
27
|
+
# def create_account(account_name=nil)
|
28
|
+
# account_name ||= self.name
|
29
|
+
# if self.account.nil?
|
30
|
+
# self.account= Account.create name: account_name
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# def good_roles
|
35
|
+
# User.roles.keys.map {|r| ([r.titleize,r] if User.roles[role] >= User.roles[r]) }
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
|
39
|
+
# This is an internal method called every time Devise needs
|
40
|
+
# to send a notification/mail. This can be overridden if you
|
41
|
+
# need to customize the e-mail delivery logic. For instance,
|
42
|
+
# if you are using a queue to deliver e-mails (delayed job,
|
43
|
+
# sidekiq, resque, etc), you must add the delivery to the queue
|
44
|
+
# just after the transaction was committed. To achieve this,
|
45
|
+
# you can override send_devise_notification to store the
|
46
|
+
# deliveries until the after_commit callback is triggered:
|
47
|
+
#
|
48
|
+
# class User
|
49
|
+
# devise :database_authenticatable, :confirmable
|
50
|
+
#
|
51
|
+
# after_commit :send_pending_notifications
|
52
|
+
#
|
53
|
+
# protected
|
54
|
+
#
|
55
|
+
# def send_devise_notification(notification, *args)
|
56
|
+
# # If the record is new or changed then delay the
|
57
|
+
# # delivery until the after_commit callback otherwise
|
58
|
+
# # send now because after_commit will not be called.
|
59
|
+
# if new_record? || changed?
|
60
|
+
# pending_notifications << [notification, args]
|
61
|
+
# else
|
62
|
+
# devise_mailer.send(notification, self, *args).deliver
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# def send_pending_notifications
|
67
|
+
# pending_notifications.each do |notification, args|
|
68
|
+
# devise_mailer.send(notification, self, *args).deliver
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# # Empty the pending notifications array because the
|
72
|
+
# # after_commit hook can be called multiple times which
|
73
|
+
# # could cause multiple emails to be sent.
|
74
|
+
# pending_notifications.clear
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# def pending_notifications
|
78
|
+
# @pending_notifications ||= []
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# def send_devise_notification(notification, *args)
|
83
|
+
# devise_mailer.send(notification, self, *args).deliver
|
84
|
+
# end
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Oxen
|
2
|
+
class UserPolicy < AbstractResourcePolicy
|
3
|
+
|
4
|
+
class Scope < Scope
|
5
|
+
def resolve
|
6
|
+
if current_user.nil?
|
7
|
+
super
|
8
|
+
elsif current_user.admin?
|
9
|
+
scope.all
|
10
|
+
else
|
11
|
+
scope.where(account_id: current_user.account.id)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def index?
|
18
|
+
current_user.admin? || current_user.account_admin?
|
19
|
+
end
|
20
|
+
|
21
|
+
def show?
|
22
|
+
current_user.admin? or current_user.account_admin? or current_user == model
|
23
|
+
end
|
24
|
+
|
25
|
+
def update?
|
26
|
+
current_user.admin? || current_user.account_admin?
|
27
|
+
end
|
28
|
+
|
29
|
+
def create?
|
30
|
+
current_user.admin? || current_user.account_admin?
|
31
|
+
end
|
32
|
+
|
33
|
+
def destroy?
|
34
|
+
return false if @current_user == model
|
35
|
+
current_user.admin? || current_user.account_admin?
|
36
|
+
end
|
37
|
+
|
38
|
+
def confirm?
|
39
|
+
current_user.admin? || current_user.account_admin?
|
40
|
+
end
|
41
|
+
|
42
|
+
def invite?
|
43
|
+
current_user.admin? || current_user.account_admin?
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%h2= t('resend.confirmation.instructions')
|
2
|
+
|
3
|
+
= simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
|
4
|
+
= f.error_notification
|
5
|
+
= f.full_error :confirmation_token
|
6
|
+
|
7
|
+
.form-inputs
|
8
|
+
= f.input :email, required: true, autofocus: true
|
9
|
+
|
10
|
+
.form-actions
|
11
|
+
= f.button :submit, t('resend.confirmation.instructions')
|
12
|
+
|
13
|
+
= render "devise/shared/links"
|
@@ -0,0 +1,10 @@
|
|
1
|
+
http://buttons.cm/
|
2
|
+
|
3
|
+
<div><!--[if mso]>
|
4
|
+
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="10%" strokecolor="#1e3650" fill="t">
|
5
|
+
<v:fill type="tile" src="http://i.imgur.com/0xPEf.gif" color="#556270" />
|
6
|
+
<w:anchorlock/>
|
7
|
+
<center style="color:#ffffff;font-family:sans-serif;font-size:13px;font-weight:bold;">Show me the button!</center>
|
8
|
+
</v:roundrect>
|
9
|
+
<![endif]--><a href="http://"
|
10
|
+
style="background-color:#556270;background-image:url(http://i.imgur.com/0xPEf.gif);border:1px solid #1e3650;border-radius:4px;color:#ffffff;display:inline-block;font-family:sans-serif;font-size:13px;font-weight:bold;line-height:40px;text-align:center;text-decoration:none;width:200px;-webkit-text-size-adjust:none;mso-hide:all;">Show me the button!</a></div>
|