mno-enterprise-core 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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?