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.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -0
  3. data/Rakefile +12 -0
  4. data/app/assets/images/mno_enterprise/main-logo.png +0 -0
  5. data/app/controllers/mno_enterprise/application_controller.rb +116 -0
  6. data/app/helpers/mno_enterprise/application_helper.rb +67 -0
  7. data/app/helpers/mno_enterprise/impersonate_helper.rb +27 -0
  8. data/app/models/mno_enterprise/ability.rb +6 -0
  9. data/app/models/mno_enterprise/app.rb +72 -0
  10. data/app/models/mno_enterprise/app_instance.rb +36 -0
  11. data/app/models/mno_enterprise/app_instances_sync.rb +6 -0
  12. data/app/models/mno_enterprise/arrears_situation.rb +6 -0
  13. data/app/models/mno_enterprise/audit_event.rb +21 -0
  14. data/app/models/mno_enterprise/base_resource.rb +228 -0
  15. data/app/models/mno_enterprise/credit_card.rb +40 -0
  16. data/app/models/mno_enterprise/deletion_request.rb +35 -0
  17. data/app/models/mno_enterprise/impac/dashboard.rb +36 -0
  18. data/app/models/mno_enterprise/impac/dashboard_provisioner.rb +5 -0
  19. data/app/models/mno_enterprise/impac/kpi.rb +9 -0
  20. data/app/models/mno_enterprise/impac/widget.rb +13 -0
  21. data/app/models/mno_enterprise/invoice.rb +53 -0
  22. data/app/models/mno_enterprise/org_invite.rb +50 -0
  23. data/app/models/mno_enterprise/organization.rb +33 -0
  24. data/app/models/mno_enterprise/team.rb +50 -0
  25. data/app/models/mno_enterprise/tenant.rb +5 -0
  26. data/app/models/mno_enterprise/tenant_invoice.rb +5 -0
  27. data/app/models/mno_enterprise/user.rb +183 -0
  28. data/app/pdf/mno_enterprise/invoice_pdf.rb +516 -0
  29. data/config/initializers/audit_log.rb +5 -0
  30. data/config/locales/devise.en.yml +60 -0
  31. data/config/routes.rb +2 -0
  32. data/config/styleguide.yml +106 -0
  33. data/lib/accountingjs_serializer.rb +51 -0
  34. data/lib/devise/controllers/extension_helpers.rb +52 -0
  35. data/lib/devise/extension_routes.rb +11 -0
  36. data/lib/devise/hooks/password_expirable.rb +5 -0
  37. data/lib/devise/models/password_expirable.rb +28 -0
  38. data/lib/devise/models/remote_authenticatable.rb +48 -0
  39. data/lib/devise/strategies/remote_authenticatable.rb +44 -0
  40. data/lib/devise_extension.rb +36 -0
  41. data/lib/faraday/adapter/net_http_no_proxy.rb +19 -0
  42. data/lib/generators/mno_enterprise/database_extension/USAGE +11 -0
  43. data/lib/generators/mno_enterprise/database_extension/database_extension_generator.rb +36 -0
  44. data/lib/generators/mno_enterprise/database_extension/templates/model.rb +9 -0
  45. data/lib/generators/mno_enterprise/dummy/dummy_generator.rb +98 -0
  46. data/lib/generators/mno_enterprise/dummy/templates/rails/application.rb.erb +9 -0
  47. data/lib/generators/mno_enterprise/dummy/templates/rails/boot.rb.erb +6 -0
  48. data/lib/generators/mno_enterprise/dummy/templates/rails/database.yml +22 -0
  49. data/lib/generators/mno_enterprise/dummy/templates/rails/routes.rb +8 -0
  50. data/lib/generators/mno_enterprise/dummy/templates/rails/test-env.rb +45 -0
  51. data/lib/generators/mno_enterprise/install/install_generator.rb +140 -0
  52. data/lib/generators/mno_enterprise/install/templates/Procfile +1 -0
  53. data/lib/generators/mno_enterprise/install/templates/config/initializers/mno_enterprise.rb +135 -0
  54. data/lib/generators/mno_enterprise/install/templates/config/mno_enterprise_styleguide.yml +104 -0
  55. data/lib/generators/mno_enterprise/install/templates/javascripts/mno_enterprise_extensions.js +7 -0
  56. data/lib/generators/mno_enterprise/install/templates/stylesheets/main.less_erb +25 -0
  57. data/lib/generators/mno_enterprise/install/templates/stylesheets/theme.less_erb +59 -0
  58. data/lib/generators/mno_enterprise/install/templates/stylesheets/variables.less +337 -0
  59. data/lib/generators/mno_enterprise/install/templates/tasks/sprites.rake +14 -0
  60. data/lib/generators/mno_enterprise/puma_stack/puma_stack_generator.rb +58 -0
  61. data/lib/generators/mno_enterprise/templates/scripts/monit/app-server.conf +8 -0
  62. data/lib/generators/mno_enterprise/templates/scripts/nginx/app +51 -0
  63. data/lib/generators/mno_enterprise/templates/scripts/puma.rb +25 -0
  64. data/lib/generators/mno_enterprise/templates/scripts/setup.sh +27 -0
  65. data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web-hotrestart.conf +26 -0
  66. data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web-server.conf +34 -0
  67. data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web.conf +2 -0
  68. data/lib/generators/mno_enterprise/templates/scripts/upstart/app.conf +11 -0
  69. data/lib/her_extension/her_orm_adapter.rb +54 -0
  70. data/lib/her_extension/middleware/mnoe_api_v1_parse_json.rb +54 -0
  71. data/lib/her_extension/model/associations/association.rb +61 -0
  72. data/lib/her_extension/model/associations/association_proxy.rb +34 -0
  73. data/lib/her_extension/model/associations/has_many_association.rb +115 -0
  74. data/lib/her_extension/model/attributes.rb +43 -0
  75. data/lib/her_extension/model/orm.rb +59 -0
  76. data/lib/her_extension/model/parse.rb +40 -0
  77. data/lib/her_extension/model/relation.rb +92 -0
  78. data/lib/her_extension/validations/remote_uniqueness_validation.rb +33 -0
  79. data/lib/html_processor.rb +106 -0
  80. data/lib/mandrill_client.rb +58 -0
  81. data/lib/mno-enterprise-core.rb +1 -0
  82. data/lib/mno_enterprise/concerns.rb +4 -0
  83. data/lib/mno_enterprise/concerns/controllers.rb +6 -0
  84. data/lib/mno_enterprise/concerns/controllers/angular_csrf.rb +59 -0
  85. data/lib/mno_enterprise/concerns/controllers/auth.rb +9 -0
  86. data/lib/mno_enterprise/concerns/controllers/auth/confirmations_controller.rb +187 -0
  87. data/lib/mno_enterprise/concerns/controllers/auth/passwords_controller.rb +54 -0
  88. data/lib/mno_enterprise/concerns/controllers/auth/registrations_controller.rb +136 -0
  89. data/lib/mno_enterprise/concerns/controllers/auth/sessions_controller.rb +54 -0
  90. data/lib/mno_enterprise/concerns/controllers/auth/unlocks_controller.rb +50 -0
  91. data/lib/mno_enterprise/concerns/models.rb +6 -0
  92. data/lib/mno_enterprise/concerns/models/ability.rb +108 -0
  93. data/lib/mno_enterprise/concerns/models/app_instance.rb +100 -0
  94. data/lib/mno_enterprise/concerns/models/organization.rb +102 -0
  95. data/lib/mno_enterprise/core.rb +279 -0
  96. data/lib/mno_enterprise/database_extendable.rb +57 -0
  97. data/lib/mno_enterprise/engine.rb +33 -0
  98. data/lib/mno_enterprise/testing_support/ability_test_helper.rb +10 -0
  99. data/lib/mno_enterprise/testing_support/common_rake.rb +19 -0
  100. data/lib/mno_enterprise/testing_support/factories.rb +13 -0
  101. data/lib/mno_enterprise/testing_support/factories/app_instances.rb +30 -0
  102. data/lib/mno_enterprise/testing_support/factories/apps.rb +45 -0
  103. data/lib/mno_enterprise/testing_support/factories/arrears_situation.rb +14 -0
  104. data/lib/mno_enterprise/testing_support/factories/audit_event.rb +15 -0
  105. data/lib/mno_enterprise/testing_support/factories/credit_card.rb +33 -0
  106. data/lib/mno_enterprise/testing_support/factories/deletion_request.rb +17 -0
  107. data/lib/mno_enterprise/testing_support/factories/impac/dashboards.rb +15 -0
  108. data/lib/mno_enterprise/testing_support/factories/impac/kpis.rb +20 -0
  109. data/lib/mno_enterprise/testing_support/factories/impac/widgets.rb +15 -0
  110. data/lib/mno_enterprise/testing_support/factories/invoices.rb +51 -0
  111. data/lib/mno_enterprise/testing_support/factories/org_invite.rb +24 -0
  112. data/lib/mno_enterprise/testing_support/factories/organizations.rb +25 -0
  113. data/lib/mno_enterprise/testing_support/factories/team.rb +17 -0
  114. data/lib/mno_enterprise/testing_support/factories/tenant.rb +12 -0
  115. data/lib/mno_enterprise/testing_support/factories/tenant_invoice.rb +29 -0
  116. data/lib/mno_enterprise/testing_support/factories/users.rb +48 -0
  117. data/lib/mno_enterprise/testing_support/jpi_v1_test_helper.rb +49 -0
  118. data/lib/mno_enterprise/testing_support/mno_enterprise_api_test_helper.rb +167 -0
  119. data/lib/mno_enterprise/testing_support/mnoe_faraday_test_adapter.rb +173 -0
  120. data/lib/mno_enterprise/testing_support/organizations_shared_helpers.rb +175 -0
  121. data/lib/mno_enterprise/testing_support/user_action_shared.rb +47 -0
  122. data/lib/mno_enterprise/version.rb +3 -0
  123. data/lib/tasks/mno_enterprise_tasks.rake +22 -0
  124. data/spec/controllers/mno_enterprise/angular_csrf_spec.rb +42 -0
  125. data/spec/lib/her_extension/her_orm_adapter.rb +7 -0
  126. data/spec/lib/her_extension/model/relation_spec.rb +7 -0
  127. data/spec/lib/mandrill_client_spec.rb +64 -0
  128. data/spec/mno_enterprise_spec.rb +79 -0
  129. data/spec/models/mno_enterprise/app_instance_spec.rb +7 -0
  130. data/spec/models/mno_enterprise/app_spec.rb +62 -0
  131. data/spec/models/mno_enterprise/base_resource_spec.rb +28 -0
  132. data/spec/models/mno_enterprise/deletion_request_spec.rb +26 -0
  133. data/spec/models/mno_enterprise/invoice_spec.rb +7 -0
  134. data/spec/models/mno_enterprise/organization_spec.rb +7 -0
  135. data/spec/models/mno_enterprise/user_spec.rb +44 -0
  136. data/spec/rails_helper.rb +73 -0
  137. data/spec/spec_helper.rb +78 -0
  138. metadata +421 -0
@@ -0,0 +1,54 @@
1
+ module MnoEnterprise::Concerns::Controllers::Auth::SessionsController
2
+ extend ActiveSupport::Concern
3
+
4
+ #==================================================================
5
+ # Included methods
6
+ #==================================================================
7
+ # 'included do' causes the included code to be evaluated in the
8
+ # context where it is included rather than being executed in the module's context
9
+ included do
10
+ prepend_before_filter :capture_return_to_redirection
11
+ # before_filter :configure_sign_in_params, only: [:create]
12
+ end
13
+
14
+ #==================================================================
15
+ # Class methods
16
+ #==================================================================
17
+ module ClassMethods
18
+ # def some_class_method
19
+ # 'some text'
20
+ # end
21
+ end
22
+
23
+ #==================================================================
24
+ # Instance methods
25
+ #==================================================================
26
+ # GET /resource/sign_in
27
+ # def new
28
+ # super
29
+ # end
30
+
31
+ # POST /resource/sign_in
32
+ # def create
33
+ # super
34
+ # end
35
+ # def create
36
+ # self.resource = warden.authenticate!(auth_options)
37
+ # set_flash_message(:notice, :signed_in) if is_flashing_format?
38
+ # sign_in(resource_name, resource)
39
+ # yield resource if block_given?
40
+ # respond_with resource, location: after_sign_in_path_for(resource)
41
+ # end
42
+
43
+ # DELETE /resource/sign_out
44
+ # def destroy
45
+ # super
46
+ # end
47
+
48
+ # protected
49
+
50
+ # You can put the params you want to permit in the empty array.
51
+ # def configure_sign_in_params
52
+ # devise_parameter_sanitizer.for(:sign_in) << :attribute
53
+ # end
54
+ end
@@ -0,0 +1,50 @@
1
+ module MnoEnterprise::Concerns::Controllers::Auth::UnlocksController
2
+ extend ActiveSupport::Concern
3
+
4
+ #==================================================================
5
+ # Included methods
6
+ #==================================================================
7
+ # 'included do' causes the included code to be evaluated in the
8
+ # context where it is included rather than being executed in the module's context
9
+ included do
10
+ end
11
+
12
+ #==================================================================
13
+ # Class methods
14
+ #==================================================================
15
+ module ClassMethods
16
+ # def some_class_method
17
+ # 'some text'
18
+ # end
19
+ end
20
+
21
+ #==================================================================
22
+ # Instance methods
23
+ #==================================================================
24
+ # GET /resource/unlock/new
25
+ # def new
26
+ # super
27
+ # end
28
+
29
+ # POST /resource/unlock
30
+ # def create
31
+ # super
32
+ # end
33
+
34
+ # GET /resource/unlock?unlock_token=abcdef
35
+ # def show
36
+ # super
37
+ # end
38
+
39
+ # protected
40
+
41
+ # The path used after sending unlock password instructions
42
+ # def after_sending_unlock_instructions_path_for(resource)
43
+ # super(resource)
44
+ # end
45
+
46
+ # The path used after unlocking the resource
47
+ # def after_unlock_path_for(resource)
48
+ # super(resource)
49
+ # end
50
+ end
@@ -0,0 +1,6 @@
1
+ module MnoEnterprise
2
+ module Concerns
3
+ module Models
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,108 @@
1
+ module MnoEnterprise::Concerns::Models::Ability
2
+ extend ActiveSupport::Concern
3
+
4
+ #==================================================================
5
+ # Included methods
6
+ #==================================================================
7
+ included do
8
+ end
9
+
10
+ #==================================================================
11
+ # Class methods
12
+ #==================================================================
13
+ module ClassMethods
14
+ # def some_class_method
15
+ # 'some text'
16
+ # end
17
+ end
18
+
19
+ #==================================================================
20
+ # Instance methods
21
+ #==================================================================
22
+ def initialize(user)
23
+ user ||= MnoEnterprise::User.new
24
+
25
+ #===================================================
26
+ # Organization
27
+ #===================================================
28
+ can :create, MnoEnterprise::Organization
29
+
30
+ can :read, MnoEnterprise::Organization do |organization|
31
+ !!user.role(organization)
32
+ end
33
+
34
+ can [:update, :destroy, :manage_billing], MnoEnterprise::Organization do |organization|
35
+ user.role(organization) == 'Super Admin'
36
+ end
37
+
38
+ can [:upload,
39
+ :purchase,
40
+ :invite_member,
41
+ :administrate,
42
+ :manage_app_instances,
43
+ :manage_teams], MnoEnterprise::Organization do |organization|
44
+ ['Super Admin','Admin'].include? user.role(organization)
45
+ end
46
+
47
+ # To be updated
48
+ can :sync_apps, MnoEnterprise::Organization do |organization|
49
+ user.role(organization)
50
+ end
51
+
52
+ # To be updated
53
+ can :check_apps_sync, MnoEnterprise::Organization do |organization|
54
+ user.role(organization)
55
+ end
56
+
57
+ #===================================================
58
+ # AppInstance
59
+ #===================================================
60
+ can :access, MnoEnterprise::AppInstance do |app_instance|
61
+ !!user.role(app_instance.owner) && (
62
+ ['Super Admin','Admin'].include?(user.role(app_instance.owner)) ||
63
+ user.teams.empty? ||
64
+ user.teams.map(&:app_instances).compact.flatten.map(&:id).include?(app_instance.id)
65
+ )
66
+ end
67
+
68
+ #===================================================
69
+ # Impac
70
+ #===================================================
71
+ impac_abilities(user)
72
+
73
+ # Define abilities for the passed in user here. For example:
74
+ #
75
+ # user ||= User.new # guest user (not logged in)
76
+ # if user.admin?
77
+ # can :manage, :all
78
+ # else
79
+ # can :read, :all
80
+ # end
81
+ #
82
+ # The first argument to `can` is the action you are giving the user
83
+ # permission to do.
84
+ # If you pass :manage it will apply to every action. Other common actions
85
+ # here are :read, :create, :update and :destroy.
86
+ #
87
+ # The second argument is the resource the user can perform the action on.
88
+ # If you pass :all it will apply to every resource. Otherwise pass a Ruby
89
+ # class of the resource.
90
+ #
91
+ # The third argument is an optional hash of conditions to further filter the
92
+ # objects.
93
+ # For example, here the user can only update published articles.
94
+ #
95
+ # can :update, Article, :published => true
96
+ #
97
+ # See the wiki for details:
98
+ # https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
99
+ end
100
+
101
+ def impac_abilities(user)
102
+ can :manage_impac, MnoEnterprise::Impac::Dashboard do |dhb|
103
+ dhb.organizations.any? && dhb.organizations.all? do |org|
104
+ !!user.role(org) && ['Super Admin', 'Admin'].include?(user.role(org))
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,100 @@
1
+ # == Schema Information
2
+ #
3
+ # Endpoint:
4
+ # - /v1/app_instances
5
+ # - /v1/organizations/:organization_id/app_instances
6
+ #
7
+ # id :integer not null, primary key
8
+ # uid :string(255)
9
+ # name :string(255)
10
+ # status :string(255)
11
+ # app_id :integer
12
+ # created_at :datetime not null
13
+ # updated_at :datetime not null
14
+ # started_at :datetime
15
+ # stack :string(255)
16
+ # owner_id :integer
17
+ # owner_type :string(255)
18
+ # terminated_at :datetime
19
+ # stopped_at :datetime
20
+ # billing_type :string(255)
21
+ # autostop_at :datetime
22
+ # autostop_interval :integer
23
+ # next_status :string(255)
24
+ # soa_enabled :boolean default(FALSE)
25
+ #
26
+ # ===> to be confirmed
27
+ # http_url
28
+ # durations :text
29
+ # microsoft_licence_id :integer
30
+ #
31
+
32
+ module MnoEnterprise::Concerns::Models::AppInstance
33
+ extend ActiveSupport::Concern
34
+
35
+ #==================================================================
36
+ # Included methods
37
+ #==================================================================
38
+ # 'included do' causes the included code to be evaluated in the
39
+ # context where it is included rather than being executed in the module's context
40
+ included do
41
+ attributes :id, :uid, :name, :status, :app_id, :created_at, :updated_at, :started_at, :stack, :owner_id,
42
+ :owner_type, :terminated_at, :stopped_at, :billing_type, :autostop_at, :autostop_interval,
43
+ :next_status, :soa_enabled, :oauth_keys_valid, :oauth_company
44
+
45
+ #==============================================================
46
+ # Constants
47
+ #==============================================================
48
+ ACTIVE_STATUSES = [:running,:stopped,:staged,:provisioning,:starting,:stopping,:updating]
49
+ TERMINATION_STATUSES = [:terminating,:terminated]
50
+
51
+ #==============================================================
52
+ # Associations
53
+ #==============================================================
54
+ belongs_to :owner, class_name: 'MnoEnterprise::Organization'
55
+ belongs_to :app, class_name: 'MnoEnterprise::App'
56
+
57
+ # Define connector_stack?, cloud_stack? etc. methods
58
+ [:cube,:cloud,:connector].each do |stackname|
59
+ define_method("#{stackname}_stack?") do
60
+ self.stack == stackname.to_s
61
+ end
62
+ end
63
+
64
+ scope :active, -> { where('status.in' => ACTIVE_STATUSES) }
65
+ end
66
+
67
+ #==================================================================
68
+ # Class methods
69
+ #==================================================================
70
+ module ClassMethods
71
+ # def some_class_method
72
+ # 'some text'
73
+ # end
74
+ end
75
+
76
+ #==================================================================
77
+ # Instance methods
78
+ #==================================================================
79
+ # Send a request to terminate the AppInstance
80
+ # Alias of destroy
81
+ # TODO: specs
82
+ def terminate
83
+ self.destroy
84
+ end
85
+
86
+ # Return true if the instance can be considered active
87
+ # Route53 DNS propagation may take up to a minute, so we force a minimum of 60 seconds before considering the application online
88
+ def active?
89
+ ACTIVE_STATUSES.include?(self.status.to_sym)
90
+ end
91
+
92
+ def running?
93
+ self.status == 'running'
94
+ end
95
+
96
+ def online?
97
+ running? && [self.created_at, self.started_at].compact.max < 70.seconds.ago
98
+ end
99
+
100
+ end
@@ -0,0 +1,102 @@
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::Concerns::Models::Organization
30
+ extend ActiveSupport::Concern
31
+
32
+ #==================================================================
33
+ # Included methods
34
+ #==================================================================
35
+ # 'included do' causes the included code to be evaluated in the
36
+ # context where it is included rather than being executed in the module's context
37
+ included do
38
+ attributes :uid, :name, :account_frozen, :free_trial_end_at, :soa_enabled, :mails, :logo,
39
+ :latitude, :longitude, :geo_country_code, :geo_state_code, :geo_city, :geo_tz, :geo_currency,
40
+ :meta_data, :industry, :size
41
+
42
+ scope :in_arrears, -> { where(in_arrears?: true) }
43
+
44
+ #================================
45
+ # Associations
46
+ #================================
47
+ has_many :users, class_name: 'MnoEnterprise::User'
48
+ has_many :org_invites, class_name: 'MnoEnterprise::OrgInvite'
49
+ has_many :app_instances, class_name: 'MnoEnterprise::AppInstance'
50
+ has_many :invoices, class_name: 'MnoEnterprise::Invoice'
51
+ has_one :credit_card, class_name: 'MnoEnterprise::CreditCard'
52
+ has_many :teams, class_name: 'MnoEnterprise::Team'
53
+ has_many :dashboards, class_name: 'MnoEnterprise::Impac::Dashboard'
54
+ has_one :raw_last_invoice, class_name: 'MnoEnterprise::Invoice', path: '/last_invoice'
55
+ has_one :app_instances_sync, class_name: 'MnoEnterprise::AppInstancesSync'
56
+ end
57
+
58
+ #==================================================================
59
+ # Class methods
60
+ #==================================================================
61
+ module ClassMethods
62
+ # def some_class_method
63
+ # 'some text'
64
+ # end
65
+ end
66
+
67
+ #==================================================================
68
+ # Instance methods
69
+ #==================================================================
70
+ # Return the list of users + active invites
71
+ # TODO: specs
72
+ def members
73
+ [self.users,self.org_invites.active].flatten
74
+ end
75
+
76
+ # Add a user to the organization with the provided role
77
+ # TODO: specs
78
+ def add_user(user,role = 'Member')
79
+ self.users.create(id: user.id, role: role)
80
+ end
81
+
82
+ def last_invoice
83
+ inv = self.raw_last_invoice
84
+ inv.id ? inv : nil
85
+ end
86
+ # def last_invoice_with_nil
87
+ # last_invoice.respond_to?(:id) ? last_invoice : nil
88
+ # end
89
+ # alias_method_chain :last_invoice, :nil
90
+
91
+ # Remove a user from the organization
92
+ # TODO: specs
93
+ def remove_user(user)
94
+ self.users.destroy(id: user.id)
95
+ end
96
+
97
+ # Change a user role in the organization
98
+ # TODO: specs
99
+ def update_user(user, role = 'Member')
100
+ self.users.update(id: user.id, role: role)
101
+ end
102
+ end
@@ -0,0 +1,279 @@
1
+ require 'prawn'
2
+ require 'prawn/table'
3
+ require 'money'
4
+ require 'deepstruct'
5
+ require 'jwt'
6
+ require 'countries'
7
+ require 'cancancan'
8
+ require 'devise'
9
+ require 'devise/strategies/remote_authenticatable'
10
+ require 'devise_extension'
11
+ require "her"
12
+ require "her_extension/her_orm_adapter"
13
+ require "her_extension/model/orm"
14
+ require "her_extension/model/relation"
15
+ require "her_extension/model/attributes"
16
+ require "her_extension/model/parse"
17
+ require "her_extension/model/associations/association"
18
+ require "her_extension/model/associations/association_proxy"
19
+ require "her_extension/model/associations/has_many_association"
20
+ require "her_extension/middleware/mnoe_api_v1_parse_json"
21
+ require "faraday_middleware"
22
+ require "mno_enterprise/engine"
23
+
24
+ require 'mno_enterprise/database_extendable'
25
+
26
+ require 'mandrill'
27
+ require "mandrill_client"
28
+
29
+ require 'accountingjs_serializer'
30
+
31
+ module MnoEnterprise
32
+
33
+ #==================================================================
34
+ # MnoEnterprise Router
35
+ # Centralizes all URLs available on the Maestrano Enterprise side
36
+ #==================================================================
37
+ class Router
38
+ attr_accessor :terms_url
39
+
40
+ # Customise after_sign_out url
41
+ attr_accessor :after_sign_out_url
42
+
43
+ def terms_url
44
+ @terms_url || '#'
45
+ end
46
+
47
+ def launch_url(id,opts = {})
48
+ host_url("/launch/#{id}",opts)
49
+ end
50
+
51
+ def authorize_oauth_url(id,opts = {})
52
+ host_url("/oauth/#{id}/authorize",opts)
53
+ end
54
+
55
+ def disconnect_oauth_url(id,opts = {})
56
+ host_url("/oauth/#{id}/disconnect",opts)
57
+ end
58
+
59
+ def sync_oauth_url(id,opts = {})
60
+ host_url("/oauth/#{id}/sync",opts)
61
+ end
62
+
63
+ def impac_root_url
64
+ URI.join(MnoEnterprise.impac_api_host,MnoEnterprise.impac_api_root_path)
65
+ end
66
+
67
+ private
68
+ def base_path
69
+ MnoEnterprise.mno_api_root_path
70
+ end
71
+
72
+ def host
73
+ MnoEnterprise.mno_api_host
74
+ end
75
+
76
+ def host_url(path,opts = {})
77
+ url = URI.join(host,"#{base_path}#{path}").to_s
78
+ url += "?#{opts.to_query}" if opts.any?
79
+ url
80
+ end
81
+ end
82
+
83
+ #==================================================================
84
+ # Module definition
85
+ #==================================================================
86
+
87
+ #====================================
88
+ # Tenant
89
+ #====================================
90
+ # Maestrano Enterprise Tenant name
91
+ mattr_accessor :app_name
92
+ @@tenant_name = 'Maestrano Enterprise'
93
+
94
+ # Maestrano Enterprise Default Country
95
+ mattr_accessor :app_country
96
+ @@app_country = 'US'
97
+
98
+ # Maestrano Enterprise Default Currency
99
+ mattr_accessor :app_currency
100
+ @@app_currency = 'USD'
101
+
102
+ # Maestrano Enterprise Tenant ID
103
+ mattr_accessor :tenant_id
104
+ @@tenant_id = nil
105
+
106
+ # Maestrano Enterprise Tenant Key
107
+ mattr_accessor :tenant_key
108
+ @@tenant_key = nil
109
+
110
+ #====================================
111
+ # Impac
112
+ #====================================
113
+ mattr_accessor :impac_api_host
114
+ @@impac_api_host = 'https://api-impac-uat.maestrano.io'
115
+
116
+ mattr_accessor :impac_api_root_path
117
+ @@impac_api_root_path = "/api/v1"
118
+
119
+ #====================================
120
+ # Enterprise API
121
+ #====================================
122
+ # The Maestrano Enterprise API Host
123
+ mattr_accessor :mno_api_host
124
+ @@mno_api_host = "https://api-enterprise.maestrano.com"
125
+
126
+ # The Maestrano Enterprise API Private Host
127
+ # Used within VPCs for making calls to mno_api using
128
+ # private DNS
129
+ mattr_accessor :mno_api_private_host
130
+ @@mno_api_private_host = nil
131
+
132
+ # The Maestrano Enterprise API base path
133
+ mattr_accessor :mno_api_root_path
134
+ @@mno_api_root_path = "/v1"
135
+
136
+ # Hold the Her API configuration (see configure_api method)
137
+ mattr_reader :mnoe_api_v1
138
+ @@mnoe_api_v1 = nil
139
+
140
+ # Hold the Maestrano enterprise router (redirection to central enterprise platform)
141
+ mattr_reader :router
142
+ @@router = Router.new
143
+
144
+
145
+ #====================================
146
+ # Emailing
147
+ #====================================
148
+ # Mandrill Key for sending emails
149
+ # Points to the default maestrano enterprise account
150
+ mattr_accessor :mandrill_key
151
+ @@mandrill_key = 'QcrLVdukhBi7iYrTeWHRPQ'
152
+
153
+ # The support email address
154
+ mattr_accessor :support_email
155
+ @@support_email = "support@example.com"
156
+
157
+ # Default sender name
158
+ mattr_accessor :default_sender_name
159
+ @@default_sender_name = nil
160
+
161
+ # Default sender email
162
+ mattr_accessor :default_sender_email
163
+ @@default_sender_email = "no-reply@example.com"
164
+
165
+ #===============================================
166
+ # Optional Modules
167
+ #===============================================
168
+ # Angular CSRF
169
+ mattr_accessor :include_angular_csrf
170
+ @@include_angular_csrf = false
171
+
172
+ #====================================
173
+ # Third Party Plugins
174
+ #====================================
175
+ mattr_accessor :google_tag_container
176
+ @@google_tag_container = nil
177
+
178
+ #====================================
179
+ # Layout & Styling
180
+ #====================================
181
+ # Nested structure defining the general style of the application
182
+ mattr_accessor :styleguide
183
+ mattr_accessor :style
184
+ @@styleguide = nil
185
+ @@style = nil
186
+
187
+ #====================================
188
+ # Marketplace
189
+ #====================================
190
+ # List of applications that should be offered on
191
+ # the marketplace
192
+ mattr_accessor :marketplace_listing
193
+ @@marketplace_listing = nil
194
+
195
+ #====================================
196
+ # Module Methods
197
+ #====================================
198
+
199
+ # Always reload style in development
200
+ def self.style
201
+ self.configure_styleguide if Rails.env.development?
202
+ @@style
203
+ end
204
+
205
+ # Default way to setup MnoEnterprise. Run rails generate mno-enterprise:install to create
206
+ # a fresh initializer with all configuration values.
207
+ def self.configure
208
+ yield self
209
+ self.configure_styleguide
210
+ self.configure_api
211
+ end
212
+
213
+ # Create a JSON web token with the provided payload
214
+ # E.g.: MnoEnterprise.jwt({ user_id: 'usr-427431' })
215
+ def self.jwt(payload)
216
+ secret = "#{self.tenant_id}:#{self.tenant_key}"
217
+ iat = Time.now.utc.to_i
218
+
219
+ JWT.encode(payload.merge(
220
+ iss: MnoEnterprise.tenant_id,
221
+ iat: iat,
222
+ jit: Digest::MD5.hexdigest("#{secret}:#{iat}")
223
+ ), secret)
224
+ end
225
+
226
+ private
227
+ # Return the options to use in the setup of the API
228
+ def self.api_options
229
+ api_host = @@mno_api_private_host || @@mno_api_host
230
+ {
231
+ url: "#{URI.join(api_host,@@mno_api_root_path).to_s}",
232
+ send_only_modified_attributes: true
233
+ }
234
+ end
235
+
236
+ # Load the provided styleguide hash into nested structure or load a default one
237
+ def self.configure_styleguide
238
+ # Load default gem configuration
239
+ hash = YAML.load(File.read(File.join(MnoEnterprise::Engine.root,'config','styleguide.yml')))
240
+
241
+ # Load default app styleguide, unless explicitly specified
242
+ default_path = File.join(Rails.root,'config','mno_enterprise_styleguide.yml')
243
+ if !@@styleguide && File.exists?(default_path)
244
+ @@styleguide = YAML.load(File.read(default_path))
245
+ end
246
+
247
+ @@styleguide.is_a?(Hash) && hash.deep_merge!(@@styleguide)
248
+ @@style = DeepStruct.wrap(hash)
249
+ end
250
+
251
+ # Configure the Her for Maestrano Enterprise API V1
252
+ def self.configure_api
253
+ # Configure HER for Maestrano Enterprise Endpoints
254
+ @@mnoe_api_v1 = Her::API.new
255
+ @@mnoe_api_v1.setup self.api_options do |c|
256
+ # Request
257
+ c.use Faraday::Request::BasicAuthentication, @@tenant_id, @@tenant_key
258
+ # c.use Faraday::Request::UrlEncoded
259
+ c.request :json
260
+
261
+ # Instrumentation in development
262
+ c.use :instrumentation if Rails.env.development?
263
+
264
+ # Response
265
+ c.use Her::Middleware::MnoeApiV1ParseJson
266
+
267
+ # Adapter
268
+ c.use Faraday::Adapter::NetHttpNoProxy
269
+ end
270
+ end
271
+ end
272
+
273
+ # Instrumentation in development
274
+ ActiveSupport::Notifications.subscribe('request.faraday') do |name, starts, ends, _, env|
275
+ url = env[:url]
276
+ http_method = env[:method].to_s.upcase
277
+ duration = ends - starts
278
+ Rails.logger.debug '[%s] %s %s (%.3f s)' % [url.host, http_method, url.request_uri, duration]
279
+ end if Rails.env.development?