usman 0.1.5 → 0.1.6dev2

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 (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +48 -16
  3. data/app/controllers/usman/admin/base_controller.rb +22 -0
  4. data/app/controllers/usman/admin/dashboard_controller.rb +1 -1
  5. data/app/controllers/usman/admin/features_controller.rb +4 -1
  6. data/app/controllers/usman/admin/permissions_controller.rb +9 -15
  7. data/app/controllers/usman/admin/resource_controller.rb +3 -1
  8. data/app/controllers/usman/admin/roles_controller.rb +4 -2
  9. data/app/controllers/usman/admin/user_roles_controller.rb +142 -0
  10. data/app/controllers/usman/admin/users_controller.rb +5 -2
  11. data/app/controllers/usman/application_controller.rb +0 -4
  12. data/app/controllers/usman/sessions_controller.rb +5 -2
  13. data/app/helpers/usman/authentication_helper.rb +35 -25
  14. data/app/models/feature.rb +50 -46
  15. data/app/models/image/feature_image.rb +1 -1
  16. data/app/models/image/profile_picture.rb +1 -1
  17. data/app/models/permission.rb +3 -8
  18. data/app/models/role.rb +4 -7
  19. data/app/models/user.rb +81 -103
  20. data/app/models/usman/application_record.rb +3 -0
  21. data/app/services/usman/authentication_service.rb +4 -3
  22. data/app/uploaders/profile_picture_uploader.rb +2 -1
  23. data/app/views/layouts/kuppayam/_header.html.erb +1 -1
  24. data/app/views/layouts/kuppayam/_navbar.html.erb +1 -1
  25. data/app/views/layouts/kuppayam/_sidebar.html.erb +8 -7
  26. data/app/views/usman/admin/dashboard/index.html.erb +0 -1
  27. data/app/views/usman/admin/features/_form.html.erb +5 -2
  28. data/app/views/usman/admin/features/_index.html.erb +4 -1
  29. data/app/views/usman/admin/features/index.html.erb +20 -3
  30. data/app/views/usman/admin/permissions/_show.html.erb +2 -10
  31. data/app/views/usman/admin/permissions/index.html.erb +20 -3
  32. data/app/views/usman/admin/roles/_form.html.erb +1 -1
  33. data/app/views/usman/admin/roles/_index.html.erb +3 -3
  34. data/app/views/usman/admin/roles/_row.html.erb +2 -2
  35. data/app/views/usman/admin/roles/_show.html.erb +41 -7
  36. data/app/views/usman/admin/roles/index.html.erb +22 -3
  37. data/app/views/usman/admin/user_roles/_form.html.erb +24 -0
  38. data/app/views/usman/admin/user_roles/_index.html.erb +59 -0
  39. data/app/views/usman/admin/user_roles/_row.html.erb +34 -0
  40. data/app/views/usman/admin/users/_index.html.erb +22 -16
  41. data/app/views/usman/admin/users/_row.html.erb +4 -4
  42. data/app/views/usman/admin/users/_show.html.erb +1 -1
  43. data/app/views/usman/admin/users/index.html.erb +4 -2
  44. data/app/views/usman/sessions/_form.html.erb +19 -7
  45. data/app/views/usman/sessions/sign_in.html.erb +1 -1
  46. data/config/initializers/overide_kuppayam_controllers.rb +74 -0
  47. data/config/locales/kuppayam/authentication.en.yml +4 -1
  48. data/config/routes.rb +3 -1
  49. data/db/import_data/dummy/features.csv +7 -0
  50. data/db/import_data/dummy/permissions.csv +18 -1
  51. data/db/import_data/dummy/roles.csv +5 -0
  52. data/db/import_data/dummy/users.csv +7 -3
  53. data/db/import_data/features.csv +7 -0
  54. data/db/import_data/permissions.csv +1 -30
  55. data/db/import_data/roles.csv +5 -0
  56. data/db/migrate/20170000000100_create_users.rb +1 -1
  57. data/db/migrate/20170000000101_create_features.rb +1 -1
  58. data/db/migrate/20170000000102_create_roles.rb +1 -1
  59. data/db/migrate/20170728095744_create_otp_registrations.rb +17 -0
  60. data/lib/tasks/usman/all.rake +34 -10
  61. data/lib/{tasks/usman → temp}/features.rake +3 -6
  62. data/lib/{tasks/usman → temp}/permissions.rake +3 -5
  63. data/lib/temp/roles.rake +24 -0
  64. data/lib/{tasks/usman → temp}/users.rake +3 -5
  65. data/lib/usman/engine.rb +2 -3
  66. data/lib/usman/version.rb +1 -1
  67. metadata +27 -45
  68. data/app/views/usman/admin/features/_action_buttons.html.erb +0 -0
  69. data/app/views/usman/admin/features/temp/create.js.erb +0 -29
  70. data/app/views/usman/admin/features/temp/destroy.js.erb +0 -16
  71. data/app/views/usman/admin/features/temp/edit.js.erb +0 -7
  72. data/app/views/usman/admin/features/temp/index.js.erb +0 -8
  73. data/app/views/usman/admin/features/temp/new.js.erb +0 -7
  74. data/app/views/usman/admin/features/temp/row.js.erb +0 -10
  75. data/app/views/usman/admin/features/temp/show.js.erb +0 -8
  76. data/app/views/usman/admin/features/temp/update.js.erb +0 -16
  77. data/app/views/usman/admin/permissions/temp/create.js.erb +0 -29
  78. data/app/views/usman/admin/permissions/temp/destroy.js.erb +0 -22
  79. data/app/views/usman/admin/permissions/temp/edit.js.erb +0 -4
  80. data/app/views/usman/admin/permissions/temp/index.js.erb +0 -14
  81. data/app/views/usman/admin/permissions/temp/new.js.erb +0 -4
  82. data/app/views/usman/admin/permissions/temp/row.js.erb +0 -24
  83. data/app/views/usman/admin/permissions/temp/show.js.erb +0 -13
  84. data/app/views/usman/admin/permissions/temp/update.js.erb +0 -29
  85. data/db/import_data/dummy/images/users/guna.neweast.png +0 -0
  86. data/db/import_data/dummy/images/users/junaid.ramzan.jpg +0 -0
  87. data/db/import_data/dummy/images/users/kpvarma.png +0 -0
  88. data/db/import_data/dummy/images/users/stephen.price.png +0 -0
  89. data/db/import_data/dummy/images/users/vinodh.jpg +0 -0
  90. data/db/import_data/images/users/junaid.ramzan.jpg +0 -0
  91. data/db/import_data/images/users/kpvarma.png +0 -0
  92. data/db/import_data/images/users/vinodh.jpg +0 -0
  93. data/lib/usman/extras/import_error_handler.rb +0 -79
@@ -1,22 +1,19 @@
1
1
  class Feature < Usman::ApplicationRecord
2
2
 
3
- require 'import_error_handler.rb'
4
- extend Usman::ImportErrorHandler
5
-
6
3
  # Constants
7
- UNPUBLISHED = "unpublished"
8
4
  PUBLISHED = "published"
5
+ UNPUBLISHED = "unpublished"
9
6
  DISABLED = "disabled"
10
7
 
11
8
  STATUS = {
12
- UNPUBLISHED => "Un-Published",
13
9
  PUBLISHED => "Published",
10
+ UNPUBLISHED => "Un-Published",
14
11
  DISABLED => "Disabled"
15
12
  }
16
13
 
17
14
  STATUS_REVERSE = {
18
- "Un-Published" => UNPUBLISHED,
19
- "Published" => PUBLISHED,
15
+ "Published" => PUBLISHED,
16
+ "Un-Published" => UNPUBLISHED,
20
17
  "Disabled" => DISABLED
21
18
  }
22
19
 
@@ -26,7 +23,7 @@ class Feature < Usman::ApplicationRecord
26
23
  has_one :feature_image, :as => :imageable, :dependent => :destroy, :class_name => "Image::FeatureImage"
27
24
 
28
25
  # Validations
29
- validates :name, presence: true
26
+ validates :name, presence: true, length: {minimum: 3, maximum: 250}
30
27
  validates :status, :presence => true, :inclusion => {:in => STATUS.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
31
28
 
32
29
  # ------------------
@@ -47,9 +44,7 @@ class Feature < Usman::ApplicationRecord
47
44
  scope :published, -> { where(status: PUBLISHED) }
48
45
  scope :disabled, -> { where(status: DISABLED) }
49
46
 
50
- def self.save_row_data(row, base_path)
51
-
52
- image_base_path = base_path + "images/"
47
+ def self.save_row_data(row)
53
48
 
54
49
  row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
55
50
 
@@ -60,45 +55,24 @@ class Feature < Usman::ApplicationRecord
60
55
  feature.status = Feature::UNPUBLISHED
61
56
 
62
57
  # Initializing error hash for displaying all errors altogether
63
- error_object = Usman::ErrorHash.new
64
-
65
- ## Adding a profile picture
66
- begin
67
- image_path = image_base_path + "features/#{feature.name.parameterize}.png"
68
- image_path = image_base_path + "features/#{feature.name.parameterize}}.jpg" unless File.exists?(image_path)
69
- if File.exists?(image_path)
70
- feature.build_feature_image
71
- feature.feature_image.image = File.open(image_path)
72
- else
73
- summary = "Feature Image not found for feature: #{feature.name}"
74
- details = "#{image_path}/png doesn't exists"
75
- error_object.warnings << { summary: summary, details: details }
76
- end
77
- rescue => e
78
- summary = "Error during processing: #{$!}"
79
- details = "Feature: #{feature.name}, Image Path: #{image_path}"
80
- stack_trace = "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
81
- error_object.errors << { summary: summary, details: details, stack_trace: stack_trace }
82
- end if feature.feature_image.blank?
83
-
84
- if feature.valid? && (feature.feature_image.blank? || feature.feature_image.valid?)
58
+ error_object = Kuppayam::Importer::ErrorHash.new
59
+
60
+ if feature.valid?
85
61
  feature.save!
86
62
  else
87
63
  summary = "Error while saving feature: #{feature.name}"
88
64
  details = "Error! #{feature.errors.full_messages.to_sentence}"
89
- details << ", #{feature.feature_image.errors.full_messages.to_sentence}" if feature.feature_image
90
65
  error_object.errors << { summary: summary, details: details }
91
66
  end
92
67
  return error_object
93
68
  end
94
69
 
95
- # * Return full name
96
- # == Examples
97
- # >>> feature.display_name
98
- # => "Products"
99
- def display_name
100
- "#{name}"
101
- end
70
+ # ------------------
71
+ # Instance Methods
72
+ # ------------------
73
+
74
+ # Status Methods
75
+ # --------------
102
76
 
103
77
  # * Return true if the user is not published, else false.
104
78
  # == Examples
@@ -145,14 +119,44 @@ class Feature < Usman::ApplicationRecord
145
119
  # change the status to :suspended
146
120
  # Return the status
147
121
  # == Examples
148
- # >>> feature.suspend!
149
- # => "suspended"
150
- def suspend!
122
+ # >>> feature.disable!
123
+ # => "disabled"
124
+ def disable!
151
125
  self.update_attribute(:status, DISABLED)
152
126
  end
153
127
 
154
- def can_be_destroyed?
155
- return true
128
+ # Permission Methods
129
+ # ------------------
130
+
131
+ def can_be_edited?
132
+ published? or unpublished?
133
+ end
134
+
135
+ def can_be_deleted?
136
+ true
137
+ end
138
+
139
+ def can_be_published?
140
+ unpublished? or disabled?
141
+ end
142
+
143
+ def can_be_unpublished?
144
+ published? or disabled?
145
+ end
146
+
147
+ def can_be_disabled?
148
+ published? or unpublished?
149
+ end
150
+
151
+ # Other Methods
152
+ # -------------
153
+
154
+ # * Return full name
155
+ # == Examples
156
+ # >>> feature.display_name
157
+ # => "Products"
158
+ def display_name
159
+ "#{name}"
156
160
  end
157
161
 
158
162
  end
@@ -1,3 +1,3 @@
1
1
  class Image::FeatureImage < Image::Base
2
- mount_uploader :image, FeatureImageUploader
2
+ mount_uploader :image, FeatureImageUploader
3
3
  end
@@ -1,3 +1,3 @@
1
1
  class Image::ProfilePicture < Image::Base
2
- mount_uploader :image, ProfilePictureUploader
2
+ mount_uploader :image, ProfilePictureUploader
3
3
  end
@@ -1,9 +1,6 @@
1
1
  class Permission < Usman::ApplicationRecord
2
2
 
3
- require 'import_error_handler.rb'
4
- extend Usman::ImportErrorHandler
5
-
6
- # Associations
3
+ # Associations
7
4
  belongs_to :user
8
5
  belongs_to :feature
9
6
 
@@ -30,16 +27,14 @@ class Permission < Usman::ApplicationRecord
30
27
  LOWER(f.name) LIKE LOWER('%#{query}%')")}
31
28
 
32
29
 
33
- def self.save_row_data(row, base_path)
34
-
35
- image_base_path = base_path + "images/"
30
+ def self.save_row_data(row)
36
31
 
37
32
  row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
38
33
 
39
34
  return if row[:user].blank? || row[:feature].blank?
40
35
 
41
36
  # Initializing error hash for displaying all errors altogether
42
- error_object = Usman::ErrorHash.new
37
+ error_object = Kuppayam::Importer::ErrorHash.new
43
38
 
44
39
  user = User.find_by_username(row[:user])
45
40
  unless user
data/app/models/role.rb CHANGED
@@ -1,13 +1,10 @@
1
1
  class Role < Usman::ApplicationRecord
2
2
 
3
- require 'import_error_handler.rb'
4
- extend Usman::ImportErrorHandler
5
-
6
3
  # Associations
7
4
  has_and_belongs_to_many :users
8
5
 
9
6
  # Validations
10
- validates :name, presence: true
7
+ validates :name, presence: true, length: {minimum: 3, maximum: 250}
11
8
 
12
9
  # ------------------
13
10
  # Class Methods
@@ -18,10 +15,10 @@ class Role < Usman::ApplicationRecord
18
15
  # == Examples
19
16
  # >>> role.search(query)
20
17
  # => ActiveRecord::Relation object
21
- scope :search, lambda {|query| where("LOWER(name) LIKE LOWER('%#{query}%')")
18
+ scope :search, lambda {|query| where("LOWER(roles.name) LIKE LOWER('%#{query}%')")
22
19
  }
23
20
 
24
- def self.save_row_data(row, base_path)
21
+ def self.save_row_data(row)
25
22
 
26
23
  row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
27
24
 
@@ -31,7 +28,7 @@ class Role < Usman::ApplicationRecord
31
28
  role.name = row[:name]
32
29
 
33
30
  # Initializing error hash for displaying all errors altogether
34
- error_object = Usman::ErrorHash.new
31
+ error_object = Kuppayam::Importer::ErrorHash.new
35
32
 
36
33
  if role.valid?
37
34
  role.save!
data/app/models/user.rb CHANGED
@@ -1,9 +1,5 @@
1
1
  class User < Usman::ApplicationRecord
2
2
 
3
- require 'import_error_handler.rb'
4
- extend Usman::ImportErrorHandler
5
- extend KuppayamValidators
6
-
7
3
  # including Password Methods
8
4
  has_secure_password
9
5
 
@@ -26,10 +22,10 @@ class User < Usman::ApplicationRecord
26
22
 
27
23
  EXCLUDED_JSON_ATTRIBUTES = [:confirmation_token, :password_digest, :reset_password_token, :unlock_token, :status, :reset_password_sent_at, :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip, :confirmed_at, :confirmation_sent_at, :unconfirmed_email, :failed_attempts, :locked_at, :created_at, :updated_at]
28
24
  DEFAULT_PASSWORD = "Password@1"
29
- SESSION_TIME_OUT = 30.minutes
25
+ SESSION_TIME_OUT = 120.minutes
30
26
 
31
27
  # Validations
32
- validates :name, presence: true
28
+ validates :name, presence: true, length: {minimum: 3, maximum: 250}
33
29
  validate_username :username
34
30
  validate_email :email
35
31
  validate_password :password, condition_method: :should_validate_password?
@@ -43,26 +39,24 @@ class User < Usman::ApplicationRecord
43
39
  has_one :profile_picture, :as => :imageable, :dependent => :destroy, :class_name => "Image::ProfilePicture"
44
40
  has_many :permissions
45
41
  has_many :features, through: :permissions
46
- has_and_belongs_to_many :users
42
+ has_and_belongs_to_many :roles
47
43
 
48
44
 
49
45
  # ------------------
50
46
  # Class Methods
51
47
  # ------------------
52
48
 
53
- def self.find_by_email_or_username(query)
54
- self.where("LOWER(email) = LOWER('#{query}') OR LOWER(username) = LOWER('#{query}')").first
55
- end
49
+ # Scopes Methods
56
50
 
57
51
  # return an active record relation object with the search query in its where clause
58
52
  # Return the ActiveRecord::Relation object
59
53
  # == Examples
60
54
  # >>> user.search(query)
61
55
  # => ActiveRecord::Relation object
62
- scope :search, lambda {|query| where("LOWER(name) LIKE LOWER('%#{query}%') OR\
63
- LOWER(username) LIKE LOWER('%#{query}%') OR\
64
- LOWER(email) LIKE LOWER('%#{query}%') OR\
65
- LOWER(designation) LIKE LOWER('%#{query}%')")
56
+ scope :search, lambda {|query| where("LOWER(users.name) LIKE LOWER('%#{query}%') OR\
57
+ LOWER(users.username) LIKE LOWER('%#{query}%') OR\
58
+ LOWER(users.email) LIKE LOWER('%#{query}%') OR\
59
+ LOWER(users.designation) LIKE LOWER('%#{query}%')")
66
60
  }
67
61
 
68
62
  scope :status, lambda { |status| where("LOWER(status)='#{status}'") }
@@ -70,10 +64,13 @@ class User < Usman::ApplicationRecord
70
64
  scope :pending, -> { where(status: PENDING) }
71
65
  scope :approved, -> { where(status: APPROVED) }
72
66
  scope :suspended, -> { where(status: SUSPENDED) }
67
+
68
+ scope :super_admins, -> { where(super_admin: TRUE) }
69
+ scope :normal_users, -> { where(super_admin: FALSE) }
73
70
 
74
- def self.save_row_data(row, base_path)
71
+ # Import Methods
75
72
 
76
- image_base_path = base_path + "images/"
73
+ def self.save_row_data(row)
77
74
 
78
75
  row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
79
76
 
@@ -92,7 +89,7 @@ class User < Usman::ApplicationRecord
92
89
  user.assign_default_password
93
90
 
94
91
  # Initializing error hash for displaying all errors altogether
95
- error_object = Usman::ErrorHash.new
92
+ error_object = Kuppayam::Importer::ErrorHash.new
96
93
 
97
94
  if user.valid?
98
95
  user.save!
@@ -102,47 +99,15 @@ class User < Usman::ApplicationRecord
102
99
  error_object.errors << { summary: summary, details: details }
103
100
  end
104
101
 
105
- ## Adding a profile picture
106
- begin
107
- image_path = image_base_path + "users/#{user.username}.png"
108
- image_path = image_base_path + "users/#{user.username}.jpg" unless File.exists?(image_path)
109
- if File.exists?(image_path)
110
- user.build_profile_picture
111
- user.profile_picture.image = File.open(image_path)
112
- if user.profile_picture.valid?
113
- user.profile_picture.save
114
- else
115
- summary = "Error while saving user: #{user.name}"
116
- details = "Error! #{user.errors.full_messages.to_sentence}"
117
- details << ", #{user.profile_picture.errors.full_messages.to_sentence}" if user.profile_picture
118
- error_object.errors << { summary: summary, details: details }
119
- end
120
- else
121
- summary = "Profile Picture not found for user: #{user.name}"
122
- details = "#{image_path}/png doesn't exists"
123
- error_object.warnings << { summary: summary, details: details }
124
- end
125
- rescue => e
126
- summary = "Error during processing: #{$!}"
127
- details = "User: #{user.name}, Image Path: #{image_path}"
128
- stack_trace = "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
129
- error_object.errors << { summary: summary, details: details, stack_trace: stack_trace }
130
- end if user.profile_picture.blank?
131
-
132
102
  return error_object
133
103
  end
134
104
 
135
105
  # ------------------
136
- # Instance variables
106
+ # Instance Methods
137
107
  # ------------------
138
-
139
- # * Return full name
140
- # == Examples
141
- # >>> user.display_name
142
- # => "Joe Black"
143
- def display_name
144
- "#{name}"
145
- end
108
+
109
+ # Status Methods
110
+ # --------------
146
111
 
147
112
  # * Return true if the user is not approved, else false.
148
113
  # == Examples
@@ -195,36 +160,26 @@ class User < Usman::ApplicationRecord
195
160
  self.update_attribute(:status, SUSPENDED)
196
161
  end
197
162
 
198
- def is_super_admin?
199
- super_admin
200
- end
163
+ # Authentication Methods
164
+ # ----------------------
165
+
166
+ def start_session(remote_ip)
167
+ self.current_sign_in_at = Time.now
168
+ self.current_sign_in_ip = remote_ip
201
169
 
202
- def start_session
203
- # FIX ME - specs are not written to ensure that all these data are saved
204
- self.token_created_at = Time.now
205
170
  self.sign_in_count = self.sign_in_count ? self.sign_in_count + 1 : 1
206
- self.last_sign_in_at = self.current_sign_in_at
207
- self.last_sign_in_ip = self.current_sign_in_ip
208
- self.current_sign_in_at = self.token_created_at
209
171
 
210
- # FIX ME - pass remote_ip to this method.
211
- # Make necessary changes to authentication service to make it work
212
- # self.current_sign_in_ip = remote_ip if remote_ip
213
172
  self.save
214
173
  end
215
174
 
216
175
  def end_session
217
- # Reseting the auth token for user when he logs out.
218
- # (Time.now - 1.second)
219
- self.update_attributes auth_token: SecureRandom.hex, token_created_at: nil
220
- end
221
-
222
- def update_token
223
- self.update_attribute(:token_created_at, Time.now)
224
- end
176
+ self.last_sign_in_at = self.current_sign_in_at
177
+ self.last_sign_in_ip = self.current_sign_in_ip
178
+
179
+ self.current_sign_in_at = nil
180
+ self.current_sign_in_ip = nil
225
181
 
226
- def token_about_to_expire?
227
- return self.token_created_at.nil? || (Time.now > self.token_created_at + (SESSION_TIME_OUT - 1.minute))
182
+ self.save
228
183
  end
229
184
 
230
185
  def assign_default_password
@@ -232,18 +187,13 @@ class User < Usman::ApplicationRecord
232
187
  self.password_confirmation = DEFAULT_PASSWORD
233
188
  end
234
189
 
235
- def token_expired?
236
- return self.token_created_at.nil? || (Time.now > self.token_created_at + SESSION_TIME_OUT)
237
- end
238
-
239
190
  def generate_reset_password_token
240
191
  self.reset_password_token = SecureRandom.hex unless self.reset_password_token
241
192
  self.reset_password_sent_at = Time.now unless self.reset_password_sent_at
242
193
  end
243
194
 
244
- def default_image_url(size="small")
245
- "/assets/kuppayam/defaults/user-#{size}.png"
246
- end
195
+ # Permission Methods
196
+ # ------------------
247
197
 
248
198
  def set_permission(feature_name, **options)
249
199
  options.reverse_merge!(
@@ -301,23 +251,68 @@ class User < Usman::ApplicationRecord
301
251
  end
302
252
 
303
253
  def can_be_deleted?
304
- return true
254
+ suspended?
305
255
  end
306
256
 
307
257
  def can_be_edited?
308
258
  !suspended?
309
259
  end
310
260
 
261
+ # Role Methods
262
+ # ------------
263
+
264
+ def add_role(role)
265
+ return false unless self.approved?
266
+ role = Role.find_by_name(role) if role.is_a?(String)
267
+ if role
268
+ self.roles << role unless self.has_role?(role)
269
+ return true
270
+ else
271
+ return false
272
+ end
273
+ end
274
+
275
+ def remove_role(role)
276
+ role = Role.find_by_name(role) if role.is_a?(String)
277
+ self.roles.delete(role) if role
278
+ end
279
+
280
+ def has_role?(role)
281
+ role = Role.find_by_name(role) if role.is_a?(String)
282
+ if role && role.persisted?
283
+ return true if self.super_admin
284
+ self.roles.exists?(:id => [role.id])
285
+ else
286
+ return false
287
+ end
288
+ end
289
+
290
+ # Other Methods
291
+ # -------------
292
+
293
+ # * Return full name
294
+ # == Examples
295
+ # >>> user.display_name
296
+ # => "Joe Black"
297
+ def display_name
298
+ "#{name}"
299
+ end
300
+
301
+ def default_image_url(size="small")
302
+ "/assets/kuppayam/defaults/user-#{size}.png"
303
+ end
304
+
311
305
  private
312
306
 
313
307
  def should_validate_password?
314
- self.new_record? || (self.new_record? == false and self.password.present?)
308
+ self.new_record? || (self.new_record? == false and self.password_digest_changed?)
315
309
  end
316
310
 
317
311
  def generate_auth_token
318
312
  self.auth_token = SecureRandom.hex unless self.auth_token
319
313
  end
320
314
 
315
+ # FIXME - this should be either removed or moved to feature model
321
316
  def get_feature(feature_name)
322
317
  case feature_name
323
318
  when Feature
@@ -332,25 +327,8 @@ class User < Usman::ApplicationRecord
332
327
  return feature
333
328
  end
334
329
 
335
- def get_role(role_name)
336
- self.roles.find_by_id(role_name) || self.roles.find_by_name(role_name)
337
- end
338
-
339
- def add_role(role_name)
340
- role = self.get_role(role_name)
341
- self.roles << role if role && role.persists?
342
- end
343
-
344
- def remove_role(role_name)
345
- role = self.get_role(role_name)
346
- if role
347
- self.roles.delete(role)
348
- end
349
- end
350
-
351
- def has_role?(role_name)
352
- role = self.get_role(role_name)
353
- role && role.persists?
330
+ def self.find_by_email_or_username(query)
331
+ self.where("LOWER(email) = LOWER('#{query}') OR LOWER(username) = LOWER('#{query}')").first
354
332
  end
355
333
 
356
334
  end
@@ -1,5 +1,8 @@
1
1
  module Usman
2
2
  class ApplicationRecord < ActiveRecord::Base
3
3
  self.abstract_class = true
4
+
5
+ extend Kuppayam::Importer
6
+ extend Kuppayam::Validators
4
7
  end
5
8
  end
@@ -1,20 +1,21 @@
1
1
  module Usman
2
2
  class AuthenticationService
3
3
 
4
- attr_reader :login_handle, :password, :error, :user
4
+ attr_reader :login_handle, :password, :error, :user, :remote_ip
5
5
 
6
6
  def initialize(params)
7
7
  @login_handle = params[:login_handle]
8
8
  @password = params[:password]
9
+ @remote_ip = params[:remote_ip]
9
10
  @error = nil
10
-
11
+
11
12
  check_if_user_exists
12
13
  if @user
13
14
  authenticate
14
15
  check_if_user_is_approved
15
16
  end
16
17
 
17
- @user.start_session unless @error
18
+ @user.start_session(@remote_ip) unless @error
18
19
  end
19
20
 
20
21
  def invalid_login_error
@@ -1,5 +1,6 @@
1
1
  class ProfilePictureUploader < ImageUploader
2
- def store_dir
2
+
3
+ def store_dir
3
4
  "uploads/profile_pictures/#{model.id}"
4
5
  end
5
6
 
@@ -33,7 +33,7 @@
33
33
  <% if @current_user %>
34
34
  <span style="color:#898989;">Welcome</span> <span style="color:#4b4b4b;"><%= @current_user.name %></span>
35
35
  &nbsp;&nbsp;|&nbsp;&nbsp;
36
- <%= link_to raw("Sign Out"), sign_out_path, method: :delete %>
36
+ <%= link_to raw("Sign Out"), usman.sign_out_path, method: :delete %>
37
37
  <% else %>
38
38
  <%= link_to raw("Sign In"), "#" %>
39
39
  <% end %>
@@ -45,7 +45,7 @@
45
45
  </a>
46
46
  </li>
47
47
  <li class="last">
48
- <%= link_to raw("<i class='fa-lock'></i>Sign Out"), sign_out_path, method: :delete %>
48
+ <%= link_to raw("<i class='fa-lock'></i>Sign Out"), usman.sign_out_path, method: :delete %>
49
49
  </li>
50
50
  </ul>
51
51
  </li>
@@ -37,6 +37,7 @@
37
37
 
38
38
  <!-- class "auto-inherit-active-class" will automatically add "active" class for parent elements who are marked already with class "active" -->
39
39
 
40
+ <!-- Admin Dashboard -->
40
41
  <li class="<%= nav_active?('admin/dashboard') ? 'active' : '' %>">
41
42
  <%= link_to raw("<i class=\"linecons-desktop\"></i> <span class='title'>Dashboard</span>"), usman.admin_dashboard_url %>
42
43
  </li>
@@ -52,29 +53,29 @@
52
53
  <li class="<%= nav_class("admin/users") %>">
53
54
  <%= link_to raw("<i class=\"linecons-user\"></i> <span class='title'>Manage Users</span>"), usman.admin_users_url %>
54
55
  </li>
55
-
56
- <li class="<%= nav_class("admin/users") %>">
57
- <%= link_to raw("<i class=\"linecons-lock\"></i> <span class='title'>Manage Permissions</span>"), usman.admin_permissions_url %>
58
- </li>
59
56
  </ul>
60
-
61
57
  </li>
62
58
 
59
+ <% if @current_user.super_admin? %>
63
60
  <li class="">
64
61
  <a href="/xenon/xenon-files/html/dashboard-1.html">
65
62
  <i class="linecons-database"></i>
66
63
  <span class="title">Master Data</span>
67
64
  </a>
65
+
68
66
  <ul>
69
67
  <li class="">
70
68
  <%= link_to raw("<i class=\"linecons-diamond\"></i> <span class='title'>Manage Features</span>"), usman.admin_features_url %>
71
69
  </li>
72
70
 
73
- <li class="">
74
- <%= link_to raw("<i class=\"linecons-diamond\"></i> <span class='title'>Manage Roles</span>"), usman.admin_roles_url %>
71
+ <li class="<%= nav_class("admin/users") %>">
72
+ <%= link_to raw("<i class=\"linecons-lock\"></i> <span class='title'>Manage Permissions</span>"), usman.admin_permissions_url %>
75
73
  </li>
76
74
  </ul>
75
+
77
76
  </li>
77
+ <% end %>
78
+
78
79
  </ul>
79
80
 
80
81
  </div>
@@ -47,6 +47,5 @@
47
47
  </div>
48
48
  </div>
49
49
  </div>
50
-
51
50
 
52
51
  </div>
@@ -9,8 +9,11 @@
9
9
  </div>
10
10
 
11
11
  <div>
12
- <%= link_to raw("<i class='fa fa-close mr-5'></i><span>Cancel</span>"), "#", onclick: "closeGenericModal();", class: "pull-left btn btn-white" %>
13
- <%= submit_tag("Save", :class=>"btn btn-secondary pull-right") %>
12
+
13
+ <%= submit_tag("Save", :class=>"btn btn-primary pull-right ml-10") %>
14
+
15
+ <%= link_to raw("<i class='fa fa-close mr-5'></i><span>Cancel</span>"), "#", onclick: "closeGenericModal();", class: "pull-right ml-10 btn btn-white" %>
16
+
14
17
  </div>
15
18
  <%= clear_tag(10) %>
16
19
  </div>
@@ -2,7 +2,8 @@
2
2
  <table class="table table-hover members-table middle-align">
3
3
  <thead>
4
4
  <tr>
5
- <th style="text-align: center;width:30px">#</th>
5
+ <th style="text-align: center;width:60px">#</th>
6
+ <th style="text-align: center;width:100px"><i class="fa fa-photo"></i></th>
6
7
  <th>Name</th>
7
8
  <th style="width:100px;">Status</th>
8
9
  <th style="text-align: center;" colspan="2">Actions</th>
@@ -16,6 +17,8 @@
16
17
 
17
18
  <tr id="tr_feature_<%= feature.id %>">
18
19
 
20
+ <td class="feature-image"></td>
21
+
19
22
  <td class="feature-image">
20
23
  <%= link_to(admin_feature_path(feature), remote: true) do %>
21
24
  <%= display_image(feature, "feature_image.image.small.url", width: "32", height: "auto", class: "img-rectangle", alt: feature.display_name) %>