usman 0.1.5 → 0.1.6dev2

Sign up to get free protection for your applications and to get access to all the features.
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) %>