sis_core 1.0.5 → 1.0.6

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/sis/core/application_controller.rb +10 -2
  3. data/app/controllers/sis/core/menus_controller.rb +22 -0
  4. data/app/controllers/sis/core/users_controller.rb +71 -0
  5. data/app/models/sis/core/academic_year.rb +1 -1
  6. data/app/models/sis/core/applicant.rb +4 -1
  7. data/app/models/sis/core/application.rb +2 -1
  8. data/app/models/sis/core/application_document.rb +1 -1
  9. data/app/models/sis/core/application_module.rb +8 -0
  10. data/app/models/sis/core/exam_result.rb +2 -0
  11. data/app/models/sis/core/menu.rb +11 -0
  12. data/app/models/sis/core/user.rb +13 -0
  13. data/app/models/sis/core/user_role.rb +10 -0
  14. data/app/services/sis/core/user_service.rb +25 -0
  15. data/app/uploaders/sis/core/application_document_uploader.rb +51 -0
  16. data/app/uploaders/sis/core/photo_uploader.rb +51 -0
  17. data/config/routes.rb +6 -0
  18. data/db/migrate/20200106133937_create_sis_core_applicants.rb +17 -3
  19. data/db/migrate/20200107094449_create_sis_core_applications.rb +4 -6
  20. data/db/migrate/20200107101638_create_sis_core_application_documents.rb +1 -1
  21. data/db/migrate/20200507114003_create_sis_core_users.rb +17 -0
  22. data/db/migrate/20200511165121_create_sis_core_application_modules.rb +15 -0
  23. data/db/migrate/20200511165241_create_sis_core_user_roles.rb +15 -0
  24. data/db/migrate/20200511165450_create_sis_core_menus.rb +18 -0
  25. data/lib/authorize_request.rb +18 -0
  26. data/lib/json_web_token.rb +12 -0
  27. data/lib/sis/core/engine.rb +2 -0
  28. data/lib/sis/core/version.rb +1 -1
  29. data/lib/sis_core.rb +3 -1
  30. data/spec/factories/sis/core/academic_years.rb +1 -1
  31. data/spec/factories/sis/core/applicants.rb +11 -2
  32. data/spec/factories/sis/core/application_modules.rb +6 -0
  33. data/spec/factories/sis/core/applications.rb +1 -6
  34. data/spec/factories/sis/core/menus.rb +9 -0
  35. data/spec/factories/sis/core/user_roles.rb +6 -0
  36. data/spec/factories/sis/core/users.rb +9 -0
  37. metadata +87 -14
  38. data/app/models/sis/core/staff.rb +0 -21
  39. data/app/models/user.rb +0 -12
  40. data/config/initializers/devise_token_auth.rb +0 -55
  41. data/db/migrate/20200108092202_devise_token_auth_create_users.rb +0 -53
  42. data/db/migrate/20200316120805_create_sis_core_staffs.rb +0 -31
  43. data/db/migrate/20200319074334_modify_user.rb +0 -16
  44. data/spec/factories/sis/core/staffs.rb +0 -34
  45. data/spec/factories/users.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 743af7d896e433bed5589a15d4d71d33e439591e95c4eb498acb8311daa19c4d
4
- data.tar.gz: d6d5bec16bb9bcdc8dbfd97f6b53ede9d7cb01018709406b34721e0cd42b3cb6
3
+ metadata.gz: 7c2e069bab5a79b5ea0e86bc34f9445920cdc3bbf883938f5e2aae454ae38763
4
+ data.tar.gz: d27da2f1dab2dbaceb1d08ac11486f325e9793f9dfdadd8a18bb9aaa4199e33f
5
5
  SHA512:
6
- metadata.gz: 024c7d8e0adc5404a3b17a695f16aeeed1055f1a9fcba94d61d1ce1959282fae2610513c8c62752d8cd31534f6335add61d8f21516afdba69cfabec352656564
7
- data.tar.gz: 51114f1222ac1c838424d215bc02aa9954a591dbd8a3e2c2204b2f8eea20bffcb2792ebb60ee76f92f79d9a8a02a7d74c386057defdb46aa14593dff1766da85
6
+ metadata.gz: e5d24cf81adef27efce96ad29dc9b1bfe5e71adb557d9a1f30d255e78a0979d1c7039e518b4658b1602be5ccb4da9d3d649c33c5bc9f39c052ed4ed032277ad5
7
+ data.tar.gz: 78c398a895cfb1bcb55fddfe7a6bb097d82dd524e9cbeb8ce1e13f1e9ece68f7660c49753ff86c0d5623fa701a51fe157f76d05912aa3eec40cc62a994d0c474
@@ -1,7 +1,15 @@
1
1
  module Sis
2
2
  module Core
3
- class ApplicationController < ActionController::Base
4
- protect_from_forgery with: :exception
3
+ class ApplicationController < ActionController::API
4
+ before_action :authenticate_request
5
+ attr_reader :current_user
6
+
7
+ private
8
+
9
+ def authenticate_request
10
+ @current_user = AuthorizeRequest.user(request.headers)
11
+ render json: { error: 'Not Authorized' }, status: 401 unless @current_user
12
+ end
5
13
  end
6
14
  end
7
15
  end
@@ -0,0 +1,22 @@
1
+ module Sis
2
+ module Core
3
+ class MenusController < ApplicationController
4
+ skip_before_action :authenticate_request, only: [:menu]
5
+ def menu
6
+ app_module_id = ApplicationModule.find_by_code(params[:app_module]).id
7
+ user_roles = User.find(params[:user_id]).user_roles.where(application_module_id: app_module_id)
8
+ menus = []
9
+ user_roles.each do |role|
10
+ user_menus = role.menus.where(parent_id: nil, application_module_id: app_module_id)
11
+ user_menus.each do |user_menu|
12
+ children = user_menu.children.where(parent_id: user_menu.id, application_module_id: app_module_id)
13
+ children = children.map { |c| { label: c.text, icon: c.icon_cls, routerLink: [c.location] } }
14
+ menus.push({ label: user_menu.text, icon: user_menu.icon_cls, location: user_menu.location,
15
+ items: children })
16
+ end
17
+ end
18
+ render json: { success: true, data: menus }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,71 @@
1
+ module Sis
2
+ module Core
3
+ class UsersController < ApplicationController
4
+ skip_before_action :authenticate_request, only: %i[login sign_in generate_recovery_token reset_password]
5
+ before_action :set_user_service, only: %i[generate_recovery_token reset_password]
6
+ def sign_in
7
+ applicant = Applicant&.find_by_email(params[:email])
8
+ if Applicant&.find_by_email(params[:email]) && applicant.authenticate(params[:password])
9
+ token = JsonWebToken.encode({ id: applicant.id, first_name: applicant.first_name,
10
+ middle_name: applicant.middle_name, last_name: applicant.last_name,
11
+ email: applicant.email })
12
+ render json: { success: true, jwt: token }
13
+ else
14
+ render json: { success: false, errors: ['Invalid username or password !'] }
15
+ end
16
+ end
17
+
18
+ def create
19
+ user = User.new(user_params)
20
+ if user.save
21
+ render json: { success: true, data: user }
22
+ else
23
+ render json: { success: false, errors: user.errors }
24
+ end
25
+ end
26
+
27
+ def login
28
+ user = User.find_by_email(params[:email])
29
+ if User&.find_by_email(params[:email]) && user.authenticate(params[:password])
30
+ token = JsonWebToken.encode({ id: user.id, first_name: user.first_name, last_name: user.last_name })
31
+ render json: { success: true, jwt: token }
32
+ else
33
+ render json: { success: false, errors: ['Invalid username or password !'] }
34
+ end
35
+ end
36
+
37
+ def generate_recovery_token
38
+ user = User.where(email: params[:email], secret_question_answer: params[:secret_question_answer])
39
+ if user.count.positive?
40
+ user = user[0]
41
+ @service.generate_password_token(user)
42
+ render json: { success: true, token: user.reset_password_token, email: user.email }
43
+ else
44
+ render json: { success: false, errors: ['User not found !'] }
45
+ end
46
+ end
47
+
48
+ def reset_password
49
+ token = params[:token].to_s
50
+ user = User.find_by_reset_password_token(token)
51
+ if user && @service.password_token_valid?(user.id)
52
+ @service.reset_password(user.id, params[:password])
53
+ render json: { success: true }
54
+ else
55
+ render json: { success: false, errors: ['Link not valid or expired. Try generating a new link !'] }
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def user_params
62
+ params.require('user').permit(:id, :first_name, :last_name, :email, :password, :reset_password_token,
63
+ :reset_password_sent_at, :secret_question, :secret_question_answer)
64
+ end
65
+
66
+ def set_user_service
67
+ @service = UserService.new
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,7 +1,7 @@
1
1
  module Sis
2
2
  module Core
3
3
  class AcademicYear < ApplicationRecord
4
- validates :year, presence: true, uniqueness: true, case_sensitive: false
4
+ validates :year, presence: true, uniqueness: { case_sensitive: false }
5
5
  end
6
6
  end
7
7
  end
@@ -1,8 +1,11 @@
1
1
  module Sis
2
2
  module Core
3
3
  class Applicant < ApplicationRecord
4
- validates :full_name, :email, :phone_number, presence: true
4
+ mount_base64_uploader :photo, PhotoUploader
5
+ validates :first_name, :middle_name, :last_name, :email, presence: true
5
6
  validates :email, uniqueness: true
7
+
8
+ has_secure_password
6
9
  end
7
10
  end
8
11
  end
@@ -36,11 +36,12 @@ module Sis
36
36
  end
37
37
  end
38
38
 
39
- validates :full_name, :email, :age, :gender, :nationality, :status, presence: true
39
+ validates :status, presence: true
40
40
  validates :payment_information, presence: true, if: :payment_made
41
41
 
42
42
  belongs_to :applicant
43
43
  belongs_to :academic_programme
44
+ belongs_to :application_setup
44
45
  end
45
46
  end
46
47
  end
@@ -1,7 +1,7 @@
1
1
  module Sis
2
2
  module Core
3
3
  class ApplicationDocument < ApplicationRecord
4
- validates :document, presence: true
4
+ mount_base64_uploader :document, ApplicationDocumentUploader
5
5
 
6
6
  belongs_to :application
7
7
  belongs_to :document_requirement
@@ -0,0 +1,8 @@
1
+ module Sis
2
+ module Core
3
+ class ApplicationModule < ApplicationRecord
4
+ has_and_belongs_to_many :users
5
+ validates :code, :name, presence: true
6
+ end
7
+ end
8
+ end
@@ -8,6 +8,8 @@ module Sis
8
8
  belongs_to :application
9
9
 
10
10
  validates :points, presence: true
11
+ validates_uniqueness_of :application_id, scope: %i[exam_id]
12
+
11
13
 
12
14
  before_validation :set_status
13
15
 
@@ -0,0 +1,11 @@
1
+ module Sis
2
+ module Core
3
+ class Menu < ApplicationRecord
4
+ has_and_belongs_to_many :user_roles
5
+ belongs_to :application_module
6
+ belongs_to :parent, class_name: 'Sis::Core::Menu', optional: true
7
+ has_many :children, class_name: 'Sis::Core::Menu', foreign_key: 'parent_id'
8
+ validates :text, presence: true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Sis
2
+ module Core
3
+ class User < ApplicationRecord
4
+ validates :first_name, :last_name, :email, presence: true
5
+ validates :password, presence: true, on: :create
6
+ validates :email, uniqueness: true
7
+ has_and_belongs_to_many :application_modules
8
+ has_and_belongs_to_many :user_roles
9
+
10
+ has_secure_password
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module Sis
2
+ module Core
3
+ class UserRole < ApplicationRecord
4
+ validates :name, presence: true
5
+ has_and_belongs_to_many :users
6
+ has_and_belongs_to_many :menus
7
+ belongs_to :application_module
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ module Sis
2
+ module Core
3
+ class UserService
4
+ def generate_password_token(user)
5
+ user.update({ reset_password_token: generate_token, reset_password_sent_at: Time.now.utc })
6
+ end
7
+
8
+ def password_token_valid?(user_id)
9
+ user = User.find(user_id)
10
+ (user.reset_password_sent_at + 4.hours) > Time.now.utc
11
+ end
12
+
13
+ def reset_password(user_id, password)
14
+ user = User.find(user_id)
15
+ user.reset_password_token = nil
16
+ user.password = password
17
+ user.save!
18
+ end
19
+
20
+ def generate_token
21
+ SecureRandom.hex(10)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,51 @@
1
+ module Sis
2
+ module Core
3
+ class ApplicationDocumentUploader < CarrierWave::Uploader::Base
4
+ # Include RMagick or MiniMagick support:
5
+ # include CarrierWave::RMagick
6
+ # include CarrierWave::MiniMagick
7
+
8
+ # Choose what kind of storage to use for this uploader:
9
+ storage :file
10
+ # storage :fog
11
+
12
+ # Override the directory where uploaded files will be stored.
13
+ # This is a sensible default for uploaders that are meant to be mounted:
14
+ def store_dir
15
+ "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
16
+ end
17
+
18
+ # Provide a default URL as a default if there hasn't been a file uploaded:
19
+ # def default_url(*args)
20
+ # # For Rails 3.1+ asset pipeline compatibility:
21
+ # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
22
+ #
23
+ # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
24
+ # end
25
+
26
+ # Process files as they are uploaded:
27
+ # process scale: [200, 300]
28
+ #
29
+ # def scale(width, height)
30
+ # # do something
31
+ # end
32
+
33
+ # Create different versions of your uploaded files:
34
+ # version :thumb do
35
+ # process resize_to_fit: [50, 50]
36
+ # end
37
+
38
+ # Add a white list of extensions which are allowed to be uploaded.
39
+ # For images you might use something like this:
40
+ def extension_whitelist
41
+ %w[pdf]
42
+ end
43
+
44
+ # Override the filename of the uploaded files:
45
+ # Avoid using model.id or version_name here, see uploader/store.rb for details.
46
+ # def filename
47
+ # "something.jpg" if original_filename
48
+ # end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,51 @@
1
+ module Sis
2
+ module Core
3
+ class PhotoUploader < CarrierWave::Uploader::Base
4
+ # Include RMagick or MiniMagick support:
5
+ # include CarrierWave::RMagick
6
+ # include CarrierWave::MiniMagick
7
+
8
+ # Choose what kind of storage to use for this uploader:
9
+ storage :file
10
+ # storage :fog
11
+
12
+ # Override the directory where uploaded files will be stored.
13
+ # This is a sensible default for uploaders that are meant to be mounted:
14
+ def store_dir
15
+ "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
16
+ end
17
+
18
+ # Provide a default URL as a default if there hasn't been a file uploaded:
19
+ # def default_url(*args)
20
+ # # For Rails 3.1+ asset pipeline compatibility:
21
+ # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
22
+ #
23
+ # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
24
+ # end
25
+
26
+ # Process files as they are uploaded:
27
+ # process scale: [200, 300]
28
+ #
29
+ # def scale(width, height)
30
+ # # do something
31
+ # end
32
+
33
+ # Create different versions of your uploaded files:
34
+ # version :thumb do
35
+ # process resize_to_fit: [50, 50]
36
+ # end
37
+
38
+ # Add a white list of extensions which are allowed to be uploaded.
39
+ # For images you might use something like this:
40
+ def extension_whitelist
41
+ %w[jpg jpeg gif png]
42
+ end
43
+
44
+ # Override the filename of the uploaded files:
45
+ # Avoid using model.id or version_name here, see uploader/store.rb for details.
46
+ # def filename
47
+ # "something.jpg" if original_filename
48
+ # end
49
+ end
50
+ end
51
+ end
@@ -1,2 +1,8 @@
1
1
  Sis::Core::Engine.routes.draw do
2
+ resources :users, only: [:create]
3
+ post '/login', controller: :users, action: :login
4
+ get '/menus', controller: :menus, action: :menu
5
+ post '/sign_in', controller: :users, action: :sign_in
6
+ post '/generate_recovery_token', controller: :users, action: :generate_recovery_token
7
+ post '/reset_password', controller: :users, action: :reset_password
2
8
  end
@@ -1,9 +1,23 @@
1
1
  class CreateSisCoreApplicants < ActiveRecord::Migration[6.0]
2
2
  def change
3
3
  create_table :sis_core_applicants do |t|
4
- t.string :full_name, null: false
5
- t.string :email, null: false, unique: true
6
- t.string :phone_number, null: false
4
+ t.string :first_name, null: false
5
+ t.string :middle_name, null: false
6
+ t.string :last_name, null: false
7
+ t.string :password_digest, null: false
8
+ t.string :email, null: false
9
+ t.string :alternative_email_address
10
+ t.string :primary_phone_number
11
+ t.string :alternative_telephone_number
12
+ t.date :date_of_birth
13
+ t.string :gender
14
+ t.string :nationality
15
+ t.string :address
16
+ t.string :photo
17
+ t.string :reset_password_token
18
+ t.datetime :reset_password_sent_at
19
+ t.string :secret_question
20
+ t.string :secret_question_answer
7
21
 
8
22
  t.timestamps
9
23
  end
@@ -1,14 +1,8 @@
1
1
  class CreateSisCoreApplications < ActiveRecord::Migration[6.0]
2
2
  def change
3
3
  create_table :sis_core_applications do |t|
4
- t.string :full_name, null: false
5
- t.string :email, null: false
6
- t.integer :age, null: false
7
- t.string :gender, null: false
8
- t.string :nationality, null: false
9
4
  t.string :status, null: false, default: 'Draft'
10
5
  t.boolean :payment_made, null: false, default: false
11
- t.string :address
12
6
  t.string :payment_information
13
7
  t.date :application_date
14
8
  t.references :applicant,
@@ -19,6 +13,10 @@ class CreateSisCoreApplications < ActiveRecord::Migration[6.0]
19
13
  null: false,
20
14
  index: { name: 'applications_on_ap_indx' },
21
15
  foreign_key: { to_table: :sis_core_academic_programmes }
16
+ t.references :application_setup,
17
+ null: false,
18
+ index: { name: 'application_setup_on_ap_indx' },
19
+ foreign_key: { to_table: :sis_core_application_setups }
22
20
 
23
21
  t.timestamps
24
22
  end
@@ -1,7 +1,7 @@
1
1
  class CreateSisCoreApplicationDocuments < ActiveRecord::Migration[6.0]
2
2
  def change
3
3
  create_table :sis_core_application_documents do |t|
4
- t.string :document, null: false
4
+ t.string :document
5
5
  t.references :document_requirement,
6
6
  null: false,
7
7
  index: { name: 'ad_on_adr_indx' },
@@ -0,0 +1,17 @@
1
+ class CreateSisCoreUsers < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :sis_core_users do |t|
4
+ t.string :first_name, null: false
5
+ t.string :last_name, null: false
6
+ t.string :email, null: false
7
+ t.boolean :active, default: true
8
+ t.string :password_digest, null: false
9
+ t.string :reset_password_token
10
+ t.datetime :reset_password_sent_at
11
+ t.string :secret_question
12
+ t.string :secret_question_answer
13
+
14
+ t.timestamps
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ class CreateSisCoreApplicationModules < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :sis_core_application_modules do |t|
4
+ t.string :code, null: false
5
+ t.string :name, null: false
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ create_table :sis_core_application_modules_users, id: false do |t|
11
+ t.belongs_to :application_module, index: { name: 'app_module_on_app_modules_usr_indx' }
12
+ t.belongs_to :user, index: { name: 'usr_on_app_modules_usr_indx' }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ class CreateSisCoreUserRoles < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :sis_core_user_roles do |t|
4
+ t.string :name, null: false
5
+ t.references :application_module, index: { name: 'app_module_on_usr_role_indx' }
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ create_table :sis_core_user_roles_users, id: false do |t|
11
+ t.belongs_to :user, index: { name: 'usr_on_usr_role_usrs_indx' }
12
+ t.belongs_to :user_role, index: { name: 'usr_role_on_usr_role_usrs_indx' }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ class CreateSisCoreMenus < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :sis_core_menus do |t|
4
+ t.string :text, null: false
5
+ t.string :icon_cls
6
+ t.string :location
7
+ t.integer :parent_id
8
+ t.references :application_module, index: { name: 'app_module_on_menus_indx' }
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ create_table :sis_core_menus_user_roles, id: false do |t|
14
+ t.belongs_to :menu, index: { name: 'menu_on_menus_usr_role_indx' }
15
+ t.belongs_to :user_role, index: { name: 'usr_role_on_menus_usr_role_indx' }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ class AuthorizeRequest
2
+ class << self
3
+ def user(headers)
4
+ @user ||= User.find(decoded_auth_token(headers)[:id]) if decoded_auth_token(headers)
5
+ @user || nil
6
+ end
7
+
8
+ def decoded_auth_token(headers)
9
+ @decoded_auth_token ||= JsonWebToken.decode(http_auth_header(headers)) if http_auth_header(headers)
10
+ end
11
+
12
+ def http_auth_header(headers)
13
+ return headers['Authorization'].split(' ').last if headers['Authorization'].present?
14
+
15
+ nil
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ class JsonWebToken
2
+ class << self
3
+ def encode(payload)
4
+ JWT.encode(payload, Rails.application.secrets.secret_key_base)
5
+ end
6
+
7
+ def decode(token)
8
+ body = JWT.decode(token, Rails.application.secrets.secret_key_base)[0]
9
+ HashWithIndifferentAccess.new body
10
+ end
11
+ end
12
+ end
@@ -4,6 +4,8 @@ module Sis
4
4
  isolate_namespace Sis::Core
5
5
 
6
6
  config.generators.api_only = true
7
+ config.eager_load_paths << Sis::Core::Engine.root.join('lib')
8
+ config.autoload_paths << Sis::Core::Engine.root.join('lib')
7
9
 
8
10
  config.generators do |g|
9
11
  g.test_framework :rspec
@@ -1,5 +1,5 @@
1
1
  module Sis
2
2
  module Core
3
- VERSION = '1.0.5'.freeze
3
+ VERSION = '1.0.6'.freeze
4
4
  end
5
5
  end
@@ -1,5 +1,7 @@
1
1
  require 'sis/core'
2
2
  require 'sis/core/engine'
3
- require 'devise_token_auth'
3
+ require 'jwt'
4
+ require 'bcrypt'
4
5
  require 'aasm'
5
6
  require 'active_model_serializers'
7
+ require 'carrierwave'
@@ -1,6 +1,6 @@
1
1
  FactoryBot.define do
2
2
  factory :academic_year, class: Sis::Core::AcademicYear do
3
- year { '2000/01' }
3
+ year { FFaker::Name.name }
4
4
  label { 'Academic year of 2000/01' }
5
5
  end
6
6
  end
@@ -1,7 +1,16 @@
1
1
  FactoryBot.define do
2
2
  factory :applicant, class: Sis::Core::Applicant do
3
- full_name { FFaker::Name.name }
3
+ first_name { FFaker::Name.name }
4
+ middle_name { FFaker::Name.name }
5
+ last_name { FFaker::Name.name }
6
+ password { FFaker::Name.name }
4
7
  email { FFaker::Internet.email }
5
- phone_number { FFaker::PhoneNumber.phone_number }
8
+ primary_phone_number { FFaker::PhoneNumber.phone_number }
9
+ alternative_telephone_number { FFaker::PhoneNumber.phone_number }
10
+ date_of_birth { '2000-10-05' }
11
+ gender { FFaker::Gender.binary }
12
+ nationality { FFaker::Name.name }
13
+ address { FFaker::Address.city }
14
+ photo { FFaker::Name.name }
6
15
  end
7
16
  end
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :application_module, class: Sis::Core::ApplicationModule do
3
+ code { FFaker::Name.unique.name }
4
+ name { FFaker::Name.name }
5
+ end
6
+ end
@@ -1,16 +1,11 @@
1
1
  FactoryBot.define do
2
2
  factory :application, class: Sis::Core::Application do
3
- full_name { FFaker::Name.name }
4
- email { FFaker::Internet.email }
5
- age { FFaker::Random.rand(20..30) }
6
- gender { Sis::Core::Application::MALE }
7
- nationality { FFaker::Address.country }
8
3
  status { :draft }
9
4
  payment_made { false }
10
5
  payment_information { nil }
11
- address { FFaker::Address.street_address }
12
6
  application_date { Date.today }
13
7
  association :applicant
14
8
  association :academic_programme
9
+ association :application_setup
15
10
  end
16
11
  end
@@ -0,0 +1,9 @@
1
+ FactoryBot.define do
2
+ factory :menu, class: Sis::Core::Menu do
3
+ text { FFaker::Name.name }
4
+ icon_cls { 'xf001' }
5
+ location { '/programme' }
6
+ parent_id { nil }
7
+ association :application_module
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :user_role, class: Sis::Core::UserRole do
3
+ name { FFaker::Name.name }
4
+ association :application_module
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ FactoryBot.define do
2
+ factory :user, class: Sis::Core::User do
3
+ first_name { FFaker::Name.name }
4
+ last_name { FFaker::Name.name }
5
+ email { FFaker::Internet.email }
6
+ active { false }
7
+ password { FFaker::Name.name }
8
+ end
9
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sis_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henock L.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-25 00:00:00.000000000 Z
11
+ date: 2020-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aasm
@@ -39,7 +39,49 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.10.0
41
41
  - !ruby/object:Gem::Dependency
42
- name: devise_token_auth
42
+ name: bcrypt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.1.7
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.7
55
+ - !ruby/object:Gem::Dependency
56
+ name: carrierwave
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: carrierwave-base64
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: jwt
43
85
  requirement: !ruby/object:Gem::Requirement
44
86
  requirements:
45
87
  - - ">="
@@ -72,6 +114,20 @@ dependencies:
72
114
  - - ">="
73
115
  - !ruby/object:Gem::Version
74
116
  version: 6.0.2.1
117
+ - !ruby/object:Gem::Dependency
118
+ name: sqlite3
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
75
131
  - !ruby/object:Gem::Dependency
76
132
  name: factory_bot_rails
77
133
  requirement: !ruby/object:Gem::Requirement
@@ -143,19 +199,25 @@ dependencies:
143
199
  - !ruby/object:Gem::Version
144
200
  version: '0'
145
201
  - !ruby/object:Gem::Dependency
146
- name: sqlite3
202
+ name: pg
147
203
  requirement: !ruby/object:Gem::Requirement
148
204
  requirements:
149
205
  - - ">="
150
206
  - !ruby/object:Gem::Version
151
- version: '0'
207
+ version: '0.18'
208
+ - - "<"
209
+ - !ruby/object:Gem::Version
210
+ version: '2.0'
152
211
  type: :development
153
212
  prerelease: false
154
213
  version_requirements: !ruby/object:Gem::Requirement
155
214
  requirements:
156
215
  - - ">="
157
216
  - !ruby/object:Gem::Version
158
- version: '0'
217
+ version: '0.18'
218
+ - - "<"
219
+ - !ruby/object:Gem::Version
220
+ version: '2.0'
159
221
  description: An engine which contains the core of the student information system app
160
222
  as a layer.
161
223
  email:
@@ -168,11 +230,14 @@ files:
168
230
  - README.md
169
231
  - Rakefile
170
232
  - app/controllers/sis/core/application_controller.rb
233
+ - app/controllers/sis/core/menus_controller.rb
234
+ - app/controllers/sis/core/users_controller.rb
171
235
  - app/models/sis/core/academic_programme.rb
172
236
  - app/models/sis/core/academic_year.rb
173
237
  - app/models/sis/core/applicant.rb
174
238
  - app/models/sis/core/application.rb
175
239
  - app/models/sis/core/application_document.rb
240
+ - app/models/sis/core/application_module.rb
176
241
  - app/models/sis/core/application_record.rb
177
242
  - app/models/sis/core/application_setup.rb
178
243
  - app/models/sis/core/course.rb
@@ -186,15 +251,18 @@ files:
186
251
  - app/models/sis/core/instructor.rb
187
252
  - app/models/sis/core/instructor_course.rb
188
253
  - app/models/sis/core/lookup.rb
254
+ - app/models/sis/core/menu.rb
189
255
  - app/models/sis/core/programme.rb
190
256
  - app/models/sis/core/programme_level.rb
191
257
  - app/models/sis/core/programme_type.rb
192
258
  - app/models/sis/core/semester.rb
193
- - app/models/sis/core/staff.rb
194
259
  - app/models/sis/core/student.rb
195
- - app/models/user.rb
260
+ - app/models/sis/core/user.rb
261
+ - app/models/sis/core/user_role.rb
262
+ - app/services/sis/core/user_service.rb
263
+ - app/uploaders/sis/core/application_document_uploader.rb
264
+ - app/uploaders/sis/core/photo_uploader.rb
196
265
  - config/database.ci.yml
197
- - config/initializers/devise_token_auth.rb
198
266
  - config/routes.rb
199
267
  - db/migrate/20200105061717_create_sis_core_lookups.rb
200
268
  - db/migrate/20200105072142_create_sis_core_academic_years.rb
@@ -209,14 +277,17 @@ files:
209
277
  - db/migrate/20200107302251_create_sis_core_exam_setups.rb
210
278
  - db/migrate/20200107333411_create_sis_core_exams.rb
211
279
  - db/migrate/20200107434658_create_sis_core_exam_results.rb
212
- - db/migrate/20200108092202_devise_token_auth_create_users.rb
213
280
  - db/migrate/20200307033100_create_sis_core_courses.rb
214
281
  - db/migrate/20200307071511_create_sis_core_instructors.rb
215
282
  - db/migrate/20200307071736_create_sis_core_instructor_courses.rb
216
283
  - db/migrate/20200307072006_create_sis_core_students.rb
217
284
  - db/migrate/20200307072317_create_sis_core_course_registrations.rb
218
- - db/migrate/20200316120805_create_sis_core_staffs.rb
219
- - db/migrate/20200319074334_modify_user.rb
285
+ - db/migrate/20200507114003_create_sis_core_users.rb
286
+ - db/migrate/20200511165121_create_sis_core_application_modules.rb
287
+ - db/migrate/20200511165241_create_sis_core_user_roles.rb
288
+ - db/migrate/20200511165450_create_sis_core_menus.rb
289
+ - lib/authorize_request.rb
290
+ - lib/json_web_token.rb
220
291
  - lib/sis/core.rb
221
292
  - lib/sis/core/engine.rb
222
293
  - lib/sis/core/version.rb
@@ -226,6 +297,7 @@ files:
226
297
  - spec/factories/sis/core/academic_years.rb
227
298
  - spec/factories/sis/core/applicants.rb
228
299
  - spec/factories/sis/core/application_documents.rb
300
+ - spec/factories/sis/core/application_modules.rb
229
301
  - spec/factories/sis/core/application_setups.rb
230
302
  - spec/factories/sis/core/applications.rb
231
303
  - spec/factories/sis/core/course_registrations.rb
@@ -238,13 +310,14 @@ files:
238
310
  - spec/factories/sis/core/instructor_courses.rb
239
311
  - spec/factories/sis/core/instructors.rb
240
312
  - spec/factories/sis/core/lookups.rb
313
+ - spec/factories/sis/core/menus.rb
241
314
  - spec/factories/sis/core/programme_levels.rb
242
315
  - spec/factories/sis/core/programme_types.rb
243
316
  - spec/factories/sis/core/programmes.rb
244
317
  - spec/factories/sis/core/semesters.rb
245
- - spec/factories/sis/core/staffs.rb
246
318
  - spec/factories/sis/core/students.rb
247
- - spec/factories/users.rb
319
+ - spec/factories/sis/core/user_roles.rb
320
+ - spec/factories/sis/core/users.rb
248
321
  homepage: http://www.mks.com.et
249
322
  licenses:
250
323
  - MIT
@@ -1,21 +0,0 @@
1
- module Sis
2
- module Core
3
- class Staff < ApplicationRecord
4
- belongs_to :user, class_name: 'User'
5
- SINGLE = 'Single'.freeze
6
- MARRIED = 'Married'.freeze
7
- MARITAL_STATUS = [SINGLE, MARRIED].freeze
8
- validates :job_title, :job_level, :department, :date_of_employment, :salary,
9
- :remark, :mothers_name, :education_level, :phone_number,
10
- :place_of_birth, :marital_status, :region, :zone, :wereda,
11
- :kebele, :id_number,
12
- :emergency_contact_name, :emergency_contact_phone,
13
- :relation_to_emergency_contact, :user_id,
14
- presence: true
15
- validates :salary, numericality: true
16
- validates :marital_status, inclusion: { in: MARITAL_STATUS }
17
- validates :id_number, uniqueness: true
18
- validates :passport_number, uniqueness: true, if: :passport_number?
19
- end
20
- end
21
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class User < ActiveRecord::Base
4
- extend Devise::Models
5
- # Include default devise modules. Others available are:
6
- # :confirmable, :lockable, :timeoutable and :omniauthable
7
- devise :database_authenticatable, :registerable,
8
- :recoverable, :rememberable, :trackable, :validatable
9
- include DeviseTokenAuth::Concerns::User
10
-
11
- validates :first_name, :middle_name, :last_name, :password, :email, :gender, :date_of_birth, presence: true
12
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- DeviseTokenAuth.setup do |config|
4
- # By default the authorization headers will change after each request. The
5
- # client is responsible for keeping track of the changing tokens. Change
6
- # this to false to prevent the Authorization header from changing after
7
- # each request.
8
- # config.change_headers_on_each_request = true
9
-
10
- # By default, users will need to re-authenticate after 2 weeks. This setting
11
- # determines how long tokens will remain valid after they are issued.
12
- # config.token_lifespan = 2.weeks
13
-
14
- # Limiting the token_cost to just 4 in testing will increase the performance of
15
- # your test suite dramatically. The possible cost value is within range from 4
16
- # to 31. It is recommended to not use a value more than 10 in other environments.
17
- config.token_cost = Rails.env.test? ? 4 : 10
18
-
19
- # Sets the max number of concurrent devices per user, which is 10 by default.
20
- # After this limit is reached, the oldest tokens will be removed.
21
- # config.max_number_of_devices = 10
22
-
23
- # Sometimes it's necessary to make several requests to the API at the same
24
- # time. In this case, each request in the batch will need to share the same
25
- # auth token. This setting determines how far apart the requests can be while
26
- # still using the same auth token.
27
- # config.batch_request_buffer_throttle = 5.seconds
28
-
29
- # This route will be the prefix for all oauth2 redirect callbacks. For
30
- # example, using the default '/omniauth', the github oauth2 provider will
31
- # redirect successful authentications to '/omniauth/github/callback'
32
- # config.omniauth_prefix = "/omniauth"
33
-
34
- # By default sending current password is not needed for the password update.
35
- # Uncomment to enforce current_password param to be checked before all
36
- # attribute updates. Set it to :password if you want it to be checked only if
37
- # password is updated.
38
- # config.check_current_password_before_update = :attributes
39
-
40
- # By default we will use callbacks for single omniauth.
41
- # It depends on fields like email, provider and uid.
42
- # config.default_callbacks = true
43
-
44
- # Makes it possible to change the headers names
45
- # config.headers_names = {:'access-token' => 'access-token',
46
- # :'client' => 'client',
47
- # :'expiry' => 'expiry',
48
- # :'uid' => 'uid',
49
- # :'token-type' => 'token-type' }
50
-
51
- # By default, only Bearer Token authentication is implemented out of the box.
52
- # If, however, you wish to integrate with legacy Devise authentication, you can
53
- # do so by enabling this flag. NOTE: This feature is highly experimental!
54
- # config.enable_standard_devise_support = false
55
- end
@@ -1,53 +0,0 @@
1
- class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[6.0]
2
- def change
3
- create_table(:users) do |t|
4
- ## Required
5
- t.string :provider, null: false, default: 'email'
6
- t.string :uid, null: false, default: ''
7
-
8
- ## Database authenticatable
9
- t.string :encrypted_password, null: false, default: ''
10
-
11
- ## Recoverable
12
- t.string :reset_password_token
13
- t.datetime :reset_password_sent_at
14
- t.boolean :allow_password_change, default: false
15
-
16
- ## Rememberable
17
- t.datetime :remember_created_at
18
-
19
- ## Confirmable
20
- t.string :confirmation_token
21
- t.datetime :confirmed_at
22
- t.datetime :confirmation_sent_at
23
- t.string :unconfirmed_email # Only if using reconfirmable
24
- ## Trackable
25
- t.integer :sign_in_count, default: 0, null: false
26
- t.datetime :current_sign_in_at
27
- t.datetime :last_sign_in_at
28
- t.string :current_sign_in_ip
29
- t.string :last_sign_in_ip
30
- ## Lockable
31
- # t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
32
- # t.string :unlock_token # Only if unlock strategy is :email or :both
33
- # t.datetime :locked_at
34
-
35
- ## User Info
36
- t.string :name
37
- t.string :nickname
38
- t.string :image
39
- t.string :email
40
-
41
- ## Tokens
42
- t.text :tokens
43
-
44
- t.timestamps
45
- end
46
-
47
- add_index :users, :email, unique: true
48
- add_index :users, %i[uid provider], unique: true
49
- add_index :users, :reset_password_token, unique: true
50
- add_index :users, :confirmation_token, unique: true
51
- # add_index :users, :unlock_token, unique: true
52
- end
53
- end
@@ -1,31 +0,0 @@
1
- class CreateSisCoreStaffs < ActiveRecord::Migration[6.0]
2
- def change
3
- create_table :sis_core_staffs do |t|
4
- t.string :job_title, null: false
5
- t.string :job_level, null: false
6
- t.string :department, null: false
7
- t.date :date_of_employment, null: false
8
- t.float :salary, null: false
9
- t.text :remark, null: false
10
- t.string :mothers_name, null: false
11
- t.string :education_level, null: false
12
- t.string :phone_number, null: false
13
- t.string :place_of_birth, null: false
14
- t.string :marital_status, null: false
15
- t.string :region, null: false
16
- t.string :zone, null: false
17
- t.string :wereda, null: false
18
- t.string :kebele, null: false
19
- t.string :passport_number
20
- t.string :id_number, null: false, unique: true
21
- t.string :emergency_contact_name, null: false
22
- t.string :emergency_contact_phone, null: false
23
- t.string :relation_to_emergency_contact, null: false
24
- t.references :user,
25
- index: { name: 'user_on_staff_indx' },
26
- null: false,
27
- foreign_key: { to_table: :users }
28
- t.timestamps
29
- end
30
- end
31
- end
@@ -1,16 +0,0 @@
1
- class ModifyUser < ActiveRecord::Migration[6.0]
2
- def change
3
- remove_column :users, :name, :string
4
- remove_column :users, :nickname, :string
5
- add_column :users, :first_name, :string
6
- add_column :users, :middle_name, :string
7
- add_column :users, :last_name, :string
8
- add_column :users, :gender, :string
9
- add_column :users, :date_of_birth, :date
10
- change_column :users, :first_name, :string, null: false
11
- change_column :users, :middle_name, :string, null: false
12
- change_column :users, :last_name, :string, null: false
13
- change_column :users, :gender, :string, null: false
14
- change_column :users, :date_of_birth, :date, null: false
15
- end
16
- end
@@ -1,34 +0,0 @@
1
- FactoryBot.define do
2
- factory :staff, class: 'Sis::Core::Staff' do
3
- end
4
- # SINGLE = 'Single'.freeze
5
- # MARRIED = 'Married'.freeze
6
- # MARITAL_STATUS = [SINGLE, MARRIED].freeze
7
- # factory :staff, class: 'Sis::Core::Staff' do
8
- # user
9
- # job_title { FFaker::Job.title }
10
- # job_level { FFaker::Company.position }
11
- # department { FFaker::Education.school_name }
12
- # date_of_employment { FFaker::Time.date }
13
- # salary { [2000, 5500.5, 10_000, 20_000].sample }
14
- # remark { FFaker::Lorem.sentence }
15
- # mothers_name { FFaker::Name.name }
16
- # education_level { FFaker::Education.degree }
17
- # phone_number { FFaker::PhoneNumber.phone_number }
18
- # place_of_birth { FFaker::Address.city }
19
- # marital_status { %w[Single Married].sample }
20
- # region { FFaker::Address.city }
21
- # zone { FFaker::Address.neighborhood }
22
- # wereda { [1, 2, 5, 13].sample }
23
- # kebele { [1, 2, 5, 13].sample }
24
- # passport_number { FFaker::Guid.guid }
25
- # id_number { FFaker::Guid.guid }
26
- # emergency_contact_name { FFaker::Name.name }
27
- # emergency_contact_phone { FFaker::PhoneNumber.phone_number }
28
- # relation_to_emergency_contact do
29
- # %w[mother,father,brother,spouse].sample
30
- # end
31
- # created_at { FFaker::Time.datetime }
32
- # updated_at { FFaker::Time.datetime }
33
- # end
34
- end
@@ -1,11 +0,0 @@
1
- FactoryBot.define do
2
- factory :user, class: 'User' do
3
- first_name { FFaker::Name.first_name }
4
- middle_name { FFaker::Name.name }
5
- last_name { FFaker::Name.last_name }
6
- password { FFaker::Internet.password }
7
- email { FFaker::Internet.email }
8
- gender { %w[male,female].sample }
9
- date_of_birth { FFaker::Time.date }
10
- end
11
- end