uffizzi_core 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/forms/uffizzi_core/api/cli/v1/compose_file/create_form.rb +0 -2
  3. data/app/lib/uffizzi_core/concerns/models/account.rb +84 -0
  4. data/app/lib/uffizzi_core/concerns/models/activity_item.rb +39 -0
  5. data/app/lib/uffizzi_core/concerns/models/build.rb +47 -0
  6. data/app/lib/uffizzi_core/concerns/models/comment.rb +20 -0
  7. data/app/lib/uffizzi_core/concerns/models/compose_file.rb +60 -0
  8. data/app/lib/uffizzi_core/concerns/models/config_file.rb +21 -0
  9. data/app/lib/uffizzi_core/concerns/models/container.rb +95 -0
  10. data/app/lib/uffizzi_core/concerns/models/container_config_file.rb +12 -0
  11. data/app/lib/uffizzi_core/concerns/models/coupon.rb +9 -0
  12. data/app/lib/uffizzi_core/concerns/models/credential.rb +65 -0
  13. data/app/lib/uffizzi_core/concerns/models/deployment.rb +71 -0
  14. data/app/lib/uffizzi_core/concerns/models/event.rb +17 -0
  15. data/app/lib/uffizzi_core/concerns/models/invitation.rb +31 -0
  16. data/app/lib/uffizzi_core/concerns/models/membership.rb +20 -0
  17. data/app/lib/uffizzi_core/concerns/models/payment.rb +15 -0
  18. data/app/lib/uffizzi_core/concerns/models/price.rb +13 -0
  19. data/app/lib/uffizzi_core/concerns/models/product.rb +15 -0
  20. data/app/lib/uffizzi_core/concerns/models/project.rb +62 -0
  21. data/app/lib/uffizzi_core/concerns/models/rating.rb +24 -0
  22. data/app/lib/uffizzi_core/concerns/models/repo.rb +33 -0
  23. data/app/lib/uffizzi_core/concerns/models/role.rb +21 -0
  24. data/app/lib/uffizzi_core/concerns/models/secret.rb +13 -0
  25. data/app/lib/uffizzi_core/concerns/models/template.rb +23 -0
  26. data/app/lib/uffizzi_core/concerns/models/user.rb +66 -0
  27. data/app/lib/uffizzi_core/concerns/models/user_project.rb +18 -0
  28. data/app/models/uffizzi_core/account.rb +1 -79
  29. data/app/models/uffizzi_core/activity_item.rb +1 -31
  30. data/app/models/uffizzi_core/build.rb +1 -35
  31. data/app/models/uffizzi_core/comment.rb +1 -12
  32. data/app/models/uffizzi_core/compose_file.rb +1 -44
  33. data/app/models/uffizzi_core/config_file.rb +1 -13
  34. data/app/models/uffizzi_core/container.rb +1 -85
  35. data/app/models/uffizzi_core/container_config_file.rb +1 -4
  36. data/app/models/uffizzi_core/coupon.rb +1 -1
  37. data/app/models/uffizzi_core/credential.rb +1 -57
  38. data/app/models/uffizzi_core/deployment.rb +1 -63
  39. data/app/models/uffizzi_core/event.rb +1 -9
  40. data/app/models/uffizzi_core/invitation.rb +1 -23
  41. data/app/models/uffizzi_core/membership.rb +1 -12
  42. data/app/models/uffizzi_core/payment.rb +1 -7
  43. data/app/models/uffizzi_core/price.rb +1 -5
  44. data/app/models/uffizzi_core/product.rb +1 -7
  45. data/app/models/uffizzi_core/project.rb +1 -54
  46. data/app/models/uffizzi_core/rating.rb +1 -16
  47. data/app/models/uffizzi_core/repo.rb +1 -25
  48. data/app/models/uffizzi_core/role.rb +1 -13
  49. data/app/models/uffizzi_core/secret.rb +1 -5
  50. data/app/models/uffizzi_core/template.rb +1 -15
  51. data/app/models/uffizzi_core/user.rb +1 -58
  52. data/app/models/uffizzi_core/user_project.rb +1 -10
  53. data/app/repositories/uffizzi_core/template_repo.rb +14 -6
  54. data/lib/uffizzi_core/version.rb +1 -1
  55. data/lib/uffizzi_core.rb +2 -0
  56. metadata +27 -2
@@ -20,67 +20,5 @@
20
20
  # @property deployed_by [object]
21
21
 
22
22
  class UffizziCore::Deployment < UffizziCore::ApplicationRecord
23
- include AASM
24
- include UffizziCore::StateMachineConcern
25
- include UffizziCore::DeploymentRepo
26
- extend Enumerize
27
-
28
- self.table_name = UffizziCore.table_names[:deployments]
29
-
30
- enumerize :kind, in: [:standard, :performance, :enterprise, :free], predicates: true, default: :standard
31
-
32
- belongs_to :project, touch: true
33
- belongs_to :deployed_by, class_name: UffizziCore::User.name, foreign_key: :deployed_by_id, optional: true
34
- belongs_to :template, optional: true
35
- belongs_to :compose_file, optional: true
36
-
37
- has_many :credentials, through: :project
38
- has_many :containers, dependent: :destroy, index_errors: true
39
- has_many :activity_items, dependent: :destroy
40
-
41
- has_one :ingress_container, -> { where(receive_incoming_requests: true) }, class_name: UffizziCore::Container.name
42
-
43
- validates :kind, presence: true
44
-
45
- enumerize :creation_source, in: [:manual, :continuous_preview, :compose_file_manual, :compose_file_continuous_preview], predicates: true,
46
- scope: true, default: :manual
47
-
48
- accepts_nested_attributes_for :containers, allow_destroy: true
49
-
50
- after_destroy_commit :clean
51
-
52
- def active_containers
53
- containers.active
54
- end
55
-
56
- aasm(:state) do
57
- state :active, initial: true
58
- state :failed
59
- state :disabled
60
-
61
- event :activate do
62
- transitions from: [:disabled], to: :active
63
- end
64
-
65
- event :fail, after: :after_fail do
66
- transitions from: [:active], to: :failed
67
- end
68
-
69
- event :disable, after: :after_disable do
70
- transitions from: [:active, :failed], to: :disabled
71
- end
72
- end
73
-
74
- def after_disable
75
- clean
76
- end
77
-
78
- def after_fail
79
- active_containers.each(&:disable!)
80
- end
81
-
82
- def clean
83
- active_containers.each(&:disable!)
84
- UffizziCore::Deployment::DeleteJob.perform_async(id)
85
- end
23
+ include UffizziCore::Concerns::Models::Deployment
86
24
  end
@@ -1,13 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Event < UffizziCore::ApplicationRecord
4
- include UffizziCore::EventRepo
5
- extend Enumerize
6
-
7
- self.table_name = UffizziCore.table_names[:events]
8
-
9
- enumerize :state, in: [:queued, :successful, :deployed, :failed, :building, :timeout, :cancelled, :deploying], predicates: true,
10
- scope: true
11
-
12
- belongs_to :activity_item, touch: true
4
+ include UffizziCore::Concerns::Models::Event
13
5
  end
@@ -1,27 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Invitation < UffizziCore::ApplicationRecord
4
- include AASM
5
- include UffizziCore::StateMachineConcern
6
- extend Enumerize
7
-
8
- self.table_name = UffizziCore.table_names[:invitations]
9
-
10
- enumerize :role, in: [:admin, :developer, :viewer], predicates: true
11
-
12
- belongs_to :entityable, polymorphic: true
13
- belongs_to :invited_by, class_name: UffizziCore::User.name, foreign_key: :invited_by_id
14
- belongs_to :invitee, class_name: UffizziCore::User.name, foreign_key: :invitee_id, optional: true
15
-
16
- validates :email, presence: true, 'uffizzi_core/email': true
17
- validates :token, presence: true, uniqueness: true
18
-
19
- aasm(:status) do
20
- state :pending, initial: true
21
- state :accepted
22
-
23
- event :accept do
24
- transitions from: :pending, to: :accepted
25
- end
26
- end
4
+ include UffizziCore::Concerns::Models::Invitation
27
5
  end
@@ -1,16 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Membership < UffizziCore::ApplicationRecord
4
- include UffizziCore::MembershipRepo
5
- extend Enumerize
6
-
7
- self.table_name = UffizziCore.table_names[:memberships]
8
-
9
- enumerize :role, in: [:admin, :developer, :viewer], predicates: true
10
- validates :role, presence: true
11
-
12
- belongs_to :account
13
- belongs_to :user
14
-
15
- validates :role, presence: true
4
+ include UffizziCore::Concerns::Models::Membership
16
5
  end
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Payment < UffizziCore::ApplicationRecord
4
- self.table_name = UffizziCore.table_names[:payments]
5
-
6
- belongs_to :account
7
-
8
- scope :succeeded, -> { where(status: :succeeded) }
9
- scope :pending, -> { where(status: :pending) }
10
- scope :failed, -> { where(status: :failed) }
4
+ include UffizziCore::Concerns::Models::Payment
11
5
  end
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Price < UffizziCore::ApplicationRecord
4
- include UffizziCore::PriceRepo
5
-
6
- self.table_name = UffizziCore.table_names[:prices]
7
-
8
- belongs_to :product
4
+ include UffizziCore::Concerns::Models::Price
9
5
  end
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Product < UffizziCore::ApplicationRecord
4
- include UffizziCore::ProductRepo
5
-
6
- self.table_name = UffizziCore.table_names[:products]
7
-
8
- has_one :price, dependent: :destroy
9
-
10
- UffizziCore::Product.inheritance_column = :sti
4
+ include UffizziCore::Concerns::Models::Product
11
5
  end
@@ -10,58 +10,5 @@
10
10
  # @property deployments [object<id: integer, domain: string>]
11
11
 
12
12
  class UffizziCore::Project < UffizziCore::ApplicationRecord
13
- include AASM
14
- include UffizziCore::StateMachineConcern
15
- include UffizziCore::ProjectRepo
16
-
17
- self.table_name = UffizziCore.table_names[:projects]
18
-
19
- belongs_to :account
20
-
21
- has_many :repos
22
- has_many :deployments, dependent: :destroy
23
- has_many :user_projects, dependent: :destroy
24
- has_many :users, through: :user_projects
25
- has_many :invitations, as: :entityable
26
- has_many :config_files, dependent: :destroy
27
- has_many :templates, dependent: :destroy
28
- has_many :credentials, through: :account
29
- has_many :compose_files, dependent: :destroy
30
- has_many :secrets, dependent: :destroy, as: :resource
31
-
32
- validates :name, presence: true, uniqueness: { scope: :account, message: 'Name already exists' }
33
- validates :slug, presence: true, uniqueness: { message: 'Project slug already taken' }
34
-
35
- aasm(:state) do
36
- state :active, initial: true
37
- state :disabled
38
-
39
- event :activate do
40
- transitions from: [:disabled], to: :active
41
- end
42
-
43
- event :disable, after: :after_disable do
44
- transitions from: [:active], to: :disabled
45
- end
46
- end
47
-
48
- def after_disable
49
- update(name: "#{name} deleted #{DateTime.current.strftime('%H:%M:%S-%m%d%Y')}")
50
- update(slug: "#{slug} deleted #{DateTime.current.strftime('%H:%M:%S-%m%d%Y')}")
51
- disable_deployments
52
- end
53
-
54
- def active_deployments
55
- deployments.active
56
- end
57
-
58
- def disable_deployments
59
- active_deployments.each do |deployment|
60
- UffizziCore::DeploymentService.disable!(deployment)
61
- end
62
- end
63
-
64
- def compose_file
65
- compose_files.main.first
66
- end
13
+ include UffizziCore::Concerns::Models::Project
67
14
  end
@@ -1,20 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Rating < UffizziCore::ApplicationRecord
4
- include AASM
5
-
6
- self.table_name = UffizziCore.table_names[:ratings]
7
-
8
- aasm(:state) do
9
- state :active, initial: true
10
- state :disabled
11
-
12
- event :activate do
13
- transitions from: [:disabled], to: :active
14
- end
15
-
16
- event :disable do
17
- transitions from: [:active], to: :disabled
18
- end
19
- end
4
+ include UffizziCore::Concerns::Models::Rating
20
5
  end
@@ -1,29 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Repo < UffizziCore::ApplicationRecord
4
- extend Enumerize
5
- include UffizziCore::RepoRepo
6
-
7
- self.table_name = UffizziCore.table_names[:repos]
8
-
9
- enumerize :kind, in: [:buildpacks18, :dockerfile, :dotnet, :gatsby, :barestatic], predicates: true
10
-
11
- belongs_to :project
12
- has_one :container, inverse_of: :repo, dependent: :destroy
13
- has_many :builds, dependent: :destroy
14
-
15
- validates :dockerfile_path, presence: true, if: :dockerfile?
16
- validates :delete_preview_after, numericality: { greater_than: 0, only_integer: true }, allow_nil: true
17
-
18
- def docker_hub?
19
- type == UffizziCore::Repo::DockerHub.name
20
- end
21
-
22
- def azure?
23
- type == UffizziCore::Repo::Azure.name
24
- end
25
-
26
- def google?
27
- type == UffizziCore::Repo::Google.name
28
- end
4
+ include UffizziCore::Concerns::Models::Repo
29
5
  end
@@ -1,17 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Role < UffizziCore::ApplicationRecord
4
- self.table_name = UffizziCore.table_names[:roles]
5
-
6
- has_and_belongs_to_many :users, join_table: UffizziCore.table_names[:users_roles]
7
-
8
- belongs_to :resource,
9
- polymorphic: true,
10
- optional: true
11
-
12
- validates :resource_type,
13
- inclusion: { in: Rolify.resource_types },
14
- allow_nil: true
15
-
16
- scopify
4
+ include UffizziCore::Concerns::Models::Role
17
5
  end
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Secret < ApplicationRecord
4
- self.table_name = UffizziCore.table_names[:secrets]
5
-
6
- belongs_to :resource, polymorphic: true
7
-
8
- validates :name, presence: true, uniqueness: { scope: :resource }
4
+ include UffizziCore::Concerns::Models::Secret
9
5
  end
@@ -1,19 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Template < UffizziCore::ApplicationRecord
4
- include UffizziCore::TemplateRepo
5
- extend Enumerize
6
-
7
- self.table_name = UffizziCore.table_names[:templates]
8
-
9
- belongs_to :added_by, class_name: UffizziCore::User.name, foreign_key: :added_by_id
10
- belongs_to :project, touch: true
11
- belongs_to :compose_file, optional: true
12
-
13
- has_many :deployments, dependent: :nullify
14
-
15
- enumerize :creation_source, in: [:manual, :compose_file, :system], predicates: true, scope: true
16
-
17
- validates :name, presence: true
18
- validates :name, uniqueness: { scope: :project }, if: -> { compose_file.blank? || compose_file.kind.main? }
4
+ include UffizziCore::Concerns::Models::Template
19
5
  end
@@ -1,62 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::User < ActiveRecord::Base
4
- include AASM
5
- include ActiveModel::Validations
6
- include UffizziCore::StateMachineConcern
7
- include UffizziCore::HashidConcern
8
- include UffizziCore::UserRepo
9
- extend Enumerize
10
-
11
- self.table_name = UffizziCore.table_names[:users]
12
-
13
- rolify
14
-
15
- has_secure_password
16
-
17
- validates :email, presence: true, 'uffizzi_core/email': true, uniqueness: { case_sensitive: false }
18
- validates :password, allow_nil: true, length: { minimum: 8 }, on: :update
19
-
20
- has_many :memberships, dependent: :destroy
21
- has_many :accounts, through: :memberships
22
- has_many :user_projects
23
- has_many :projects, through: :user_projects
24
-
25
- has_one_attached :avatar
26
-
27
- enumerize :creation_source, in: [:system, :online_registration, :google, :sso], predicates: true
28
-
29
- def organizational_account
30
- accounts.find_by(kind: UffizziCore::Account.kind.organizational)
31
- end
32
-
33
- def active_projects
34
- projects.active
35
- end
36
-
37
- def deployments
38
- UffizziCore::Deployment.where(project_id: active_projects)
39
- end
40
-
41
- def full_name
42
- "#{first_name} #{last_name}"
43
- end
44
-
45
- aasm(:state) do
46
- state :initial, initial: true
47
- state :active
48
- state :disabled
49
-
50
- event :activate do
51
- transitions from: [:initial, :disabled], to: :active
52
- end
53
-
54
- event :disable do
55
- transitions from: [:initial, :active], to: :disabled
56
- end
57
- end
58
-
59
- def admin_access_to_project?(project)
60
- projects.by_ids(project).by_accounts(memberships.by_role_admin.select(:account_id)).exists?
61
- end
4
+ include UffizziCore::Concerns::Models::User
62
5
  end
@@ -1,14 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::UserProject < UffizziCore::ApplicationRecord
4
- extend Enumerize
5
-
6
- self.table_name = UffizziCore.table_names[:user_projects]
7
-
8
- enumerize :role, in: [:admin, :developer, :viewer], predicates: true
9
- validates :role, presence: true
10
-
11
- belongs_to :user
12
- belongs_to :project
13
- belongs_to :invited_by, class_name: UffizziCore::User.name, foreign_key: :invited_by_id, optional: true
4
+ include UffizziCore::Concerns::Models::UserProject
14
5
  end
@@ -30,7 +30,7 @@ module UffizziCore::TemplateRepo
30
30
  ],
31
31
  }
32
32
 
33
- where('payload @> ?', general_query.to_json).where.not('payload @> ?', excluding_query.to_json)
33
+ where('templates.payload @> ?', general_query.to_json).where.not('templates.payload @> ?', excluding_query.to_json)
34
34
  }
35
35
 
36
36
  scope :by_docker_containers_with_delete_preview_when_image_tag_is_updated, ->(source, image, tag) {
@@ -47,7 +47,7 @@ module UffizziCore::TemplateRepo
47
47
  ],
48
48
  }
49
49
 
50
- where('payload @> ?', general_query.to_json)
50
+ where('templates.payload @> ?', general_query.to_json)
51
51
  }
52
52
 
53
53
  scope :by_github_containers_with_deploy_preview_when_pull_request_is_opened, ->(repository_id, branch) {
@@ -55,7 +55,7 @@ module UffizziCore::TemplateRepo
55
55
  containers_attributes: [
56
56
  {
57
57
  repo_attributes: {
58
- type: Repo::Github.name,
58
+ type: UffizziCore::Repo::Github.name,
59
59
  repository_id: repository_id,
60
60
  branch: branch,
61
61
  deploy_preview_when_pull_request_is_opened: true,
@@ -64,7 +64,7 @@ module UffizziCore::TemplateRepo
64
64
  ],
65
65
  }
66
66
 
67
- where('payload @> ?', query.to_json)
67
+ where('templates.payload @> ?', query.to_json)
68
68
  }
69
69
 
70
70
  scope :by_github_containers_with_delete_preview_when_pull_request_is_closed, ->(repository_id, branch) {
@@ -72,7 +72,7 @@ module UffizziCore::TemplateRepo
72
72
  containers_attributes: [
73
73
  {
74
74
  repo_attributes: {
75
- type: Repo::Github.name,
75
+ type: UffizziCore::Repo::Github.name,
76
76
  repository_id: repository_id,
77
77
  branch: branch,
78
78
  delete_preview_when_pull_request_is_closed: true,
@@ -81,7 +81,15 @@ module UffizziCore::TemplateRepo
81
81
  ],
82
82
  }
83
83
 
84
- where('payload @> ?', query.to_json)
84
+ where('templates.payload @> ?', query.to_json)
85
+ }
86
+
87
+ scope :by_compose_file_kind, ->(kind) {
88
+ left_joins(:compose_file).where(compose_files: { kind: kind })
89
+ }
90
+
91
+ scope :without_compose, -> {
92
+ left_joins(:compose_file).where(compose_files: { id: nil })
85
93
  }
86
94
  end
87
95
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UffizziCore
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.1'
5
5
  end
data/lib/uffizzi_core.rb CHANGED
@@ -58,4 +58,6 @@ module UffizziCore
58
58
  users: :uffizzi_core_users,
59
59
  users_roles: :uffizzi_core_users_roles,
60
60
  }
61
+ mattr_accessor :user_creation_sources, default: [:system, :online_registration, :google, :sso]
62
+ mattr_accessor :user_project_roles, default: [:admin, :developer, :viewer]
61
63
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uffizzi_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Thurman
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-06-07 00:00:00.000000000 Z
12
+ date: 2022-06-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aasm
@@ -759,6 +759,31 @@ files:
759
759
  - app/jobs/uffizzi_core/deployment/delete_job.rb
760
760
  - app/jobs/uffizzi_core/deployment/deploy_containers_job.rb
761
761
  - app/jobs/uffizzi_core/deployment/manage_deploy_activity_item_job.rb
762
+ - app/lib/uffizzi_core/concerns/models/account.rb
763
+ - app/lib/uffizzi_core/concerns/models/activity_item.rb
764
+ - app/lib/uffizzi_core/concerns/models/build.rb
765
+ - app/lib/uffizzi_core/concerns/models/comment.rb
766
+ - app/lib/uffizzi_core/concerns/models/compose_file.rb
767
+ - app/lib/uffizzi_core/concerns/models/config_file.rb
768
+ - app/lib/uffizzi_core/concerns/models/container.rb
769
+ - app/lib/uffizzi_core/concerns/models/container_config_file.rb
770
+ - app/lib/uffizzi_core/concerns/models/coupon.rb
771
+ - app/lib/uffizzi_core/concerns/models/credential.rb
772
+ - app/lib/uffizzi_core/concerns/models/deployment.rb
773
+ - app/lib/uffizzi_core/concerns/models/event.rb
774
+ - app/lib/uffizzi_core/concerns/models/invitation.rb
775
+ - app/lib/uffizzi_core/concerns/models/membership.rb
776
+ - app/lib/uffizzi_core/concerns/models/payment.rb
777
+ - app/lib/uffizzi_core/concerns/models/price.rb
778
+ - app/lib/uffizzi_core/concerns/models/product.rb
779
+ - app/lib/uffizzi_core/concerns/models/project.rb
780
+ - app/lib/uffizzi_core/concerns/models/rating.rb
781
+ - app/lib/uffizzi_core/concerns/models/repo.rb
782
+ - app/lib/uffizzi_core/concerns/models/role.rb
783
+ - app/lib/uffizzi_core/concerns/models/secret.rb
784
+ - app/lib/uffizzi_core/concerns/models/template.rb
785
+ - app/lib/uffizzi_core/concerns/models/user.rb
786
+ - app/lib/uffizzi_core/concerns/models/user_project.rb
762
787
  - app/lib/uffizzi_core/rbac/user_access_service.rb
763
788
  - app/mailers/uffizzi_core/application_mailer.rb
764
789
  - app/models/concerns/uffizzi_core/hashid_concern.rb