sis_core 1.0.4 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/sis/core/application_controller.rb +10 -2
- data/app/controllers/sis/core/menus_controller.rb +22 -0
- data/app/controllers/sis/core/users_controller.rb +71 -0
- data/app/models/sis/core/academic_programme.rb +15 -5
- data/app/models/sis/core/academic_year.rb +1 -1
- data/app/models/sis/core/applicant.rb +18 -1
- data/app/models/sis/core/application.rb +6 -3
- data/app/models/sis/core/application_document.rb +3 -1
- data/app/models/sis/core/application_module.rb +8 -0
- data/app/models/sis/core/application_setup.rb +18 -9
- data/app/models/sis/core/document_requirement.rb +4 -1
- data/app/models/sis/core/exam.rb +7 -1
- data/app/models/sis/core/exam_result.rb +7 -1
- data/app/models/sis/core/exam_setup.rb +12 -4
- data/app/models/sis/core/menu.rb +11 -0
- data/app/models/sis/core/programme_level.rb +1 -1
- data/app/models/sis/core/semester.rb +2 -0
- data/app/models/sis/core/user.rb +13 -0
- data/app/models/sis/core/user_role.rb +10 -0
- data/app/services/sis/core/user_service.rb +25 -0
- data/app/uploaders/sis/core/application_document_uploader.rb +51 -0
- data/app/uploaders/sis/core/photo_uploader.rb +51 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20200106133937_create_sis_core_applicants.rb +17 -3
- data/db/migrate/20200107094449_create_sis_core_applications.rb +4 -6
- data/db/migrate/20200107101638_create_sis_core_application_documents.rb +1 -1
- data/db/migrate/20200507114003_create_sis_core_users.rb +17 -0
- data/db/migrate/20200511165121_create_sis_core_application_modules.rb +15 -0
- data/db/migrate/20200511165241_create_sis_core_user_roles.rb +15 -0
- data/db/migrate/20200511165450_create_sis_core_menus.rb +18 -0
- data/lib/authorize_request.rb +18 -0
- data/lib/json_web_token.rb +12 -0
- data/lib/sis/core/engine.rb +2 -0
- data/lib/sis/core/version.rb +1 -1
- data/lib/sis_core.rb +4 -2
- data/spec/factories/sis/core/academic_years.rb +1 -1
- data/spec/factories/sis/core/applicants.rb +11 -2
- data/spec/factories/sis/core/application_modules.rb +6 -0
- data/spec/factories/sis/core/applications.rb +1 -6
- data/spec/factories/sis/core/menus.rb +9 -0
- data/spec/factories/sis/core/programme_levels.rb +1 -1
- data/spec/factories/sis/core/user_roles.rb +6 -0
- data/spec/factories/sis/core/users.rb +9 -0
- metadata +87 -14
- data/app/models/sis/core/staff.rb +0 -21
- data/app/models/user.rb +0 -12
- data/config/initializers/devise_token_auth.rb +0 -55
- data/db/migrate/20200108092202_devise_token_auth_create_users.rb +0 -53
- data/db/migrate/20200316120805_create_sis_core_staffs.rb +0 -31
- data/db/migrate/20200319074334_modify_user.rb +0 -16
- data/spec/factories/sis/core/staffs.rb +0 -35
- data/spec/factories/users.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6b30327db722ca3f16bad73c555e382920cacff0baec011f504b999840e9cc4
|
4
|
+
data.tar.gz: 9f92fb5a3268456261cf45e3cc870196705638c5b6fbc19c5effbc48157f3420
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c2f778c15f7791999026a1a6e5114be6ac25e072abda5ce91535cad9818c9dfa90096fefe14eb4e50a0f284a295496ec0e7a6ff25f25ed7e193fa8aa8c105d0
|
7
|
+
data.tar.gz: b67d563aa05be808f40ea3618945e45a99538000ad225510158b0203636dba471604c6d949c9d26f5f2f867f8a8fc4ccb8071c3b21db4cecbebec59e49f6d446
|
@@ -1,7 +1,15 @@
|
|
1
1
|
module Sis
|
2
2
|
module Core
|
3
|
-
class ApplicationController < ActionController::
|
4
|
-
|
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({ id: user_menu.id, label: user_menu.text, icon: user_menu.icon_cls,
|
15
|
+
location: user_menu.location, items: children, expanded: true })
|
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,17 @@
|
|
1
|
-
module Sis
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module Sis
|
2
|
+
module Core
|
3
|
+
class AcademicProgramme < ApplicationRecord
|
4
|
+
belongs_to :programme
|
5
|
+
belongs_to :programme_type
|
6
|
+
belongs_to :programme_level
|
7
|
+
|
8
|
+
delegate(:name, to: :programme, prefix: true, allow_nil: false)
|
9
|
+
delegate(:name, to: :programme_type, prefix: true, allow_nil: false)
|
10
|
+
delegate(:name, to: :programme_level, prefix: true, allow_nil: false)
|
11
|
+
|
12
|
+
def name
|
13
|
+
programme.name.to_s + ' ' + programme_level.name.to_s + ' ' + programme_type.name.to_s
|
14
|
+
end
|
15
|
+
end
|
6
16
|
end
|
7
17
|
end
|
@@ -1,8 +1,25 @@
|
|
1
1
|
module Sis
|
2
2
|
module Core
|
3
3
|
class Applicant < ApplicationRecord
|
4
|
-
|
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_many :applications
|
9
|
+
|
10
|
+
has_secure_password
|
11
|
+
|
12
|
+
def full_name
|
13
|
+
first_name + ' ' + middle_name + ' ' + last_name
|
14
|
+
end
|
15
|
+
|
16
|
+
scope :by_application_setup, (lambda do |app_setup_id|
|
17
|
+
joins(applications: :application_setup).where('sis_core_applications.application_setup_id': app_setup_id)
|
18
|
+
end)
|
19
|
+
|
20
|
+
scope :by_status, (lambda do |status|
|
21
|
+
joins(:applications).where('sis_core_applications.status': status)
|
22
|
+
end)
|
6
23
|
end
|
7
24
|
end
|
8
25
|
end
|
@@ -16,7 +16,7 @@ module Sis
|
|
16
16
|
end
|
17
17
|
|
18
18
|
event :review do
|
19
|
-
transitions from: [
|
19
|
+
transitions from: %i[submitted rejected accepted], to: :under_review
|
20
20
|
end
|
21
21
|
|
22
22
|
event :accept do
|
@@ -34,14 +34,17 @@ module Sis
|
|
34
34
|
event :select_for_admission do
|
35
35
|
transitions from: :selected_for_exam, to: :selected_for_admission
|
36
36
|
end
|
37
|
-
|
38
37
|
end
|
39
38
|
|
40
|
-
validates :
|
39
|
+
validates :status, presence: true
|
41
40
|
validates :payment_information, presence: true, if: :payment_made
|
42
41
|
|
43
42
|
belongs_to :applicant
|
44
43
|
belongs_to :academic_programme
|
44
|
+
belongs_to :application_setup
|
45
|
+
|
46
|
+
delegate(:name, to: :academic_programme, prefix: true, allow_nil: false)
|
47
|
+
delegate(:full_name, to: :applicant, prefix: true, allow_nil: false)
|
45
48
|
end
|
46
49
|
end
|
47
50
|
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
module Sis
|
2
2
|
module Core
|
3
3
|
class ApplicationDocument < ApplicationRecord
|
4
|
-
|
4
|
+
mount_base64_uploader :document, ApplicationDocumentUploader
|
5
5
|
|
6
6
|
belongs_to :application
|
7
7
|
belongs_to :document_requirement
|
8
|
+
|
9
|
+
delegate(:name, to: :document_requirement, prefix: true, allow_nil: false)
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
@@ -1,14 +1,23 @@
|
|
1
|
-
module Sis
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Sis
|
2
|
+
module Core
|
3
|
+
class ApplicationSetup < ApplicationRecord
|
4
|
+
OPEN = 'Open'.freeze
|
5
|
+
CLOSED = 'Closed'.freeze
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
belongs_to :academic_programme
|
8
|
+
belongs_to :target_semester, class_name: 'Sis::Core::Semester'
|
9
|
+
has_many :document_requirements
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
validates :start_date, :end_date, :status, presence: true
|
12
|
+
validates :status, inclusion: [OPEN, CLOSED]
|
12
13
|
|
14
|
+
delegate(:name, to: :target_semester, prefix: true, allow_nil: false)
|
15
|
+
delegate(:name, to: :academic_programme, prefix: true, allow_nil: false)
|
16
|
+
|
17
|
+
def name
|
18
|
+
academic_programme.programme.name.to_s + ' ' + academic_programme.programme_level.name.to_s + ' ' +
|
19
|
+
academic_programme.programme_type.name.to_s
|
20
|
+
end
|
21
|
+
end
|
13
22
|
end
|
14
23
|
end
|
@@ -5,6 +5,9 @@ module Sis
|
|
5
5
|
belongs_to :application_setup
|
6
6
|
|
7
7
|
validates :original, :copy, presence: true
|
8
|
+
|
9
|
+
delegate(:name, to: :document_type, prefix: true, allow_nil: false)
|
10
|
+
delegate(:name, to: :application_setup, prefix: true, allow_nil: false)
|
8
11
|
end
|
9
12
|
end
|
10
|
-
end
|
13
|
+
end
|
data/app/models/sis/core/exam.rb
CHANGED
@@ -8,8 +8,14 @@ module Sis
|
|
8
8
|
before_validation :set_pass_point
|
9
9
|
|
10
10
|
def set_pass_point
|
11
|
-
self.pass_point =
|
11
|
+
self.pass_point = points / 2 unless pass_point || !points
|
12
12
|
end
|
13
|
+
|
14
|
+
delegate(:name, to: :exam_setup, prefix: true, allow_nil: false)
|
15
|
+
|
16
|
+
scope :by_application_setup, (lambda do |app_setup_id|
|
17
|
+
joins(:exam_setup).where('sis_core_exam_setups.application_setup_id': app_setup_id)
|
18
|
+
end)
|
13
19
|
end
|
14
20
|
end
|
15
21
|
end
|
@@ -8,11 +8,17 @@ 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
|
|
14
16
|
def set_status
|
15
|
-
self.status =
|
17
|
+
self.status = if exam && exam.pass_point >= points
|
18
|
+
PASS
|
19
|
+
else
|
20
|
+
FAIL
|
21
|
+
end
|
16
22
|
end
|
17
23
|
end
|
18
24
|
end
|
@@ -1,7 +1,15 @@
|
|
1
|
-
module Sis
|
2
|
-
|
3
|
-
|
1
|
+
module Sis
|
2
|
+
module Core
|
3
|
+
class ExamSetup < ApplicationRecord
|
4
|
+
belongs_to :application_setup
|
4
5
|
|
5
|
-
|
6
|
+
validates :date, :hours, :venue, presence: true
|
7
|
+
|
8
|
+
def name
|
9
|
+
application_setup.academic_programme.name
|
10
|
+
end
|
11
|
+
|
12
|
+
delegate(:name, to: :application_setup, prefix: true, allow_nil: false)
|
13
|
+
end
|
6
14
|
end
|
7
15
|
end
|
@@ -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,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
|