anoubis 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +38 -0
- data/app/controllers/anoubis/application_controller.rb +78 -0
- data/app/controllers/anoubis/core/application_controller.rb +343 -0
- data/app/controllers/anoubis/core/data/actions.rb +962 -0
- data/app/controllers/anoubis/core/data/callbacks.rb +68 -0
- data/app/controllers/anoubis/core/data/convert.rb +407 -0
- data/app/controllers/anoubis/core/data/defaults.rb +217 -0
- data/app/controllers/anoubis/core/data/get.rb +531 -0
- data/app/controllers/anoubis/core/data/load.rb +89 -0
- data/app/controllers/anoubis/core/data/set.rb +49 -0
- data/app/controllers/anoubis/core/data/setup.rb +104 -0
- data/app/controllers/anoubis/core/data_controller.rb +28 -0
- data/app/controllers/anoubis/core/index/actions.rb +53 -0
- data/app/controllers/anoubis/core/index/callbacks.rb +23 -0
- data/app/controllers/anoubis/core/index_controller.rb +36 -0
- data/app/controllers/anoubis/etc/base.rb +52 -0
- data/app/controllers/anoubis/etc/data.rb +89 -0
- data/app/controllers/anoubis/etc/field.rb +468 -0
- data/app/controllers/anoubis/etc/field_options.rb +83 -0
- data/app/controllers/anoubis/etc/field_order.rb +51 -0
- data/app/controllers/anoubis/etc/filter.rb +251 -0
- data/app/controllers/anoubis/etc/menu.rb +101 -0
- data/app/controllers/anoubis/etc/model.rb +67 -0
- data/app/controllers/anoubis/etc/tab_item.rb +91 -0
- data/app/controllers/anoubis/etc.rb +8 -0
- data/app/controllers/anoubis/export.rb +47 -0
- data/app/controllers/anoubis/output/autocomplete.rb +30 -0
- data/app/controllers/anoubis/output/basic.rb +86 -0
- data/app/controllers/anoubis/output/data.rb +101 -0
- data/app/controllers/anoubis/output/delete.rb +41 -0
- data/app/controllers/anoubis/output/edit.rb +55 -0
- data/app/controllers/anoubis/output/frame.rb +227 -0
- data/app/controllers/anoubis/output/login.rb +71 -0
- data/app/controllers/anoubis/output/menu.rb +220 -0
- data/app/controllers/anoubis/output/update.rb +43 -0
- data/app/controllers/anoubis/sso/client/application_controller.rb +139 -0
- data/app/controllers/anoubis/sso/client/data/actions.rb +5 -0
- data/app/controllers/anoubis/sso/client/data/callbacks.rb +5 -0
- data/app/controllers/anoubis/sso/client/data/convert.rb +5 -0
- data/app/controllers/anoubis/sso/client/data/defaults.rb +5 -0
- data/app/controllers/anoubis/sso/client/data/get.rb +5 -0
- data/app/controllers/anoubis/sso/client/data/load.rb +26 -0
- data/app/controllers/anoubis/sso/client/data/set.rb +5 -0
- data/app/controllers/anoubis/sso/client/data/setup.rb +5 -0
- data/app/controllers/anoubis/sso/client/data_controller.rb +21 -0
- data/app/controllers/anoubis/sso/client/index/actions.rb +79 -0
- data/app/controllers/anoubis/sso/client/index/callbacks.rb +13 -0
- data/app/controllers/anoubis/sso/client/index_controller.rb +18 -0
- data/app/controllers/anoubis/sso/server/application_controller.rb +49 -0
- data/app/controllers/anoubis/sso/server/login_controller.rb +342 -0
- data/app/controllers/anoubis/sso/server/user_controller.rb +142 -0
- data/app/controllers/anoubis/tenant/application_controller.rb +54 -0
- data/app/controllers/anoubis/tenant/data/actions.rb +11 -0
- data/app/controllers/anoubis/tenant/data/callbacks.rb +11 -0
- data/app/controllers/anoubis/tenant/data/convert.rb +11 -0
- data/app/controllers/anoubis/tenant/data/defaults.rb +11 -0
- data/app/controllers/anoubis/tenant/data/get.rb +11 -0
- data/app/controllers/anoubis/tenant/data/load.rb +52 -0
- data/app/controllers/anoubis/tenant/data/set.rb +11 -0
- data/app/controllers/anoubis/tenant/data/setup.rb +11 -0
- data/app/controllers/anoubis/tenant/data_controller.rb +28 -0
- data/app/controllers/anoubis/tenant/index/actions.rb +191 -0
- data/app/controllers/anoubis/tenant/index/callbacks.rb +11 -0
- data/app/controllers/anoubis/tenant/index_controller.rb +38 -0
- data/app/controllers/anoubis/tenants_controller.rb +7 -0
- data/app/controllers/anoubis/users_controller.rb +7 -0
- data/app/jobs/anoubis/application_job.rb +6 -0
- data/app/mailers/anoubis/application_mailer.rb +8 -0
- data/app/models/anoubis/application_record.rb +45 -0
- data/app/models/anoubis/core/application_record.rb +250 -0
- data/app/models/anoubis/core/locales.rb +27 -0
- data/app/models/anoubis/sso/client/application_record.rb +3 -0
- data/app/models/anoubis/sso/client/group.rb +19 -0
- data/app/models/anoubis/sso/client/group_menu.rb +109 -0
- data/app/models/anoubis/sso/client/menu.rb +145 -0
- data/app/models/anoubis/sso/client/user.rb +81 -0
- data/app/models/anoubis/sso/client/user_group.rb +32 -0
- data/app/models/anoubis/sso/server/system.rb +36 -0
- data/app/models/anoubis/sso/server/user.rb +79 -0
- data/app/models/anoubis/tenant/application_record.rb +41 -0
- data/app/models/anoubis/tenant/group.rb +95 -0
- data/app/models/anoubis/tenant/group_locale.rb +19 -0
- data/app/models/anoubis/tenant/group_menu.rb +84 -0
- data/app/models/anoubis/tenant/menu.rb +156 -0
- data/app/models/anoubis/tenant/menu_locale.rb +27 -0
- data/app/models/anoubis/tenant/system.rb +127 -0
- data/app/models/anoubis/tenant/system_locale.rb +19 -0
- data/app/models/anoubis/tenant/system_menu.rb +51 -0
- data/app/models/anoubis/tenant/tenant.rb +107 -0
- data/app/models/anoubis/tenant/tenant_system.rb +19 -0
- data/app/models/anoubis/tenant/user.rb +225 -0
- data/app/models/anoubis/tenant/user_group.rb +32 -0
- data/app/services/anoubis/core_service.rb +16 -0
- data/app/services/anoubis/session_service.rb +17 -0
- data/app/validators/presence_in_tenant_validator.rb +20 -0
- data/config/initializers/mime_type.rb +1 -0
- data/config/locales/en.yml +120 -0
- data/config/locales/ru.yml +245 -0
- data/config/routes.rb +74 -0
- data/db/migrate/20181018085843_create_tenants.rb +13 -0
- data/db/migrate/20181018111217_create_systems.rb +10 -0
- data/db/migrate/20181018111713_create_tenant_systems.rb +11 -0
- data/db/migrate/20181018111925_create_groups.rb +13 -0
- data/db/migrate/20181018112151_create_users.rb +25 -0
- data/db/migrate/20181018115737_add_title_to_users.rb +10 -0
- data/db/migrate/20181022060211_create_menus.rb +18 -0
- data/db/migrate/20181115055245_create_group_menus.rb +12 -0
- data/db/migrate/20181115060830_create_system_menus.rb +11 -0
- data/db/migrate/20181122062131_create_user_groups.rb +11 -0
- data/db/migrate/20181221060727_create_menu_locales.rb +14 -0
- data/db/migrate/20181225062303_create_system_locales.rb +11 -0
- data/db/migrate/20181225062339_create_group_locales.rb +11 -0
- data/db/seeds.rb +268 -0
- data/lib/anoubis/engine.rb +13 -0
- data/lib/anoubis/version.rb +5 -0
- data/lib/anoubis.rb +213 -0
- data/lib/tasks/anubis_tasks.rake +10 -0
- data/lib/tasks/sessions/clear_sessions.rake +10 -0
- data/spec/anubis_spec.rb +5 -0
- data/spec/controllers/anoubis/index_controller_spec.rb +77 -0
- data/spec/dummy/Rakefile +3 -0
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- data/spec/dummy/app/jobs/application_job.rb +2 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +33 -0
- data/spec/dummy/bin/update +28 -0
- data/spec/dummy/config/application.rb +14 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/cable.yml +10 -0
- data/spec/dummy/config/database.yml +54 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +54 -0
- data/spec/dummy/config/environments/production.rb +85 -0
- data/spec/dummy/config/environments/test.rb +46 -0
- data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cors.rb +16 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +33 -0
- data/spec/dummy/config/puma.rb +34 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/spring.rb +6 -0
- data/spec/dummy/config/storage.yml +34 -0
- data/spec/dummy/config.ru +5 -0
- data/spec/dummy/db/schema.rb +167 -0
- data/spec/dummy/db/seeds.rb +1 -0
- data/spec/factories/anubis_group_locales.rb +7 -0
- data/spec/factories/anubis_group_menus.rb +7 -0
- data/spec/factories/anubis_groups.rb +6 -0
- data/spec/factories/anubis_menu_locales.rb +9 -0
- data/spec/factories/anubis_menus.rb +6 -0
- data/spec/factories/anubis_system_locales.rb +7 -0
- data/spec/factories/anubis_system_menus.rb +6 -0
- data/spec/factories/anubis_systems.rb +5 -0
- data/spec/factories/anubis_tenants.rb +7 -0
- data/spec/factories/anubis_users.rb +10 -0
- data/spec/integration/navigation_test.rb +7 -0
- data/spec/models/anoubis/group_locale_spec.rb +25 -0
- data/spec/models/anoubis/group_menu_spec.rb +50 -0
- data/spec/models/anoubis/group_spec.rb +52 -0
- data/spec/models/anoubis/menu_locale_spec.rb +31 -0
- data/spec/models/anoubis/menu_spec.rb +48 -0
- data/spec/models/anoubis/system_locale_spec.rb +20 -0
- data/spec/models/anoubis/system_menu_spec.rb +49 -0
- data/spec/models/anoubis/system_spec.rb +53 -0
- data/spec/models/anoubis/tenant_spec.rb +67 -0
- data/spec/models/anoubis/user_spec.rb +57 -0
- data/spec/rails_helper.rb +32 -0
- data/spec/requests/anoubis/users_request_spec.rb +5 -0
- data/spec/spec_helper.rb +13 -0
- metadata +408 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
##
|
2
|
+
# Model links {Menu} and {Group}. Describes group access to menu.
|
3
|
+
class Anoubis::Tenant::GroupMenu < Anoubis::Core::ApplicationRecord
|
4
|
+
# Redefines default table name
|
5
|
+
self.table_name = 'group_menus'
|
6
|
+
|
7
|
+
before_validation :before_validation_group_menu
|
8
|
+
after_create :after_create_group_menu
|
9
|
+
before_update :before_update_group_menu
|
10
|
+
after_destroy :after_destroy_group_menu
|
11
|
+
|
12
|
+
|
13
|
+
# @!attribute group
|
14
|
+
# @return [Group] reference to the {Group} model
|
15
|
+
belongs_to :group, :class_name => 'Anoubis::Tenant::Group'
|
16
|
+
validates :group, presence: true, uniqueness: { scope: [:menu_id] }
|
17
|
+
|
18
|
+
# @!attribute menu
|
19
|
+
# @return [Menu] reference to the {Menu} model
|
20
|
+
belongs_to :menu, :class_name => 'Anoubis::Tenant::Menu'
|
21
|
+
validates :menu, presence: true, uniqueness: { scope: [:group_id] }
|
22
|
+
|
23
|
+
# @!attribute access
|
24
|
+
# @return ['not', 'read', 'write', 'disable'] group access to menu element.
|
25
|
+
# - 'not' --- menu element doesn't available for this group
|
26
|
+
# - 'read' --- group has access to menu element only for read data
|
27
|
+
# - 'write' --- group has access to menu element for read and write data
|
28
|
+
# - 'disable' --- group hasn't access to menu element
|
29
|
+
enum access: { not: 0, read: 20, write: 40, disable: 60 }
|
30
|
+
|
31
|
+
##
|
32
|
+
# Is called before validation when the link between menu and group is being created or updated.
|
33
|
+
# Procedure checks if group belongs a system that has access to this menu element. If {#access} doesn't
|
34
|
+
# defined then {#access} sets to 'read'
|
35
|
+
def before_validation_group_menu
|
36
|
+
if !Anoubis::Tenant::SystemMenu.where(system_id: self.group.system_id, menu_id: self.menu_id).first
|
37
|
+
errors.add(:base, I18n.t('anubis.group_menus.errors.no_access'))
|
38
|
+
throw(:abort, __method__)
|
39
|
+
end
|
40
|
+
self.access = Anubis::Tenant::GroupMenu.accesses[:read] if !self.access
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Is called after new link between menu and group was created. If new element has parent with link that
|
45
|
+
# doesn't present in database then adds this link to database with {#access} defined as 'read'.
|
46
|
+
def after_create_group_menu
|
47
|
+
if self.menu.menu_id != nil
|
48
|
+
Anubis::Tenant::GroupMenu.find_or_create_by(menu_id: self.menu.menu_id, group_id: self.group_id) do |menu|
|
49
|
+
menu.access = Anubis::Tenant::GroupMenu.accesses[:read]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
self.after_modify_group_menu
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Is called before link between menu and group will be updated. Procedure prevents changing {#menu}
|
57
|
+
# and {#group} value.
|
58
|
+
def before_update_group_menu
|
59
|
+
self.menu_id = self.menu_id_was if self.menu_id_changed?
|
60
|
+
self.group_id = self.group_id_was if self.group_id_changed?
|
61
|
+
self.after_modify_group_menu
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Is called after link between menu and group had been deleted from database. It also deletes all child links.
|
66
|
+
def after_destroy_group_menu
|
67
|
+
Anubis::Tenant::Menu.select(:id).where(menu_id: self.menu_id).each do |menu|
|
68
|
+
Anubis::Tenant::GroupMenu.where(menu_id: menu.id, group_id: self.group_id).each do |group_menu|
|
69
|
+
group_menu.destroy
|
70
|
+
end
|
71
|
+
end
|
72
|
+
self.after_modify_group_menu
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Deletes all user's keys that belong this menu element in Redis database.
|
77
|
+
def after_modify_group_menu
|
78
|
+
if self.redis
|
79
|
+
self.redis.keys(self.redis_prefix + '*_'+self.menu.mode).each do |data|
|
80
|
+
self.redis.del data
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
##
|
2
|
+
# Menu model. Stores information about all menu elements of the portal. Menu model defines the dependence
|
3
|
+
# between controller and user access.
|
4
|
+
class Anubis::Tenant::Menu < ApplicationRecord
|
5
|
+
# Redefines default table name
|
6
|
+
self.table_name = 'menus'
|
7
|
+
|
8
|
+
before_create :before_create_menu
|
9
|
+
before_update :before_update_menu
|
10
|
+
before_save :before_save_menu
|
11
|
+
before_destroy :before_destroy_menu
|
12
|
+
after_destroy :after_destroy_menu
|
13
|
+
|
14
|
+
# @!attribute mode
|
15
|
+
# @return [String] the controller path for menu element.
|
16
|
+
validates :mode, presence: true, uniqueness: true
|
17
|
+
|
18
|
+
# @!attribute action
|
19
|
+
# @return [String] the default action of menu element ('data', 'menu', etc.).
|
20
|
+
validates :action, presence: true
|
21
|
+
|
22
|
+
# @!attribute tab
|
23
|
+
# @return [Integer] the nesting level of menu element
|
24
|
+
validates :tab, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
25
|
+
|
26
|
+
# @!attribute position
|
27
|
+
# @return [Integer] the order position of menu element in current level.
|
28
|
+
validates :position, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
29
|
+
|
30
|
+
# @!attribute page_size
|
31
|
+
# @return [Integer] the default page size for table of data frame.
|
32
|
+
validates :page_size, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
33
|
+
|
34
|
+
# @!attribute menu
|
35
|
+
# @return [Menu, nil] the parent menu for element menu (if exists).
|
36
|
+
belongs_to :menu, class_name: 'Anubis::Tenant::Menu', optional: true
|
37
|
+
has_many :menus, class_name: 'Anubis::Tenant::Menu'
|
38
|
+
|
39
|
+
has_many :group_menus, class_name: 'Anubis::Tenant::GroupMenu'
|
40
|
+
has_many :system_menus, class_name: 'Anubis::Tenant::SystemMenu'
|
41
|
+
has_many :menu_locales, class_name: 'Anubis::Tenant::MenuLocale'
|
42
|
+
|
43
|
+
# @!attribute status
|
44
|
+
# @return ['enabled', 'disabled'] the status of menu element.
|
45
|
+
# - 'enabled' --- element is enabled and is used by the system.
|
46
|
+
# - 'disabled' --- element is disabled and isn't used by the system.
|
47
|
+
enum status: { enabled: 0, disabled: 1 }
|
48
|
+
|
49
|
+
# @!attribute state
|
50
|
+
# @return ['visible', 'hidden'] the visibility of menu element. Attribute is used in fronted application.
|
51
|
+
# - 'visible' --- element is visible.
|
52
|
+
# - 'hidden' --- element is hidden.
|
53
|
+
enum state: { visible: 0, hidden: 1 }
|
54
|
+
|
55
|
+
##
|
56
|
+
# Is called before menu will be created in database. Sets {#position} as last {#position} + 1 on current {#tab}.
|
57
|
+
# After this calls {#before_update_menu} for additional modification.
|
58
|
+
def before_create_menu
|
59
|
+
data = Anubis::Tenant::Menu.where(menu_id: self.menu_id).maximum(:position)
|
60
|
+
self.position = if data then data + 1 else 0 end
|
61
|
+
|
62
|
+
self.before_update_menu
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Is called before menu will be stored in database. Sets {#mode} and {#action} in lowercase. If {#page_size}
|
67
|
+
# doesn't defined then sets it to 20. If defined parent menu element then sets {#tab} based on {#tab} of
|
68
|
+
# parent menu element + 1.
|
69
|
+
def before_update_menu
|
70
|
+
self.mode = mode.downcase
|
71
|
+
self.action = self.action.downcase
|
72
|
+
self.page_size = 20 if !self.page_size
|
73
|
+
self.page_size = self.page_size.to_i
|
74
|
+
|
75
|
+
parent_menu = Anubis::Tenant::Menu.where(id: self.menu_id).first
|
76
|
+
if parent_menu
|
77
|
+
self.tab = parent_menu.tab + 1
|
78
|
+
else
|
79
|
+
self.tab = 0
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Is called right before menu will be stored in database (after {#before_create_menu} and {#before_update_menu}).
|
85
|
+
# Deletes cache data for this menu in Redis database.
|
86
|
+
def before_save_menu
|
87
|
+
self.redis.del(self.redis_prefix + 'menu_' + self.mode) if self.redis
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Is called before menu will be deleted from database. Checks the ability to destroy a menu. Delete
|
92
|
+
# all translations for menu model from {MenuLocale}.
|
93
|
+
def before_destroy_menu
|
94
|
+
Anubis::Tenant::MenuLocale.where(menu_id: self.id).each do |menu_locale|
|
95
|
+
menu_locale.destroy
|
96
|
+
end
|
97
|
+
|
98
|
+
if !can_destroy?
|
99
|
+
errors.add(:base, I18n.t('anubis.menus.errors.has_childs'))
|
100
|
+
throw(:abort, __method__)
|
101
|
+
end
|
102
|
+
#childs = !self.menus.empty?
|
103
|
+
#childs = !self.group_menus.empty? if !childs
|
104
|
+
#childs = !self.system_menus.empty? if !childs
|
105
|
+
|
106
|
+
#return if !childs
|
107
|
+
|
108
|
+
#errors.add(:base, I18n.t('menus.errors.has_childs'))
|
109
|
+
#throw(:abort, __method__)
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Is called after menu was deleted from database. Procedure recalculates position of other menu elements.
|
114
|
+
def after_destroy_menu
|
115
|
+
query = <<-SQL
|
116
|
+
UPDATE menus
|
117
|
+
SET menus.position = menus.position - 1
|
118
|
+
WHERE menus.tab = #{self.tab} AND menus.position > #{self.position}
|
119
|
+
SQL
|
120
|
+
Anubis::Tenant::Menu.connection.execute query
|
121
|
+
#i = self.position
|
122
|
+
#Anubis::Tenant::Menu.where(menu_id: self.menu_id, position: (self.position+1..Float::INFINITY)).find_each do |menu|
|
123
|
+
# menu.position = i
|
124
|
+
# menu.save
|
125
|
+
# i += 1
|
126
|
+
# end
|
127
|
+
Anubis::Tenant::Menu.where(menu_id: self.id).find_each do |menu|
|
128
|
+
menu.destroy
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Returns model localization data from {MenuLocale}.
|
134
|
+
# @return [MenuLocale] localization for current menu
|
135
|
+
def model_locale
|
136
|
+
@model_locale ||= self.menu_locales.where(locale: Anubis::Tenant::MenuLocale.locales[self.current_locale.to_sym]).first
|
137
|
+
end
|
138
|
+
|
139
|
+
# @!attribute title
|
140
|
+
# @return [String] the menu's title. Title loads from {MenuLocale#title} based on {#current_locale}
|
141
|
+
def title
|
142
|
+
self.model_locale.title if self.model_locale
|
143
|
+
end
|
144
|
+
|
145
|
+
# @!attribute page_title
|
146
|
+
# @return [String] the menu's page title. Page title loads from {MenuLocale#page_title} based on {#current_locale}
|
147
|
+
def page_title
|
148
|
+
self.model_locale.page_title if self.model_locale
|
149
|
+
end
|
150
|
+
|
151
|
+
# @!attribute short_title
|
152
|
+
# @return [String] the menu's short title. Short title loads from {MenuLocale#short_title} based on {#current_locale}
|
153
|
+
def short_title
|
154
|
+
self.model_locale.short_title if self.model_locale
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
##
|
2
|
+
# Localization for {Menu} model. Model stores all translations for {Menu} model.
|
3
|
+
class Anoubis::Tenant::MenuLocale < Anoubis::Core::ApplicationRecord
|
4
|
+
# Redefines default table name
|
5
|
+
self.table_name = 'menu_locales'
|
6
|
+
|
7
|
+
# @!attribute menu
|
8
|
+
# @return [Menu] reference to the {Menu} model
|
9
|
+
belongs_to :menu, :class_name => 'Anoubis::Tenant::Menu'
|
10
|
+
validates :menu, presence: true, uniqueness: { scope: [:locale] }
|
11
|
+
|
12
|
+
# @!attribute title
|
13
|
+
# @return [String] the menu's localized title
|
14
|
+
validates :title, presence: true, length: { minimum: 3, maximum: 100 }
|
15
|
+
|
16
|
+
# @!attribute page_title
|
17
|
+
# @return [String] the menu's localized page title. Uses in frontend application.
|
18
|
+
validates :page_title, presence: true, length: { minimum: 3, maximum: 200 }
|
19
|
+
|
20
|
+
# @!attribute short_title
|
21
|
+
# @return [String] the menu's localized short title. Uses in frontend application.
|
22
|
+
validates :short_title, length: { maximum: 200 }
|
23
|
+
|
24
|
+
# @!attribute locale
|
25
|
+
# @return [Locales] reference to locale
|
26
|
+
enum locale: Anoubis::Core::Locales.enums
|
27
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
##
|
2
|
+
# System model. Stores information about all portal's systems.
|
3
|
+
class Anoubis::Tenant::System < Anoubis::Core::ApplicationRecord
|
4
|
+
# Redefines default table name
|
5
|
+
self.table_name = 'systems'
|
6
|
+
|
7
|
+
before_validation :before_validation_system_create, on: :create
|
8
|
+
before_validation :before_validation_system_update, on: :update
|
9
|
+
after_create :after_create_system
|
10
|
+
before_save :before_save_system
|
11
|
+
after_update :after_update_system
|
12
|
+
before_destroy :before_destroy_system
|
13
|
+
|
14
|
+
# System's identifier consists of lowercase alphabetic symbols.
|
15
|
+
VALID_SYSTEM_REGEX = /[a-z]\z/i
|
16
|
+
|
17
|
+
# @!attribute ident
|
18
|
+
# @return [String] the system's identifier. Identifier consists of lowercase alphabetical symbols.
|
19
|
+
validates :ident, length: { minimum: 3, maximum: 15 }, uniqueness: true, format: { with: VALID_SYSTEM_REGEX }
|
20
|
+
|
21
|
+
has_many :tenant_systems, class_name: 'Anoubis::Tenant::TenantSystem'
|
22
|
+
has_many :groups, class_name: 'Anoubis::Tenant::Group'
|
23
|
+
has_many :system_menus, class_name: 'Anoubis::Tenant::SystemMenu'
|
24
|
+
has_many :system_locales, class_name: 'Anoubis::Tenant::SystemLocale'
|
25
|
+
|
26
|
+
##
|
27
|
+
# Is called before validation when new system is being created. If it's a first system then it sets {#ident}
|
28
|
+
# value to 'sys'
|
29
|
+
def before_validation_system_create
|
30
|
+
if self.id
|
31
|
+
if self.id == 1
|
32
|
+
self.ident = 'sys'
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Is called before validation when system is being updated. Prevents the changing {#ident} value for
|
40
|
+
# system with id 1.
|
41
|
+
def before_validation_system_update
|
42
|
+
if self.id == 1 && self.ident_was != self.ident
|
43
|
+
errors.add(:ident, I18n.t('anubis.systems.errors.cant_change_ident'))
|
44
|
+
throw(:abort, __method__)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Is called after new system was created. Creates administration group for new system.
|
50
|
+
def after_create_system
|
51
|
+
if self.id == 1
|
52
|
+
data = Anoubis::Tenant::Group.create(id: 1)
|
53
|
+
I18n.available_locales.each do |locale|
|
54
|
+
I18n.locale = locale
|
55
|
+
Anoubis::Tenant::GroupLocale.find_or_create_by(group_id: data.id, locale: Anoubis::Tenant::MenuLocale.locales[locale.to_s.to_sym]) do |system_locale|
|
56
|
+
system_locale.title = I18n.t('anubis.install.admins_group')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
else
|
60
|
+
data = Anoubis::Tenant::Group.find_or_create_by(ident: 'admin', system_id: self.id)
|
61
|
+
I18n.available_locales.each do |locale|
|
62
|
+
I18n.locale = locale
|
63
|
+
Anubis::Tenant::GroupLocale.find_or_create_by(group_id: data.id, locale: Anubis::Tenant::MenuLocale.locales[locale.to_s.to_sym]) do |system_locale|
|
64
|
+
system_locale.title = I18n.t('anubis.install.admins_group')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Is called before system will be stored in database. Changes {#ident} value to lower case.
|
72
|
+
def before_save_system
|
73
|
+
self.ident = self.ident.downcase if self.ident
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Is called after system had been updated. If {#ident} value had been changed then procedure updates
|
78
|
+
# every {Anubis::Group#full_ident} value.
|
79
|
+
def after_update_system
|
80
|
+
if self.ident_was != self.ident
|
81
|
+
update_groups_full_ident self.id, self.ident
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Is called before system will be deleted from database. Checks the ability to destroy a system. Delete
|
87
|
+
# all translations for system model from {GroupLocale}.
|
88
|
+
def before_destroy_system
|
89
|
+
if self.id == 1
|
90
|
+
errors.add(:base, I18n.t('anubis.tenants.errors.cant_destroy'))
|
91
|
+
throw(:abort, __method__)
|
92
|
+
end
|
93
|
+
|
94
|
+
Anubis::Tenant::SystemLocale.where(system_id: self.id).each do |system_locale|
|
95
|
+
system_locale.destroy
|
96
|
+
end
|
97
|
+
|
98
|
+
if !can_destroy?
|
99
|
+
errors.add(:base, I18n.t('anubis.tenants.errors.has_childs'))
|
100
|
+
throw(:abort, __method__)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Updates {Group#full_ident} when changed system's identifier.
|
106
|
+
# @param id [Integer] group unique identifier
|
107
|
+
# @param ident [String] new system identifier
|
108
|
+
def update_groups_full_ident (id, ident)
|
109
|
+
query = <<-SQL
|
110
|
+
UPDATE groups SET groups.full_ident = CONCAT('#{ident}.', groups.ident) WHERE groups.system_id = #{id}
|
111
|
+
SQL
|
112
|
+
Anubis::Tenant::Group.connection.execute query
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Returns model localization data from {SystemLocale}.
|
117
|
+
# @return [SystemLocale] localization for current system
|
118
|
+
def model_locale
|
119
|
+
@model_locale ||= self.system_locales.where(locale: Anubis::Tenant::SystemLocale.locales[self.current_locale.to_sym]).first
|
120
|
+
end
|
121
|
+
|
122
|
+
# @!attribute title
|
123
|
+
# @return [String] the system's title. Title loads from {SystemLocale#title} based on {#current_locale}
|
124
|
+
def title
|
125
|
+
self.model_locale.title if self.model_locale
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
##
|
2
|
+
# Localization for {System} model. Model stores all translations for {System} model.
|
3
|
+
class Anoubis::Tenant::SystemLocale < Anoubis::Core::ApplicationRecord
|
4
|
+
# Redefines default table name
|
5
|
+
self.table_name = 'system_locales'
|
6
|
+
|
7
|
+
# @!attribute title
|
8
|
+
# @return [String] the system's localized title
|
9
|
+
validates :title, length: { minimum: 3, maximum: 100 }, uniqueness: { scope: [:system_id, :locale] }
|
10
|
+
|
11
|
+
# @!attribute system
|
12
|
+
# @return [System] reference to the {System} model
|
13
|
+
belongs_to :system, :class_name => 'Anoubis::Tenant::System'
|
14
|
+
validates :system, presence: true, uniqueness: { scope: [:locale] }
|
15
|
+
|
16
|
+
# @!attribute locale
|
17
|
+
# @return [Locales] reference to locale
|
18
|
+
enum locale: Anoubis::Core::Locales.enums
|
19
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
##
|
2
|
+
# Model links menu and systems. Describes if system has access to menu.
|
3
|
+
class Anoubis::Tenant::SystemMenu < Anoubis::Core::ApplicationRecord
|
4
|
+
# Redefines default table name
|
5
|
+
self.table_name = 'system_menus'
|
6
|
+
|
7
|
+
after_create :after_create_system_menu
|
8
|
+
after_destroy :after_destroy_system_menu
|
9
|
+
|
10
|
+
# @!attribute system
|
11
|
+
# @return [System] reference to the {System} model
|
12
|
+
belongs_to :system, class_name: 'Anoubis::Tenant::System'
|
13
|
+
validates :system, presence: true, uniqueness: { scope: [:menu_id] }
|
14
|
+
|
15
|
+
# @!attribute menu
|
16
|
+
# @return [Menu] reference to the {Menu} model
|
17
|
+
belongs_to :menu, class_name: 'Anoubis::Tenant::Menu'
|
18
|
+
validates :menu, presence: true, uniqueness: { scope: [:system_id] }
|
19
|
+
|
20
|
+
##
|
21
|
+
# Is called after create new link between system and menu. If created element has parent element and
|
22
|
+
# link to this parent element doesn't present in database then adds this link too.
|
23
|
+
def after_create_system_menu
|
24
|
+
if self.menu.menu_id != nil
|
25
|
+
Anoubis::Tenant::SystemMenu.find_or_create_by(menu: self.menu.menu, system: self.system)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Is called after link between system and menu was deleted from database. It also deletes all child links.
|
31
|
+
def after_destroy_system_menu
|
32
|
+
ids = []
|
33
|
+
|
34
|
+
Anoubis::Tenant::Menu.where(menu_id: self.menu_id).each do |data|
|
35
|
+
ids.push data.id
|
36
|
+
end
|
37
|
+
|
38
|
+
Anoubis::Tenant::SystemMenu.where(menu_id: ids, system_id: self.system_id).each do |data|
|
39
|
+
data.destroy
|
40
|
+
end
|
41
|
+
|
42
|
+
ids = []
|
43
|
+
Anoubis::Tenant::Group.where(system_id: self.system_id).each do |data|
|
44
|
+
ids.push data.id
|
45
|
+
end
|
46
|
+
|
47
|
+
Anoubis::Tenant::GroupMenu.where(menu_id: self.menu_id, group_id: ids).each do |data|
|
48
|
+
data.destroy
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
##
|
2
|
+
# Tenant model. Stores information about all portal's tenants.
|
3
|
+
class Anoubis::Tenant::Tenant < Anoubis::Core::ApplicationRecord
|
4
|
+
# Redefines default table name
|
5
|
+
self.table_name = 'tenants'
|
6
|
+
|
7
|
+
before_validation :before_validation_tenant_create, on: :create
|
8
|
+
before_validation :before_validation_tenant_update, on: :update
|
9
|
+
before_save :before_save_tenant
|
10
|
+
after_create :after_create_tenant
|
11
|
+
after_update :after_update_tenant
|
12
|
+
before_destroy :before_destroy_tenant
|
13
|
+
|
14
|
+
# Tenant's identifier consists of lowercase alphabetic symbols.
|
15
|
+
VALID_TENANT_REGEX = /[a-z]\z/i
|
16
|
+
|
17
|
+
# @!attribute ident
|
18
|
+
# @return [String] the tenant's identifier. Identifier consists of lowercase alphabetical symbols.
|
19
|
+
validates :ident, length: { minimum: 3, maximum: 10 }, uniqueness: true, format: { with: VALID_TENANT_REGEX }
|
20
|
+
|
21
|
+
# @!attribute title
|
22
|
+
# @return [String] the tenant's title
|
23
|
+
validates :title, length: { minimum: 5, maximum: 100 }, uniqueness: true
|
24
|
+
|
25
|
+
# @!attribute state
|
26
|
+
# @return ['standard', 'default'] the tenant's status.
|
27
|
+
# - 'default' --- tenant is marked as default (only one tenant may be default)
|
28
|
+
# - 'standard' --- tenant is marked as standard
|
29
|
+
enum state: { standard: 0, default: 1 }
|
30
|
+
|
31
|
+
has_many :tenant_systems, class_name: 'Anoubis::Tenant::TenantSystem'
|
32
|
+
|
33
|
+
##
|
34
|
+
# Is called before validation when new tenant is being created. If it's a first tenant then it sets {#ident}
|
35
|
+
# value to 'sys'
|
36
|
+
def before_validation_tenant_create
|
37
|
+
if self.id
|
38
|
+
if self.id == 1
|
39
|
+
self.ident = 'sys'
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Is called before validation when tenant is being updated. Prevents the changing {#ident} value.
|
47
|
+
def before_validation_tenant_update
|
48
|
+
if self.id == 1 && self.ident != self.ident_was
|
49
|
+
errors.add(:ident, I18n.t('anubis.tenants.errors.cant_change_ident'))
|
50
|
+
throw(:abort, __method__)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Is called after new tenant was created. Adds access for this tenant to main system with id 1.
|
56
|
+
def after_create_tenant
|
57
|
+
Anoubis::Tenant::TenantSystem.find_or_create_by(tenant_id: self.id, system_id: 1) if self.id != 1
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Is called after tenant had been updated. If {#ident} value had been changed then procedure updates
|
62
|
+
# every {Anoubis::User#login} value.
|
63
|
+
# Also if current tenant {#state} value had been set as 'default', then procedure sets {#state}
|
64
|
+
# value of all other tenants as 'standard'.
|
65
|
+
def after_update_tenant
|
66
|
+
if self.ident_was != self.ident
|
67
|
+
self.update_users_login self.id, self.ident
|
68
|
+
end
|
69
|
+
|
70
|
+
# If current tenant had been set as 'default', then sets all other tenants as 'standard'.
|
71
|
+
if self.state != self.state_was && self.state = 'default'
|
72
|
+
Anoubis::Tenant::Tenant.where(state: Anoubis::Tenant::Tenant.states[:default]).update_all(state: Anoubis::Tenant::Tenant.states[:standard])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Is called before tenant will be stored in database. Changes {#ident} value to lower case.
|
78
|
+
def before_save_tenant
|
79
|
+
self.ident = self.ident.downcase if self.ident
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Is called before tenant will be deleted from database. Checks the ability to destroy a tenant.
|
84
|
+
def before_destroy_tenant
|
85
|
+
if self.id == 1
|
86
|
+
errors.add(:base, I18n.t('anubis.tenants.errors.cant_destroy'))
|
87
|
+
throw(:abort, __method__)
|
88
|
+
end
|
89
|
+
|
90
|
+
if !can_destroy?
|
91
|
+
errors.add(:base, I18n.t('anubis.tenants.errors.has_childs'))
|
92
|
+
throw(:abort, __method__)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Changes every {User#login} value based on {#ident} value. Procedure makes direct update
|
98
|
+
# in database and doesn't call any callbacks of {Anoubis::Tenant::User} model.
|
99
|
+
# @param id [Integer] user unique identifier
|
100
|
+
# @param ident [String] new tenant identifier
|
101
|
+
def update_users_login (id, ident)
|
102
|
+
query = <<-SQL
|
103
|
+
UPDATE users SET users.login = CONCAT(users.email, '.#{ident}') WHERE users.tenant_id = #{id}
|
104
|
+
SQL
|
105
|
+
Anoubis::Tenant::User.connection.execute query
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
##
|
2
|
+
# Model for links Tenant and System models
|
3
|
+
class Anoubis::Tenant::TenantSystem < ApplicationRecord
|
4
|
+
self.table_name = 'tenant_systems'
|
5
|
+
|
6
|
+
before_update :before_update_tenant_system
|
7
|
+
|
8
|
+
belongs_to :tenant, class_name: 'Anoubis::Tenant::Tenant'
|
9
|
+
validates :tenant, presence: true, uniqueness: { scope: [:system_id] }
|
10
|
+
belongs_to :system, class_name: 'Anoubis::Tenant::System'
|
11
|
+
validates :system, presence: true, uniqueness: { scope: [:tenant_id] }
|
12
|
+
|
13
|
+
##
|
14
|
+
# Checks before update data in model. Prevents from changing element data
|
15
|
+
def before_update_tenant_system
|
16
|
+
self.tenant_id = self.tenant_id_was if self.tenant_id_changed?
|
17
|
+
self.system_id = self.system_id_was if self.system_id_changed?
|
18
|
+
end
|
19
|
+
end
|