dscf-core 0.3.3 → 0.3.5
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/concerns/dscf/core/auditable_controller.rb +0 -2
- data/app/controllers/concerns/dscf/core/role_assignable.rb +15 -0
- data/app/controllers/dscf/core/account_management_controller.rb +109 -0
- data/app/controllers/dscf/core/auth_controller.rb +2 -8
- data/app/controllers/dscf/core/fayda_verifications_controller.rb +30 -0
- data/app/models/concerns/dscf/core/notifiable.rb +11 -0
- data/app/models/dscf/core/business.rb +3 -1
- data/app/models/dscf/core/notification.rb +32 -0
- data/app/models/dscf/core/user.rb +6 -3
- data/app/policies/dscf/core/account_management_policy.rb +17 -0
- data/app/serializers/dscf/core/user_serializer.rb +1 -1
- data/app/services/dscf/core/notification_service.rb +34 -0
- data/config/routes.rb +9 -0
- data/db/migrate/20260616000000_create_dscf_core_notifications.rb +21 -0
- data/db/migrate/20260616000001_add_status_to_dscf_core_users.rb +7 -0
- data/lib/dscf/core/version.rb +1 -1
- data/spec/factories/dscf/core/notifications.rb +13 -0
- data/spec/factories/dscf/core/users.rb +3 -0
- metadata +11 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '07479b97a14690388c3ad7d6d8104d07e5d0495115a89732b0098eedbfb7cb53'
|
|
4
|
+
data.tar.gz: b3fc923aec6c9d9d1f9b6a8e75f97aecd4b89337b44659bb479c6c9b9ac8e6a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0369e0fe5f6914f227ebd6e0dc3fe96c299ce1e50978d4a592b15c114f47928974a1b4a27bbff14ae5814449bc08038eabdb02a816daef451f05c45a0ca3feb8'
|
|
7
|
+
data.tar.gz: 91aff4a210139997fd2ca7272bee083c8a4aa0d7407a699da923e2677aac7fa1ebfa8a0de3ab1c71f99669eca5d595ac8ceaf1cee0cd0ec3b33423a5195e9949
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Core
|
|
3
|
+
module RoleAssignable
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
def assign_default_role(user)
|
|
7
|
+
role = Role.find_or_create_by!(code: "USER") do |r|
|
|
8
|
+
r.name = "User"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
UserRole.find_or_create_by!(user: user, role: role)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Core
|
|
3
|
+
class AccountManagementController < ApplicationController
|
|
4
|
+
include Dscf::Core::Common
|
|
5
|
+
|
|
6
|
+
def index
|
|
7
|
+
authorize @clazz.new, :index?, policy_class: Dscf::Core::AccountManagementPolicy
|
|
8
|
+
|
|
9
|
+
data = policy_scope(@clazz)
|
|
10
|
+
data = data.includes(eager_loaded_associations) if eager_loaded_associations.present?
|
|
11
|
+
data = filter_records(data)
|
|
12
|
+
|
|
13
|
+
total_count = data.count if params[:page]
|
|
14
|
+
data = data.then(&paginate) if params[:page]
|
|
15
|
+
|
|
16
|
+
options = {}
|
|
17
|
+
includes = serializer_includes_for_action(:index)
|
|
18
|
+
options[:include] = includes if includes.present?
|
|
19
|
+
|
|
20
|
+
if params[:page]
|
|
21
|
+
total_pages = (total_count.to_f / per_page).ceil
|
|
22
|
+
count = data.is_a?(Array) ? data.length : data.count
|
|
23
|
+
options[:pagination] = {
|
|
24
|
+
current_page: page_no,
|
|
25
|
+
per_page: per_page,
|
|
26
|
+
count: count,
|
|
27
|
+
total_count: total_count,
|
|
28
|
+
total_pages: total_pages,
|
|
29
|
+
links: pagination_links(total_pages)
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
render_success(data: data, serializer_options: options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def suspend
|
|
37
|
+
@obj = find_record
|
|
38
|
+
authorize @obj, :suspend?, policy_class: Dscf::Core::AccountManagementPolicy
|
|
39
|
+
|
|
40
|
+
return render_error(errors: "User is already suspended", status: :unprocessable_entity) if @obj.suspended?
|
|
41
|
+
|
|
42
|
+
if @obj.update(status: :suspended, suspended_at: Time.current, suspension_reason: params[:suspension_reason])
|
|
43
|
+
notification = Dscf::Core::Notification.create!(
|
|
44
|
+
notifiable: @obj,
|
|
45
|
+
recipient: @obj,
|
|
46
|
+
notification_type: :suspension,
|
|
47
|
+
title: "Account Suspended",
|
|
48
|
+
body: params[:suspension_reason] || "Your account has been suspended"
|
|
49
|
+
)
|
|
50
|
+
Dscf::Core::NotificationService.deliver(notification)
|
|
51
|
+
|
|
52
|
+
render_success(data: @obj)
|
|
53
|
+
else
|
|
54
|
+
render_error(errors: @obj.errors.full_messages[0], status: :unprocessable_entity)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def activate
|
|
59
|
+
@obj = find_record
|
|
60
|
+
authorize @obj, :activate?, policy_class: Dscf::Core::AccountManagementPolicy
|
|
61
|
+
|
|
62
|
+
return render_error(errors: "User is already active", status: :unprocessable_entity) if @obj.active?
|
|
63
|
+
|
|
64
|
+
if @obj.update(status: :active, suspended_at: nil)
|
|
65
|
+
notification = Dscf::Core::Notification.create!(
|
|
66
|
+
notifiable: @obj,
|
|
67
|
+
recipient: @obj,
|
|
68
|
+
notification_type: :activation,
|
|
69
|
+
title: "Account Activated",
|
|
70
|
+
body: params[:reason] || "Your account has been activated"
|
|
71
|
+
)
|
|
72
|
+
Dscf::Core::NotificationService.deliver(notification)
|
|
73
|
+
|
|
74
|
+
render_success(data: @obj)
|
|
75
|
+
else
|
|
76
|
+
render_error(errors: @obj.errors.full_messages[0], status: :unprocessable_entity)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def set_clazz
|
|
83
|
+
@clazz = Dscf::Core::User
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def model_params
|
|
87
|
+
params.permit(:suspension_reason, :reason)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def find_record
|
|
91
|
+
@clazz.find(params[:id])
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def eager_loaded_associations
|
|
95
|
+
[:user_profile]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def default_serializer_includes
|
|
99
|
+
{
|
|
100
|
+
index: [:user_profile]
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def allowed_order_columns
|
|
105
|
+
%w[id email phone status suspended_at created_at updated_at]
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Dscf
|
|
2
2
|
module Core
|
|
3
3
|
class AuthController < ApplicationController
|
|
4
|
+
include Dscf::Core::RoleAssignable
|
|
5
|
+
|
|
4
6
|
skip_before_action :authenticate_user, only: %i[login signup refresh]
|
|
5
7
|
skip_before_action :validate_token_expiry, only: %i[login signup refresh]
|
|
6
8
|
skip_before_action :validate_device_consistency, only: %i[login signup refresh]
|
|
@@ -122,14 +124,6 @@ module Dscf
|
|
|
122
124
|
def refresh_params
|
|
123
125
|
params.permit(:refresh_token)
|
|
124
126
|
end
|
|
125
|
-
|
|
126
|
-
def assign_default_role(user)
|
|
127
|
-
role = Role.find_or_create_by!(code: "USER") do |r|
|
|
128
|
-
r.name = "User"
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
UserRole.find_or_create_by!(user: user, role: role)
|
|
132
|
-
end
|
|
133
127
|
end
|
|
134
128
|
end
|
|
135
129
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Core
|
|
3
|
+
class FaydaVerificationsController < ApplicationController
|
|
4
|
+
skip_before_action :authenticate_user, only: %i[verify]
|
|
5
|
+
skip_before_action :validate_token_expiry, only: %i[verify]
|
|
6
|
+
skip_before_action :validate_device_consistency, only: %i[verify]
|
|
7
|
+
skip_before_action :authorize_action!, only: %i[verify]
|
|
8
|
+
|
|
9
|
+
def verify
|
|
10
|
+
skip_authorization
|
|
11
|
+
|
|
12
|
+
fayda_number = params[:fayda_number].presence
|
|
13
|
+
|
|
14
|
+
return render_error(errors: "fayda_number is required", status: :unprocessable_entity) unless fayda_number
|
|
15
|
+
return render_error(errors: "Invalid fayda_number format", status: :unprocessable_entity) unless fayda_number.match?(/\A\d{12}\z/)
|
|
16
|
+
|
|
17
|
+
render_success(
|
|
18
|
+
data: {
|
|
19
|
+
verified: true,
|
|
20
|
+
fayda_number: fayda_number,
|
|
21
|
+
full_name: "Mock Person",
|
|
22
|
+
gender: "Male",
|
|
23
|
+
date_of_birth: "1990-01-01",
|
|
24
|
+
verification_date: Time.zone.now.iso8601
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -8,6 +8,8 @@ module Dscf
|
|
|
8
8
|
|
|
9
9
|
has_one_attached :logo
|
|
10
10
|
|
|
11
|
+
include Dscf::Core::Notifiable
|
|
12
|
+
|
|
11
13
|
has_many :documents, as: :documentable, dependent: :destroy, class_name: "Dscf::Core::Document"
|
|
12
14
|
|
|
13
15
|
validates :name, presence: true
|
|
@@ -20,7 +22,7 @@ module Dscf
|
|
|
20
22
|
|
|
21
23
|
def self.ransackable_attributes(_auth_object = nil)
|
|
22
24
|
%w[business_type_id contact_email contact_phone created_at description id id_value name tin_number
|
|
23
|
-
|
|
25
|
+
updated_at user_id is_system]
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def self.ransackable_associations(_auth_object = nil)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Core
|
|
3
|
+
class Notification < ApplicationRecord
|
|
4
|
+
self.table_name = "dscf_core_notifications"
|
|
5
|
+
|
|
6
|
+
belongs_to :notifiable, polymorphic: true
|
|
7
|
+
belongs_to :recipient, polymorphic: true
|
|
8
|
+
|
|
9
|
+
enum :status, {pending: 0, delivered: 1, failed: 2, read: 3}, default: :pending
|
|
10
|
+
enum :notification_type, {
|
|
11
|
+
approval: 0, rejection: 1, modification: 2,
|
|
12
|
+
suspension: 3, activation: 4, listing: 5, general: 6
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
validates :notification_type, presence: true
|
|
16
|
+
validates :title, presence: true
|
|
17
|
+
validates :body, presence: true
|
|
18
|
+
validates :recipient, presence: true
|
|
19
|
+
|
|
20
|
+
scope :unread, -> { where(read_at: nil) }
|
|
21
|
+
scope :for_recipient, ->(recipient) { where(recipient: recipient) }
|
|
22
|
+
|
|
23
|
+
def self.ransackable_attributes(_auth_object = nil)
|
|
24
|
+
%w[id notification_type status title body read_at delivered_at created_at updated_at]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.ransackable_associations(_auth_object = nil)
|
|
28
|
+
%w[notifiable recipient]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -10,13 +10,17 @@ module Dscf
|
|
|
10
10
|
has_many :documents, as: :documentable, dependent: :destroy, class_name: "Dscf::Core::Document"
|
|
11
11
|
has_one :user_profile, dependent: :destroy, class_name: "Dscf::Core::UserProfile"
|
|
12
12
|
|
|
13
|
+
enum :status, {active: 0, suspended: 1}, default: :active
|
|
14
|
+
|
|
15
|
+
scope :active, -> { where(status: :active) }
|
|
16
|
+
scope :suspended, -> { where(status: :suspended) }
|
|
17
|
+
|
|
13
18
|
accepts_nested_attributes_for :user_profile
|
|
14
19
|
|
|
15
20
|
before_create :set_default_temp_password
|
|
16
21
|
|
|
17
22
|
# --- RBAC Helper Methods ---
|
|
18
23
|
|
|
19
|
-
# rubocop:disable Naming/PredicateName
|
|
20
24
|
def has_role?(role_code)
|
|
21
25
|
active_role_codes.include?(role_code.to_s.upcase)
|
|
22
26
|
end
|
|
@@ -36,7 +40,6 @@ module Dscf
|
|
|
36
40
|
def has_any_permission?(*permission_codes)
|
|
37
41
|
permission_codes.flatten.any? { |code| has_permission?(code) }
|
|
38
42
|
end
|
|
39
|
-
# rubocop:enable Naming/PredicateName
|
|
40
43
|
|
|
41
44
|
def super_admin?
|
|
42
45
|
active_role_codes.include?("SUPER_ADMIN")
|
|
@@ -71,7 +74,7 @@ module Dscf
|
|
|
71
74
|
end
|
|
72
75
|
|
|
73
76
|
def self.ransackable_attributes(_auth_object = nil)
|
|
74
|
-
%w[id email phone verified_at created_at updated_at]
|
|
77
|
+
%w[id email phone status suspended_at suspension_reason verified_at created_at updated_at]
|
|
75
78
|
end
|
|
76
79
|
|
|
77
80
|
def self.ransackable_associations(_auth_object = nil)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Core
|
|
3
|
+
class AccountManagementPolicy < ApplicationPolicy
|
|
4
|
+
def index?
|
|
5
|
+
user.has_permission?("account_management.index")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def suspend?
|
|
9
|
+
user.has_permission?("account_management.suspend")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def activate?
|
|
13
|
+
user.has_permission?("account_management.activate")
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Dscf
|
|
2
2
|
module Core
|
|
3
3
|
class UserSerializer < ActiveModel::Serializer
|
|
4
|
-
attributes :id, :email, :phone, :verified_at, :created_at, :updated_at
|
|
4
|
+
attributes :id, :email, :phone, :status, :suspended_at, :suspension_reason, :verified_at, :created_at, :updated_at
|
|
5
5
|
|
|
6
6
|
has_many :user_roles, serializer: Dscf::Core::UserRoleSerializer
|
|
7
7
|
has_many :roles, serializer: Dscf::Core::RoleSerializer
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require "securerandom"
|
|
2
|
+
|
|
3
|
+
module Dscf
|
|
4
|
+
module Core
|
|
5
|
+
class NotificationService
|
|
6
|
+
class << self
|
|
7
|
+
def deliver(notification)
|
|
8
|
+
adapter = resolve_adapter
|
|
9
|
+
adapter.send_sms(notification.recipient.phone, notification.body)
|
|
10
|
+
notification.update!(status: :delivered, delivered_at: Time.current)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def resolve_adapter
|
|
14
|
+
adapter_name = Rails.application.config.x.sms_adapter || :stub
|
|
15
|
+
|
|
16
|
+
case adapter_name.to_sym
|
|
17
|
+
when :stub then Adapters::SmsStub
|
|
18
|
+
else raise ArgumentError, "Unknown SMS adapter: #{adapter_name}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module Adapters
|
|
24
|
+
class SmsStub
|
|
25
|
+
class << self
|
|
26
|
+
def send_sms(_phone, _message)
|
|
27
|
+
{success: true, message_id: "stub-#{SecureRandom.hex(6)}"}
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
data/config/routes.rb
CHANGED
|
@@ -35,4 +35,13 @@ Dscf::Core::Engine.routes.draw do
|
|
|
35
35
|
|
|
36
36
|
resources :addresses, only: %i[index show create update]
|
|
37
37
|
resources :business_types, only: %i[index show create update]
|
|
38
|
+
|
|
39
|
+
post "fayda/verify", to: "fayda_verifications#verify"
|
|
40
|
+
|
|
41
|
+
resources :account_management, only: [:index], controller: "account_management" do
|
|
42
|
+
member do
|
|
43
|
+
post :suspend
|
|
44
|
+
post :activate
|
|
45
|
+
end
|
|
46
|
+
end
|
|
38
47
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class CreateDscfCoreNotifications < ActiveRecord::Migration[8.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :dscf_core_notifications do |t|
|
|
4
|
+
t.references :notifiable, polymorphic: true, null: false, index: false
|
|
5
|
+
t.references :recipient, polymorphic: true, null: false, index: false
|
|
6
|
+
t.integer :notification_type, null: false
|
|
7
|
+
t.string :title, null: false
|
|
8
|
+
t.text :body, null: false
|
|
9
|
+
t.integer :status, default: 0, null: false
|
|
10
|
+
t.datetime :read_at
|
|
11
|
+
t.datetime :delivered_at
|
|
12
|
+
|
|
13
|
+
t.timestamps
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
add_index :dscf_core_notifications, :status
|
|
17
|
+
add_index :dscf_core_notifications, :notification_type
|
|
18
|
+
add_index :dscf_core_notifications, %i[recipient_type recipient_id], name: "idx_dscf_core_notifications_on_recipient"
|
|
19
|
+
add_index :dscf_core_notifications, %i[notifiable_type notifiable_id], name: "idx_dscf_core_notifications_on_notifiable"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
class AddStatusToDscfCoreUsers < ActiveRecord::Migration[8.0]
|
|
2
|
+
def change
|
|
3
|
+
add_column :dscf_core_users, :status, :integer, default: 0, null: false
|
|
4
|
+
add_column :dscf_core_users, :suspended_at, :datetime, null: true
|
|
5
|
+
add_column :dscf_core_users, :suspension_reason, :text, null: true
|
|
6
|
+
end
|
|
7
|
+
end
|
data/lib/dscf/core/version.rb
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :notification, class: "Dscf::Core::Notification" do
|
|
3
|
+
association :notifiable, factory: :user
|
|
4
|
+
association :recipient, factory: :user
|
|
5
|
+
|
|
6
|
+
notification_type { :approval }
|
|
7
|
+
title { "Notification #{SecureRandom.hex(4)}" }
|
|
8
|
+
body { Faker::Lorem.paragraph }
|
|
9
|
+
status { :pending }
|
|
10
|
+
read_at { nil }
|
|
11
|
+
delivered_at { nil }
|
|
12
|
+
end
|
|
13
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dscf-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Asrat
|
|
@@ -434,12 +434,15 @@ files:
|
|
|
434
434
|
- app/controllers/concerns/dscf/core/json_response.rb
|
|
435
435
|
- app/controllers/concerns/dscf/core/pagination.rb
|
|
436
436
|
- app/controllers/concerns/dscf/core/reviewable_controller.rb
|
|
437
|
+
- app/controllers/concerns/dscf/core/role_assignable.rb
|
|
437
438
|
- app/controllers/concerns/dscf/core/token_authenticatable.rb
|
|
439
|
+
- app/controllers/dscf/core/account_management_controller.rb
|
|
438
440
|
- app/controllers/dscf/core/addresses_controller.rb
|
|
439
441
|
- app/controllers/dscf/core/application_controller.rb
|
|
440
442
|
- app/controllers/dscf/core/auth_controller.rb
|
|
441
443
|
- app/controllers/dscf/core/business_types_controller.rb
|
|
442
444
|
- app/controllers/dscf/core/businesses_controller.rb
|
|
445
|
+
- app/controllers/dscf/core/fayda_verifications_controller.rb
|
|
443
446
|
- app/controllers/dscf/core/files_controller.rb
|
|
444
447
|
- app/controllers/dscf/core/permissions_controller.rb
|
|
445
448
|
- app/controllers/dscf/core/role_permissions_controller.rb
|
|
@@ -452,6 +455,7 @@ files:
|
|
|
452
455
|
- app/mailers/dscf/core/application_mailer.rb
|
|
453
456
|
- app/models/concerns/dscf/core/attachable.rb
|
|
454
457
|
- app/models/concerns/dscf/core/auditable_model.rb
|
|
458
|
+
- app/models/concerns/dscf/core/notifiable.rb
|
|
455
459
|
- app/models/concerns/dscf/core/reviewable_model.rb
|
|
456
460
|
- app/models/concerns/dscf/core/user_authenticatable.rb
|
|
457
461
|
- app/models/dscf/core/address.rb
|
|
@@ -461,6 +465,7 @@ files:
|
|
|
461
465
|
- app/models/dscf/core/business_type.rb
|
|
462
466
|
- app/models/dscf/core/document.rb
|
|
463
467
|
- app/models/dscf/core/file_attachment.rb
|
|
468
|
+
- app/models/dscf/core/notification.rb
|
|
464
469
|
- app/models/dscf/core/permission.rb
|
|
465
470
|
- app/models/dscf/core/refresh_token.rb
|
|
466
471
|
- app/models/dscf/core/review.rb
|
|
@@ -469,6 +474,7 @@ files:
|
|
|
469
474
|
- app/models/dscf/core/user.rb
|
|
470
475
|
- app/models/dscf/core/user_profile.rb
|
|
471
476
|
- app/models/dscf/core/user_role.rb
|
|
477
|
+
- app/policies/dscf/core/account_management_policy.rb
|
|
472
478
|
- app/policies/dscf/core/application_policy.rb
|
|
473
479
|
- app/policies/dscf/core/business_policy.rb
|
|
474
480
|
- app/policies/dscf/core/business_type_policy.rb
|
|
@@ -493,6 +499,7 @@ files:
|
|
|
493
499
|
- app/services/dscf/core/file_storage.rb
|
|
494
500
|
- app/services/dscf/core/file_storage/client.rb
|
|
495
501
|
- app/services/dscf/core/file_storage/uploader.rb
|
|
502
|
+
- app/services/dscf/core/notification_service.rb
|
|
496
503
|
- app/services/dscf/core/token_service.rb
|
|
497
504
|
- config/initializers/jwt.rb
|
|
498
505
|
- config/initializers/ransack.rb
|
|
@@ -516,6 +523,8 @@ files:
|
|
|
516
523
|
- db/migrate/20260304000001_create_dscf_core_permissions.rb
|
|
517
524
|
- db/migrate/20260304000002_create_dscf_core_role_permissions.rb
|
|
518
525
|
- db/migrate/20260501000001_add_is_system_to_dscf_core_businesses.rb
|
|
526
|
+
- db/migrate/20260616000000_create_dscf_core_notifications.rb
|
|
527
|
+
- db/migrate/20260616000001_add_status_to_dscf_core_users.rb
|
|
519
528
|
- lib/dscf/core.rb
|
|
520
529
|
- lib/dscf/core/engine.rb
|
|
521
530
|
- lib/dscf/core/permission_registry.rb
|
|
@@ -532,6 +541,7 @@ files:
|
|
|
532
541
|
- spec/factories/dscf/core/business_types.rb
|
|
533
542
|
- spec/factories/dscf/core/businesses.rb
|
|
534
543
|
- spec/factories/dscf/core/documents.rb
|
|
544
|
+
- spec/factories/dscf/core/notifications.rb
|
|
535
545
|
- spec/factories/dscf/core/permissions.rb
|
|
536
546
|
- spec/factories/dscf/core/refresh_tokens.rb
|
|
537
547
|
- spec/factories/dscf/core/reviews.rb
|