xolo-server 1.0.1 → 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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/data/client/xolo +152 -79
  3. data/lib/xolo/core/base_classes/title.rb +254 -18
  4. data/lib/xolo/core/base_classes/version.rb +47 -7
  5. data/lib/xolo/core/constants.rb +7 -3
  6. data/lib/xolo/core/security_cmd.rb +128 -0
  7. data/lib/xolo/core/version.rb +1 -1
  8. data/lib/xolo/core.rb +1 -0
  9. data/lib/xolo/server/app.rb +7 -0
  10. data/lib/xolo/server/configuration.rb +243 -37
  11. data/lib/xolo/server/constants.rb +10 -0
  12. data/lib/xolo/server/helpers/auth.rb +19 -2
  13. data/lib/xolo/server/helpers/autopkg.rb +157 -0
  14. data/lib/xolo/server/helpers/client_data.rb +90 -60
  15. data/lib/xolo/server/helpers/file_transfers.rb +412 -82
  16. data/lib/xolo/server/helpers/jamf_pro.rb +30 -7
  17. data/lib/xolo/server/helpers/log.rb +2 -0
  18. data/lib/xolo/server/helpers/maintenance.rb +1 -0
  19. data/lib/xolo/server/helpers/notification.rb +4 -3
  20. data/lib/xolo/server/helpers/pkg_signing.rb +16 -12
  21. data/lib/xolo/server/helpers/progress_streaming.rb +9 -12
  22. data/lib/xolo/server/helpers/subscriptions.rb +119 -0
  23. data/lib/xolo/server/helpers/titles.rb +27 -3
  24. data/lib/xolo/server/helpers/versions.rb +23 -11
  25. data/lib/xolo/server/mixins/changelog.rb +9 -16
  26. data/lib/xolo/server/mixins/title_jamf_access.rb +375 -385
  27. data/lib/xolo/server/mixins/title_ted_access.rb +29 -3
  28. data/lib/xolo/server/mixins/version_jamf_access.rb +95 -112
  29. data/lib/xolo/server/mixins/version_ted_access.rb +25 -0
  30. data/lib/xolo/server/object_locks.rb +2 -1
  31. data/lib/xolo/server/routes/auth.rb +2 -2
  32. data/lib/xolo/server/routes/jamf_pro.rb +11 -1
  33. data/lib/xolo/server/routes/maint.rb +2 -1
  34. data/lib/xolo/server/routes/subscriptions.rb +126 -0
  35. data/lib/xolo/server/routes/title_editor.rb +1 -1
  36. data/lib/xolo/server/routes/titles.rb +26 -11
  37. data/lib/xolo/server/routes/uploads.rb +0 -14
  38. data/lib/xolo/server/routes/versions.rb +14 -13
  39. data/lib/xolo/server/routes.rb +9 -0
  40. data/lib/xolo/server/title.rb +100 -77
  41. data/lib/xolo/server/version.rb +177 -15
  42. data/lib/xolo/server.rb +8 -0
  43. metadata +7 -9
@@ -65,6 +65,11 @@ module Xolo
65
65
  # @return [Windoo::SoftwareTitle]
66
66
  ##########################
67
67
  def create_title_in_ted
68
+ if subscribed?
69
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor creation"
70
+ return
71
+ end
72
+
68
73
  # delete an old one if its there
69
74
  ted_title&.delete if Windoo::SoftwareTitle.all_ids(cnx: ted_cnx).include? title
70
75
 
@@ -173,6 +178,10 @@ module Xolo
173
178
  # @return [void]
174
179
  ##########################
175
180
  def update_title_in_ted
181
+ if subscribed?
182
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor update"
183
+ return
184
+ end
176
185
  return unless changes_for_update
177
186
 
178
187
  unless any_ted_changes?
@@ -217,10 +226,12 @@ module Xolo
217
226
  req_change = requirement_change
218
227
  return unless req_change
219
228
 
220
- new_app_name = changes_for_update.dig :app_name, :new
221
- new_app_bundle_id = changes_for_update.dig :app_bundle_id, :new
222
229
  new_ea_script = changes_for_update.dig :version_script, :new
223
230
 
231
+ # if either of these are nil in changes, then use the existing value
232
+ new_app_name = changes_for_update.dig(:app_name, :new) || app_name
233
+ new_app_bundle_id = changes_for_update.dig(:app_bundle_id, :new) || app_bundle_id
234
+
224
235
  case req_change
225
236
  when :app_to_ea
226
237
  # create the ea
@@ -241,6 +252,7 @@ module Xolo
241
252
  when :update_app
242
253
  # set the requirement to use the new app data
243
254
  set_ted_title_requirement app_name: new_app_name, app_bundle_id: new_app_bundle_id
255
+
244
256
  # for all versions, update the patch compotent criteria to use the new app data
245
257
  set_ted_patch_component_criteria_after_update app_name: new_app_name, app_bundle_id: new_app_bundle_id
246
258
 
@@ -292,11 +304,19 @@ module Xolo
292
304
  end
293
305
  end
294
306
 
307
+ # In the TitleEditor, the version script is
308
+ # stored as an Extension Attribute - each title can
309
+ # only have one.
310
+ # and it needs a 'key', which is the name used to indicate the
311
+ # EA in various criteria, and is the EA name in Jamf Patch.
312
+ # The key is jamf_obj_name_pfx on the title
313
+ # so for title 'foobar', it is 'xolo-foobar' or 'xolotest-foobar' for test servers
314
+ # That value is also used as the display name
295
315
  # @return [String] The key and display name of a version script stored
296
316
  # in the title editor as the ExtAttr for this title
297
317
  #####################
298
318
  def ted_ea_key
299
- @ted_ea_key ||= self.class.ted_ea_key title
319
+ @ted_ea_key ||= "#{jamf_obj_name_pfx_base}#{title}"
300
320
  end
301
321
 
302
322
  # Create the EA in the Title Editor
@@ -470,6 +490,8 @@ module Xolo
470
490
  # @return [String] the URL for the title in the Title Editor
471
491
  #####################
472
492
  def ted_title_url
493
+ return unless managed?
494
+
473
495
  "https://#{Xolo::Server.config.ted_hostname}/softwaretitles/#{ted_id_number}"
474
496
  end
475
497
 
@@ -482,6 +504,10 @@ module Xolo
482
504
  # @return [void]
483
505
  ############################
484
506
  def repair_ted_title
507
+ if subscribed?
508
+ log_debug "Title Editor: SoftwareTitle '#{title}' is subscribed, skipping Title Editor repair"
509
+ return
510
+ end
485
511
  progress "Title Editor: Repairing SoftwareTitle '#{title}'", log: :info
486
512
 
487
513
  # TODO: version order??
@@ -26,29 +26,24 @@ module Xolo
26
26
 
27
27
  # The group of macs with this version installed
28
28
  # is named the full prefix plus this suffix.
29
- JAMF_SMART_GROUP_NAME_INSTALLED_SFX = '-installed'
29
+ JAMF_SMART_GROUP_NAME_INSTALLED_SFX = 'installed'
30
30
 
31
31
  # The policy that does initial installs on-demand
32
32
  # (via 'xolo install <title> <version') is named the full
33
33
  # prefix plus this suffix.
34
- JAMF_POLICY_NAME_MANUAL_INSTALL_SFX = '-manual-install'
34
+ JAMF_POLICY_NAME_MANUAL_INSTALL_SFX = 'manual-install'
35
35
 
36
36
  # The policy that does auto-installs is named the full
37
37
  # prefix plus this suffix.
38
38
  # The scope is changed as needed when a version's status
39
39
  # changes
40
- JAMF_POLICY_NAME_AUTO_INSTALL_SFX = '-auto-install'
40
+ JAMF_POLICY_NAME_AUTO_INSTALL_SFX = 'auto-install'
41
41
 
42
42
  # The policy that does auto-re-installs is named the full
43
43
  # prefix plus this suffix.
44
44
  # The scope is changed as needed when a version's status
45
45
  # changes
46
- JAMF_POLICY_NAME_AUTO_REINSTALL_SFX = '-auto-reinstall'
47
-
48
- # How long to wait after a pkg re-upload before creating/enabling/flushing
49
- # the auto-reinstall policy
50
- # See TODO in #wait_to_enable_reinstall_policy
51
- JAMF_AUTO_REINSTALL_WAIT_SECS = 15 * 60
46
+ JAMF_POLICY_NAME_AUTO_REINSTALL_SFX = 'auto-reinstall'
52
47
 
53
48
  # POLICIES, PATCH POLICIES, SCOPING
54
49
  #############################
@@ -197,7 +192,11 @@ module Xolo
197
192
  jamf_auto_install_policy
198
193
  jamf_manual_install_policy
199
194
 
200
- activate_patch_version_in_jamf
195
+ if subscribed?
196
+ activate_subscribed_patch_version_in_jamf
197
+ else
198
+ activate_managed_patch_version_in_jamf
199
+ end
201
200
  end
202
201
 
203
202
  # Apply edits to the Xolo version to Jamf as needed
@@ -276,8 +275,6 @@ module Xolo
276
275
  # Delete package object
277
276
  # This is slow and it blocks, so do it in a thread and update progress every
278
277
  # 15 secs
279
- return unless Jamf::JPackage.valid_id packageName: jamf_pkg_name, cnx: jamf_cnx
280
-
281
278
  delete_jamf_package
282
279
 
283
280
  # The code below is used when we want real-time progress updates to xadm
@@ -321,6 +318,8 @@ module Xolo
321
318
  @jamf_package =
322
319
  if id
323
320
  log_debug "Jamf: Fetching Jamf::JPackage '#{id}'"
321
+ self.jamf_pkg_id = id # in case we only had the name before, now we have the id, so save it
322
+ save_local_data
324
323
  Jamf::JPackage.fetch id: id, cnx: jamf_cnx
325
324
  else
326
325
  return if deleting?
@@ -329,10 +328,16 @@ module Xolo
329
328
  end
330
329
  end
331
330
 
331
+ # @return [Boolean] does the jamf_package exist?
332
+ #########################
333
+ def jamf_package_exist?
334
+ !Jamf::JPackage.valid_id(packageName: jamf_pkg_name, cnx: jamf_cnx).nil?
335
+ end
336
+
332
337
  # @return [Jamf::JPackage] Create the Jamf::JPackage object for this version and return it
333
338
  #########################
334
339
  def create_jamf_package
335
- progress "Jamf: Creating Package object '#{jamf_pkg_name}'", log: :info
340
+ progress "Jamf: Creating Jamf::JPackage '#{jamf_pkg_name}'", log: :info
336
341
 
337
342
  # The filename is temporary, and will be replaced when the file is uploaded
338
343
  pkg = Jamf::JPackage.create(
@@ -442,13 +447,13 @@ module Xolo
442
447
  # @return [void]
443
448
  #########################
444
449
  def delete_jamf_package
445
- pkg_id = Jamf::JPackage.valid_id packageName: jamf_pkg_name, cnx: jamf_cnx
450
+ pkg_id = jamf_pkg_id || Jamf::JPackage.valid_id(packageName: jamf_pkg_name, cnx: jamf_cnx)
446
451
  return unless pkg_id
447
452
 
448
453
  msg = "Jamf: Starting deletion of Package '#{jamf_pkg_name}' id #{jamf_pkg_id} at #{Time.now.strftime '%F %T'}"
449
454
  progress msg, log: :info
450
455
 
451
- warning = +"IMPORTANT: Package deletion is slow. If you plan to re-add this version, '#{version}', please\n "
456
+ warning = +"IMPORTANT: Package deletion can be slow. If you plan to re-add this version, '#{version}', please\n "
452
457
  warning <<
453
458
  if Xolo::Server.config.alert_tool
454
459
  'check your Xolo alerts for completion, which can take up to 5 minutes,'
@@ -685,8 +690,6 @@ module Xolo
685
690
  )
686
691
  else
687
692
  return if deleting?
688
- # don't create unless there's been a re-upload of the pkg
689
- return unless reupload_date
690
693
 
691
694
  create_jamf_installed_group
692
695
  end
@@ -736,51 +739,20 @@ module Xolo
736
739
  # The criteria for the smart group in Jamf that contains all Macs
737
740
  # with this version of this title installed
738
741
  #
739
- # If we have, or are about to update to, a version_script (EA) then use it,
740
- # otherwise use the app_name and app_bundle_id.
742
+ # We use the "Patch Reporting: #{title_object.display_name}" criterion so that we don't
743
+ # care whether the title uses a version-script or app data.
741
744
  #
742
745
  # @return [Array<Jamf::Criteriable::Criterion>]
743
746
  ###################################
744
747
  def jamf_installed_group_criteria
745
- # does this title use an app bundle?
746
- if title_object.app_name
747
- [
748
- Jamf::Criteriable::Criterion.new(
749
- and_or: :and,
750
- name: 'Application Title',
751
- search_type: 'is',
752
- value: title_object.app_name
753
- ),
754
-
755
- Jamf::Criteriable::Criterion.new(
756
- and_or: :and,
757
- name: 'Application Bundle ID',
758
- search_type: 'is',
759
- value: title_object.app_bundle_id
760
- ),
761
-
762
- Jamf::Criteriable::Criterion.new(
763
- and_or: :and,
764
- name: 'Application Version',
765
- search_type: 'is',
766
- value: version
767
- )
768
- ]
769
-
770
- # if not, it must have a version script
771
- elsif title_object.version_script
772
- [
773
- Jamf::Criteriable::Criterion.new(
774
- and_or: :and,
775
- name: title_object.jamf_normal_ea_name,
776
- search_type: 'is',
777
- value: version
778
- )
779
- ]
780
-
781
- else
782
- raise Xolo::Core::Exceptions::InvalidDataError, "Title #{title} has neither a version_script nor a defined app bundle."
783
- end
748
+ [
749
+ Jamf::Criteriable::Criterion.new(
750
+ and_or: :or,
751
+ name: "Patch Reporting: #{title_object.display_name}",
752
+ search_type: 'is',
753
+ value: version
754
+ )
755
+ ]
784
756
  end
785
757
 
786
758
  #########################
@@ -800,7 +772,7 @@ module Xolo
800
772
  # @return [Boolean] does the jamf_auto_reinstall_policy exist?
801
773
  ##########################
802
774
  def jamf_auto_reinstall_policy_exist?
803
- Jamf::Policy.all_names(cnx: jamf_cnx).include? jamf_auto_reinstall_policy_name
775
+ Jamf::Policy.all_names(:refresh, cnx: jamf_cnx).include? jamf_auto_reinstall_policy_name
804
776
  end
805
777
 
806
778
  # Create or fetch the auto re-install policy for this version
@@ -814,8 +786,6 @@ module Xolo
814
786
  Jamf::Policy.fetch(name: jamf_auto_reinstall_policy_name, cnx: jamf_cnx)
815
787
  else
816
788
  return if deleting?
817
- # don't create unless there's been a re-upload of the pkg
818
- return unless reupload_date
819
789
 
820
790
  create_jamf_auto_reinstall_policy
821
791
  end
@@ -845,6 +815,9 @@ module Xolo
845
815
  # @param pol [Jamf::Policy] the policy to configure
846
816
  ######################
847
817
  def configure_jamf_auto_reinstall_policy(pol)
818
+ # this creates the installed group if it doesn't already exist
819
+ jamf_installed_group
820
+
848
821
  pol.category = Xolo::Server::JAMF_XOLO_CATEGORY
849
822
  pol.set_trigger_event :checkin, true
850
823
  pol.set_trigger_event :custom, Xolo::BLANK
@@ -852,7 +825,7 @@ module Xolo
852
825
  pol.recon = false
853
826
  pol.retry_event = :checkin
854
827
  pol.retry_attempts = 5
855
- pol.scope.set_targets :computer_groups, [jamf_installed_group_name]
828
+ pol.scope.set_targets :computer_groups, [jamf_installed_group.name]
856
829
 
857
830
  # exclusions are for always
858
831
  set_policy_exclusions pol
@@ -876,41 +849,6 @@ module Xolo
876
849
  @jamf_auto_reinstall_policy_url = "#{jamf_gui_url}/policies.html?id=#{pol_id}&o=r"
877
850
  end
878
851
 
879
- # This will start a thread
880
- # that will wait some period of time (to allow for pkg uploads
881
- # to complete) before enabling and flushing the logs for the reinstall policy.
882
- # This will make all macs with this version installed get it re-installed.
883
- # @return [void]
884
- def wait_to_enable_reinstall_policy
885
- return if @enable_reinstall_policy_thread&.alive?
886
- return unless reupload_date
887
-
888
- # TODO: some setting to determine how long to wait?
889
- # - If uploading via the Jamf API, we need to give it time
890
- # to then upload the file to the cloud distribution point
891
- # - If uploading via a custom tool, we need to give that
892
- # tool time to re-upload to wherever it uploads to
893
- # - May need to wait for other non-jamf/non-xolo processes
894
- # to sync the package to other distribution points. This
895
- # might be very site-specific.
896
-
897
- # For now, we wait 15 minutes.
898
- wait_time = JAMF_AUTO_REINSTALL_WAIT_SECS
899
-
900
- @enable_reinstall_policy_thread = Thread.new do
901
- log_debug "Jamf: Starting enable_reinstall_policy_thread: waiting #{wait_time} seconds before enabling reinstall policy for version #{version} of title #{title}"
902
- sleep wait_time
903
-
904
- log_debug "Jamf: enable_reinstall_policy_thread: enabling and flushing logs for reinstall policy for version #{version} of title #{title}"
905
-
906
- pol = jamf_auto_reinstall_policy
907
- pol.enable
908
- pol.flush_logs
909
- pol.save
910
- end
911
- @enable_reinstall_policy_thread.name = "enable_reinstall_policy_thread-#{title}-#{version}"
912
- end
913
-
914
852
  ####### The Jamf Patch Policy
915
853
  ###########################################
916
854
  ###########################################
@@ -983,10 +921,10 @@ module Xolo
983
921
  # a rollback is being done
984
922
  ppol.allow_downgrade = false
985
923
 
986
- # This should always be false, so that
924
+ # This should default to false, so that
987
925
  # we don't accidentally downgrade non-xolo test installs,
988
926
  # or server-pushed updates (like with commvault or cisco VPN)
989
- ppol.patch_unknown = false
927
+ ppol.patch_unknown = patch_unknown ? true : false
990
928
 
991
929
  ppol.enable
992
930
 
@@ -1006,10 +944,10 @@ module Xolo
1006
944
  ppol.name = jamf_patch_policy_name
1007
945
  ppol.target_version = version
1008
946
 
1009
- # This should always be false, so that
947
+ # This should default tofalse, so that
1010
948
  # we don't accidentally downgrade non-xolo test installs,
1011
949
  # or server-pushed updates (like with commvault or cisco VPN)
1012
- ppol.patch_unknown = false
950
+ ppol.patch_unknown = patch_unknown ? true : false
1013
951
 
1014
952
  if pilot?
1015
953
  set_policy_pilot_groups ppol
@@ -1296,7 +1234,14 @@ module Xolo
1296
1234
  @jamf_patch_version = title_object.jamf_patch_title.versions[version]
1297
1235
  return @jamf_patch_version if @jamf_patch_version
1298
1236
 
1299
- # TODO: wait for it to appear when adding?
1237
+ if repairing?
1238
+ # if we're repairing, and the version isn't visible in Jamf, then
1239
+ # jamf polled the title editor in the few moments it was disabled.
1240
+ # and jamf will see it again within 5 minutes.
1241
+ return nil
1242
+ end
1243
+
1244
+ # TODO: wait for it to appear when adding, or re-appear when repairing?
1300
1245
  msg = "Jamf: Version '#{version}' of Title '#{title}' is not visible in Jamf. Is the Patch enabled in the Title Editor?"
1301
1246
  log_error msg
1302
1247
  raise Xolo::NoSuchItemError, msg
@@ -1310,7 +1255,7 @@ module Xolo
1310
1255
  #
1311
1256
  # @return [void]
1312
1257
  #########################
1313
- def activate_patch_version_in_jamf
1258
+ def activate_managed_patch_version_in_jamf
1314
1259
  # don't do this if there's already one running for this instance
1315
1260
  if @activate_patch_version_thread&.alive?
1316
1261
  log_debug "Jamf: activate_patch_version_thread already running. Caller: #{caller_locations.first}"
@@ -1342,13 +1287,7 @@ module Xolo
1342
1287
  end
1343
1288
 
1344
1289
  if did_it
1345
- assign_pkg_to_patch_in_jamf
1346
- # give jamf a moment to catch up and refresh the patch title
1347
- # so we see the pkg has been assigned
1348
- sleep 2
1349
- title_object.jamf_patch_title(refresh: true)
1350
-
1351
- create_jamf_patch_policy
1290
+ activate_patch_version_in_jamf
1352
1291
  msg = "Jamf: Version '#{version}' of title '#{title}' is now visible in Jamf Pro. Package assigned and Patch policy created."
1353
1292
  log_info msg, alert: true
1354
1293
  else
@@ -1359,6 +1298,37 @@ module Xolo
1359
1298
  @activate_patch_version_thread.name = "activate_patch_version_thread-#{title}-#{version}"
1360
1299
  end
1361
1300
 
1301
+ # Patches for subscribed titles are already visible in Jamf Patch Management
1302
+ # So we just need to assign the pkg to the patch version, and create the patch policy.
1303
+ ##########################
1304
+ def activate_subscribed_patch_version_in_jamf
1305
+ msg = "Jamf: Assigning package and creating patch policy for version '#{version}' of subscribed title '#{title}'"
1306
+ log_info msg
1307
+ activate_patch_version_in_jamf
1308
+ end
1309
+
1310
+ # Assign the package for this version to the Jamf::PatchTitle::Version in Jamf
1311
+ # and create the patch policy for this version.
1312
+ #
1313
+ # @return [void]
1314
+ ##########################
1315
+ def activate_patch_version_in_jamf
1316
+ log_debug "Jamf: Activating patch version in Jamf for version '#{version}' of title '#{title}'"
1317
+
1318
+ # create the Jamf::JPackage object if needed
1319
+ jamf_package
1320
+ title_object.jamf_patch_title(refresh: true)
1321
+ sleep 3
1322
+
1323
+ assign_pkg_to_patch_in_jamf
1324
+ # give jamf a moment to catch up and refresh the patch title
1325
+ # so we see the pkg has been assigned
1326
+ sleep 2
1327
+ title_object.jamf_patch_title(refresh: true)
1328
+
1329
+ create_jamf_patch_policy
1330
+ end
1331
+
1362
1332
  # Assign the Package to the Jamf::PatchTitle::Version for this Xolo version.
1363
1333
  # This 'activates' the version in Jamf Patch, and must happen before
1364
1334
  # patch policies can be created
@@ -1374,10 +1344,23 @@ module Xolo
1374
1344
  # @return [void]
1375
1345
  ########################################
1376
1346
  def assign_pkg_to_patch_in_jamf
1377
- log_info "Jamf: Assigning package '#{jamf_pkg_name}' to patch version '#{version}' of title '#{title}'"
1347
+ patch_vers_obj = jamf_patch_version
1348
+
1349
+ if patch_vers_obj.nil? && repairing?
1350
+ msg = "Jamf: Cant re-assign package '#{jamf_pkg_name}' to patch version '#{version}' of title '#{title}' at this time. If there are problems with it, try 'repair' again later."
1351
+ progress msg, log: :info
1352
+ return
1353
+ end
1354
+
1355
+ progress "Jamf: Assigning package '#{jamf_pkg_name}' to patch version '#{version}' of title '#{title}'", log: :info
1356
+
1357
+ log_debug "Jamf: jamf_patch_version is: #{patch_vers_obj}"
1358
+
1359
+ patch_vers_obj.package = jamf_pkg_name
1360
+ log_debug "Jamf: jamf_patch_version after assignment is: #{patch_vers_obj}"
1378
1361
 
1379
- jamf_patch_version.package = jamf_pkg_name
1380
1362
  title_object.jamf_patch_title.save
1363
+ log_debug 'Jamf: Saved jamf_patch_title after assigning package to version.'
1381
1364
  end
1382
1365
 
1383
1366
  # Get the patch report for this version
@@ -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,
@@ -75,6 +88,11 @@ module Xolo
75
88
  # @return [void]
76
89
  ##########################
77
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
+
78
96
  progress "Title Editor: Updating Patch '#{version}' SoftwareTitle '#{title}'", log: :info
79
97
 
80
98
  Xolo::Server::Version::ATTRIBUTES.each do |attr, deets|
@@ -340,12 +358,19 @@ module Xolo
340
358
  # @return [String] the URL for the Title Editor Web App page for this patch
341
359
  ###################################
342
360
  def ted_patch_url
361
+ return unless managed?
362
+
343
363
  "https://#{Xolo::Server.config.ted_hostname}/patches/#{ted_id_number}"
344
364
  end
345
365
 
346
366
  # Ensure all the TEd items for this version are correct based on the server data.
347
367
  #########################
348
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
+
349
374
  progress "Title Editor: Repairing Patch '#{version}' of SoftwareTitle '#{title}'", log: :info
350
375
 
351
376
  Xolo::Server::Version::ATTRIBUTES.each do |attr, deets|
@@ -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],