xolo-server 1.0.0 → 2.0.2

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +42 -4
  3. data/bin/xoloserver +3 -0
  4. data/data/client/xolo +1233 -0
  5. data/lib/optimist_with_insert_blanks.rb +1216 -0
  6. data/lib/xolo/core/base_classes/configuration.rb +238 -0
  7. data/lib/xolo/core/base_classes/server_object.rb +112 -0
  8. data/lib/xolo/core/base_classes/title.rb +884 -0
  9. data/lib/xolo/core/base_classes/version.rb +641 -0
  10. data/lib/xolo/core/constants.rb +85 -0
  11. data/lib/xolo/core/exceptions.rb +52 -0
  12. data/lib/xolo/core/json_wrappers.rb +43 -0
  13. data/lib/xolo/core/loading.rb +59 -0
  14. data/lib/xolo/core/output.rb +292 -0
  15. data/lib/xolo/core/security_cmd.rb +128 -0
  16. data/lib/xolo/core/version.rb +21 -0
  17. data/lib/xolo/core.rb +47 -0
  18. data/lib/xolo/server/app.rb +7 -0
  19. data/lib/xolo/server/configuration.rb +243 -38
  20. data/lib/xolo/server/constants.rb +10 -0
  21. data/lib/xolo/server/helpers/auth.rb +19 -2
  22. data/lib/xolo/server/helpers/autopkg.rb +157 -0
  23. data/lib/xolo/server/helpers/client_data.rb +90 -60
  24. data/lib/xolo/server/helpers/file_transfers.rb +412 -82
  25. data/lib/xolo/server/helpers/jamf_pro.rb +31 -7
  26. data/lib/xolo/server/helpers/log.rb +2 -0
  27. data/lib/xolo/server/helpers/maintenance.rb +1 -0
  28. data/lib/xolo/server/helpers/notification.rb +4 -3
  29. data/lib/xolo/server/helpers/pkg_signing.rb +16 -12
  30. data/lib/xolo/server/helpers/progress_streaming.rb +9 -12
  31. data/lib/xolo/server/helpers/subscriptions.rb +119 -0
  32. data/lib/xolo/server/helpers/titles.rb +27 -3
  33. data/lib/xolo/server/helpers/versions.rb +23 -11
  34. data/lib/xolo/server/mixins/changelog.rb +9 -16
  35. data/lib/xolo/server/mixins/title_jamf_access.rb +375 -390
  36. data/lib/xolo/server/mixins/title_ted_access.rb +50 -8
  37. data/lib/xolo/server/mixins/version_jamf_access.rb +118 -129
  38. data/lib/xolo/server/mixins/version_ted_access.rb +34 -4
  39. data/lib/xolo/server/object_locks.rb +2 -1
  40. data/lib/xolo/server/routes/auth.rb +2 -2
  41. data/lib/xolo/server/routes/jamf_pro.rb +11 -1
  42. data/lib/xolo/server/routes/maint.rb +2 -1
  43. data/lib/xolo/server/routes/subscriptions.rb +126 -0
  44. data/lib/xolo/server/routes/title_editor.rb +1 -1
  45. data/lib/xolo/server/routes/titles.rb +26 -11
  46. data/lib/xolo/server/routes/uploads.rb +0 -14
  47. data/lib/xolo/server/routes/versions.rb +14 -13
  48. data/lib/xolo/server/routes.rb +15 -23
  49. data/lib/xolo/server/title.rb +100 -77
  50. data/lib/xolo/server/version.rb +178 -18
  51. data/lib/xolo/server.rb +8 -0
  52. metadata +20 -11
@@ -48,6 +48,19 @@ module Xolo
48
48
  # @return [void]
49
49
  ##########################
50
50
  def create_patch_in_ted
51
+ if subscribed?
52
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor patch creation"
53
+ return
54
+ end
55
+
56
+ # if the patch exists, remove and recreate it
57
+ if ted_patch
58
+ progress "Title Editor: Patch '#{version}' of SoftwareTitle '#{title}' already exists, removing & readding it..."
59
+ ted_title.patches.delete_patch ted_patch.patchId
60
+ sleep 2
61
+ ted_patch(refresh: true)
62
+ end
63
+
51
64
  progress "Title Editor: Creating Patch '#{version}' of SoftwareTitle '#{title}'", log: :info
52
65
  ted_title.patches.add_patch(
53
66
  version: version,
@@ -62,6 +75,9 @@ module Xolo
62
75
  set_patch_capabilites
63
76
  set_ted_patch_component_criteria ttl_obj: title_object
64
77
 
78
+ enable_ted_patch
79
+ title_object.enable_ted_title
80
+
65
81
  self.ted_id_number = new_patch.patchId
66
82
  end
67
83
 
@@ -72,6 +88,11 @@ module Xolo
72
88
  # @return [void]
73
89
  ##########################
74
90
  def update_patch_in_ted
91
+ if subscribed?
92
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor patch update"
93
+ return
94
+ end
95
+
75
96
  progress "Title Editor: Updating Patch '#{version}' SoftwareTitle '#{title}'", log: :info
76
97
 
77
98
  Xolo::Server::Version::ATTRIBUTES.each do |attr, deets|
@@ -94,6 +115,9 @@ module Xolo
94
115
  # those are handled by the title object calling the same method
95
116
  #
96
117
  # set_ted_patch_component_criteria ttl_obj: title_object
118
+
119
+ enable_ted_patch
120
+ title_object.enable_ted_title
97
121
  end
98
122
 
99
123
  # Set any killapps for this version in the title editor.
@@ -235,9 +259,6 @@ module Xolo
235
259
  comp = ted_patch.component
236
260
 
237
261
  ea_name ? set_ea_component(comp, ea_name) : set_app_component(comp, app_name, app_bundle_id)
238
-
239
- # SHouldn't be needed here, is called in both create and update
240
- # enable_ted_patch
241
262
  end
242
263
 
243
264
  # get the param values for patch component criteria from the title object,
@@ -337,12 +358,19 @@ module Xolo
337
358
  # @return [String] the URL for the Title Editor Web App page for this patch
338
359
  ###################################
339
360
  def ted_patch_url
361
+ return unless managed?
362
+
340
363
  "https://#{Xolo::Server.config.ted_hostname}/patches/#{ted_id_number}"
341
364
  end
342
365
 
343
366
  # Ensure all the TEd items for this version are correct based on the server data.
344
367
  #########################
345
368
  def repair_ted_patch
369
+ if subscribed?
370
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor patch repair"
371
+ return
372
+ end
373
+
346
374
  progress "Title Editor: Repairing Patch '#{version}' of SoftwareTitle '#{title}'", log: :info
347
375
 
348
376
  Xolo::Server::Version::ATTRIBUTES.each do |attr, deets|
@@ -361,7 +389,9 @@ module Xolo
361
389
  set_patch_killapps
362
390
  set_patch_capabilites
363
391
  set_ted_patch_component_criteria ttl_obj: title_object
364
- enable_ted_patch unless ted_patch(refresh: true).enabled?
392
+ enable_ted_patch
393
+
394
+ title_object.enable_ted_title
365
395
  end
366
396
 
367
397
  end # VersionTedAccess
@@ -27,7 +27,8 @@ module Xolo
27
27
  end
28
28
 
29
29
  # How many seconds are update locks valid for?
30
- OBJECT_LOCK_LIMIT = 60 * 60
30
+ # 15 min
31
+ OBJECT_LOCK_LIMIT = 60 * 15
31
32
 
32
33
  # The locks for titles and versions - when they are being created or updated
33
34
  # they appear in this data structure with an expiration timestamp.
@@ -16,7 +16,7 @@ module Xolo
16
16
 
17
17
  module Auth
18
18
 
19
- # This is how we 'mix in' modules to Sinatra servers:
19
+ # This is how we 'extend' modules to Sinatra servers:
20
20
  # We make them extentions here with
21
21
  # extend Sinatra::Extension (from sinatra-contrib)
22
22
  # and then 'register' them in the server with
@@ -33,7 +33,7 @@ module Xolo
33
33
  # Auth a Xolo Admin via Jamf API login
34
34
  # Must be a member of the Jamf Admin group
35
35
  # named in Xolo::Server.config.admin_jamf_group
36
- # before
36
+ # NOTE: This cannot be an API Client - must be a real user account
37
37
  ###################
38
38
  post '/auth/login' do
39
39
  request.body.rewind
@@ -16,7 +16,7 @@ module Xolo
16
16
 
17
17
  module JamfPro
18
18
 
19
- # This is how we 'mix in' modules to Sinatra servers
19
+ # This is how we 'extend' modules to Sinatra servers
20
20
  # for route definitions and similar things
21
21
  #
22
22
  # (things to be 'included' for use in route and view processing
@@ -80,6 +80,16 @@ module Xolo
80
80
  jcnx&.disconnect
81
81
  end
82
82
 
83
+ # A list of all currently available titles that can be subscribed to
84
+ ###############
85
+ get '/jamf/available-titles-for-subscription' do
86
+ log_debug "Jamf: Fetching titles available for subscription for #{session[:admin]}"
87
+ jcnx = jamf_cnx
88
+ body available_titles_for_subscription
89
+ ensure
90
+ jcnx&.disconnect
91
+ end
92
+
83
93
  end # Module
84
94
 
85
95
  end # Routes
@@ -16,7 +16,7 @@ module Xolo
16
16
 
17
17
  module Maint
18
18
 
19
- # This is how we 'mix in' modules to Sinatra servers:
19
+ # This is how we 'extend' modules to Sinatra servers:
20
20
  # We make them extentions here with
21
21
  # extend Sinatra::Extension (from sinatra-contrib)
22
22
  # and then 'register' them in the server with
@@ -52,6 +52,7 @@ module Xolo
52
52
  uptime: uptime_secs.pix_humanize_secs,
53
53
  uptime_secs: uptime_secs,
54
54
  app_env: Xolo::Server.app_env,
55
+ test_server: Xolo::Server.test_server?,
55
56
  data_dir: Xolo::Server::DATA_DIR,
56
57
  log_file: Xolo::Server::Log::LOG_FILE,
57
58
  log_level: Xolo::Server::Log::LEVELS[Xolo::Server.logger.level],
@@ -0,0 +1,126 @@
1
+ # Copyright 2025 Pixar
2
+ #
3
+ # Licensed under the terms set forth in the LICENSE.txt file available at
4
+ # at the root of this project.
5
+ #
6
+
7
+ # frozen_string_literal: true
8
+
9
+ # main module
10
+ module Xolo
11
+
12
+ # Server Module
13
+ module Server
14
+
15
+ module Routes
16
+
17
+ # See comments for Xolo::Server::Helpers::TitleEditor
18
+ #
19
+ module Subscriptions
20
+
21
+ # This is how we 'extend' modules to Sinatra servers
22
+ # for route definitions and similar things
23
+ #
24
+ # (things to be 'included' for use in route and view processing
25
+ # are mixed in by delcaring them to be helpers)
26
+ #
27
+ # We make them extentions here with
28
+ # extend Sinatra::Extension (from sinatra-contrib)
29
+ # and then 'register' them in the server with
30
+ # register Xolo::Server::<Module>
31
+ # Doing it this way allows us to split the code into a logical
32
+ # file structure, without re-opening the Sinatra::Base server app,
33
+ # and let xeitwork do the requiring of those files
34
+ extend Sinatra::Extension
35
+
36
+ # Module methods
37
+ #
38
+ ##############################
39
+ ##############################
40
+
41
+ # when this module is included
42
+ def self.included(includer)
43
+ Xolo.verbose_include includer, self
44
+ end
45
+
46
+ # when this module is extended
47
+ def self.extended(extender)
48
+ Xolo.verbose_extend extender, self
49
+ end
50
+
51
+ # Routes
52
+ #
53
+ ##############################
54
+ ##############################
55
+
56
+ # This endpoint receives Jamf Webhook PatchSoftwareTitleUpdated events
57
+ # from the Jamf Pro server, indicating that a subscribed title has a new version available.
58
+ #
59
+ # If the title is subscribed in Xolo, this creates a new xolo version for the title,
60
+ # and either notifies the contact email for the title, or uses autopkg to get an installer.
61
+ #
62
+ # The body will be JSON like this:
63
+ # {
64
+ # "event": {
65
+ # "jssID": integer,
66
+ # "lastUpdate": epoch,
67
+ # "latestVersion": "string",
68
+ # "name": "string",
69
+ # "reportUrls": [
70
+ # "string",
71
+ # "string"
72
+ # ]
73
+ # },
74
+ # "webhook": {
75
+ # "eventTimestamp": epoch,
76
+ # "id": integer,
77
+ # "name": "string",
78
+ # "webhookEvent": "PatchSoftwareTitleUpdated"
79
+ # }
80
+ # }
81
+ #
82
+ # Some real data:
83
+ # {
84
+ # "event": {
85
+ # "jssID": 145,
86
+ # "lastUpdate":1765926131000,
87
+ # "latestVersion": "1.0.3",
88
+ # "name": "Xolo Testing",
89
+ # "reportUrls": [
90
+ # "https://myjamf.mycompany.com:8443//patch.html?id=145&o=r"
91
+ # ]
92
+ # },
93
+ # "webhook": {
94
+ # "eventTimestamp":1765926428322,
95
+ # "id": 4,
96
+ # "name": "PatchSoftwareTitleUpdated",
97
+ # "webhookEvent": "PatchSoftwareTitleUpdated"
98
+ # }
99
+ # }
100
+ #
101
+ # NOTE: The above reportUrls is incorrect on modern Jamf Pro servers.
102
+ # the correct one would be https://myjamf.mycompany.com:8443/view/computers/patch/145?tab=report
103
+ #
104
+ ###############
105
+ post '/subscribed-title-updates' do
106
+ session[:admin] = Xolo::Server::WEBHOOK_HANDLER_ADMIN_USERNAME
107
+ request.body.rewind
108
+
109
+ # this happens in a thread so that we can return a 200 response to the
110
+ # webhook immediately, and do the processing asynchronously (which may
111
+ # involve time-consuming tasks like autopkg runs)
112
+ process_patch_title_updated_webhook(request.body.read)
113
+
114
+ # always return 200 to the webhook sender
115
+ status 200
116
+ resp = { status: 200, message: 'Webhook event received' }
117
+ body resp
118
+ end
119
+
120
+ end # Module
121
+
122
+ end # Routes
123
+
124
+ end # Server
125
+
126
+ end # module Xolo
@@ -18,7 +18,7 @@ module Xolo
18
18
  #
19
19
  module TitleEditor
20
20
 
21
- # This is how we 'mix in' modules to Sinatra servers
21
+ # This is how we 'extend' modules to Sinatra servers
22
22
  # for route definitions and similar things
23
23
  #
24
24
  # (things to be 'included' for use in route and view processing
@@ -16,7 +16,7 @@ module Xolo
16
16
 
17
17
  module Titles
18
18
 
19
- # This is how we 'mix in' modules to Sinatra servers
19
+ # This is how we 'extend' modules to Sinatra servers
20
20
  # for route definitions and similar things
21
21
  #
22
22
  # (things to be 'included' for use in route and view processing
@@ -48,11 +48,17 @@ module Xolo
48
48
  halt_on_existing_title title.title
49
49
 
50
50
  log_info "Admin #{session[:admin]} is creating title '#{title.title}'"
51
+ info = { status: 'created', title: title.title }
52
+ body info
53
+
51
54
  with_streaming do
52
55
  title.create
53
- # we don't need to update client data when titles are created
56
+ # we don't need to update client data when managed titles are created
54
57
  # because they don't have any versions yet, so there's nothing a
55
58
  # client can do with them.
59
+ #
60
+ # However subscribed titles will have their latest version activated
61
+ # will need client data updated
56
62
  end
57
63
  end
58
64
 
@@ -240,13 +246,14 @@ module Xolo
240
246
  #################################
241
247
  get '/titles/:title/urls' do
242
248
  log_debug "Admin #{session[:admin]} is fetching GUI URLS for title '#{params[:title]}'"
249
+
243
250
  halt_on_missing_title params[:title]
244
251
  title = instantiate_title params[:title]
245
- data = {
246
- ted_title_url: title.ted_title_url,
247
- jamf_installed_group_url: title.jamf_installed_group_url,
248
- jamf_frozen_group_url: title.jamf_frozen_group_url
249
- }
252
+
253
+ data = {}
254
+ data[:ted_title_url] = title.ted_title_url if title.managed?
255
+ data[:jamf_installed_group_url] = title.jamf_installed_group_url if title.jamf_installed_group_exist?
256
+ data[:jamf_frozen_group_url] = title.jamf_frozen_group_url if title.jamf_frozen_group_exist?
250
257
  data[:jamf_manual_install_released_policy_url] = title.jamf_manual_install_released_policy_url if title.jamf_manual_install_released_policy_exist?
251
258
 
252
259
  if title.uninstallable?
@@ -255,13 +262,11 @@ module Xolo
255
262
  data[:jamf_expire_policy_url] = title.jamf_expire_policy_url if title.expiration
256
263
  end
257
264
 
258
- if title.jamf_ted_title_active?
259
- data[:jamf_patch_title_url] = title.jamf_patch_title_url unless title.versions.empty?
265
+ if title.jamf_title_active?
266
+ data[:jamf_patch_title_url] = title.jamf_patch_title_url unless title.jamf_patch_title_id.pix_empty?
260
267
  data[:jamf_patch_ea_url] = title.jamf_patch_ea_url if title.version_script
261
268
  end
262
269
 
263
- data[:jamf_normal_ea_url] = title.jamf_normal_ea_url if title.version_script
264
-
265
270
  body data
266
271
  end
267
272
 
@@ -276,6 +281,16 @@ module Xolo
276
281
  body title.changelog
277
282
  end
278
283
 
284
+ # Does this xolo server support autopkg integration?
285
+ #
286
+ # @return [Array<Hash>] The changelog for a title
287
+ #################################
288
+ get '/titles/autopkg_enabled' do
289
+ log_debug "Admin #{session[:admin]} is checking if autopkg is enabled on this server"
290
+ data = { autopkg_enabled: autopkg_enabled? }
291
+ body data
292
+ end
293
+
279
294
  end # Titles
280
295
 
281
296
  end # Routes
@@ -62,20 +62,6 @@ module Xolo
62
62
  ##############################
63
63
  ##############################
64
64
 
65
- # # param with the uploaded file must be :file
66
- # ######################
67
- # post '/upload/ssvc-icon/:title' do
68
- # process_incoming_ssvc_icon
69
- # body({ result: :uploaded })
70
- # end
71
-
72
- # # param with the uploaded file must be :file
73
- # ######################
74
- # post '/upload/pkg/:title/:version' do
75
- # process_incoming_pkg
76
- # body({ result: :uploaded })
77
- # end
78
-
79
65
  # param with the uploaded file must be :file
80
66
  ######################
81
67
  post '/upload/test' do
@@ -16,7 +16,7 @@ module Xolo
16
16
 
17
17
  module Versions
18
18
 
19
- # This is how we 'mix in' modules to Sinatra servers
19
+ # This is how we 'extend' modules to Sinatra servers
20
20
  # for route definitions and similar things
21
21
  #
22
22
  # (things to be 'included' for use in route and view processing
@@ -58,9 +58,10 @@ module Xolo
58
58
  data[:min_os] = default_min_os if data[:min_os].pix_empty?
59
59
 
60
60
  log_debug "Incoming new version data: #{data}"
61
- log_debug "Incoming new version data: #{data.class}"
62
61
 
63
- vers = instantiate_version(data)
62
+ vers = instantiate_version(**data)
63
+ log_debug "Instantiated version object: #{vers.class} - #{vers.title} #{vers.version}"
64
+
64
65
  halt_on_existing_version vers.title, vers.version
65
66
 
66
67
  if vers.title_object.jamf_patch_ea_awaiting_acceptance? && !Xolo::Server.config.jamf_auto_accept_xolo_eas
@@ -89,9 +90,9 @@ module Xolo
89
90
 
90
91
  log_debug "Admin #{session[:admin]} is listing all versions for title '#{params[:title]}'"
91
92
  # body all_versions(params[:title])
92
- vers_ins = all_version_instances(params[:title])
93
+ vers_objs = all_version_objects(params[:title])
93
94
  # log_debug "vers_ins: #{vers_ins}"
94
- body vers_ins.map(&:to_h)
95
+ body vers_objs.map(&:to_h)
95
96
  end
96
97
 
97
98
  # get all the data for a single version
@@ -156,7 +157,7 @@ module Xolo
156
157
  # param with the uploaded file must be :file
157
158
  ######################
158
159
  post '/titles/:title/versions/:version/pkg' do
159
- process_incoming_pkg
160
+ process_and_upload_uploaded_pkg
160
161
  body({ result: :uploaded })
161
162
  end
162
163
 
@@ -239,13 +240,13 @@ module Xolo
239
240
 
240
241
  halt_on_missing_version params[:title], params[:version]
241
242
  vers = instantiate_version title: params[:title], version: params[:version]
242
- data = {
243
- ted_patch_url: vers.ted_patch_url,
244
- jamf_auto_install_policy_url: vers.jamf_auto_install_policy_url,
245
- jamf_manual_install_policy_url: vers.jamf_manual_install_policy_url,
246
- jamf_patch_policy_url: vers.jamf_patch_policy_url,
247
- jamf_package_url: vers.jamf_package_url
248
- }
243
+
244
+ data = {}
245
+ data[:ted_patch_url] = vers.ted_patch_url if vers.managed?
246
+ data[:jamf_auto_install_policy_url] = vers.jamf_auto_install_policy_url if vers.jamf_auto_install_policy_exist?
247
+ data[:jamf_manual_install_policy_url] = vers.jamf_manual_install_policy_url if vers.jamf_manual_install_policy_exist?
248
+ data[:jamf_patch_policy_url] = vers.jamf_patch_policy_url if vers.jamf_patch_policy_exist?
249
+ data[:jamf_package_url] = vers.jamf_package_url if vers.jamf_package_exist?
249
250
  data[:jamf_version_installed_group] = vers.jamf_installed_group_url if vers.jamf_installed_group_exist?
250
251
  data[:jamf_auto_reinstall_policy_url] = vers.jamf_auto_reinstall_policy_url if vers.jamf_auto_reinstall_policy_exist?
251
252
 
@@ -49,6 +49,14 @@ module Xolo
49
49
  log_debug "Checking if request path '#{request.path}' is in INTERNAL_ROUTES"
50
50
  break if Xolo::Server::Helpers::Auth::INTERNAL_ROUTES.include?(request.path) && valid_internal_auth_token?
51
51
 
52
+ # This route is used by Jamf Pro Webhooks to notify Xolo of subscribed title updates
53
+ log_debug "Checking if request path '#{request.path}' is PATCH_TITLE_UPDATED_WEBHOOK_ROUTE"
54
+ if request.path == Xolo::Server::Helpers::Auth::PATCH_TITLE_UPDATED_WEBHOOK_ROUTE
55
+ break if jamf_webhook_auth_token_ok?
56
+
57
+ halt 401, { status: 401, error: 'Valid Bearer Token Required' }
58
+ end
59
+
52
60
  # these routes are for server admins only, and require an authenticated session
53
61
  log_debug "Checking if request path '#{request.path}' is in SERVER_ADMIN_ROUTES"
54
62
  break if Xolo::Server::Helpers::Auth::SERVER_ADMIN_ROUTES.include?(request.path) && valid_server_admin?
@@ -71,15 +79,12 @@ module Xolo
71
79
  ##############
72
80
  after do
73
81
  # log a stack trace if the response status is 4xx or 5xx, or if there's a sinatra.error
74
- if response.status >= 400
75
- log_error "Response status #{response.status} for #{request.request_method} #{request.path}"
76
- if env['sinatra.error']
77
- log_error "Sinatra Error message: #{env['sinatra.error'].message}"
78
- env['sinatra.error'].backtrace.each { |line| log_error "..#{line}" }
79
- else
80
- log_error 'Xolo Stack trace:'
81
- caller.each { |line| log_error "..#{line}" }
82
- end
82
+ log_debug "Response status #{response.status} for #{request.request_method} #{request.path}" if response.status >= 400
83
+
84
+ sinatra_error = env['sinatra.error']
85
+ if sinatra_error
86
+ log_error "Sinatra Error message: #{sinatra_error.message}"
87
+ sinatra_error.backtrace.each { |line| log_error "..#{line}" }
83
88
  end
84
89
 
85
90
  if @no_json
@@ -99,7 +104,6 @@ module Xolo
99
104
  # from ruby-jss and windoo api connections?
100
105
  # perhaps a callback to when a Sinatra server instance
101
106
  # 'finishes'?
102
- # can't
103
107
  end
104
108
 
105
109
  # Ping
@@ -135,19 +139,6 @@ module Xolo
135
139
  # test
136
140
  ##########
137
141
  get '/test' do
138
- # Xolo::Server::Helpers::Maintenance.post_to_start_cleanup force: true
139
- # result = { result: 'posted to start cleanup' }
140
-
141
- # send_email(
142
- # to: 'xolo@pixar.com',
143
- # subject: 'Test Email from Xolo Server',
144
- # msg: 'This is a test email from the Xolo Server'
145
- # )
146
- # result = { result: 'message sent' }
147
-
148
- # client_data_testing
149
- # update_client_data
150
-
151
142
  result = { result: 'test' }
152
143
 
153
144
  body result
@@ -166,3 +157,4 @@ require 'xolo/server/routes/title_editor'
166
157
  require 'xolo/server/routes/titles'
167
158
  require 'xolo/server/routes/uploads'
168
159
  require 'xolo/server/routes/versions'
160
+ require 'xolo/server/routes/subscriptions'