api_models 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +2 -0
  4. data/lib/api_models/version.rb +5 -0
  5. data/lib/api_models.rb +68 -0
  6. data/lib/models/account.rb +39 -0
  7. data/lib/models/agent.rb +439 -0
  8. data/lib/models/app.rb +18 -0
  9. data/lib/models/app47_cache.rb +69 -0
  10. data/lib/models/app_active_build.rb +32 -0
  11. data/lib/models/app_policy.rb +24 -0
  12. data/lib/models/app_shield_policy.rb +35 -0
  13. data/lib/models/authorized_user_policy.rb +44 -0
  14. data/lib/models/b2b_app.rb +8 -0
  15. data/lib/models/cat/customer.rb +9 -0
  16. data/lib/models/cat/customer_device.rb +10 -0
  17. data/lib/models/cl/customer.rb +9 -0
  18. data/lib/models/cl/customer_device.rb +10 -0
  19. data/lib/models/commerce_app_store.rb +8 -0
  20. data/lib/models/concerns/app47_app_analyzable.rb +46 -0
  21. data/lib/models/concerns/app47_app_buildable.rb +46 -0
  22. data/lib/models/concerns/app47_app_configurable.rb +34 -0
  23. data/lib/models/concerns/app47_app_policies.rb +59 -0
  24. data/lib/models/concerns/app47_cdn_url.rb +50 -0
  25. data/lib/models/concerns/app47_email_sendable.rb +29 -0
  26. data/lib/models/concerns/app47_logger.rb +109 -0
  27. data/lib/models/concerns/checkin_able.rb +28 -0
  28. data/lib/models/concerns/searchable.rb +54 -0
  29. data/lib/models/configuration_constraint.rb +22 -0
  30. data/lib/models/configuration_group.rb +50 -0
  31. data/lib/models/configuration_rule.rb +58 -0
  32. data/lib/models/device.rb +124 -0
  33. data/lib/models/external_app.rb +15 -0
  34. data/lib/models/gehc/customer.rb +17 -0
  35. data/lib/models/gehc/customer_device.rb +23 -0
  36. data/lib/models/group.rb +40 -0
  37. data/lib/models/internal_app.rb +11 -0
  38. data/lib/models/metric_data_job.rb +16 -0
  39. data/lib/models/option.rb +37 -0
  40. data/lib/models/pin_code_policy.rb +50 -0
  41. data/lib/models/platform.rb +26 -0
  42. data/lib/models/platform_model.rb +14 -0
  43. data/lib/models/product_app.rb +22 -0
  44. data/lib/models/product_support_app.rb +19 -0
  45. data/lib/models/queue_manager.rb +67 -0
  46. data/lib/models/redis_configuration.rb +137 -0
  47. data/lib/models/sso_ad_group.rb +7 -0
  48. data/lib/models/sso_ad_server.rb +13 -0
  49. data/lib/models/sso_ad_user.rb +13 -0
  50. data/lib/models/sso_azure_server.rb +18 -0
  51. data/lib/models/sso_directory_group.rb +13 -0
  52. data/lib/models/sso_directory_server.rb +21 -0
  53. data/lib/models/sso_google_server.rb +13 -0
  54. data/lib/models/sso_ldap_group.rb +8 -0
  55. data/lib/models/sso_ldap_rest_server.rb +34 -0
  56. data/lib/models/sso_ldap_server.rb +19 -0
  57. data/lib/models/sso_ldap_user.rb +7 -0
  58. data/lib/models/sso_oauth_server.rb +16 -0
  59. data/lib/models/sso_saml_v2_server.rb +25 -0
  60. data/lib/models/sso_server.rb +38 -0
  61. data/lib/models/sso_user.rb +13 -0
  62. data/lib/models/system_configuration.rb +92 -0
  63. data/lib/models/time_bomb_policy.rb +138 -0
  64. data/lib/models/user.rb +53 -0
  65. data/lib/models/user_app_permission.rb +16 -0
  66. data/lib/models/user_device.rb +83 -0
  67. data/lib/models/version_management_policy.rb +113 -0
  68. data/lib/models/web_app.rb +12 -0
  69. metadata +408 -0
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Easily fetch the redis configuration from redis.yml in the config directory.
5
+ # There are several formats to support
6
+ #
7
+ # URL with single server
8
+ # development:
9
+ # url: 'redis://localhost:6379/0'
10
+ #
11
+ # Host/port combination for single server
12
+ # development:
13
+ # host: localhost
14
+ # port: 6379
15
+ # db: 0
16
+ #
17
+ # Sentinel
18
+ # development:
19
+ # master: production
20
+ # sentinels:
21
+ # - host1:6379
22
+ # - host2:6379
23
+ # - host3:6379
24
+ # role: master
25
+ #
26
+ # Available for all options
27
+ # connect_timeout: 0.2
28
+ # read_timeout: 0.2
29
+ # write_timeout: 0.2
30
+ # timeout: 1
31
+ #
32
+ class RedisConfiguration
33
+ #
34
+ # Methods are static
35
+ #
36
+ class << self
37
+ #
38
+ # Load the configuration using the given DB
39
+ #
40
+ # Trying first the URL, then host, then sentinel, then default method
41
+ #
42
+ def load(database = nil)
43
+ load_url(database) || load_host(database) || load_sentinel(database) || load_default(database)
44
+ end
45
+
46
+ private
47
+
48
+ #
49
+ # Load the base set of parameters from the config file
50
+ #
51
+ def load_base(raw_config)
52
+ base = {}
53
+ %i[connect_timeout namespace read_timeout write_timeout timeout].each do |key|
54
+ base[key] = raw_config[key.to_s] unless raw_config[key.to_s].nil?
55
+ end
56
+ base
57
+ end
58
+
59
+ #
60
+ # Load a default configuration with the given database
61
+ #
62
+ def load_default(database = 0)
63
+ { host: '127.0.0.1', port: 6_379, db: (database || 0) }
64
+ end
65
+
66
+ #
67
+ # Load the url
68
+ #
69
+ def load_url(database = 0)
70
+ raw_config = load_file
71
+ return if raw_config.nil? || raw_config['url'].nil?
72
+
73
+ config = load_base(raw_config)
74
+ config[:url] = raw_config['url']
75
+ config[:db] = (database || 0)
76
+ config
77
+ end
78
+
79
+ #
80
+ # Load the given host
81
+ #
82
+ def load_host(database = nil)
83
+ raw_config = load_file
84
+ return if raw_config.nil? || raw_config['host'].nil?
85
+
86
+ config = load_base(raw_config)
87
+ config[:host] = raw_config['host']
88
+ config[:port] = raw_config['port'] || 6_379
89
+ config[:db] = database || raw_config['db'] || 0
90
+ config
91
+ end
92
+
93
+ #
94
+ # Load the sentinel configuration
95
+ #
96
+ def load_sentinel(database = 0)
97
+ raw_config = load_file
98
+ return if raw_config.nil? || raw_config['master'].nil?
99
+
100
+ config = load_base(raw_config)
101
+ config[:url] = "redis://#{raw_config['master']}"
102
+ config[:sentinels] = raw_config['sentinels'].collect do |sentinel|
103
+ parts = sentinel.split(':')
104
+ host = parts.first
105
+ port = parts.count.eql?(2) ? parts.last : 26_379
106
+ { host: host, port: port }
107
+ end
108
+ config[:db] = database || 0
109
+ config[:role] = raw_config['role'] || 'master'
110
+ config
111
+ end
112
+
113
+ #
114
+ # Return the config file
115
+ #
116
+ def config_file_path
117
+ File.expand_path([ENV['APP_CONFIG_DIR'], 'config', 'redis.yml'].compact.join('/'))
118
+ end
119
+
120
+ #
121
+ # Load the config/redis.yml and return the environment name
122
+ #
123
+ def load_file
124
+ config = nil
125
+ file_path = config_file_path
126
+ if File.exist? file_path
127
+ yaml_data = YAML.load_file(file_path)
128
+ config = yaml_data[ENV['RACK_ENV']] if yaml_data
129
+ end
130
+
131
+ config
132
+ rescue StandardError => error
133
+ puts "Error loading #{config_file_path} file", error
134
+ nil # return nothing if there is an error
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Active Directory Group
5
+ #
6
+ class SsoAdGroup < SsoDirectoryGroup
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Connection to AD Server
5
+ #
6
+ class SsoAdServer < SsoDirectoryServer
7
+ #
8
+ # Return the AD Server display name.
9
+ #
10
+ def display_name
11
+ 'AD Server'
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Active Directory (AD) User
5
+ #
6
+ class SsoAdUser < SsoUser
7
+ #
8
+ # Fields
9
+ #
10
+ field :dn, type: String
11
+ field :user_id, type: String
12
+ field :last_synchronized_at, type: DateTime
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Azure SSO Server
5
+ #
6
+ class SsoAzureServer < SsoOauthServer
7
+ #
8
+ # Fields
9
+ #
10
+ field :tenant_id, type: String
11
+
12
+ #
13
+ # Google Server SSO name
14
+ #
15
+ def display_name
16
+ 'Azure OAuth 2.0'
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Base class for SSO directory (AD/LDAP) group
5
+ #
6
+ class SsoDirectoryGroup < Group
7
+ #
8
+ # Fields
9
+ #
10
+ field :dn, type: String
11
+ field :synchronize, type: Boolean, default: false
12
+ field :auto_approve_devices, type: Boolean, default: true
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Base class for SSO Directory servers, i.e., AD and LDAP
5
+ #
6
+ class SsoDirectoryServer < SsoServer
7
+ # fields
8
+ field :ssl, type: Boolean, default: false
9
+ field :currently_syncing, type: Boolean, default: false
10
+ field :server_name, type: String
11
+ field :port, type: String, default: '389'
12
+ field :username, type: String
13
+ field :password, type: String
14
+ field :frequency, type: String, default: '24'
15
+ field :last_sync_time, type: DateTime
16
+ field :last_sync_message, type: String
17
+ field :treebase, type: String
18
+ field :user_identifier, type: String
19
+ # relationships
20
+ has_many :groups, inverse_of: :sso_server, dependent: :nullify
21
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Google OAuth 2.0
5
+ #
6
+ class SsoGoogleServer < SsoOauthServer
7
+ #
8
+ # Google Server SSO name
9
+ #
10
+ def display_name
11
+ 'Google OAuth 2.0'
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Light Weight Active Directory Group
5
+ #
6
+ class SsoLdapGroup < SsoDirectoryGroup
7
+ # Marker class for now
8
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Interact with the Ldap Restful API for authentication
5
+ #
6
+ class SsoLdapRestServer < SsoServer
7
+ #
8
+ # Fields
9
+ #
10
+ field :auth_url, type: String
11
+ field :auth_bearer_token, type: String
12
+ field :auth_params, type: String
13
+ field :search_url, type: String
14
+ field :search_bearer_token, type: String
15
+ field :search_key_name, type: String, default: 'staff_id'
16
+ field :image_url, type: String
17
+ field :image_bearer_token, type: String
18
+ field :image_api_key, type: String
19
+
20
+ #
21
+ # Display name for this server, should be overriden by concrete implementations.
22
+ #
23
+ def display_name
24
+ 'LDAP Rest API Server'
25
+ end
26
+
27
+ #
28
+ # Using the appropriate SSO server configuration obtain the
29
+ # the user profile address
30
+ #
31
+ def user_profile(user_id)
32
+ account.users.find(user_id)
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Hold the configuration for LDAP synchronization, Using the ad_configuration logic to sync with server
5
+ #
6
+ class SsoLdapServer < SsoDirectoryServer
7
+ #
8
+ # Fields
9
+ #
10
+ field :user_filter, type: String, default: 'ou=users'
11
+ field :group_filter, type: String, default: 'ou=groups'
12
+ field :group_identifier, type: String, default: 'gidNumber'
13
+ #
14
+ # Return the display name for this server type
15
+ #
16
+ def display_name
17
+ 'LDAP Server'
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Light Weight Directory Access Protocol (LDAP) User
5
+ #
6
+ class SsoLdapUser < SsoAdUser
7
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # OAuth 2.0 Server
5
+ #
6
+ class SsoOauthServer < SsoServer
7
+ # Fields
8
+ field :server_url, type: String
9
+ field :auth_url, type: String
10
+ field :token_url, type: String
11
+ field :profile_url, type: String
12
+ field :redirect_path, type: String, default: 'eas/auth/oauth'
13
+ field :client_id, type: String
14
+ field :client_secret, type: String
15
+ field :scopes, type: String
16
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # SSO SAML V2 Server
5
+ #
6
+ class SsoSamlV2Server < SsoServer
7
+ #
8
+ # Fields
9
+ #
10
+ field :idp_url, type: String
11
+ field :idp_xml, type: String
12
+ field :xml_last_fetched_at, type: Time, default: Time.now.utc
13
+ field :xml_cache_days, type: Integer, default: 365
14
+ field :name_identifier_format, type: String, default: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
15
+ field :name_attribute_key, type: String
16
+ field :email_attribute_key, type: String
17
+ field :groups_attribute_key, type: String
18
+
19
+ #
20
+ # Display name for this server, should be overriden by concrete implementations.
21
+ #
22
+ def display_name
23
+ 'SAML V2 Server'
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Base server container for an account which can have 0..N sso servers configured.
5
+ #
6
+ class SsoServer
7
+ include Mongoid::Document
8
+ include Mongoid::Timestamps
9
+ include App47Logger
10
+ #
11
+ # fields
12
+ #
13
+ field :active, type: Boolean, default: false
14
+ field :external_authentication, type: Boolean, default: false
15
+ field :name, type: String
16
+ field :default_user_invitation_message, type: String
17
+ #
18
+ # relationships
19
+ #
20
+ belongs_to :account, inverse_of: :sso_servers
21
+ has_many :users, inverse_of: :sso_server, dependent: :nullify, class_name: 'SsoUser'
22
+ has_many :groups, inverse_of: :sso_server, class_name: 'Group'
23
+
24
+ #
25
+ # Display name for this server, should be overriden by concrete implementations.
26
+ #
27
+ def display_name
28
+ 'SSO Server'
29
+ end
30
+
31
+ #
32
+ # Using the appropriate SSO server configuration obtain the
33
+ # the user profile address, this should be implemented by the child class.
34
+ #
35
+ def user_profile(_code)
36
+ raise 'Failed to retrieve user profile from provider'
37
+ end
38
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Base class for a SSO User
5
+ #
6
+ class SsoUser < User
7
+ field :session_hours_length, type: Integer, default: 24
8
+ field :last_code, type: String
9
+ #
10
+ # Relationships
11
+ #
12
+ belongs_to :sso_server, class_name: 'SsoServer', inverse_of: :users
13
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # The System configuration. Various configuration items that can be updated/defined at run time instead
5
+ # of AppConfiguration that is defining things statically in code.
6
+ #
7
+ # In hindsight (being 20/20) this should have been named stack_configuration as now the stack UI is
8
+ # what allows the administrator to update/configure this information.
9
+ #
10
+ # Use of this class allows you to simply ask for the configuration parameter directly without
11
+ # first having to get an instance of it.
12
+ #
13
+ # SystemConfiguration.queue_impl #=> 'RedisQueue'
14
+ #
15
+ # This method only is allowed for accessors, you should NEVER set values on the SystemConfiguration
16
+ # unless you are updating via the Admin or Stack UI, or during testing to setup a specific configuration
17
+ # for that.
18
+ #
19
+ class SystemConfiguration
20
+ include Mongoid::Document
21
+ include Mongoid::Timestamps
22
+
23
+ field :environment, type: String, default: 'test'
24
+ # Queue Implementation
25
+ field :queue_impl, type: String, default: 'DelayedJob'
26
+ field :queue_base, type: String, default: 'test'
27
+ # AWS
28
+ field :aws_access_key_id, type: String
29
+ field :aws_secret_access_key, type: String
30
+ field :s3_bucket_name, type: String
31
+ field :cdn_url, type: String
32
+ # Redis
33
+ field :redis_queue_url, type: String, default: 'redis://localhost:6379/10'
34
+ # URLs
35
+ field :webui_url, type: String, default: 'https://cirrus.app47.com'
36
+ field :api_url, type: String, default: 'https://api.app47.mobi'
37
+ field :slack_api_url, type: String
38
+ field :company_name, type: String, default: 'App47'
39
+ field :api_version, type: String, default: '3.0'
40
+ #
41
+ # Validations
42
+ #
43
+ validates :environment, presence: true, uniqueness: true
44
+ #
45
+ # Call backs
46
+ #
47
+ after_save :clear_cache
48
+
49
+ class << self
50
+ #
51
+ # Fetch the system configuration based on environment name. First try the rails cache
52
+ # if not there, then go to the database.
53
+ #
54
+ # Also, if an argument error is thrown, then just fetch from the database.
55
+ #
56
+ def configuration
57
+ cache_key = "SystemConfiguration::#{ENV['RACK_ENV']}"
58
+
59
+ begin
60
+ config = App47Cache.get(cache_key) || SystemConfiguration.where(environment: ENV['RACK_ENV']).first
61
+ rescue ArgumentError
62
+ # This seems to happen in testing relative to Country, when it does, remove
63
+ # ourselves from the cache and return the DB entry.
64
+ App47Cache.delete cache_key
65
+ config = SystemConfiguration.where(environment: ENV['RACK_ENV']).first
66
+ end
67
+ if config.nil?
68
+ SystemConfiguration.create
69
+ else
70
+ App47Cache.set(cache_key, config, 300)
71
+ config
72
+ end
73
+ end
74
+
75
+ def method_missing(method, *_args)
76
+ configuration.send method
77
+ end
78
+
79
+ def respond_to_missing?(method_name, _include_private = false)
80
+ SystemConfiguration.fields.include?(method_name.to_sym)
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ #
87
+ # Clear the cache when the object is saved
88
+ #
89
+ def clear_cache
90
+ App47Cache.delete "SystemConfiguration::#{ENV['RACK_ENV']}"
91
+ end
92
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Time Bomb policy for this app
5
+ #
6
+ class TimeBombPolicy < AppPolicy
7
+ #
8
+ # Constants
9
+ #
10
+ OPTION_KILL = 'kill' unless defined? OPTION_KILL
11
+ OPTION_WIPE = 'wipe' unless defined? OPTION_WIPE
12
+ BOMB_OPTIONS = [OPTION_KILL, OPTION_WIPE].freeze unless defined? BOMB_OPTIONS
13
+ OPTION_AM = 'am' unless defined? OPTION_AM
14
+ OPTION_PM = 'pm' unless defined? OPTION_PM
15
+ TIME_OPTIONS = [OPTION_AM, OPTION_PM].freeze unless defined? TIME_OPTIONS
16
+ HOURS_TO_MS = 60 * 60 * 1000
17
+ UNIT_HOURS = 'hours' unless defined? UNIT_HOURS
18
+ UNIT_DAYS = 'days' unless defined? UNIT_DAYS
19
+ UNIT_WEEKS = 'weeks' unless defined? UNIT_WEEKS
20
+ UNIT_MONTHS = 'months' unless defined? UNIT_MONTHS
21
+ ALL_UNITS = [UNIT_HOURS, UNIT_DAYS, UNIT_WEEKS, UNIT_MONTHS].freeze unless defined? ALL_UNITS
22
+ #
23
+ # fields
24
+ #
25
+ field :expire_at, type: Integer
26
+ field :expiration_type, type: String, default: OPTION_KILL
27
+ field :expiration_message, type: String, default: 'The application has expired'
28
+ field :expiration_time_zone, type: String, default: 'local'
29
+ # field :kill_after_hours, type: Integer
30
+ field :kill_after_interval, type: Integer
31
+ field :kill_after_unit, type: String
32
+ field :wipe_after_interval, type: Integer
33
+ field :wipe_after_unit, type: String
34
+ # field :wipe_after_hours, type: Integer
35
+ field :inactivity_message, type: String, default: 'The application has been inactive for too long a period'
36
+ field :start_time, type: String
37
+ field :end_time, type: String
38
+ field :time_window_time_zone, type: String, default: 'local'
39
+ field :days, type: String, default: 'MTWHFSU'
40
+ field :time_window_message, type: String, default: 'The application is trying to run outside of the allowed time'
41
+ field :time_window_active, type: Boolean, default: false
42
+ field :expiration_active, type: Boolean, default: false
43
+ field :check_in_active, type: Boolean, default: false
44
+
45
+ #
46
+ # return the policy hash for this agent
47
+ #
48
+ def enforce_policy(agent)
49
+ policy = super.merge(enforce_time_bomb: 0)
50
+ return policy unless active?
51
+
52
+ time_bomb_policies = expiration_policy.merge(check_in_policy).merge(time_window_policy)
53
+
54
+ if time_bomb_policies.present?
55
+ policy[:time_bomb] = time_bomb_policies
56
+ policy[:enforce_time_bomb] = 1
57
+ end
58
+
59
+ policy
60
+ rescue StandardError => error
61
+ log_error("Unable to build time bomb policy for agent: #{agent.inspect} - #{inspect}", error)
62
+ # Return the default policy
63
+ { enforce_time_bomb: 0 }
64
+ end
65
+
66
+ #
67
+ # Determine if we should enforce time of day policy
68
+ #
69
+ def time_window_policy
70
+ return {} unless time_window_active?
71
+
72
+ {
73
+ time_window:
74
+ { start_time: start_time,
75
+ end_time: end_time,
76
+ time_zone: time_window_time_zone,
77
+ days: days,
78
+ message: time_window_message }
79
+ }
80
+ rescue StandardError => error
81
+ log_error("Unable to build time bomb time window policy: #{inspect}", error)
82
+ {}
83
+ end
84
+
85
+ #
86
+ # determine if we should enforce the expire at policy
87
+ #
88
+ def expiration_policy
89
+ return {} unless expiration_active? && expire_at.present?
90
+
91
+ {
92
+ expire:
93
+ {
94
+ expiration_after: expire_at,
95
+ time_zone: expiration_time_zone,
96
+ type: expiration_type,
97
+ message: expiration_message
98
+ }
99
+ }
100
+ rescue StandardError => error
101
+ log_error("Unable to build time bomb expire at policy: #{inspect}", error)
102
+ {}
103
+ end
104
+
105
+ #
106
+ # Determine if the check in, or "Time bomb" policy should be enforced
107
+ #
108
+ def check_in_policy
109
+ return {} unless check_in_active
110
+
111
+ policy = { message: inactivity_message }
112
+ policy[:kill_after] = check_in_milliseconds(:kill) if kill_after_interval.present?
113
+ policy[:wipe_after] = check_in_milliseconds(:wipe) if wipe_after_interval.present?
114
+ { check_in: policy }
115
+ rescue StandardError => error
116
+ log_error("Unable to build time bomb check in policy: #{inspect}", error)
117
+ {}
118
+ end
119
+
120
+ #
121
+ # Return the number of milli seconds between check ins
122
+ #
123
+ def check_in_milliseconds(type)
124
+ interval = send("#{type}_after_interval").to_i
125
+ case send "#{type}_after_unit"
126
+ when UNIT_HOURS
127
+ interval * HOURS_TO_MS
128
+ when UNIT_DAYS
129
+ 24 * interval * HOURS_TO_MS
130
+ when UNIT_WEEKS
131
+ 7 * 24 * interval * HOURS_TO_MS
132
+ when UNIT_MONTHS
133
+ 30 * 24 * interval * HOURS_TO_MS
134
+ else
135
+ raise "Unknown unit: #{type}"
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # A user in the system is someone who has access to the enterprise app store
5
+ #
6
+ class User
7
+ include Mongoid::Document
8
+ include Mongoid::Timestamps
9
+ include App47EmailSendable
10
+ include App47Logger
11
+ include Searchable
12
+ #
13
+ # Fields
14
+ #
15
+ field :name, type: String
16
+ field :active, type: Boolean, default: true
17
+ field :pin_code, type: String
18
+ field :pin_code_locked, type: Boolean, default: false
19
+ #
20
+ # Relationships
21
+ #
22
+ belongs_to :account, inverse_of: :users
23
+ # has_and_belongs_to_many :groups, dependent: :nullify
24
+ has_and_belongs_to_many :allowed_apps, class_name: 'App', dependent: :nullify, inverse_of: :user_apps
25
+ has_and_belongs_to_many :test_apps, class_name: 'App', dependent: :nullify, inverse_of: :test_users
26
+ has_many :app_permissions, class_name: 'UserAppPermission', dependent: :destroy
27
+ has_many :devices, class_name: 'UserDevice'
28
+
29
+ #
30
+ # Return the unique set of application ids for this given user
31
+ #
32
+ def allowed_app_set
33
+ app_permissions.collect(&:app) + account.apps.distinct_all_users
34
+ end
35
+
36
+ #
37
+ # Find a user device by safely trying a number of approaches
38
+ # 1. By ID
39
+ # 2. By unique identifier
40
+ # 3. By app47 identifier
41
+ # 4. By token
42
+ #
43
+ def find_device_by(device_id)
44
+ raise 'Invalid ID' if device_id.blank?
45
+
46
+ devices.where(_id: device_id).first ||
47
+ devices.where(unique_identifier: device_id).first ||
48
+ devices.where(app47_identifier: device_id).first ||
49
+ devices.where(token: device_id).first
50
+ rescue StandardError
51
+ nil
52
+ end
53
+ end