mno-enterprise-core 2.0.0
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 +7 -0
- data/LICENSE +1 -0
- data/Rakefile +12 -0
- data/app/assets/images/mno_enterprise/main-logo.png +0 -0
- data/app/controllers/mno_enterprise/application_controller.rb +116 -0
- data/app/helpers/mno_enterprise/application_helper.rb +67 -0
- data/app/helpers/mno_enterprise/impersonate_helper.rb +27 -0
- data/app/models/mno_enterprise/ability.rb +6 -0
- data/app/models/mno_enterprise/app.rb +72 -0
- data/app/models/mno_enterprise/app_instance.rb +36 -0
- data/app/models/mno_enterprise/app_instances_sync.rb +6 -0
- data/app/models/mno_enterprise/arrears_situation.rb +6 -0
- data/app/models/mno_enterprise/audit_event.rb +21 -0
- data/app/models/mno_enterprise/base_resource.rb +228 -0
- data/app/models/mno_enterprise/credit_card.rb +40 -0
- data/app/models/mno_enterprise/deletion_request.rb +35 -0
- data/app/models/mno_enterprise/impac/dashboard.rb +36 -0
- data/app/models/mno_enterprise/impac/dashboard_provisioner.rb +5 -0
- data/app/models/mno_enterprise/impac/kpi.rb +9 -0
- data/app/models/mno_enterprise/impac/widget.rb +13 -0
- data/app/models/mno_enterprise/invoice.rb +53 -0
- data/app/models/mno_enterprise/org_invite.rb +50 -0
- data/app/models/mno_enterprise/organization.rb +33 -0
- data/app/models/mno_enterprise/team.rb +50 -0
- data/app/models/mno_enterprise/tenant.rb +5 -0
- data/app/models/mno_enterprise/tenant_invoice.rb +5 -0
- data/app/models/mno_enterprise/user.rb +183 -0
- data/app/pdf/mno_enterprise/invoice_pdf.rb +516 -0
- data/config/initializers/audit_log.rb +5 -0
- data/config/locales/devise.en.yml +60 -0
- data/config/routes.rb +2 -0
- data/config/styleguide.yml +106 -0
- data/lib/accountingjs_serializer.rb +51 -0
- data/lib/devise/controllers/extension_helpers.rb +52 -0
- data/lib/devise/extension_routes.rb +11 -0
- data/lib/devise/hooks/password_expirable.rb +5 -0
- data/lib/devise/models/password_expirable.rb +28 -0
- data/lib/devise/models/remote_authenticatable.rb +48 -0
- data/lib/devise/strategies/remote_authenticatable.rb +44 -0
- data/lib/devise_extension.rb +36 -0
- data/lib/faraday/adapter/net_http_no_proxy.rb +19 -0
- data/lib/generators/mno_enterprise/database_extension/USAGE +11 -0
- data/lib/generators/mno_enterprise/database_extension/database_extension_generator.rb +36 -0
- data/lib/generators/mno_enterprise/database_extension/templates/model.rb +9 -0
- data/lib/generators/mno_enterprise/dummy/dummy_generator.rb +98 -0
- data/lib/generators/mno_enterprise/dummy/templates/rails/application.rb.erb +9 -0
- data/lib/generators/mno_enterprise/dummy/templates/rails/boot.rb.erb +6 -0
- data/lib/generators/mno_enterprise/dummy/templates/rails/database.yml +22 -0
- data/lib/generators/mno_enterprise/dummy/templates/rails/routes.rb +8 -0
- data/lib/generators/mno_enterprise/dummy/templates/rails/test-env.rb +45 -0
- data/lib/generators/mno_enterprise/install/install_generator.rb +140 -0
- data/lib/generators/mno_enterprise/install/templates/Procfile +1 -0
- data/lib/generators/mno_enterprise/install/templates/config/initializers/mno_enterprise.rb +135 -0
- data/lib/generators/mno_enterprise/install/templates/config/mno_enterprise_styleguide.yml +104 -0
- data/lib/generators/mno_enterprise/install/templates/javascripts/mno_enterprise_extensions.js +7 -0
- data/lib/generators/mno_enterprise/install/templates/stylesheets/main.less_erb +25 -0
- data/lib/generators/mno_enterprise/install/templates/stylesheets/theme.less_erb +59 -0
- data/lib/generators/mno_enterprise/install/templates/stylesheets/variables.less +337 -0
- data/lib/generators/mno_enterprise/install/templates/tasks/sprites.rake +14 -0
- data/lib/generators/mno_enterprise/puma_stack/puma_stack_generator.rb +58 -0
- data/lib/generators/mno_enterprise/templates/scripts/monit/app-server.conf +8 -0
- data/lib/generators/mno_enterprise/templates/scripts/nginx/app +51 -0
- data/lib/generators/mno_enterprise/templates/scripts/puma.rb +25 -0
- data/lib/generators/mno_enterprise/templates/scripts/setup.sh +27 -0
- data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web-hotrestart.conf +26 -0
- data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web-server.conf +34 -0
- data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web.conf +2 -0
- data/lib/generators/mno_enterprise/templates/scripts/upstart/app.conf +11 -0
- data/lib/her_extension/her_orm_adapter.rb +54 -0
- data/lib/her_extension/middleware/mnoe_api_v1_parse_json.rb +54 -0
- data/lib/her_extension/model/associations/association.rb +61 -0
- data/lib/her_extension/model/associations/association_proxy.rb +34 -0
- data/lib/her_extension/model/associations/has_many_association.rb +115 -0
- data/lib/her_extension/model/attributes.rb +43 -0
- data/lib/her_extension/model/orm.rb +59 -0
- data/lib/her_extension/model/parse.rb +40 -0
- data/lib/her_extension/model/relation.rb +92 -0
- data/lib/her_extension/validations/remote_uniqueness_validation.rb +33 -0
- data/lib/html_processor.rb +106 -0
- data/lib/mandrill_client.rb +58 -0
- data/lib/mno-enterprise-core.rb +1 -0
- data/lib/mno_enterprise/concerns.rb +4 -0
- data/lib/mno_enterprise/concerns/controllers.rb +6 -0
- data/lib/mno_enterprise/concerns/controllers/angular_csrf.rb +59 -0
- data/lib/mno_enterprise/concerns/controllers/auth.rb +9 -0
- data/lib/mno_enterprise/concerns/controllers/auth/confirmations_controller.rb +187 -0
- data/lib/mno_enterprise/concerns/controllers/auth/passwords_controller.rb +54 -0
- data/lib/mno_enterprise/concerns/controllers/auth/registrations_controller.rb +136 -0
- data/lib/mno_enterprise/concerns/controllers/auth/sessions_controller.rb +54 -0
- data/lib/mno_enterprise/concerns/controllers/auth/unlocks_controller.rb +50 -0
- data/lib/mno_enterprise/concerns/models.rb +6 -0
- data/lib/mno_enterprise/concerns/models/ability.rb +108 -0
- data/lib/mno_enterprise/concerns/models/app_instance.rb +100 -0
- data/lib/mno_enterprise/concerns/models/organization.rb +102 -0
- data/lib/mno_enterprise/core.rb +279 -0
- data/lib/mno_enterprise/database_extendable.rb +57 -0
- data/lib/mno_enterprise/engine.rb +33 -0
- data/lib/mno_enterprise/testing_support/ability_test_helper.rb +10 -0
- data/lib/mno_enterprise/testing_support/common_rake.rb +19 -0
- data/lib/mno_enterprise/testing_support/factories.rb +13 -0
- data/lib/mno_enterprise/testing_support/factories/app_instances.rb +30 -0
- data/lib/mno_enterprise/testing_support/factories/apps.rb +45 -0
- data/lib/mno_enterprise/testing_support/factories/arrears_situation.rb +14 -0
- data/lib/mno_enterprise/testing_support/factories/audit_event.rb +15 -0
- data/lib/mno_enterprise/testing_support/factories/credit_card.rb +33 -0
- data/lib/mno_enterprise/testing_support/factories/deletion_request.rb +17 -0
- data/lib/mno_enterprise/testing_support/factories/impac/dashboards.rb +15 -0
- data/lib/mno_enterprise/testing_support/factories/impac/kpis.rb +20 -0
- data/lib/mno_enterprise/testing_support/factories/impac/widgets.rb +15 -0
- data/lib/mno_enterprise/testing_support/factories/invoices.rb +51 -0
- data/lib/mno_enterprise/testing_support/factories/org_invite.rb +24 -0
- data/lib/mno_enterprise/testing_support/factories/organizations.rb +25 -0
- data/lib/mno_enterprise/testing_support/factories/team.rb +17 -0
- data/lib/mno_enterprise/testing_support/factories/tenant.rb +12 -0
- data/lib/mno_enterprise/testing_support/factories/tenant_invoice.rb +29 -0
- data/lib/mno_enterprise/testing_support/factories/users.rb +48 -0
- data/lib/mno_enterprise/testing_support/jpi_v1_test_helper.rb +49 -0
- data/lib/mno_enterprise/testing_support/mno_enterprise_api_test_helper.rb +167 -0
- data/lib/mno_enterprise/testing_support/mnoe_faraday_test_adapter.rb +173 -0
- data/lib/mno_enterprise/testing_support/organizations_shared_helpers.rb +175 -0
- data/lib/mno_enterprise/testing_support/user_action_shared.rb +47 -0
- data/lib/mno_enterprise/version.rb +3 -0
- data/lib/tasks/mno_enterprise_tasks.rake +22 -0
- data/spec/controllers/mno_enterprise/angular_csrf_spec.rb +42 -0
- data/spec/lib/her_extension/her_orm_adapter.rb +7 -0
- data/spec/lib/her_extension/model/relation_spec.rb +7 -0
- data/spec/lib/mandrill_client_spec.rb +64 -0
- data/spec/mno_enterprise_spec.rb +79 -0
- data/spec/models/mno_enterprise/app_instance_spec.rb +7 -0
- data/spec/models/mno_enterprise/app_spec.rb +62 -0
- data/spec/models/mno_enterprise/base_resource_spec.rb +28 -0
- data/spec/models/mno_enterprise/deletion_request_spec.rb +26 -0
- data/spec/models/mno_enterprise/invoice_spec.rb +7 -0
- data/spec/models/mno_enterprise/organization_spec.rb +7 -0
- data/spec/models/mno_enterprise/user_spec.rb +44 -0
- data/spec/rails_helper.rb +73 -0
- data/spec/spec_helper.rb +78 -0
- metadata +421 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# == Schema Information
|
|
2
|
+
#
|
|
3
|
+
# Endpoint:
|
|
4
|
+
# - /v1/credit_cards
|
|
5
|
+
# - /v1/organizations/:organization_id/credit_card
|
|
6
|
+
#
|
|
7
|
+
# id :integer not null, primary key
|
|
8
|
+
# title :string(255)
|
|
9
|
+
# first_name :string(255)
|
|
10
|
+
# last_name :string(255)
|
|
11
|
+
# country :string(255)
|
|
12
|
+
# masked_number :string(255)
|
|
13
|
+
# month :integer
|
|
14
|
+
# year :integer
|
|
15
|
+
# user_id :integer
|
|
16
|
+
# token :string(255)
|
|
17
|
+
# created_at :datetime not null
|
|
18
|
+
# updated_at :datetime not null
|
|
19
|
+
# owner_id :integer
|
|
20
|
+
# owner_type :string(255)
|
|
21
|
+
# billing_address :text
|
|
22
|
+
# billing_city :string(255)
|
|
23
|
+
# billing_postcode :string(255)
|
|
24
|
+
# billing_country :string(255)
|
|
25
|
+
# duplicated :boolean default(FALSE)
|
|
26
|
+
#
|
|
27
|
+
|
|
28
|
+
module MnoEnterprise
|
|
29
|
+
class CreditCard < BaseResource
|
|
30
|
+
|
|
31
|
+
attributes :id, :created_at, :updated_at, :title, :first_name, :last_name, :country, :masked_number, :number,
|
|
32
|
+
:month, :year, :billing_address, :billing_city, :billing_postcode, :billing_country, :verification_value, :organization_id
|
|
33
|
+
|
|
34
|
+
#==============================================================
|
|
35
|
+
# Associations
|
|
36
|
+
#==============================================================
|
|
37
|
+
belongs_to :organization, class_name: 'MnoEnterprise::Organization'
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# == Schema Information
|
|
2
|
+
#
|
|
3
|
+
# Table name: deletion_requests
|
|
4
|
+
#
|
|
5
|
+
# id :integer not null, primary key
|
|
6
|
+
# token :string(255)
|
|
7
|
+
# status :string(255)
|
|
8
|
+
# created_at :datetime not null
|
|
9
|
+
# updated_at :datetime not null
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
module MnoEnterprise
|
|
13
|
+
class DeletionRequest < BaseResource
|
|
14
|
+
attributes :id, :token, :status, :user_id
|
|
15
|
+
|
|
16
|
+
#==============================================================
|
|
17
|
+
# Associations
|
|
18
|
+
#==============================================================
|
|
19
|
+
belongs_to :user, class_name: 'MnoEnterprise::User'
|
|
20
|
+
|
|
21
|
+
#============================================
|
|
22
|
+
# Instance methods
|
|
23
|
+
#============================================
|
|
24
|
+
# We want to use the token instead of the id
|
|
25
|
+
def to_param
|
|
26
|
+
self.token
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# TODO: specs
|
|
30
|
+
# Freeze user acocunt and update the deletion request
|
|
31
|
+
def freeze_account!
|
|
32
|
+
self.put(operation: 'freeze')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module MnoEnterprise
|
|
2
|
+
class Impac::Dashboard < BaseResource
|
|
3
|
+
|
|
4
|
+
attributes :name, :widgets_order, :organization_ids, :widgets_templates, :currency
|
|
5
|
+
|
|
6
|
+
has_many :widgets, class_name: 'MnoEnterprise::Impac::Widget', dependent: :destroy
|
|
7
|
+
has_many :kpis, class_name: 'MnoEnterprise::Impac::Kpi', dependent: :destroy
|
|
8
|
+
belongs_to :owner, polymorphic: true
|
|
9
|
+
|
|
10
|
+
#============================================
|
|
11
|
+
# Instance methods
|
|
12
|
+
#============================================
|
|
13
|
+
# Return the full name of this dashboard
|
|
14
|
+
# Currently a simple accessor to the dashboard name (used to include the company name)
|
|
15
|
+
def full_name
|
|
16
|
+
self.name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Return all the organizations linked to this dashboard and to which
|
|
20
|
+
# the user has access
|
|
21
|
+
def organizations
|
|
22
|
+
self.organization_ids.map do |uid|
|
|
23
|
+
MnoEnterprise::Organization.find_by(uid: uid)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def sorted_widgets
|
|
28
|
+
order = self.widgets_order.map(&:to_i) | self.widgets.map{|w| w.id }
|
|
29
|
+
order.map { |id| self.widgets.to_a.find{ |w| w.id == id} }.compact
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_audit_event
|
|
33
|
+
name
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# == Schema Information
|
|
2
|
+
#
|
|
3
|
+
# Endpoint:
|
|
4
|
+
# - /v1/invoices
|
|
5
|
+
# - /v1/organizations/:organization_id/invoices
|
|
6
|
+
#
|
|
7
|
+
# id :integer not null, primary key
|
|
8
|
+
# price_cents :integer
|
|
9
|
+
# currency :string(255)
|
|
10
|
+
# invoicable_type :string(255)
|
|
11
|
+
# invoicable_id :integer
|
|
12
|
+
# started_at :datetime
|
|
13
|
+
# ended_at :datetime
|
|
14
|
+
# created_at :datetime not null
|
|
15
|
+
# updated_at :datetime not null
|
|
16
|
+
# paid_at :datetime
|
|
17
|
+
# pdf :string(255)
|
|
18
|
+
# payment_id :integer
|
|
19
|
+
# transferred_from_id :integer
|
|
20
|
+
# transferred_from_type :string(255)
|
|
21
|
+
# transferred_at :datetime
|
|
22
|
+
# account_transaction_id :integer
|
|
23
|
+
# resolver_invoice_id :integer
|
|
24
|
+
# resolving_invoice_id :integer
|
|
25
|
+
# slug :string(255)
|
|
26
|
+
# promo_voucher_id :integer
|
|
27
|
+
# tax_pips_applied :integer
|
|
28
|
+
# billing_address :text
|
|
29
|
+
# partner_invoice_id :integer
|
|
30
|
+
# mnoe_tenant_id :integer
|
|
31
|
+
#
|
|
32
|
+
|
|
33
|
+
module MnoEnterprise
|
|
34
|
+
class Invoice < BaseResource
|
|
35
|
+
#==============================================================
|
|
36
|
+
# Associations
|
|
37
|
+
#==============================================================
|
|
38
|
+
belongs_to :organization, class_name: 'MnoEnterprise::Organization'
|
|
39
|
+
|
|
40
|
+
# Return a label describing the time period
|
|
41
|
+
# this invoice covers
|
|
42
|
+
def period_label
|
|
43
|
+
return '' unless self.started_at && self.ended_at
|
|
44
|
+
"#{self.started_at.strftime("%b %d,%Y")} to #{self.ended_at.strftime("%b %d,%Y")}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Return true if the invoice has been paid
|
|
48
|
+
# false otherwise
|
|
49
|
+
def paid?
|
|
50
|
+
!self.paid_at.blank?
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# == Schema Information
|
|
2
|
+
#
|
|
3
|
+
# Endpoint:
|
|
4
|
+
# - /v1/org_invites
|
|
5
|
+
# - /v1/organizations/:organization_id/org_invites
|
|
6
|
+
#
|
|
7
|
+
# id :integer not null, primary key
|
|
8
|
+
# user_id :integer
|
|
9
|
+
# user_email :string(255)
|
|
10
|
+
# organization_id :integer
|
|
11
|
+
# referrer_id :integer
|
|
12
|
+
# token :string(255)
|
|
13
|
+
# status :string(255)
|
|
14
|
+
# created_at :datetime not null
|
|
15
|
+
# updated_at :datetime not null
|
|
16
|
+
# user_role :string(255)
|
|
17
|
+
# team_id :integer
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module MnoEnterprise
|
|
21
|
+
class OrgInvite < BaseResource
|
|
22
|
+
scope :active, -> { where(status: 'pending') }
|
|
23
|
+
|
|
24
|
+
#==============================================================
|
|
25
|
+
# Associations
|
|
26
|
+
#==============================================================
|
|
27
|
+
belongs_to :user, class_name: 'MnoEnterprise::User'
|
|
28
|
+
belongs_to :referrer, class_name: 'MnoEnterprise::User'
|
|
29
|
+
belongs_to :organization, class_name: 'MnoEnterprise::Organization'
|
|
30
|
+
belongs_to :team, class_name: 'MnoEnterprise::Team'
|
|
31
|
+
|
|
32
|
+
# TODO: specs
|
|
33
|
+
# Add the user to the organization and update the status of the invite
|
|
34
|
+
# Add team
|
|
35
|
+
def accept!(user = self.user)
|
|
36
|
+
self.put(operation: 'accept', data: { user_id: user.id})
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# TODO: specs
|
|
40
|
+
def cancel!
|
|
41
|
+
self.put(operation: 'cancel')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# TODO: specs
|
|
45
|
+
# Check whether the invite is expired or not
|
|
46
|
+
def expired?
|
|
47
|
+
self.status != 'pending' || self.created_at < 3.days.ago
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# == Schema Information
|
|
2
|
+
#
|
|
3
|
+
# Endpoint:
|
|
4
|
+
# - /v1/organizations
|
|
5
|
+
# - /v1/users/:user_id/organizations
|
|
6
|
+
#
|
|
7
|
+
# id :integer not null, primary key
|
|
8
|
+
# uid :string(255)
|
|
9
|
+
# name :string(255)
|
|
10
|
+
# created_at :datetime not null
|
|
11
|
+
# updated_at :datetime not null
|
|
12
|
+
# account_frozen :boolean default(FALSE)
|
|
13
|
+
# free_trial_end_at :datetime
|
|
14
|
+
# soa_enabled :boolean default(TRUE)
|
|
15
|
+
# mails :text
|
|
16
|
+
# logo :string(255)
|
|
17
|
+
# latitude :float default(0.0)
|
|
18
|
+
# longitude :float default(0.0)
|
|
19
|
+
# geo_country_code :string(255)
|
|
20
|
+
# geo_state_code :string(255)
|
|
21
|
+
# geo_city :string(255)
|
|
22
|
+
# geo_tz :string(255)
|
|
23
|
+
# geo_currency :string(255)
|
|
24
|
+
# meta_data :text
|
|
25
|
+
# industry :string(255)
|
|
26
|
+
# size :string(255)
|
|
27
|
+
#
|
|
28
|
+
|
|
29
|
+
module MnoEnterprise
|
|
30
|
+
class Organization < BaseResource
|
|
31
|
+
include MnoEnterprise::Concerns::Models::Organization
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# == Schema Information
|
|
2
|
+
#
|
|
3
|
+
# Endpoint:
|
|
4
|
+
# - /v1/teams
|
|
5
|
+
# - /v1/organizations/:organization_id/teams
|
|
6
|
+
#
|
|
7
|
+
# id :integer not null, primary key
|
|
8
|
+
# name :string(255)
|
|
9
|
+
# created_at :datetime not null
|
|
10
|
+
# updated_at :datetime not null
|
|
11
|
+
# organization_id :integer
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
module MnoEnterprise
|
|
15
|
+
class Team < BaseResource
|
|
16
|
+
|
|
17
|
+
attributes :id, :name, :organization_id
|
|
18
|
+
|
|
19
|
+
#=====================================
|
|
20
|
+
# Associations
|
|
21
|
+
#=====================================
|
|
22
|
+
belongs_to :organization, class_name: 'MnoEnterprise::Organization'
|
|
23
|
+
has_many :users, class_name: 'MnoEnterprise::User'
|
|
24
|
+
has_many :app_instances, class_name: 'MnoEnterprise::AppInstance'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Add a user to the team
|
|
28
|
+
# TODO: specs
|
|
29
|
+
def add_user(user)
|
|
30
|
+
self.users.create(id: user.id)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Remove a user from the team
|
|
34
|
+
# TODO: specs
|
|
35
|
+
def remove_user(user)
|
|
36
|
+
self.users.destroy(id: user.id)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Set the app_instance permissions of this team
|
|
40
|
+
# Accept a collection of hashes or an array of ids
|
|
41
|
+
# TODO: specs
|
|
42
|
+
def set_access_to(collection_or_array)
|
|
43
|
+
# Empty arrays do not seem to be passed in the request. Force value in this case
|
|
44
|
+
list = collection_or_array.empty? ? [""] : collection_or_array
|
|
45
|
+
self.put(data: { set_access_to: list })
|
|
46
|
+
self.reload
|
|
47
|
+
self
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# == Schema Information
|
|
2
|
+
#
|
|
3
|
+
# Endpoint:
|
|
4
|
+
# - /v1/users
|
|
5
|
+
# - /v1/organizations/:organization_id/users
|
|
6
|
+
#
|
|
7
|
+
# id :string e.g.: 1
|
|
8
|
+
# uid :string e.g.: usr-k3j23npo
|
|
9
|
+
# email :string(255) default(""), not null
|
|
10
|
+
# authenticatable_salt :string(255) used for session authentication
|
|
11
|
+
# encrypted_password :string(255) default(""), not null
|
|
12
|
+
# reset_password_token :string(255)
|
|
13
|
+
# reset_password_sent_at :datetime
|
|
14
|
+
# remember_created_at :datetime
|
|
15
|
+
# sign_in_count :integer default(0)
|
|
16
|
+
# current_sign_in_at :datetime
|
|
17
|
+
# last_sign_in_at :datetime
|
|
18
|
+
# current_sign_in_ip :string(255)
|
|
19
|
+
# last_sign_in_ip :string(255)
|
|
20
|
+
# confirmation_token :string(255)
|
|
21
|
+
# confirmed_at :datetime
|
|
22
|
+
# confirmation_sent_at :datetime
|
|
23
|
+
# unconfirmed_email :string(255)
|
|
24
|
+
# failed_attempts :integer default(0)
|
|
25
|
+
# unlock_token :string(255)
|
|
26
|
+
# locked_at :datetime
|
|
27
|
+
# created_at :datetime not null
|
|
28
|
+
# updated_at :datetime not null
|
|
29
|
+
# name :string(255)
|
|
30
|
+
# surname :string(255)
|
|
31
|
+
# company :string(255)
|
|
32
|
+
# phone :string(255)
|
|
33
|
+
# phone_country_code :string(255)
|
|
34
|
+
# geo_country_code :string(255)
|
|
35
|
+
# geo_state_code :string(255)
|
|
36
|
+
# geo_city :string(255)
|
|
37
|
+
# website :string(255)
|
|
38
|
+
#
|
|
39
|
+
|
|
40
|
+
module MnoEnterprise
|
|
41
|
+
class User < BaseResource
|
|
42
|
+
extend Devise::Models
|
|
43
|
+
|
|
44
|
+
# Note: password and encrypted_password are write-only attributes and are never returned by
|
|
45
|
+
# the remote API. If you are looking for a session token, use authenticatable_salt
|
|
46
|
+
attributes :uid, :email, :password, :current_password, :password_confirmation, :authenticatable_salt, :encrypted_password, :reset_password_token, :reset_password_sent_at,
|
|
47
|
+
:remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
|
|
48
|
+
:last_sign_in_ip, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email,
|
|
49
|
+
:failed_attempts, :unlock_token, :locked_at, :name, :surname, :company, :phone, :phone_country_code,
|
|
50
|
+
:geo_country_code, :geo_state_code, :geo_city, :website, :orga_on_create, :sso_session, :current_password_required
|
|
51
|
+
|
|
52
|
+
define_model_callbacks :validation #required by Devise
|
|
53
|
+
devise :remote_authenticatable, :registerable, :recoverable, :rememberable,
|
|
54
|
+
:trackable, :validatable, :lockable, :confirmable, :timeoutable, :password_expirable
|
|
55
|
+
|
|
56
|
+
#================================
|
|
57
|
+
# Validation
|
|
58
|
+
#================================
|
|
59
|
+
validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
|
|
60
|
+
|
|
61
|
+
if Devise.password_regex
|
|
62
|
+
validates :password, format: { with: Devise.password_regex, message: Devise.password_regex_message }, if: :password_required?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#================================
|
|
66
|
+
# Associations
|
|
67
|
+
#================================
|
|
68
|
+
has_many :organizations, class_name: 'MnoEnterprise::Organization'
|
|
69
|
+
has_many :org_invites, class_name: 'MnoEnterprise::OrgInvite'
|
|
70
|
+
has_one :deletion_request, class_name: 'MnoEnterprise::DeletionRequest'
|
|
71
|
+
has_many :dashboards, class_name: 'MnoEnterprise::Impac::Dashboard'
|
|
72
|
+
has_many :teams, class_name: 'MnoEnterprise::Team'
|
|
73
|
+
|
|
74
|
+
#================================
|
|
75
|
+
# Callbacks
|
|
76
|
+
#================================
|
|
77
|
+
before_save :expire_user_cache
|
|
78
|
+
|
|
79
|
+
#================================
|
|
80
|
+
# Class Methods
|
|
81
|
+
#================================
|
|
82
|
+
# The auth_hash includes an email and password
|
|
83
|
+
# Return nil in case of failure
|
|
84
|
+
def self.authenticate(auth_hash)
|
|
85
|
+
u = self.post("user_sessions", auth_hash)
|
|
86
|
+
|
|
87
|
+
if u && u.id
|
|
88
|
+
u.clear_attribute_changes!
|
|
89
|
+
return u
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
#================================
|
|
96
|
+
# Devise Confirmation
|
|
97
|
+
# TODO: should go in a module
|
|
98
|
+
#================================
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# Override Devise to allow confirmation via original token
|
|
102
|
+
# Less secure but useful if user has been created by Maestrano Enterprise
|
|
103
|
+
# (happens when an orga_invite is sent to a new user)
|
|
104
|
+
#
|
|
105
|
+
# Find a user by its confirmation token and try to confirm it.
|
|
106
|
+
# If no user is found, returns a new user with an error.
|
|
107
|
+
# If the user is already confirmed, create an error for the user
|
|
108
|
+
# Options must have the confirmation_token
|
|
109
|
+
def self.confirm_by_token(confirmation_token)
|
|
110
|
+
confirmable = self.find_for_confirmation(confirmation_token)
|
|
111
|
+
confirmable.perform_confirmation(confirmation_token)
|
|
112
|
+
confirmable
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Find a user using a confirmation token
|
|
116
|
+
def self.find_for_confirmation(confirmation_token)
|
|
117
|
+
original_token = confirmation_token
|
|
118
|
+
confirmation_token = Devise.token_generator.digest(self, :confirmation_token, confirmation_token)
|
|
119
|
+
|
|
120
|
+
confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
|
|
121
|
+
confirmable = find_or_initialize_with_error_by(:confirmation_token, original_token) if confirmable.errors.any?
|
|
122
|
+
confirmable
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Confirm the user and store confirmation_token
|
|
126
|
+
def perform_confirmation(confirmation_token)
|
|
127
|
+
self.confirm if self.persisted?
|
|
128
|
+
self.confirmation_token = confirmation_token
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# It may happen that that the errors attribute become nil, which breaks the controller logic (rails responder)
|
|
132
|
+
# This getter ensures that 'errors' is always initialized
|
|
133
|
+
def errors
|
|
134
|
+
@errors ||= ActiveModel::Errors.new(self)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
#================================
|
|
138
|
+
# Instance Methods
|
|
139
|
+
#================================
|
|
140
|
+
|
|
141
|
+
def to_s
|
|
142
|
+
"#{name} #{surname}"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Format for audit log
|
|
146
|
+
def to_audit_event
|
|
147
|
+
{
|
|
148
|
+
user_name: to_s,
|
|
149
|
+
user_email: email
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Default value for failed attempts
|
|
154
|
+
def failed_attempts
|
|
155
|
+
read_attribute(:failed_attempts) || 0
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Override Devise default method
|
|
159
|
+
def authenticatable_salt
|
|
160
|
+
read_attribute(:authenticatable_salt)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Return the role of this user for the provided
|
|
164
|
+
# organization
|
|
165
|
+
def role(organization = nil)
|
|
166
|
+
# Return cached version if available
|
|
167
|
+
return self.read_attribute(:role) if !organization
|
|
168
|
+
|
|
169
|
+
org = self.organizations.to_a.find { |o| o.id.to_s == organization.id.to_s }
|
|
170
|
+
org ? org.role : nil
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def expire_user_cache
|
|
174
|
+
Rails.cache.delete(['user', self.to_key])
|
|
175
|
+
true # Don't skip save if above return false (memory_store)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def refresh_user_cache
|
|
179
|
+
self.reload
|
|
180
|
+
Rails.cache.write(['user', self.to_key], self)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|