├── .swift-version ├── _config.yml ├── JamfKit ├── Tests │ ├── Resources │ │ └── Mocks.bundle │ │ │ ├── Site │ │ │ ├── site_invalid.json │ │ │ └── site_valid.json │ │ │ ├── Building │ │ │ ├── building_invalid.json │ │ │ └── building_valid.json │ │ │ ├── Department │ │ │ ├── department_invalid.json │ │ │ └── department_valid.json │ │ │ ├── BaseObject │ │ │ ├── base_object_invalid.json │ │ │ └── base_object_valid.json │ │ │ ├── Category │ │ │ ├── category_invalid.json │ │ │ └── category_valid.json │ │ │ ├── Script │ │ │ ├── script_incomplete.json │ │ │ ├── script_invalid.json │ │ │ └── script_valid.json │ │ │ ├── ComputerCommand │ │ │ ├── computer_command_general_invalid.json │ │ │ ├── computer_command_general_valid.json │ │ │ ├── computer_command_incomplete.json │ │ │ ├── computer_command_invalid.json │ │ │ └── computer_command.json │ │ │ ├── Package │ │ │ ├── package_incomplete.json │ │ │ ├── package_invalid.json │ │ │ └── package_valid.json │ │ │ ├── Policy │ │ │ ├── policy_general_incomplete.json │ │ │ ├── policy_incomplete.json │ │ │ ├── policy_network_limitations.json │ │ │ ├── policy_override_default_settings.json │ │ │ ├── policy_date_time_limitations.json │ │ │ ├── policy_general_invalid.json │ │ │ ├── policy_general_valid.json │ │ │ ├── policy_invalid.json │ │ │ └── policy.json │ │ │ ├── Printer │ │ │ ├── printer_incomplete.json │ │ │ ├── printer_invalid.json │ │ │ └── printer_valid.json │ │ │ ├── Computer │ │ │ ├── computer_general_incomplete.json │ │ │ ├── computer_remote_management.json │ │ │ ├── computer_incomplete.json │ │ │ ├── computer_location.json │ │ │ ├── computer_purchasing.json │ │ │ ├── computer_general_invalid.json │ │ │ ├── computer_general_valid.json │ │ │ └── computer.json │ │ │ ├── ComputerGroup │ │ │ ├── computer_group_incomplete.json │ │ │ ├── computer_group_invalid.json │ │ │ ├── computer_group_valid.json │ │ │ ├── computer_group_invalid_computer.json │ │ │ └── computer_group_invalid_criterion.json │ │ │ ├── PreciseDate │ │ │ ├── precise_date_incomplete.json │ │ │ └── precise_date.json │ │ │ ├── NetbootServer │ │ │ ├── netboot_server_incomplete.json │ │ │ ├── netboot_server_invalid.json │ │ │ └── netboot_server_valid.json │ │ │ ├── SMTPServer │ │ │ ├── smtp_server_incomplete.json │ │ │ └── smtp_server.json │ │ │ ├── DirectoryBinding │ │ │ ├── directory_binding_incomplete.json │ │ │ ├── directory_binding_invalid.json │ │ │ └── directory_binding_valid.json │ │ │ ├── NetworkSegment │ │ │ ├── network_segment_incomplete.json │ │ │ ├── network_segment_invalid.json │ │ │ └── network_segment_valid.json │ │ │ ├── MobileDeviceGroup │ │ │ ├── mobile_device_group_incomplete.json │ │ │ ├── mobile_device_group_invalid.json │ │ │ ├── mobile_device_group_valid.json │ │ │ ├── mobile_device_group_invalid_criterion.json │ │ │ └── mobile_device_group_invalid_mobile_device.json │ │ │ ├── ComputerConfiguration │ │ │ ├── computer_configuration_general_incomplete.json │ │ │ └── computer_configuration_management.json │ │ │ ├── HardwareGroup │ │ │ ├── hardware_group_criterion.json │ │ │ ├── hardware_group_invalid.json │ │ │ └── hardware_group_valid.json │ │ │ ├── Partition │ │ │ └── partition.json │ │ │ ├── ConfigurationProfileGeneral │ │ │ ├── configuration_profile_general_invalid.json │ │ │ └── configuration_profile_general_valid.json │ │ │ ├── ComputerConfigurationProfile │ │ │ ├── computer_configuration_profile_general_invalid.json │ │ │ ├── computer_configuration_profile_general_valid.json │ │ │ ├── computer_configuration_profile_invalid.json │ │ │ └── computer_configuration_profile_valid.json │ │ │ ├── MobileDeviceConfigurationProfile │ │ │ ├── mobile_device_configuration_profile_general_invalid.json │ │ │ ├── mobile_device_configuration_profile_general_valid.json │ │ │ ├── mobile_device_configuration_profile_invalid.json │ │ │ └── mobile_device_configuration_profile_valid.json │ │ │ ├── MobileDevice │ │ │ ├── mobile_device_general_incomplete.json │ │ │ ├── mobile_device_general_invalid.json │ │ │ ├── mobile_device_general_valid.json │ │ │ └── mobile_device.json │ │ │ └── User │ │ │ ├── user_incomplete.json │ │ │ ├── user_invalid.json │ │ │ ├── user_valid.json │ │ │ └── user_multiple.json │ ├── Extensions │ │ └── StringExtensionTests.swift │ ├── Helpers │ │ └── JSONHelper.swift │ ├── Models │ │ ├── HardwareGroup │ │ │ ├── HardwareGroupTests.swift │ │ │ └── HardwareGroupCriterionTests.swift │ │ ├── BaseObjectTests.swift │ │ ├── Computer │ │ │ ├── ComputerRemoteManagementTests.swift │ │ │ ├── ComputerTests.swift │ │ │ └── ComputerLocationTests.swift │ │ ├── Policy │ │ │ ├── PolicyNetworkLimitationsTests.swift │ │ │ ├── PolicyOverrideDefaultSettingsTests.swift │ │ │ └── PolicyTests.swift │ │ ├── MobileDevice │ │ │ └── MobileDeviceTests.swift │ │ ├── SiteTests.swift │ │ ├── DepartmentTests.swift │ │ ├── ComputerConfiguration │ │ │ ├── ComputerConfigurationTests.swift │ │ │ └── ComputerConfigurationManagementTests.swift │ │ ├── ComputerCommand │ │ │ ├── ComputerCommandGeneralTests.swift │ │ │ └── ComputerCommandTests.swift │ │ ├── CategoryTests.swift │ │ ├── ConfigurationProfile │ │ │ ├── ComputerConfigurationProfile │ │ │ │ └── ComputerConfigurationProfileTests.swift │ │ │ ├── MobileDeviceConfigurationProfile │ │ │ │ └── MobileDeviceConfigurationProfileTests.swift │ │ │ └── ConfigurationProfileGeneralTests.swift │ │ ├── BuildingTests.swift │ │ ├── PreciseDateTests.swift │ │ ├── PartitionTests.swift │ │ └── SMTPServerTests.swift │ └── Session │ │ ├── Requests │ │ ├── SMTPServerRequestsTests.swift │ │ ├── ComputerCommand │ │ │ └── ComputerCommandRequestsTests.swift │ │ └── SessionManagerRequestsTests.swift │ │ └── SessionManagerTests.swift ├── .swiftlint.yml ├── JamfKit.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Playgrounds │ └── Examples.playground │ │ ├── Pages │ │ ├── Summary.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Classes.xcplaygroundpage │ │ │ └── Contents.swift │ │ └── Requests.xcplaygroundpage │ │ │ └── Contents.swift │ │ └── contents.xcplayground ├── Sources │ ├── Constants.swift │ ├── Protocols │ │ ├── Subset.swift │ │ ├── Identifiable.swift │ │ ├── Endpoint.swift │ │ ├── Requests │ │ │ ├── Creatable.swift │ │ │ ├── Updatable.swift │ │ │ ├── Deletable.swift │ │ │ └── Readable.swift │ │ └── Requestable.swift │ ├── JamfKit.h │ ├── Extensions │ │ └── StringExtension.swift │ ├── Session │ │ └── SessionManagerError.swift │ └── Models │ │ ├── Category.swift │ │ ├── Computer │ │ ├── ComputerRemoteManagement.swift │ │ └── ComputerLocation.swift │ │ ├── Policy │ │ ├── PolicyNetworkLimitations.swift │ │ ├── PolicyOverrideDefaultSettings.swift │ │ └── PolicyDateTimeLimitations.swift │ │ ├── ComputerCommand │ │ ├── ComputerCommandGeneral.swift │ │ └── ComputerCommand.swift │ │ ├── ConfigurationProfile │ │ ├── MobileDeviceConfigurationProfile │ │ │ └── MobileDeviceConfigurationProfileGeneral.swift │ │ ├── ComputerConfigurationProfile │ │ │ └── ComputerConfigurationProfileGeneral.swift │ │ └── ConfigurationProfileGeneral.swift │ │ ├── HardwareGroup │ │ ├── HardwareGroup.swift │ │ └── HardwareGroupCriterion.swift │ │ ├── ComputerConfiguration │ │ └── ComputerConfigurationManagement.swift │ │ ├── Site.swift │ │ ├── Department.swift │ │ ├── PreciseDate.swift │ │ ├── Partition.swift │ │ └── BaseObject.swift └── Configurations │ ├── JamfKitTests.plist │ └── JamfKit.plist ├── Assets ├── JamfKit_1024.png ├── JamfKit_256.png ├── JamfKit_512.png ├── JamfKit_Black_256.png ├── JamfKit_Black_512.png ├── JamfKit_White_256.png ├── JamfKit_White_512.png ├── JamfKit_Black_1024.png └── JamfKit_White_1024.png ├── JamfKit.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ ├── WorkspaceSettings.xcsettings │ ├── IDEWorkspaceChecks.plist │ └── IDETemplateMacros.plist ├── codecov.yml ├── .jazzy.yaml ├── .gitignore ├── .travis.yml ├── JAMFKit.podspec ├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── LICENSE └── CODE_OF_CONDUCT.md /.swift-version: -------------------------------------------------------------------------------- 1 | 4.0 -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Site/site_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345 3 | } 4 | -------------------------------------------------------------------------------- /Assets/JamfKit_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_1024.png -------------------------------------------------------------------------------- /Assets/JamfKit_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_256.png -------------------------------------------------------------------------------- /Assets/JamfKit_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_512.png -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Building/building_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345 3 | } 4 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Department/department_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345 3 | } 4 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/BaseObject/base_object_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345 3 | } 4 | -------------------------------------------------------------------------------- /Assets/JamfKit_Black_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_Black_256.png -------------------------------------------------------------------------------- /Assets/JamfKit_Black_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_Black_512.png -------------------------------------------------------------------------------- /Assets/JamfKit_White_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_White_256.png -------------------------------------------------------------------------------- /Assets/JamfKit_White_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_White_512.png -------------------------------------------------------------------------------- /Assets/JamfKit_Black_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_Black_1024.png -------------------------------------------------------------------------------- /Assets/JamfKit_White_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damien-rivet/JamfKit/HEAD/Assets/JamfKit_White_1024.png -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Site/site_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Nowhere" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/BaseObject/base_object_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Test" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Category/category_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "category" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Department/department_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Unknown" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Script/script_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Script" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerCommand/computer_command_general_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "command": "command" 3 | } 4 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Package/package_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Package.dmg" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy_general_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Policy" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Printer/printer_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "HP 9th Floor" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Computer/computer_general_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "computer" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerGroup/computer_group_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "computers" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/PreciseDate/precise_date_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "precise_date": "2017-07-07T18:37:04.000Z" 3 | } 4 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/NetbootServer/netboot_server_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Netboot Server" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/SMTPServer/smtp_server_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "enabled": true, 3 | "host": "smtp.jamfkit.com" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Category/category_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "category", 4 | "priority": 10 5 | } 6 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/DirectoryBinding/directory_binding_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "AD Binding" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/NetworkSegment/network_segment_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "network_segment" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Computer/computer_remote_management.json: -------------------------------------------------------------------------------- 1 | { 2 | "managed": true, 3 | "management_username": "username" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerCommand/computer_command_general_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "command": "command", 3 | "passcode": 123456 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceGroup/mobile_device_group_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "mobile_devices" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "name": "Policy" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Computer/computer_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "name": "computer" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy_network_limitations.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimum_network_connection": "No Minimum", 3 | "any_ip_address": true 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerConfiguration/computer_configuration_general_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "High Sierra Base OS" 4 | } 5 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerCommand/computer_command_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "command": "command", 4 | "passcode": 123456 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerCommand/computer_command_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "computers": { 3 | "computer": { 4 | "id": 1 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /JamfKit/.swiftlint.yml: -------------------------------------------------------------------------------- 1 | included: 2 | - Sources 3 | 4 | line_length: 200 5 | type_body_length: 300 # JSS objects can get be pretty big 6 | function_body_length: 50 # JSS objects can get be pretty big 7 | -------------------------------------------------------------------------------- /JamfKit.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JamfKit/JamfKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/PreciseDate/precise_date.json: -------------------------------------------------------------------------------- 1 | { 2 | "precise_date": "2017-07-07T18:37:04.000Z", 3 | "precise_date_epoch": 1499470624555, 4 | "precise_date_utc": "2017-07-07T18:37:04.555-0500" 5 | } 6 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | enabled: yes 6 | target: 75% 7 | patch: 8 | default: 9 | enabled: yes 10 | target: 75% 11 | ignore: 12 | - "JamfKit/Tests" 13 | -------------------------------------------------------------------------------- /JamfKit.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy_override_default_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_drive": "target_drive", 3 | "distribution_point": "distribution_point", 4 | "force_afp_smb": true, 5 | "sus": "sus", 6 | "netboot_server": "netboot_server" 7 | } 8 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerConfiguration/computer_configuration_management.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "administrator", 3 | "password": "password", 4 | "create_account": true, 5 | "hide_account": true, 6 | "allow_ssh_for_management_only": true 7 | } 8 | -------------------------------------------------------------------------------- /JamfKit/Playgrounds/Examples.playground/Pages/Summary.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: # JamfKit - Playgrounds 2 | 3 | //: You'll find below the summary of the available Playgrounds to get you started with `JamfKit`. 4 | 5 | //: [Classes](Classes) 6 | 7 | //: [Requests](Requests) 8 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerCommand/computer_command.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "command": "command", 4 | "passcode": 123456 5 | }, 6 | "computers": { 7 | "computer": { 8 | "id": 1 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.jazzy.yaml: -------------------------------------------------------------------------------- 1 | author: Ethenyl 2 | author_url: https://github.com/Ethenyl 3 | github_url: https://github.com/Ethenyl/JamfKit 4 | root_url: https://ethenyl.github.io/JamfKit/ 5 | module: JamfKit 6 | output: docs 7 | theme: fullwidth 8 | xcodebuild_arguments: [-workspace, 'JamfKit.xcworkspace', -scheme, 'JamfKit iOS'] 9 | -------------------------------------------------------------------------------- /JamfKit/Sources/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | struct Constants { 7 | 8 | static let domain = "com.github.ethenyl.JamfKit" 9 | } 10 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/HardwareGroup/hardware_group_criterion.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Last Inventory Update", 3 | "priority": 0, 4 | "and_or": "and", 5 | "search_type": "more than x days ago", 6 | "value": 7, 7 | "opening_paren": false, 8 | "closing_paren": false 9 | } 10 | -------------------------------------------------------------------------------- /JamfKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Building/building_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Building", 4 | "streetAddress1": "Doe Street", 5 | "streetAddress2": "", 6 | "city": "Doeville", 7 | "stateProvince": "Doe county", 8 | "zipPostalCode": "012345", 9 | "country": "Doeland" 10 | } 11 | -------------------------------------------------------------------------------- /JamfKit/Sources/Protocols/Subset.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents any JSS object that contains a general object that can identify it. 7 | public protocol Subset { } 8 | -------------------------------------------------------------------------------- /JamfKit/Playgrounds/Examples.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Partition/partition.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "partition", 3 | "size_gb": 50, 4 | "maximum_percentage": 25, 5 | "format": "Journaled HFS+", 6 | "is_restore_partition": true, 7 | "computer_configuration": "Recovery HD", 8 | "reimage": true, 9 | "append_to_name": "suffix" 10 | } 11 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/DirectoryBinding/directory_binding_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "priority": 1, 4 | "domain": "ad.company.com", 5 | "username": "AD\\Administrator", 6 | "password": "password", 7 | "computer_ou": "CN=Computers,DC=ad,DC=company,DC=com", 8 | "type": "Active Directory" 9 | } 10 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/DirectoryBinding/directory_binding_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "AD Binding", 4 | "priority": 1, 5 | "domain": "ad.company.com", 6 | "username": "AD\\Administrator", 7 | "password": "password", 8 | "computer_ou": "CN=Computers,DC=ad,DC=company,DC=com", 9 | "type": "Active Directory" 10 | } 11 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/SMTPServer/smtp_server.json: -------------------------------------------------------------------------------- 1 | { 2 | "enabled": true, 3 | "host": "smtp.jamfkit.com", 4 | "port": 12345, 5 | "timeout": 5, 6 | "authorization_required": true, 7 | "username": "username", 8 | "password": "password", 9 | "ssl": true, 10 | "tls": true, 11 | "send_from_name": "JamfKit SMTP Server", 12 | "send_from_email": "smtp@jamfkit.com" 13 | } 14 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Computer/computer_location.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "JDoe", 3 | "realname": "John Doe", 4 | "real_name": "John Doe", 5 | "email_address": "john.doe@doecorp.com", 6 | "position": "Unknown", 7 | "phone": "123-456-7890", 8 | "phone_number": "123-456-7890", 9 | "department": "Unknown department", 10 | "building": "Unknown building", 11 | "room": 1234 12 | } 13 | -------------------------------------------------------------------------------- /JamfKit/Sources/JamfKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #import 7 | 8 | //! Project version number for Core. 9 | FOUNDATION_EXPORT double JamfKitVersionNumber; 10 | 11 | //! Project version string for Core. 12 | FOUNDATION_EXPORT const unsigned char JamfKitVersionString[]; 13 | -------------------------------------------------------------------------------- /JamfKit/Sources/Extensions/StringExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | extension String { 7 | 8 | // MARK: - Functions 9 | 10 | /// Returns the String without useless characters 11 | func asCleanedKey() -> String { 12 | return self.replacingOccurrences(of: "_", with: "") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/NetbootServer/netboot_server_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "ip_address": "127.0.0.1", 4 | "default_image": true, 5 | "specific_image": false, 6 | "target_platform": "PowerPC", 7 | "share_point": "string", 8 | "set": "string", 9 | "image": "string", 10 | "protocol": "nfs", 11 | "configure_manually": true, 12 | "boot_args": "string", 13 | "boot_file": "string", 14 | "boot_device": "string" 15 | } 16 | -------------------------------------------------------------------------------- /JamfKit.xcworkspace/xcshareddata/IDETemplateMacros.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FILEHEADER 6 | 7 | // Copyright © 2017-present JamfKit. All rights reserved. 8 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 9 | // 10 | 11 | 12 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ConfigurationProfileGeneral/configuration_profile_general_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "description": "Description", 4 | "site": { 5 | "id": 12345, 6 | "name": "Site" 7 | }, 8 | "category": { 9 | "id": 12345, 10 | "name": "Category", 11 | "priority": 0 12 | }, 13 | "uuid": "88F8C1DB-D92A-4D10-95FB-CE7EDE82B93E", 14 | "redeploy_on_update": "Newly Assigned", 15 | "payloads": "Payloads" 16 | } 17 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/NetbootServer/netboot_server_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Netboot Server", 4 | "ip_address": "127.0.0.1", 5 | "default_image": true, 6 | "specific_image": false, 7 | "target_platform": "PowerPC", 8 | "share_point": "string", 9 | "set": "string", 10 | "image": "string", 11 | "protocol": "nfs", 12 | "configure_manually": true, 13 | "boot_args": "string", 14 | "boot_file": "string", 15 | "boot_device": "string" 16 | } 17 | -------------------------------------------------------------------------------- /JamfKit/Sources/Protocols/Identifiable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents any JSS object that can be identified (either by ID or by name). 7 | @objc(JMFKIdentifiable) 8 | public protocol Identifiable { 9 | 10 | // MARK: - Properties 11 | 12 | @objc 13 | var identifier: UInt { get } 14 | 15 | @objc 16 | var name: String { get } 17 | } 18 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/NetworkSegment/network_segment_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "starting_address": "127.0.0.1", 4 | "ending_address": "127.0.0.255", 5 | "distribution_server": "distribution_server", 6 | "distribution_point": "distribution_point", 7 | "url": "url", 8 | "netboot_server": "netboot_server", 9 | "swu_server": "swu_server", 10 | "building": "building", 11 | "department": "department", 12 | "override_buildings": true, 13 | "override_departments": false 14 | } 15 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ConfigurationProfileGeneral/configuration_profile_general_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Configuration Profile", 4 | "description": "Description", 5 | "site": { 6 | "id": 12345, 7 | "name": "Site" 8 | }, 9 | "category": { 10 | "id": 12345, 11 | "name": "Category", 12 | "priority": 0 13 | }, 14 | "uuid": "88F8C1DB-D92A-4D10-95FB-CE7EDE82B93E", 15 | "redeploy_on_update": "Newly Assigned", 16 | "payloads": "Payloads" 17 | } 18 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy_date_time_limitations.json: -------------------------------------------------------------------------------- 1 | { 2 | "activation_date": "2017-07-07T18:37:04.000Z", 3 | "activation_date_epoch": 1499470624555, 4 | "activation_date_utc": "2017-07-07T18:37:04.555-0500", 5 | "expiration_date": "2017-07-07T18:37:04.000Z", 6 | "expiration_date_epoch": 1499470624555, 7 | "expiration_date_utc": "2017-07-07T18:37:04.555-0500", 8 | "no_execute_on": { 9 | "day": "Sun" 10 | }, 11 | "no_execute_start": "2:00 AM", 12 | "no_execute_end": "4:00 AM" 13 | } 14 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/NetworkSegment/network_segment_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "network_segment", 4 | "starting_address": "127.0.0.1", 5 | "ending_address": "127.0.0.255", 6 | "distribution_server": "distribution_server", 7 | "distribution_point": "distribution_point", 8 | "url": "url", 9 | "netboot_server": "netboot_server", 10 | "swu_server": "swu_server", 11 | "building": "building", 12 | "department": "department", 13 | "override_buildings": true, 14 | "override_departments": false 15 | } 16 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Printer/printer_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 0, 3 | "category": "Printers", 4 | "uri": "lpd://10.1.20.204/", 5 | "CUPS_name": "HP_9th_Floor", 6 | "location": "string", 7 | "model": "HP LaserJet 500 color MFP M575", 8 | "info": "string", 9 | "notes": "string", 10 | "make_default": true, 11 | "use_generic": true, 12 | "ppd": "9th_Floor_HP.ppd", 13 | "ppd_path": "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Resources/Generic.ppd", 14 | "ppd_contents": "string" 15 | } 16 | -------------------------------------------------------------------------------- /JamfKit/Sources/Protocols/Endpoint.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents any JSS object that is matched by a JSS endpoint. 7 | public protocol Endpoint { 8 | 9 | // MARK: - Properties 10 | 11 | static var Endpoint: String { get } 12 | 13 | var endpoint: String { get } 14 | } 15 | 16 | extension Endpoint { 17 | 18 | // MARK: - Properties 19 | 20 | public var endpoint: String { 21 | return Self.Endpoint 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/HardwareGroup/hardware_group_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "is_smart": true, 4 | "criteria": [ 5 | { 6 | "criterion": { 7 | "name": "Last Inventory Update", 8 | "priority": 0, 9 | "and_or": "and", 10 | "search_type": "more than x days ago", 11 | "value": 7, 12 | "opening_paren": false, 13 | "closing_paren": false 14 | } 15 | } 16 | ], 17 | "site": { 18 | "id": 0, 19 | "name": "site" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /JamfKit/Tests/Extensions/StringExtensionTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class StringExtensionTests: XCTestCase { 11 | 12 | // MARK: - Tests 13 | 14 | func testShouldReturnCleanedUpKey() { 15 | let actualValue = ComputerGeneral.SerialNumberKey.asCleanedKey() 16 | 17 | XCTAssertEqual(actualValue, ComputerGeneral.SerialNumberKey.replacingOccurrences(of: "_", with: "")) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerConfigurationProfile/computer_configuration_profile_general_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "description": "Description", 4 | "site": { 5 | "id": 12345, 6 | "name": "Site" 7 | }, 8 | "category": { 9 | "id": 12345, 10 | "name": "Category", 11 | "priority": 0 12 | }, 13 | "distribution_method": "Install Automatically", 14 | "user_removable": true, 15 | "level": "computer", 16 | "uuid": "88F8C1DB-D92A-4D10-95FB-CE7EDE82B93E", 17 | "redeploy_on_update": "Newly Assigned", 18 | "payloads": "Payloads" 19 | } 20 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceConfigurationProfile/mobile_device_configuration_profile_general_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "description": "Description", 4 | "site": { 5 | "id": 12345, 6 | "name": "Site" 7 | }, 8 | "category": { 9 | "id": 12345, 10 | "name": "Category", 11 | "priority": 0 12 | }, 13 | "uuid": "55900BDC-347C-58B1-D249-F32244B11D30", 14 | "deployment_method": "Install Automatically", 15 | "redeploy_on_update": "Newly Assigned", 16 | "redeploy_Dayss_before_certificate_expires": 0, 17 | "payloads": "Payloads" 18 | } 19 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Printer/printer_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "HP 9th Floor", 4 | "category": "Printers", 5 | "uri": "lpd://10.1.20.204/", 6 | "CUPS_name": "HP_9th_Floor", 7 | "location": "Somewhere", 8 | "model": "HP LaserJet 500 color MFP M575", 9 | "info": "None", 10 | "notes": "None", 11 | "make_default": true, 12 | "use_generic": true, 13 | "ppd": "9th_Floor_HP.ppd", 14 | "ppd_path": "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Resources/Generic.ppd", 15 | "ppd_contents": "string" 16 | } 17 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/HardwareGroup/hardware_group_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "hardwares", 4 | "is_smart": true, 5 | "criteria": [ 6 | { 7 | "criterion": { 8 | "name": "Last Inventory Update", 9 | "priority": 0, 10 | "and_or": "and", 11 | "search_type": "more than x days ago", 12 | "value": 7, 13 | "opening_paren": false, 14 | "closing_paren": false 15 | } 16 | } 17 | ], 18 | "site": { 19 | "id": 0, 20 | "name": "site" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerConfigurationProfile/computer_configuration_profile_general_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Corporate Wireless", 4 | "description": "Description", 5 | "site": { 6 | "id": 12345, 7 | "name": "Site" 8 | }, 9 | "category": { 10 | "id": 12345, 11 | "name": "Category", 12 | "priority": 0 13 | }, 14 | "distribution_method": "Install Automatically", 15 | "user_removable": true, 16 | "level": "computer", 17 | "uuid": "88F8C1DB-D92A-4D10-95FB-CE7EDE82B93E", 18 | "redeploy_on_update": "Newly Assigned", 19 | "payloads": "Payloads" 20 | } 21 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceConfigurationProfile/mobile_device_configuration_profile_general_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Corporate Wireless", 4 | "description": "Description", 5 | "site": { 6 | "id": 12345, 7 | "name": "Site" 8 | }, 9 | "category": { 10 | "id": 12345, 11 | "name": "Category", 12 | "priority": 0 13 | }, 14 | "uuid": "55900BDC-347C-58B1-D249-F32244B11D30", 15 | "deployment_method": "Install Automatically", 16 | "redeploy_on_update": "Newly Assigned", 17 | "redeploy_Dayss_before_certificate_expires": 0, 18 | "payloads": "Payloads" 19 | } 20 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Package/package_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "category": "Unknown", 4 | "filename": "Package.dmg", 5 | "info": "information", 6 | "notes": "notes", 7 | "priority": 5, 8 | "reboot_required": true, 9 | "fill_user_template": true, 10 | "fill_existing_users": true, 11 | "boot_volume_required": true, 12 | "allow_uninstalled": true, 13 | "os_requirements": "requirement", 14 | "required_processor": "None", 15 | "switch_with_package": "Do Not Install", 16 | "install_if_reported_available": true, 17 | "reinstall_option": "Do Not Reinstall", 18 | "triggering_files": "files", 19 | "send_notification": true 20 | } 21 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceConfigurationProfile/mobile_device_configuration_profile_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "description": "Description", 5 | "site": { 6 | "id": 12345, 7 | "name": "Site" 8 | }, 9 | "category": { 10 | "id": 12345, 11 | "name": "Category", 12 | "priority": 0 13 | }, 14 | "uuid": "55900BDC-347C-58B1-D249-F32244B11D30", 15 | "deployment_method": "Install Automatically", 16 | "redeploy_on_update": "Newly Assigned", 17 | "redeploy_Dayss_before_certificate_expires": 0, 18 | "payloads": "Payloads" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X 2 | 3 | .DS_Store 4 | 5 | # Xcode 6 | 7 | ## Build generated 8 | build/ 9 | DerivedData/ 10 | 11 | ## Various settings 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | *xcuserdata/ 21 | 22 | ## Other 23 | *.moved-aside 24 | *.xccheckout 25 | *.xcscmblueprint 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Carthage 38 | */Carthage/ 39 | 40 | # fastlane 41 | */fastlane/report.xml 42 | */fastlane/Preview.html 43 | */fastlane/screenshots 44 | */fastlane/test_output 45 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerConfigurationProfile/computer_configuration_profile_invalid.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "general": { 4 | "id": 12345, 5 | "description": "Description", 6 | "site": { 7 | "id": 12345, 8 | "name": "Site" 9 | }, 10 | "category": { 11 | "id": 12345, 12 | "name": "Category", 13 | "priority": 0 14 | }, 15 | "distribution_method": "Install Automatically", 16 | "user_removable": true, 17 | "level": "computer", 18 | "uuid": "88F8C1DB-D92A-4D10-95FB-CE7EDE82B93E", 19 | "redeploy_on_update": "Newly Assigned", 20 | "payloads": "Payloads" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Package/package_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Package.dmg", 4 | "category": "Unknown", 5 | "filename": "Package.dmg", 6 | "info": "information", 7 | "notes": "notes", 8 | "priority": 5, 9 | "reboot_required": true, 10 | "fill_user_template": true, 11 | "fill_existing_users": true, 12 | "boot_volume_required": true, 13 | "allow_uninstalled": true, 14 | "os_requirements": "requirement", 15 | "required_processor": "None", 16 | "switch_with_package": "Do Not Install", 17 | "install_if_reported_available": true, 18 | "reinstall_option": "Do Not Reinstall", 19 | "triggering_files": "files", 20 | "send_notification": true 21 | } 22 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Script/script_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "category": "None", 4 | "filename": "filename", 5 | "info": "Script information", 6 | "notes": "Script to decrypt FV2 encrypted drives", 7 | "priority": "Before", 8 | "parameters": { 9 | "parameter4": "string", 10 | "parameter5": "string", 11 | "parameter6": "string", 12 | "parameter7": "string", 13 | "parameter8": "string", 14 | "parameter9": "string", 15 | "parameter10": "string", 16 | "parameter11": "string" 17 | }, 18 | "os_requirements": "requirements", 19 | "script_contents": "echo \"Sample script\"", 20 | "script_contents_encoded": "encoded" 21 | } 22 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceConfigurationProfile/mobile_device_configuration_profile_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "name": "Corporate Wireless", 5 | "description": "Description", 6 | "site": { 7 | "id": 12345, 8 | "name": "Site" 9 | }, 10 | "category": { 11 | "id": 12345, 12 | "name": "Category", 13 | "priority": 0 14 | }, 15 | "uuid": "55900BDC-347C-58B1-D249-F32244B11D30", 16 | "deployment_method": "Install Automatically", 17 | "redeploy_on_update": "Newly Assigned", 18 | "redeploy_Dayss_before_certificate_expires": 0, 19 | "payloads": "Payloads" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerConfigurationProfile/computer_configuration_profile_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "name": "Corporate Wireless", 5 | "description": "Description", 6 | "site": { 7 | "id": 12345, 8 | "name": "Site" 9 | }, 10 | "category": { 11 | "id": 12345, 12 | "name": "Category", 13 | "priority": 0 14 | }, 15 | "distribution_method": "Install Automatically", 16 | "user_removable": true, 17 | "level": "computer", 18 | "uuid": "88F8C1DB-D92A-4D10-95FB-CE7EDE82B93E", 19 | "redeploy_on_update": "Newly Assigned", 20 | "payloads": "Payloads" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: osx 2 | language: objective-c 3 | osx_image: xcode10.2 4 | 5 | env: 6 | global: 7 | - WORKSPACE="JamfKit.xcworkspace" 8 | matrix: 9 | - PLATFORM="macOS" SCHEME="JamfKit macOS" DESTINATION="arch=x86_64" 10 | - PLATFORM="iOS" SCHEME="JamfKit iOS" DESTINATION='platform=iOS Simulator,name=iPhone 8' 11 | - PLATFORM="tvOS" SCHEME="JamfKit tvOS" DESTINATION='platform=tvOS Simulator,name=Apple TV 4K' 12 | 13 | before_install: 14 | - gem install xcpretty 15 | 16 | before_script: 17 | - pod lib lint --quick 18 | 19 | script: 20 | - set -o pipefail && xcodebuild clean test -workspace "$WORKSPACE" -scheme "$SCHEME" -destination "$DESTINATION" | xcpretty 21 | 22 | after_success: 23 | - bash <(curl -s https://codecov.io/bash) -J 'JamfKit' 24 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Script/script_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Script", 4 | "category": "None", 5 | "filename": "filename", 6 | "info": "Script information", 7 | "notes": "Script to decrypt FV2 encrypted drives", 8 | "priority": "Before", 9 | "parameters": { 10 | "parameter4": "string", 11 | "parameter5": "string", 12 | "parameter6": "string", 13 | "parameter7": "string", 14 | "parameter8": "string", 15 | "parameter9": "string", 16 | "parameter10": "string", 17 | "parameter11": "string" 18 | }, 19 | "os_requirements": "requirements", 20 | "script_contents": "echo \"Sample script\"", 21 | "script_contents_encoded": "encoded" 22 | } 23 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDevice/mobile_device_general_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Mobile Device", 4 | "last_inventory_update": "2017-07-07T18:37:04.000Z", 5 | "last_inventory_update_epoch": 1499470624555, 6 | "last_inventory_update_utc": "2017-07-07T18:37:04.555-0500", 7 | "initial_entry_date_epoch": 1499470624555, 8 | "initial_entry_date_utc": "2017-07-07T18:37:04.555-0500", 9 | "last_enrollment_epoch": 1499470624555, 10 | "last_enrollment_utc": "2017-07-07T18:37:04.555-0500", 11 | "last_cloud_backup_date_epoch": 1499470624555, 12 | "last_cloud_backup_date_utc": "2017-07-07T18:37:04.555-0500", 13 | "last_backup_time_epoch": 1499470624555, 14 | "last_backup_time_utc": "2017-07-07T18:37:04.555-0500" 15 | } 16 | -------------------------------------------------------------------------------- /JAMFKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "JAMFKit" 3 | s.version = "0.3.3" 4 | s.summary = "A JSS communication framework written in Swift" 5 | s.description = <<-DESC 6 | JamfKit is an iOS / macOS / tvOS framework to communicate with the JSS API offered by any Jamf host. 7 | DESC 8 | 9 | s.homepage = "https://github.com/Ethenyl/JamfKit" 10 | s.license = { :type => "MIT", :file => "LICENSE" } 11 | s.author = { "Damien Rivet" => "damien.rivet@gmail.com" } 12 | 13 | s.ios.deployment_target = "9.0" 14 | s.osx.deployment_target = "10.10" 15 | s.tvos.deployment_target = "9.0" 16 | 17 | s.source = { :git => "https://github.com/Ethenyl/JamfKit.git", :tag => s.version.to_s } 18 | s.source_files = "JamfKit/Sources/**/*.swift" 19 | 20 | s.frameworks = "Foundation" 21 | end 22 | -------------------------------------------------------------------------------- /JamfKit/Configurations/JamfKitTests.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /JamfKit/Sources/Protocols/Requests/Creatable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents an object that can be created with an URLRequest 7 | @objc(JMFKCreatable) 8 | public protocol Creatable { 9 | 10 | // MARK: - Functions 11 | 12 | /// Returns a POST **URLRequest** based on the identifier property of the supplied JSS object. 13 | func createRequest() -> URLRequest? 14 | } 15 | 16 | // MARK: - Implementation 17 | 18 | extension Creatable where Self: Endpoint & Identifiable & Requestable { 19 | 20 | func getCreateRequest() -> URLRequest? { 21 | return SessionManager.instance.createRequest(for: self, key: BaseObject.CodingKeys.identifier.rawValue, value: String(identifier)) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Computer/computer_purchasing.json: -------------------------------------------------------------------------------- 1 | { 2 | "is_purchased": true, 3 | "is_leased": true, 4 | "po_number": "po_number", 5 | "vendor": "vendor", 6 | "applecare_id": "applecare_id", 7 | "purchase_price": "purchase_price", 8 | "purchasing_account": "purchasing_account", 9 | "purchasing_contact": "purchasing_contact", 10 | "po_date": "2017-07-07T18:37:04.000Z", 11 | "po_date_epoch": 1499470624555, 12 | "po_date_utc": "2017-07-07T18:37:04.555-0500", 13 | "warranty_expires": "2017-07-07T18:37:04.000Z", 14 | "warranty_expires_epoch": 1499470624555, 15 | "warranty_expires_utc": "2017-07-07T18:37:04.555-0500", 16 | "lease_expires": "2017-07-07T18:37:04.000Z", 17 | "lease_expires_epoch": 1499470624555, 18 | "lease_expires_utc": "2017-07-07T18:37:04.555-0500", 19 | "life_expectancy": 0 20 | } 21 | -------------------------------------------------------------------------------- /JamfKit/Sources/Protocols/Requestable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents an object that can be used to perform requests with any JSS endpoint. 7 | @objc(JMFKRequestable) 8 | public protocol Requestable { 9 | 10 | // MARK: - Initialization 11 | 12 | /** 13 | * Returns a JSS object instantiated from the supplied JSON payload. 14 | * 15 | * - Parameter json: The creation key to use for generating the URLRequest 16 | * - Parameter node: Some JSS object can be nested inside a specific node, this parameter can be used to enforce it 17 | */ 18 | init?(json: [String: Any], node: String) 19 | 20 | // MARK: - Functions 21 | 22 | /// Returns a JSS object as a JSON payload. 23 | func toJSON() -> [String: Any] 24 | } 25 | -------------------------------------------------------------------------------- /JamfKit/Tests/Helpers/JSONHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | extension XCTestCase { 9 | 10 | // MARK: - Functions 11 | 12 | func payload(for jsonFile: String, subfolder: String = "") -> [String: AnyObject]? { 13 | let bundle = Bundle(for: type(of: self)).url(forResource: "Mocks", withExtension: "bundle")! 14 | let urlBundle = Bundle(url: bundle)! 15 | 16 | if let data = try? Data(contentsOf: urlBundle.url(forResource: subfolder + jsonFile, withExtension: "json")!) { 17 | if let payload = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] { 18 | return payload 19 | } 20 | } 21 | 22 | return [String: AnyObject]() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceGroup/mobile_device_group_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "is_smart": true, 4 | "criteria": { 5 | "criterion": { 6 | "name": "Last Inventory Update", 7 | "priority": 0, 8 | "and_or": "and", 9 | "search_type": "more than x days ago", 10 | "value": 7, 11 | "opening_paren": false, 12 | "closing_paren": false 13 | } 14 | }, 15 | "site": { 16 | "id": 0, 17 | "name": "site" 18 | }, 19 | "mobile_devices": { 20 | "mobile_device": { 21 | "id": 0, 22 | "name": "John's iPhone", 23 | "mac_address": "E0:AC:CB:97:36:G4", 24 | "udid": "55900BDC-347C-58B1-D249-F32244B11D30", 25 | "wifi_mac_address": "E0:AC:CB:97:36:G4", 26 | "serial_number": "C02Q7KHTGFWF" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | :warning: 2 | 3 | :heart: Thanks a lot for contributing to `JamfKit`. :heart: 4 | 5 | ## Pull request checklist ## 6 | 7 | - [ ] Title must be clear about what will change 8 | - [ ] Description must contain a comprehensive explanation of what changed and links toward related issues 9 | - [ ] Unit tests must put in place for every single new object 10 | - [ ] New objects must be fully documented (inline + README) 11 | - [ ] Pull request is following the [CODE OF CONDUCT](https://github.com/Ethenyl/JamfKit/blob/master/CODE_OF_CONDUCT.md) 12 | 13 | :warning: 14 | 15 | # Summary # 16 | 17 | *Please fill this section with information related to the changes / fixes you introduced. Make sure to add a reference to all the tickets that are impacted by this pull request.* 18 | 19 | # Miscellaneous # 20 | 21 | *Please fill this section with anything else that can be relevant to the review of your pull request (benchmarks, blogs, StackOverflow threads, etc.).* 22 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerGroup/computer_group_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "is_smart": true, 4 | "site": { 5 | "id": 12345, 6 | "name": "None" 7 | }, 8 | "criteria": [ 9 | { 10 | "criterion": { 11 | "name": "Last Inventory Update", 12 | "priority": 0, 13 | "and_or": "and", 14 | "search_type": "more than x days ago", 15 | "value": 7, 16 | "opening_paren": false, 17 | "closing_paren": false 18 | } 19 | } 20 | ], 21 | "computers": [ 22 | { 23 | "computer": { 24 | "id": 12345, 25 | "name": "Joes iMac", 26 | "mac_address": "E0:AC:CB:97:36:G4", 27 | "alt_mac_address": "E0:AC:CB:67:36:T4", 28 | "serial_number": "C02Q7KHTGFWF" 29 | } 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerGroup/computer_group_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "computers", 4 | "is_smart": true, 5 | "site": { 6 | "id": 12345, 7 | "name": "None" 8 | }, 9 | "criteria": [ 10 | { 11 | "criterion": { 12 | "name": "Last Inventory Update", 13 | "priority": 0, 14 | "and_or": "and", 15 | "search_type": "more than x days ago", 16 | "value": 7, 17 | "opening_paren": false, 18 | "closing_paren": false 19 | } 20 | } 21 | ], 22 | "computers": [ 23 | { 24 | "computer": { 25 | "id": 12345, 26 | "name": "Joes iMac", 27 | "mac_address": "E0:AC:CB:97:36:G4", 28 | "alt_mac_address": "E0:AC:CB:67:36:T4", 29 | "serial_number": "C02Q7KHTGFWF" 30 | } 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerGroup/computer_group_invalid_computer.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "computers", 4 | "is_smart": true, 5 | "site": { 6 | "id": 12345, 7 | "name": "None" 8 | }, 9 | "criteria": [ 10 | { 11 | "criterion": { 12 | "name": "Last Inventory Update", 13 | "priority": 0, 14 | "and_or": "and", 15 | "search_type": "more than x days ago", 16 | "value": 7, 17 | "opening_paren": false, 18 | "closing_paren": false 19 | } 20 | } 21 | ], 22 | "computers": [ 23 | { 24 | "computers": { 25 | "id": 12345, 26 | "name": "Joes iMac", 27 | "mac_address": "E0:AC:CB:97:36:G4", 28 | "alt_mac_address": "E0:AC:CB:67:36:T4", 29 | "serial_number": "C02Q7KHTGFWF" 30 | } 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/ComputerGroup/computer_group_invalid_criterion.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "computers", 4 | "is_smart": true, 5 | "site": { 6 | "id": 12345, 7 | "name": "None" 8 | }, 9 | "criteria": [ 10 | { 11 | "criteria": { 12 | "name": "Last Inventory Update", 13 | "priority": 0, 14 | "and_or": "and", 15 | "search_type": "more than x days ago", 16 | "value": 7, 17 | "opening_paren": false, 18 | "closing_paren": false 19 | } 20 | } 21 | ], 22 | "computers": [ 23 | { 24 | "computer": { 25 | "id": 12345, 26 | "name": "Joes iMac", 27 | "mac_address": "E0:AC:CB:97:36:G4", 28 | "alt_mac_address": "E0:AC:CB:67:36:T4", 29 | "serial_number": "C02Q7KHTGFWF" 30 | } 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /JamfKit/Sources/Protocols/Requests/Updatable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents an object that can be updated with an URLRequest 7 | @objc(JMFKUpdatable) 8 | public protocol Updatable { 9 | 10 | // MARK: - Functions 11 | 12 | /// Returns a PUT **URLRequest** based on the identifier property of the supplied JSS object. 13 | func updateRequest() -> URLRequest? 14 | } 15 | 16 | // MARK: - Implementation 17 | 18 | extension Updatable where Self: Endpoint & Identifiable & Requestable { 19 | 20 | func getUpdateRequest() -> URLRequest? { 21 | return SessionManager.instance.updateRequest(for: self, key: BaseObject.CodingKeys.identifier.rawValue, value: String(identifier)) 22 | } 23 | 24 | func getUpdateRequestWithName() -> URLRequest? { 25 | return SessionManager.instance.updateRequest(for: self, key: BaseObject.CodingKeys.name.rawValue, value: name) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /JamfKit/Configurations/JamfKit.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | $(CURRENT_PROJECT_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2017-present JamfKit. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceGroup/mobile_device_group_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "mobile_devices", 4 | "is_smart": true, 5 | "criteria": [ 6 | { 7 | "criterion": { 8 | "name": "Last Inventory Update", 9 | "priority": 0, 10 | "and_or": "and", 11 | "search_type": "more than x days ago", 12 | "value": 7, 13 | "opening_paren": false, 14 | "closing_paren": false 15 | } 16 | } 17 | ], 18 | "site": { 19 | "id": 0, 20 | "name": "site" 21 | }, 22 | "mobile_devices": [ 23 | { 24 | "mobile_device": { 25 | "id": 0, 26 | "name": "John's iPhone", 27 | "mac_address": "E0:AC:CB:97:36:G4", 28 | "udid": "55900BDC-347C-58B1-D249-F32244B11D30", 29 | "wifi_mac_address": "E0:AC:CB:97:36:G4", 30 | "serial_number": "C02Q7KHTGFWF" 31 | } 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceGroup/mobile_device_group_invalid_criterion.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "mobile_devices", 4 | "is_smart": true, 5 | "criteria": [ 6 | { 7 | "criteria": { 8 | "name": "Last Inventory Update", 9 | "priority": 0, 10 | "and_or": "and", 11 | "search_type": "more than x days ago", 12 | "value": 7, 13 | "opening_paren": false, 14 | "closing_paren": false 15 | } 16 | } 17 | ], 18 | "site": { 19 | "id": 0, 20 | "name": "site" 21 | }, 22 | "mobile_devices": [ 23 | { 24 | "mobile_device": { 25 | "id": 0, 26 | "name": "John's iPhone", 27 | "mac_address": "E0:AC:CB:97:36:G4", 28 | "udid": "55900BDC-347C-58B1-D249-F32244B11D30", 29 | "wifi_mac_address": "E0:AC:CB:97:36:G4", 30 | "serial_number": "C02Q7KHTGFWF" 31 | } 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /JamfKit/Tests/Models/HardwareGroup/HardwareGroupTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class HardwareGroupTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "ComputerGroup/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "computers" 17 | let defaultIsSmart = true 18 | 19 | // MARK: - Tests 20 | 21 | func testShouldInstantiate() { 22 | let actualValue = HardwareGroup(identifier: defaultIdentifier, name: defaultName) 23 | 24 | XCTAssertNotNil(actualValue) 25 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 26 | XCTAssertEqual(actualValue?.name, defaultName) 27 | } 28 | 29 | func testShouldNotInstantiateWithInvalidParameters() { 30 | let actualValue = HardwareGroup(identifier: defaultIdentifier, name: "") 31 | 32 | XCTAssertNil(actualValue) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDeviceGroup/mobile_device_group_invalid_mobile_device.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "mobile_devices", 4 | "is_smart": true, 5 | "criteria": [ 6 | { 7 | "criterion": { 8 | "name": "Last Inventory Update", 9 | "priority": 0, 10 | "and_or": "and", 11 | "search_type": "more than x days ago", 12 | "value": 7, 13 | "opening_paren": false, 14 | "closing_paren": false 15 | } 16 | } 17 | ], 18 | "site": { 19 | "id": 0, 20 | "name": "site" 21 | }, 22 | "mobile_devices": [ 23 | { 24 | "mobile_devices": { 25 | "id": 0, 26 | "name": "John's iPhone", 27 | "mac_address": "E0:AC:CB:97:36:G4", 28 | "udid": "55900BDC-347C-58B1-D249-F32244B11D30", 29 | "wifi_mac_address": "E0:AC:CB:97:36:G4", 30 | "serial_number": "C02Q7KHTGFWF" 31 | } 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /JamfKit/Sources/Session/SessionManagerError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKSessionManagerErrorCode) 7 | public enum SessionManagerErrorCode: Int { 8 | /// The configuration is missing either the JSS host's URL or the login / password 9 | case incompleteHostConfiguration 10 | 11 | /// The supplied URL for the JSS host is not a valid URL 12 | case invalidURL 13 | 14 | /// The supplied credentials (either the username or the password) are not valid 15 | case invalidCredentials 16 | 17 | /// The supplied [host | username & password] pair is not valid 18 | case invalidConfiguration 19 | 20 | /// The host is not configured 21 | case missingHostConfiguration 22 | } 23 | 24 | @objc(JMFKSessionManagerError) 25 | public class SessionManagerError: NSError { 26 | 27 | // MARK: - Initialization 28 | 29 | convenience init(code: SessionManagerErrorCode) { 30 | self.init(domain: Constants.domain, code: code.rawValue) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Damien Rivet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/User/user_incomplete.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "JDoe", 4 | "ldap_server": { 5 | "id": -1, 6 | "name": "None" 7 | }, 8 | "extension_attributes": { 9 | "extension_attribute": { 10 | "id": 0, 11 | "name": "Teacher ID", 12 | "type": "String", 13 | "value": "K52" 14 | } 15 | }, 16 | "links": { 17 | "computers": { 18 | "computer": { 19 | "id": 0, 20 | "name": "string" 21 | } 22 | }, 23 | "peripherals": { 24 | "peripheral": { 25 | "id": 0, 26 | "name": "string" 27 | } 28 | }, 29 | "mobile_devices": { 30 | "mobile_device": { 31 | "id": 0, 32 | "name": "string" 33 | } 34 | }, 35 | "vpp_assignments": { 36 | "vpp_assignment": { 37 | "id": 0, 38 | "name": "string" 39 | } 40 | }, 41 | "total_vpp_code_count": 0 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Category.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKCategory) 7 | public final class Category: BaseObject { 8 | 9 | // MARK: - Constants 10 | 11 | static let PriorityKey = "priority" 12 | 13 | // MARK: - Properties 14 | 15 | @objc 16 | public var priority: UInt = 0 17 | 18 | // MARK: - Initialization 19 | 20 | public required init?(json: [String: Any], node: String = "") { 21 | guard let priority = json[Category.PriorityKey] as? UInt else { 22 | return nil 23 | } 24 | 25 | self.priority = priority 26 | 27 | super.init(json: json) 28 | } 29 | 30 | public override init?(identifier: UInt, name: String) { 31 | super.init(identifier: identifier, name: name) 32 | } 33 | 34 | // MARK: - Functions 35 | 36 | public override func toJSON() -> [String: Any] { 37 | var json = super.toJSON() 38 | 39 | json[Category.PriorityKey] = priority 40 | 41 | return json 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Computer/ComputerRemoteManagement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKComputerRemoteManagement) 7 | public final class ComputerRemoteManagement: NSObject, Requestable { 8 | 9 | // MARK: - Constants 10 | 11 | static let ManagedKey = "managed" 12 | static let ManagementUsernameKey = "management_username" 13 | 14 | // MARK: - Properties 15 | 16 | @objc 17 | public var isManaged = false 18 | 19 | @objc 20 | public var managementUsername = "" 21 | 22 | // MARK: - Initialization 23 | 24 | public init?(json: [String: Any], node: String = "") { 25 | isManaged = json[ComputerRemoteManagement.ManagedKey] as? Bool ?? false 26 | managementUsername = json[ComputerRemoteManagement.ManagementUsernameKey] as? String ?? "" 27 | } 28 | 29 | public override init() { 30 | super.init() 31 | } 32 | 33 | // MARK: - Functions 34 | 35 | public func toJSON() -> [String: Any] { 36 | var json = [String: Any]() 37 | 38 | json[ComputerRemoteManagement.ManagedKey] = isManaged 39 | json[ComputerRemoteManagement.ManagementUsernameKey] = managementUsername 40 | 41 | return json 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Policy/PolicyNetworkLimitations.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKPolicyNetworkLimitations) 7 | public final class PolicyNetworkLimitations: NSObject, Requestable { 8 | 9 | // MARK: - Constants 10 | 11 | static let MinimumNetworkConnectionKey = "minimum_network_connection" 12 | static let AnyIpAddressKey = "any_ip_address" 13 | 14 | // MARK: - Properties 15 | 16 | @objc 17 | public var minimumNetworkConnection = "" 18 | 19 | @objc 20 | public var anyIpAddress = false 21 | 22 | // MARK: - Initialization 23 | 24 | public init?(json: [String: Any], node: String = "") { 25 | minimumNetworkConnection = json[PolicyNetworkLimitations.MinimumNetworkConnectionKey] as? String ?? "" 26 | anyIpAddress = json[PolicyNetworkLimitations.AnyIpAddressKey] as? Bool ?? false 27 | } 28 | 29 | public override init() { 30 | super.init() 31 | } 32 | 33 | // MARK: - Functions 34 | 35 | public func toJSON() -> [String: Any] { 36 | var json = [String: Any]() 37 | 38 | json[PolicyNetworkLimitations.MinimumNetworkConnectionKey] = minimumNetworkConnection 39 | json[PolicyNetworkLimitations.AnyIpAddressKey] = anyIpAddress 40 | 41 | return json 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/User/user_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "full_name": "John Doe", 4 | "email": "john.doe@doecorp.com", 5 | "email_address": "john.doe@doecorp.com", 6 | "phone_number": "123-444-5678", 7 | "position": "Unknowns", 8 | "enable_custom_photo_url": true, 9 | "custom_photo_url": "string", 10 | "ldap_server": { 11 | "id": -1, 12 | "name": "None" 13 | }, 14 | "extension_attributes": { 15 | "extension_attribute": { 16 | "id": 0, 17 | "name": "Teacher ID", 18 | "type": "String", 19 | "value": "K52" 20 | } 21 | }, 22 | "sites": { 23 | "id": 0, 24 | "name": "None" 25 | }, 26 | "links": { 27 | "computers": { 28 | "computer": { 29 | "id": 0, 30 | "name": "string" 31 | } 32 | }, 33 | "peripherals": { 34 | "peripheral": { 35 | "id": 0, 36 | "name": "string" 37 | } 38 | }, 39 | "mobile_devices": { 40 | "mobile_device": { 41 | "id": 0, 42 | "name": "string" 43 | } 44 | }, 45 | "vpp_assignments": { 46 | "vpp_assignment": { 47 | "id": 0, 48 | "name": "string" 49 | } 50 | }, 51 | "total_vpp_code_count": 0 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/User/user_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "JDoe", 4 | "full_name": "John Doe", 5 | "email": "john.doe@doecorp.com", 6 | "email_address": "john.doe@doecorp.com", 7 | "phone_number": "123-444-5678", 8 | "position": "Unknowns", 9 | "enable_custom_photo_url": true, 10 | "custom_photo_url": "string", 11 | "ldap_server": { 12 | "id": -1, 13 | "name": "None" 14 | }, 15 | "extension_attributes": { 16 | "extension_attribute": { 17 | "id": 0, 18 | "name": "Teacher ID", 19 | "type": "String", 20 | "value": "K52" 21 | } 22 | }, 23 | "sites": { 24 | "id": 0, 25 | "name": "None" 26 | }, 27 | "links": { 28 | "computers": { 29 | "computer": { 30 | "id": 0, 31 | "name": "string" 32 | } 33 | }, 34 | "peripherals": { 35 | "peripheral": { 36 | "id": 0, 37 | "name": "string" 38 | } 39 | }, 40 | "mobile_devices": { 41 | "mobile_device": { 42 | "id": 0, 43 | "name": "string" 44 | } 45 | }, 46 | "vpp_assignments": { 47 | "vpp_assignment": { 48 | "id": 0, 49 | "name": "string" 50 | } 51 | }, 52 | "total_vpp_code_count": 0 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/ComputerCommand/ComputerCommandGeneral.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKComputerCommandGeneral) 7 | public final class ComputerCommandGeneral: NSObject, Requestable { 8 | 9 | // MARK: - Constants 10 | 11 | static let CommandKey = "command" 12 | static let PasscodeKey = "passcode" 13 | 14 | // MARK: - Properties 15 | 16 | @objc 17 | public var command = "" 18 | 19 | @objc 20 | public var passcode: UInt = 0 21 | 22 | // MARK: - Initialization 23 | 24 | public init?(json: [String: Any], node: String = "") { 25 | guard 26 | let command = json[ComputerCommandGeneral.CommandKey] as? String, 27 | let passcode = json[ComputerCommandGeneral.PasscodeKey] as? UInt 28 | else { 29 | return nil 30 | } 31 | 32 | self.command = command 33 | self.passcode = passcode 34 | } 35 | 36 | public init?(command: String, passcode: UInt) { 37 | guard !command.isEmpty, passcode > 0 else { 38 | return nil 39 | } 40 | 41 | self.command = command 42 | self.passcode = passcode 43 | } 44 | 45 | // MARK: - Functions 46 | 47 | public func toJSON() -> [String: Any] { 48 | var json = [String: Any]() 49 | 50 | json[ComputerCommandGeneral.CommandKey] = command 51 | json[ComputerCommandGeneral.PasscodeKey] = passcode 52 | 53 | return json 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/User/user_multiple.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "JDoe", 4 | "full_name": "John Doe", 5 | "email": "john.doe@doecorp.com", 6 | "email_address": "john.doe@doecorp.com", 7 | "phone_number": "123-444-5678", 8 | "position": "Unknowns", 9 | "enable_custom_photo_url": true, 10 | "custom_photo_url": "string", 11 | "ldap_server": { 12 | "id": -1, 13 | "name": "None" 14 | }, 15 | "extension_attributes": { 16 | "extension_attribute": { 17 | "id": 0, 18 | "name": "Teacher ID", 19 | "type": "String", 20 | "value": "K52" 21 | } 22 | }, 23 | "sites": [ 24 | { 25 | "id": 0, 26 | "name": "First" 27 | }, 28 | { 29 | "id": 1, 30 | "name": "Second" 31 | } 32 | ], 33 | "links": { 34 | "computers": { 35 | "computer": { 36 | "id": 0, 37 | "name": "string" 38 | } 39 | }, 40 | "peripherals": { 41 | "peripheral": { 42 | "id": 0, 43 | "name": "string" 44 | } 45 | }, 46 | "mobile_devices": { 47 | "mobile_device": { 48 | "id": 0, 49 | "name": "string" 50 | } 51 | }, 52 | "vpp_assignments": { 53 | "vpp_assignment": { 54 | "id": 0, 55 | "name": "string" 56 | } 57 | }, 58 | "total_vpp_code_count": 0 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/BaseObjectTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class BaseObjectTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "BaseObject/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "Test" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInitializeFromJSON() { 21 | let payload = self.payload(for: "base_object_valid", subfolder: subfolder)! 22 | 23 | let actualValue = BaseObject(json: payload) 24 | 25 | XCTAssertNotNil(actualValue) 26 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 27 | XCTAssertEqual(actualValue?.name, defaultName) 28 | XCTAssertEqual(actualValue?.description, "[BaseObject][\(defaultIdentifier) - \(defaultName)]") 29 | } 30 | 31 | func testShouldNotInitializeFromInvalidJSON() { 32 | let payload = self.payload(for: "base_object_invalid", subfolder: subfolder)! 33 | 34 | let actualValue = BaseObject(json: payload) 35 | 36 | XCTAssertNil(actualValue) 37 | } 38 | 39 | func testShouldEncodeToJSON() { 40 | let payload = self.payload(for: "base_object_valid", subfolder: subfolder)! 41 | 42 | let actualValue = BaseObject(json: payload) 43 | let encodedObject = actualValue?.toJSON() 44 | 45 | XCTAssertNotNil(encodedObject) 46 | XCTAssertEqual(encodedObject?.count, 2) 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy_general_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "enabled": true, 4 | "trigger": "string", 5 | "trigger_checkin": false, 6 | "trigger_enrollment_complete": false, 7 | "trigger_login": false, 8 | "trigger_logout": false, 9 | "trigger_network_state_changed": false, 10 | "trigger_startup": false, 11 | "trigger_other": "string", 12 | "frequency": "Once per computer", 13 | "location_user_only": true, 14 | "target_drive": "/", 15 | "offline": true, 16 | "category": { 17 | "id": 0, 18 | "name": "string", 19 | "priority": 0 20 | }, 21 | "date_time_limitations": { 22 | "activation_date": "2017-07-07T18:37:04.000Z", 23 | "activation_date_epoch": 1499470624555, 24 | "activation_date_utc": "2017-07-07T18:37:04.555-0500", 25 | "expiration_date": "2017-07-07T18:37:04.000Z", 26 | "expiration_date_epoch": 1499470624555, 27 | "expiration_date_utc": "2017-07-07T18:37:04.555-0500", 28 | "no_execute_on": { 29 | "day": "Sun" 30 | }, 31 | "no_execute_start": "2:00 AM", 32 | "no_execute_end": "4:00 AM" 33 | }, 34 | "network_limitations": { 35 | "minimum_network_connection": "No Minimum", 36 | "any_ip_address": true 37 | }, 38 | "override_default_settings": { 39 | "target_drive": "string", 40 | "distribution_point": "string", 41 | "force_afp_smb": true, 42 | "sus": "string", 43 | "netboot_server": "string" 44 | }, 45 | "network_requirements": "Any", 46 | "site": { 47 | "id": 0, 48 | "name": "None" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Computer/computer_general_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "mac_address": "E0:AC:CB:97:36:G4", 4 | "alt_mac_address": "E0:AC:CB:97:36:G4", 5 | "ip_address": "10.1.1.1", 6 | "last_reported_ip": "192.0.0.1", 7 | "serial_number": "C02Q7KHTGFWF", 8 | "udid": "55900BDC-347C-58B1-D249-F32244B11D30", 9 | "jamf_version": "9.99.0-t1494340586", 10 | "platform": "Mac", 11 | "barcode_1": "string", 12 | "barcode_2": "string", 13 | "asset_tag": "string", 14 | "remote_management": { 15 | "managed": true, 16 | "management_username": "casperadmin" 17 | }, 18 | "mdm_capable": true, 19 | "mdm_capable_users": { 20 | "mdm_capable_user": "string" 21 | }, 22 | "report_date": "2017-07-07T18:37:04.000Z", 23 | "report_date_epoch": 1499470624555, 24 | "report_date_utc": "2017-07-07T18:37:04.555-0500", 25 | "last_contact_time": "2017-07-07T18:37:04.000Z", 26 | "last_contact_time_epoch": 1499470624555, 27 | "last_contact_time_utc": "2017-07-07T18:37:04.555-0500", 28 | "initial_entry_date": "2017-07-07T18:37:04.000Z", 29 | "initial_entry_date_epoch": 1499470624555, 30 | "initial_entry_date_utc": "2017-07-07T18:37:04.555-0500", 31 | "last_cloud_backup_date_epoch": 1499470624555, 32 | "last_cloud_backup_date_utc": "2017-07-07T18:37:04.555-0500", 33 | "last_enrolled_date_epoch": 1499470624555, 34 | "last_enrolled_date_utc": "2017-07-07T18:37:04.555-0500", 35 | "distribution_point": "string", 36 | "sus": "string", 37 | "netboot_server": "string", 38 | "site": { 39 | "id": 0, 40 | "name": "None" 41 | }, 42 | "itunes_store_account_is_active": true 43 | } 44 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy_general_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "Policy", 4 | "enabled": true, 5 | "trigger": "trigger", 6 | "trigger_checkin": false, 7 | "trigger_enrollment_complete": false, 8 | "trigger_login": false, 9 | "trigger_logout": false, 10 | "trigger_network_state_changed": false, 11 | "trigger_startup": false, 12 | "trigger_other": "trigger_other", 13 | "frequency": "Once per computer", 14 | "location_user_only": true, 15 | "target_drive": "/", 16 | "offline": true, 17 | "category": { 18 | "id": 0, 19 | "name": "string", 20 | "priority": 0 21 | }, 22 | "date_time_limitations": { 23 | "activation_date": "2017-07-07T18:37:04.000Z", 24 | "activation_date_epoch": 1499470624555, 25 | "activation_date_utc": "2017-07-07T18:37:04.555-0500", 26 | "expiration_date": "2017-07-07T18:37:04.000Z", 27 | "expiration_date_epoch": 1499470624555, 28 | "expiration_date_utc": "2017-07-07T18:37:04.555-0500", 29 | "no_execute_on": { 30 | "day": "Sun" 31 | }, 32 | "no_execute_start": "2:00 AM", 33 | "no_execute_end": "4:00 AM" 34 | }, 35 | "network_limitations": { 36 | "minimum_network_connection": "No Minimum", 37 | "any_ip_address": true 38 | }, 39 | "override_default_settings": { 40 | "target_drive": "string", 41 | "distribution_point": "string", 42 | "force_afp_smb": true, 43 | "sus": "string", 44 | "netboot_server": "string" 45 | }, 46 | "network_requirements": "Any", 47 | "site": { 48 | "id": 0, 49 | "name": "None" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Computer/computer_general_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "name": "computer", 4 | "mac_address": "E0:AC:CB:97:36:G4", 5 | "alt_mac_address": "E0:AC:CB:97:36:G4", 6 | "ip_address": "10.1.1.1", 7 | "last_reported_ip": "192.0.0.1", 8 | "serial_number": "C02Q7KHTGFWF", 9 | "udid": "55900BDC-347C-58B1-D249-F32244B11D30", 10 | "jamf_version": "9.99.0-t1494340586", 11 | "platform": "Mac", 12 | "barcode_1": "string", 13 | "barcode_2": "string", 14 | "asset_tag": "string", 15 | "remote_management": { 16 | "managed": true, 17 | "management_username": "username" 18 | }, 19 | "mdm_capable": true, 20 | "mdm_capable_users": { 21 | "mdm_capable_user": "string" 22 | }, 23 | "report_date": "2017-07-07T18:37:04.000Z", 24 | "report_date_epoch": 1499470624555, 25 | "report_date_utc": "2017-07-07T18:37:04.555-0500", 26 | "last_contact_time": "2017-07-07T18:37:04.000Z", 27 | "last_contact_time_epoch": 1499470624555, 28 | "last_contact_time_utc": "2017-07-07T18:37:04.555-0500", 29 | "initial_entry_date": "2017-07-07T18:37:04.000Z", 30 | "initial_entry_date_epoch": 1499470624555, 31 | "initial_entry_date_utc": "2017-07-07T18:37:04.555-0500", 32 | "last_cloud_backup_date_epoch": 1499470624555, 33 | "last_cloud_backup_date_utc": "2017-07-07T18:37:04.555-0500", 34 | "last_enrolled_date_epoch": 1499470624555, 35 | "last_enrolled_date_utc": "2017-07-07T18:37:04.555-0500", 36 | "distribution_point": "string", 37 | "sus": "string", 38 | "netboot_server": "string", 39 | "site": { 40 | "id": 0, 41 | "name": "None" 42 | }, 43 | "itunes_store_account_is_active": true 44 | } 45 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/ConfigurationProfile/MobileDeviceConfigurationProfile/MobileDeviceConfigurationProfileGeneral.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKMobileDeviceConfigurationProfileGeneral) 7 | public final class MobileDeviceConfigurationProfileGeneral: ConfigurationProfileGeneral { 8 | 9 | // MARK: - Constants 10 | 11 | static let DeploymentMethodKey = "deployment_method" 12 | static let RedeployDaysBeforeCertificateExpiresKey = "redeploy_Dayss_before_certificate_expires" 13 | 14 | // MARK: - Properties 15 | 16 | @objc 17 | public var deploymentMethod: String = "" 18 | 19 | @objc 20 | public var redeployDaysBeforeCertificateExpires: UInt = 0 21 | 22 | // MARK: - Initialization 23 | 24 | public required init?(json: [String: Any], node: String = "") { 25 | deploymentMethod = json[MobileDeviceConfigurationProfileGeneral.DeploymentMethodKey] as? String ?? "" 26 | redeployDaysBeforeCertificateExpires = json[MobileDeviceConfigurationProfileGeneral.RedeployDaysBeforeCertificateExpiresKey] as? UInt ?? 0 27 | 28 | super.init(json: json) 29 | } 30 | 31 | override init?(identifier: UInt, name: String) { 32 | super.init(identifier: identifier, name: name) 33 | } 34 | 35 | // MARK: - Functions 36 | 37 | public override func toJSON() -> [String: Any] { 38 | var json = super.toJSON() 39 | 40 | json[MobileDeviceConfigurationProfileGeneral.DeploymentMethodKey] = deploymentMethod 41 | json[MobileDeviceConfigurationProfileGeneral.RedeployDaysBeforeCertificateExpiresKey] = redeployDaysBeforeCertificateExpires 42 | 43 | return json 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/Computer/ComputerRemoteManagementTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerRemoteManagementTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Computer/" 15 | let defaultManaged = true 16 | let defaultManagementUsername = "username" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInitializeFromJSON() { 21 | let payload = self.payload(for: "computer_remote_management", subfolder: subfolder)! 22 | 23 | let actualValue = ComputerRemoteManagement(json: payload) 24 | 25 | XCTAssertNotNil(actualValue) 26 | XCTAssertEqual(actualValue?.isManaged, defaultManaged) 27 | XCTAssertEqual(actualValue?.managementUsername, defaultManagementUsername) 28 | } 29 | 30 | func testShouldInitializeFromEmptyJSON() { 31 | let actualValue = ComputerRemoteManagement(json: [String: Any]()) 32 | 33 | XCTAssertNotNil(actualValue) 34 | XCTAssertEqual(actualValue?.isManaged, false) 35 | XCTAssertEqual(actualValue?.managementUsername, "") 36 | } 37 | 38 | func testShouldEncodeToJSON() { 39 | let payload = self.payload(for: "computer_remote_management", subfolder: subfolder)! 40 | 41 | let actualValue = ComputerRemoteManagement(json: payload) 42 | let encodedObject = actualValue?.toJSON() 43 | 44 | XCTAssertNotNil(encodedObject) 45 | XCTAssertEqual(encodedObject?.count, 2) 46 | XCTAssertNotNil(encodedObject?[ComputerRemoteManagement.ManagedKey]) 47 | XCTAssertNotNil(encodedObject?[ComputerRemoteManagement.ManagementUsernameKey]) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /JamfKit/Playgrounds/Examples.playground/Pages/Classes.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | //: # JamfKit - Requests 4 | 5 | //: 1. Import JamfKit 6 | 7 | import JamfKit 8 | 9 | //: 2. Instantiate any class you need for your current usage 10 | 11 | let building = Building(identifier: 12345, name: "Building") 12 | let computer = Computer(identifier: 12345, name: "Computer") 13 | let computerCommand = ComputerCommand(command: "Command", passcode: 12345) 14 | let computerConfiguration = ComputerConfiguration(identifier: 12345, name: "Computer configuration") 15 | let computerConfigurationProfile = ComputerConfigurationProfile(identifier: 12345, name: "Computer configuration profile") 16 | let computerGroup = ComputerGroup(identifier: 12345, name: "Computer group") 17 | let department = Department(identifier: 12345, name: "Department") 18 | let directoryBinding = DirectoryBinding(identifier: 12345, name: "Directory binding") 19 | let mobileDevice = MobileDevice(identifier: 12345, name: "Mobile device") 20 | let mobileDeviceConfigurationProfile = MobileDeviceConfigurationProfile(identifier: 12345, name: "Mobile device configuration profile") 21 | let mobileDeviceGroup = MobileDeviceGroup(identifier: 12345, name: "Mobile device group") 22 | let netbootServer = NetbootServer(identifier: 12345, name: "Netboot server") 23 | let networkSegment = NetworkSegment(identifier: 12345, name: "Network segment") 24 | let package = Package(identifier: 12345, name: "Package") 25 | let partition = Partition(name: "Partition") 26 | let policy = Policy(identifier: 12345, name: "Policy") 27 | let printer = Printer(identifier: 12345, name: "Printer") 28 | let script = Script(identifier: 12345, name: "Script") 29 | let site = Site(identifier: 12345, name: "Site") 30 | let smtpServer = SMTPServer(host: "127.0.0.1", port: 1234) 31 | let user = User(identifier: 12345, name: "User") 32 | 33 | //: [Next](@next) 34 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/Policy/PolicyNetworkLimitationsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class PolicyNetworkLimitationsTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Policy/" 15 | let defaultMinimumNetworkConnection = "No Minimum" 16 | let defaultAnyIpAddress = true 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInitializeFromJSON() { 21 | let payload = self.payload(for: "policy_network_limitations", subfolder: subfolder)! 22 | 23 | let actualValue = PolicyNetworkLimitations(json: payload) 24 | 25 | XCTAssertNotNil(actualValue) 26 | XCTAssertEqual(actualValue?.minimumNetworkConnection, defaultMinimumNetworkConnection) 27 | XCTAssertEqual(actualValue?.anyIpAddress, defaultAnyIpAddress) 28 | } 29 | 30 | func testShouldInitializeFromEmptyJSON() { 31 | let actualValue = PolicyNetworkLimitations(json: [String: Any]()) 32 | 33 | XCTAssertNotNil(actualValue) 34 | XCTAssertEqual(actualValue?.minimumNetworkConnection, "") 35 | XCTAssertEqual(actualValue?.anyIpAddress, false) 36 | } 37 | 38 | func testShouldEncodeToJSON() { 39 | let payload = self.payload(for: "policy_network_limitations", subfolder: subfolder)! 40 | 41 | let actualValue = PolicyNetworkLimitations(json: payload) 42 | let encodedObject = actualValue?.toJSON() 43 | 44 | XCTAssertNotNil(encodedObject) 45 | XCTAssertEqual(encodedObject?.count, 2) 46 | XCTAssertNotNil(encodedObject?[PolicyNetworkLimitations.MinimumNetworkConnectionKey]) 47 | XCTAssertNotNil(encodedObject?[PolicyNetworkLimitations.AnyIpAddressKey]) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/ConfigurationProfile/ComputerConfigurationProfile/ComputerConfigurationProfileGeneral.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKComputerConfigurationProfileGeneral) 7 | public final class ComputerConfigurationProfileGeneral: ConfigurationProfileGeneral { 8 | 9 | // MARK: - Constants 10 | 11 | static let DistributionMethodKey = "distribution_method" 12 | static let UserRemovableKey = "user_removable" 13 | static let LevelKey = "level" 14 | 15 | // MARK: - Properties 16 | 17 | @objc 18 | public var distributionMethod: String = "" 19 | 20 | @objc 21 | public var isUserRemovable: Bool = false 22 | 23 | @objc 24 | public var level: String = "" 25 | 26 | // MARK: - Initialization 27 | 28 | public required init?(json: [String: Any], node: String = "") { 29 | distributionMethod = json[ComputerConfigurationProfileGeneral.DistributionMethodKey] as? String ?? "" 30 | isUserRemovable = json[ComputerConfigurationProfileGeneral.UserRemovableKey] as? Bool ?? false 31 | level = json[ComputerConfigurationProfileGeneral.LevelKey] as? String ?? "" 32 | 33 | super.init(json: json) 34 | } 35 | 36 | override init?(identifier: UInt, name: String) { 37 | super.init(identifier: identifier, name: name) 38 | } 39 | 40 | // MARK: - Functions 41 | 42 | public override func toJSON() -> [String: Any] { 43 | var json = super.toJSON() 44 | 45 | json[ComputerConfigurationProfileGeneral.DistributionMethodKey] = distributionMethod 46 | json[ComputerConfigurationProfileGeneral.UserRemovableKey] = isUserRemovable 47 | json[ComputerConfigurationProfileGeneral.LevelKey] = level 48 | 49 | return json 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "enabled": true, 5 | "trigger": "string", 6 | "trigger_checkin": false, 7 | "trigger_enrollment_complete": false, 8 | "trigger_login": false, 9 | "trigger_logout": false, 10 | "trigger_network_state_changed": false, 11 | "trigger_startup": false, 12 | "trigger_other": "string", 13 | "frequency": "Once per computer", 14 | "location_user_only": true, 15 | "target_drive": "/", 16 | "offline": true, 17 | "category": { 18 | "id": 0, 19 | "name": "string", 20 | "priority": 0 21 | }, 22 | "date_time_limitations": { 23 | "activation_date": "2017-07-07T18:37:04.000Z", 24 | "activation_date_epoch": 1499470624555, 25 | "activation_date_utc": "2017-07-07T18:37:04.555-0500", 26 | "expiration_date": "2017-07-07T18:37:04.000Z", 27 | "expiration_date_epoch": 1499470624555, 28 | "expiration_date_utc": "2017-07-07T18:37:04.555-0500", 29 | "no_execute_on": { 30 | "day": "Sun" 31 | }, 32 | "no_execute_start": "2:00 AM", 33 | "no_execute_end": "4:00 AM" 34 | }, 35 | "network_limitations": { 36 | "minimum_network_connection": "No Minimum", 37 | "any_ip_address": true 38 | }, 39 | "override_default_settings": { 40 | "target_drive": "string", 41 | "distribution_point": "string", 42 | "force_afp_smb": true, 43 | "sus": "string", 44 | "netboot_server": "string" 45 | }, 46 | "network_requirements": "Any", 47 | "site": { 48 | "id": 0, 49 | "name": "None" 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Policy/policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "name": "Policy", 5 | "enabled": true, 6 | "trigger": "string", 7 | "trigger_checkin": false, 8 | "trigger_enrollment_complete": false, 9 | "trigger_login": false, 10 | "trigger_logout": false, 11 | "trigger_network_state_changed": false, 12 | "trigger_startup": false, 13 | "trigger_other": "string", 14 | "frequency": "Once per computer", 15 | "location_user_only": true, 16 | "target_drive": "/", 17 | "offline": true, 18 | "category": { 19 | "id": 0, 20 | "name": "string", 21 | "priority": 0 22 | }, 23 | "date_time_limitations": { 24 | "activation_date": "2017-07-07T18:37:04.000Z", 25 | "activation_date_epoch": 1499470624555, 26 | "activation_date_utc": "2017-07-07T18:37:04.555-0500", 27 | "expiration_date": "2017-07-07T18:37:04.000Z", 28 | "expiration_date_epoch": 1499470624555, 29 | "expiration_date_utc": "2017-07-07T18:37:04.555-0500", 30 | "no_execute_on": { 31 | "day": "Sun" 32 | }, 33 | "no_execute_start": "2:00 AM", 34 | "no_execute_end": "4:00 AM" 35 | }, 36 | "network_limitations": { 37 | "minimum_network_connection": "No Minimum", 38 | "any_ip_address": true 39 | }, 40 | "override_default_settings": { 41 | "target_drive": "string", 42 | "distribution_point": "string", 43 | "force_afp_smb": true, 44 | "sus": "string", 45 | "netboot_server": "string" 46 | }, 47 | "network_requirements": "Any", 48 | "site": { 49 | "id": 0, 50 | "name": "None" 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | :warning: 2 | 3 | New issue checklist: 4 | 5 | - [ ] Issue tracker does not already contain the same (or a very similar) issue 6 | - [ ] Title must be clear about what is the issue 7 | - [ ] All relevant fields of the description are filled 8 | - [ ] Issue is following the [CODE OF CONDUCT](https://github.com/Ethenyl/JamfKit/blob/master/CODE_OF_CONDUCT.md) 9 | 10 | **Please delete this section once you're ready to finally create the issue.** 11 | 12 | :warning: 13 | 14 | # Short description # 15 | 16 | *Please fill this section with a short description of your issue / new feature.* 17 | 18 | ----- 19 | 20 | **If the ticket is about an issue, use the following sections to give more details about the issue you're facing.** 21 | 22 | ### Expected outcome ### 23 | 24 | *Please fill this section with a description of what you're expecting to happen.* 25 | 26 | ### Actual outcome ### 27 | 28 | *Please fill the following section with a description of what is actually happening. Please add as much information as you can (how easy it is to reproduce, steps, etc.).* 29 | 30 | ----- 31 | 32 | **If the ticket is about a new feature, use the following sections to give more details about the changes you ask for / want to implement.** 33 | 34 | ### Missing functionnality ### 35 | 36 | *Please fill this section with a description of what's missing for you.* 37 | 38 | ### Implementation ### 39 | 40 | *Please fill this section with details of the implementation you expect or plan to do.* 41 | 42 | ## Miscellaneous ## 43 | 44 | Information | Value | 45 | ------------------------------|------------------------------| 46 | Language | e.g. Objective-C/Swift 47 | Platform | e.g. iOS/macOS 48 | Platform version | e.g. 9.0 49 | JamfKit version | e.g. 1.0.0 50 | Package manager | e.g. Carthage/CocoaPods 51 | Package manager version | e.g. 0.25.0 52 | XCode version | e.g. 9.2 53 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDevice/mobile_device_general_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "display_name": "Mobile Device", 4 | "device_name": "mobile_device", 5 | "asset_tag": "asset_tag", 6 | "last_inventory_update": "2017-07-07T18:37:04.000Z", 7 | "last_inventory_update_epoch": 1499470624555, 8 | "last_inventory_update_utc": "2017-07-07T18:37:04.555-0500", 9 | "capacity": 1024, 10 | "capacity_mb": 1024, 11 | "available": 1024, 12 | "available_mb": 1024, 13 | "percentage_used": 5, 14 | "os_type": "iOS", 15 | "os_version": "10.3.2", 16 | "os_build": "14F89", 17 | "serial_number": "C02Q7KHTGFWF", 18 | "udid": "270aae10800b6e61a2ee2bbc285eb967050b5984", 19 | "initial_entry_date_epoch": 1499470624555, 20 | "initial_entry_date_utc": "2017-07-07T18:37:04.555-0500", 21 | "phone_number": "123-555-6789", 22 | "ip_address": "192.0.0.1", 23 | "wifi_mac_address": "E0:AC:CB:97:36:G4", 24 | "bluetooth_mac_address": "E0:AC:CB:97:36:G6", 25 | "modem_firmware": "2.61.00", 26 | "model": "iPhone 6S", 27 | "model_identifier": "iPhone8,1", 28 | "model_number": "MKRY2LL", 29 | "model_display": "iPhone 6S", 30 | "device_ownership_level": "Institutional", 31 | "last_enrollment_epoch": 1499470624555, 32 | "last_enrollment_utc": "2017-07-07T18:37:04.555-0500", 33 | "managed": true, 34 | "supervised": true, 35 | "exchange_activesync_device_identifier": "TUCLLFJHPL779ACL9DCJQFN39F", 36 | "shared": "shared", 37 | "tethered": "tethered", 38 | "battery_level": 95, 39 | "ble_capable": true, 40 | "device_locator_service_enabled": true, 41 | "do_not_disturb_enabled": true, 42 | "cloud_backup_enabled": true, 43 | "last_cloud_backup_date_epoch": 1499470624555, 44 | "last_cloud_backup_date_utc": "2017-07-07T18:37:04.555-0500", 45 | "location_services_enabled": true, 46 | "itunes_store_account_is_active": true, 47 | "last_backup_time_epoch": 1499470624555, 48 | "last_backup_time_utc": "2017-07-07T18:37:04.555-0500" 49 | } 50 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/MobileDevice/MobileDeviceTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class MobileDeviceTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "MobileDevice/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "computer" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = MobileDevice(identifier: defaultIdentifier, name: defaultName) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.general.identifier, defaultIdentifier) 25 | XCTAssertEqual(actualValue?.general.name, defaultName) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = MobileDevice(identifier: defaultIdentifier, name: "") 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "mobile_device", subfolder: subfolder)! 36 | 37 | let actualValue = MobileDevice(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.description, "[MobileDevice][12345 - Mobile Device]") 41 | XCTAssertNotNil(actualValue?.general) 42 | } 43 | 44 | func testShouldNotInitializeFromEmptyJSON() { 45 | let actualValue = MobileDevice(json: [String: Any]()) 46 | 47 | XCTAssertNil(actualValue) 48 | } 49 | 50 | func testShouldEncodeToJSON() { 51 | let payload = self.payload(for: "mobile_device", subfolder: subfolder)! 52 | 53 | let actualValue = MobileDevice(json: payload) 54 | let encodedObject = actualValue?.toJSON() 55 | 56 | XCTAssertNotNil(encodedObject) 57 | XCTAssertEqual(encodedObject?.count, 1) 58 | XCTAssertNotNil(encodedObject?[MobileDevice.GeneralKey]) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/SiteTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class SiteTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Site/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "Nowhere" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = Site(identifier: defaultIdentifier, name: defaultName) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 25 | XCTAssertEqual(actualValue?.name, defaultName) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = Site(identifier: defaultIdentifier, name: "") 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "site_valid", subfolder: subfolder)! 36 | 37 | let actualValue = Site(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 41 | XCTAssertEqual(actualValue?.name, defaultName) 42 | XCTAssertEqual(actualValue?.description, "[Site][\(defaultIdentifier) - \(defaultName)]") 43 | } 44 | 45 | func testShouldNotInitializeFromInvalidJSON() { 46 | let payload = self.payload(for: "site_invalid", subfolder: subfolder)! 47 | 48 | let actualValue = Site(json: payload) 49 | 50 | XCTAssertNil(actualValue) 51 | } 52 | 53 | func testShouldEncodeToJSON() { 54 | let payload = self.payload(for: "site_valid", subfolder: subfolder)! 55 | 56 | let actualValue = Site(json: payload) 57 | let encodedObject = actualValue?.toJSON() 58 | 59 | XCTAssertNotNil(encodedObject) 60 | XCTAssertEqual(encodedObject?.count, 2) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDevice/mobile_device_general_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12345, 3 | "display_name": "Mobile Device", 4 | "device_name": "mobile_device", 5 | "name": "Mobile Device", 6 | "asset_tag": "asset_tag", 7 | "last_inventory_update": "2017-07-07T18:37:04.000Z", 8 | "last_inventory_update_epoch": 1499470624555, 9 | "last_inventory_update_utc": "2017-07-07T18:37:04.555-0500", 10 | "capacity": 1024, 11 | "capacity_mb": 1024, 12 | "available": 1024, 13 | "available_mb": 1024, 14 | "percentage_used": 5, 15 | "os_type": "iOS", 16 | "os_version": "10.3.2", 17 | "os_build": "14F89", 18 | "serial_number": "C02Q7KHTGFWF", 19 | "udid": "270aae10800b6e61a2ee2bbc285eb967050b5984", 20 | "initial_entry_date_epoch": 1499470624555, 21 | "initial_entry_date_utc": "2017-07-07T18:37:04.555-0500", 22 | "phone_number": "123-555-6789", 23 | "ip_address": "192.0.0.1", 24 | "wifi_mac_address": "E0:AC:CB:97:36:G4", 25 | "bluetooth_mac_address": "E0:AC:CB:97:36:G6", 26 | "modem_firmware": "2.61.00", 27 | "model": "iPhone 6S", 28 | "model_identifier": "iPhone8,1", 29 | "model_number": "MKRY2LL", 30 | "model_display": "iPhone 6S", 31 | "device_ownership_level": "Institutional", 32 | "last_enrollment_epoch": 1499470624555, 33 | "last_enrollment_utc": "2017-07-07T18:37:04.555-0500", 34 | "managed": true, 35 | "supervised": true, 36 | "exchange_activesync_device_identifier": "TUCLLFJHPL779ACL9DCJQFN39F", 37 | "shared": "shared", 38 | "tethered": "tethered", 39 | "battery_level": 95, 40 | "ble_capable": true, 41 | "device_locator_service_enabled": true, 42 | "do_not_disturb_enabled": true, 43 | "cloud_backup_enabled": true, 44 | "last_cloud_backup_date_epoch": 1499470624555, 45 | "last_cloud_backup_date_utc": "2017-07-07T18:37:04.555-0500", 46 | "location_services_enabled": true, 47 | "itunes_store_account_is_active": true, 48 | "last_backup_time_epoch": 1499470624555, 49 | "last_backup_time_utc": "2017-07-07T18:37:04.555-0500" 50 | } 51 | -------------------------------------------------------------------------------- /JamfKit/Tests/Session/Requests/SMTPServerRequestsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class SMTPServerRequestsTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "SMTPServer/" 15 | let defaultHost = "http://localhost" 16 | var element: SMTPServer! 17 | 18 | // MARK: - Lifecycle 19 | 20 | override func setUp() { 21 | try? SessionManager.instance.configure(for: defaultHost, username: "username", password: "password") 22 | 23 | let payload = self.payload(for: "smtp_server", subfolder: subfolder)! 24 | element = SMTPServer(json: payload)! 25 | } 26 | 27 | override func tearDown() { 28 | SessionManager.instance.clearConfiguration() 29 | } 30 | 31 | // MARK: - Tests 32 | 33 | func testShouldNotReturnReadAllRequest() { 34 | let actualValue = SMTPServer.readAllRequest() 35 | 36 | XCTAssertNil(actualValue) 37 | } 38 | 39 | func testShouldNotReturnStaticReadRequestWithIdentifier() { 40 | let actualValue = SMTPServer.readRequest(identifier: "12345") 41 | 42 | XCTAssertNil(actualValue) 43 | } 44 | 45 | func testShouldReturnReadRequest() { 46 | let actualValue = element.readRequest() 47 | 48 | XCTAssertNotNil(actualValue) 49 | XCTAssertEqual(actualValue?.httpMethod, HttpMethod.get.rawValue) 50 | XCTAssertEqual(actualValue?.url?.absoluteString, "\(defaultHost)/\(element.endpoint)") 51 | XCTAssertNil(actualValue?.httpBody) 52 | } 53 | 54 | func testShouldReturnUpdateRequestWithIdentifier() { 55 | let actualValue = element.updateRequest() 56 | 57 | XCTAssertNotNil(actualValue) 58 | XCTAssertEqual(actualValue?.httpMethod, HttpMethod.put.rawValue) 59 | XCTAssertEqual(actualValue?.url?.absoluteString, "\(defaultHost)/\(element.endpoint)") 60 | XCTAssertNotNil(actualValue?.httpBody) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/HardwareGroup/HardwareGroup.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKHardwareGroup) 7 | public class HardwareGroup: BaseObject { 8 | 9 | // MARK: - Constants 10 | 11 | static let IsSmartKey = "is_smart" 12 | static let CriteriaKey = "criteria" 13 | static let SiteKey = "site" 14 | 15 | // MARK: - Properties 16 | 17 | @objc 18 | public var isSmart = false 19 | 20 | @objc 21 | public var criteria = [HardwareGroupCriterion]() 22 | 23 | @objc 24 | public var site: Site? 25 | 26 | // MARK: - Initialization 27 | 28 | public required init?(json: [String: Any], node: String = "") { 29 | isSmart = json[HardwareGroup.IsSmartKey] as? Bool ?? false 30 | criteria = HardwareGroup.parseCriteria(json: json) 31 | 32 | if let siteNode = json[HardwareGroup.SiteKey] as? [String: Any] { 33 | site = Site(json: siteNode) 34 | } 35 | 36 | super.init(json: json) 37 | } 38 | 39 | override init?(identifier: UInt, name: String) { 40 | super.init(identifier: identifier, name: name) 41 | } 42 | 43 | // MARK: - Functions 44 | 45 | public override func toJSON() -> [String: Any] { 46 | var json = super.toJSON() 47 | 48 | json[MobileDeviceGroup.IsSmartKey] = isSmart 49 | 50 | if !criteria.isEmpty { 51 | let criterions = criteria.map { criterion -> [String: [String: Any]] in 52 | return ["criterion": criterion.toJSON()] 53 | } 54 | 55 | json[MobileDeviceGroup.CriteriaKey] = criterions 56 | } 57 | 58 | if let site = site { 59 | json[MobileDeviceGroup.SiteKey] = site.toJSON() 60 | } 61 | 62 | return json 63 | } 64 | 65 | private static func parseCriteria(json: [String: Any]) -> [HardwareGroupCriterion] { 66 | return BaseObject.parseElements(from: json, nodeKey: MobileDeviceGroup.CriteriaKey, singleNodeKey: "criterion") 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/DepartmentTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class DepartmentTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Department/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "Unknown" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = Department(identifier: defaultIdentifier, name: defaultName) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 25 | XCTAssertEqual(actualValue?.name, defaultName) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = Department(identifier: defaultIdentifier, name: "") 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "department_valid", subfolder: subfolder)! 36 | 37 | let actualValue = Department(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 41 | XCTAssertEqual(actualValue?.name, defaultName) 42 | XCTAssertEqual(actualValue?.description, "[Department][\(defaultIdentifier) - \(defaultName)]") 43 | } 44 | 45 | func testShouldNotInitializeFromInvalidJSON() { 46 | let payload = self.payload(for: "department_invalid", subfolder: subfolder)! 47 | 48 | let actualValue = Department(json: payload) 49 | 50 | XCTAssertNil(actualValue) 51 | } 52 | 53 | func testShouldEncodeToJSON() { 54 | let payload = self.payload(for: "department_valid", subfolder: subfolder)! 55 | 56 | let actualValue = Department(json: payload) 57 | let encodedObject = actualValue?.toJSON() 58 | 59 | XCTAssertNotNil(encodedObject) 60 | XCTAssertEqual(encodedObject?.count, 2) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /JamfKit/Sources/Protocols/Requests/Deletable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents an object that can be deleted with an URLRequest 7 | @objc(JMFKDeletable) 8 | public protocol Deletable { 9 | 10 | // MARK: - Functions 11 | 12 | /// Returns a DELETE **URLRequest** based on the JSS object type & the supplied identifier. 13 | static func deleteRequest(identifier: String) -> URLRequest? 14 | 15 | /// Returns a DELETE **URLRequest** based on the identifier property of the supplied JSS object. 16 | func deleteRequest() -> URLRequest? 17 | } 18 | 19 | // MARK: - Implementation 20 | 21 | extension Deletable where Self: Endpoint & Identifiable { 22 | 23 | static func getDeleteRequest(identifier: String) -> URLRequest? { 24 | return SessionManager.instance.deleteRequest(for: self, key: BaseObject.CodingKeys.identifier.rawValue, value: identifier) 25 | } 26 | 27 | func getDeleteRequest() -> URLRequest? { 28 | return SessionManager.instance.deleteRequest(for: self, key: BaseObject.CodingKeys.identifier.rawValue, value: String(identifier)) 29 | } 30 | 31 | static func getDeleteRequest(name: String) -> URLRequest? { 32 | return SessionManager.instance.deleteRequest(for: self, key: BaseObject.CodingKeys.name.rawValue, value: name) 33 | } 34 | 35 | func getDeleteRequestWithName() -> URLRequest? { 36 | return SessionManager.instance.deleteRequest(for: self, key: BaseObject.CodingKeys.name.rawValue, value: name) 37 | } 38 | } 39 | 40 | extension Deletable where Self: Endpoint & Requestable & Subset { 41 | 42 | static func getDeleteRequest(identifier: String) -> URLRequest? { 43 | return SessionManager.instance.deleteRequest(for: self, key: BaseObject.CodingKeys.identifier.rawValue, value: identifier) 44 | } 45 | 46 | static func getDeleteRequest(name: String) -> URLRequest? { 47 | return SessionManager.instance.deleteRequest(for: self, key: BaseObject.CodingKeys.name.rawValue, value: name) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/ComputerConfiguration/ComputerConfigurationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerConfigurationTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "ComputerConfiguration/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "High Sierra Base OS" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = ComputerConfiguration(identifier: defaultIdentifier, name: defaultName) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.general.identifier, defaultIdentifier) 25 | XCTAssertEqual(actualValue?.general.name, defaultName) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = ComputerConfiguration(identifier: defaultIdentifier, name: "") 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "computer_configuration", subfolder: subfolder)! 36 | 37 | let actualValue = ComputerConfiguration(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.description, "[ComputerConfiguration][12345. High Sierra Base OS]") 41 | XCTAssertNotNil(actualValue?.general) 42 | } 43 | 44 | func testShouldNotInitializeFromEmptyJSON() { 45 | let actualValue = ComputerConfiguration(json: [String: Any]()) 46 | 47 | XCTAssertNil(actualValue) 48 | } 49 | 50 | func testShouldEncodeToJSON() { 51 | let payload = self.payload(for: "computer_configuration", subfolder: subfolder)! 52 | 53 | let actualValue = ComputerConfiguration(json: payload) 54 | let encodedObject = actualValue?.toJSON() 55 | 56 | XCTAssertNotNil(encodedObject) 57 | XCTAssertEqual(encodedObject?.count, 1) 58 | XCTAssertNotNil(encodedObject?[ComputerConfiguration.GeneralKey]) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Policy/PolicyOverrideDefaultSettings.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKPolicyOverrideDefaultSettings) 7 | public final class PolicyOverrideDefaultSettings: NSObject, Requestable { 8 | 9 | // MARK: - Constants 10 | 11 | static let TargetDriveKey = "target_drive" 12 | static let DistributionPointKey = "distribution_point" 13 | static let ForceAfpSmbKey = "force_afp_smb" 14 | static let SusKey = "sus" 15 | static let NetbootServerKey = "netboot_server" 16 | 17 | // MARK: - Properties 18 | 19 | @objc 20 | public var targetDrive = "" 21 | 22 | @objc 23 | public var distributionPoint = "" 24 | 25 | @objc 26 | public var shouldForceAfpSmb = false 27 | 28 | @objc 29 | public var sus = "" 30 | 31 | @objc 32 | public var netbootServer = "" 33 | 34 | // MARK: - Initialization 35 | 36 | public init?(json: [String: Any], node: String = "") { 37 | targetDrive = json[PolicyOverrideDefaultSettings.TargetDriveKey] as? String ?? "" 38 | distributionPoint = json[PolicyOverrideDefaultSettings.DistributionPointKey] as? String ?? "" 39 | shouldForceAfpSmb = json[PolicyOverrideDefaultSettings.ForceAfpSmbKey] as? Bool ?? false 40 | sus = json[PolicyOverrideDefaultSettings.SusKey] as? String ?? "" 41 | netbootServer = json[PolicyOverrideDefaultSettings.NetbootServerKey] as? String ?? "" 42 | } 43 | 44 | public override init() { 45 | super.init() 46 | } 47 | 48 | // MARK: - Functions 49 | 50 | public func toJSON() -> [String: Any] { 51 | var json = [String: Any]() 52 | 53 | json[PolicyOverrideDefaultSettings.TargetDriveKey] = targetDrive 54 | json[PolicyOverrideDefaultSettings.DistributionPointKey] = distributionPoint 55 | json[PolicyOverrideDefaultSettings.ForceAfpSmbKey] = shouldForceAfpSmb 56 | json[PolicyOverrideDefaultSettings.SusKey] = sus 57 | json[PolicyOverrideDefaultSettings.NetbootServerKey] = netbootServer 58 | 59 | return json 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /JamfKit/Tests/Session/Requests/ComputerCommand/ComputerCommandRequestsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerCommandRequestsTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "ComputerCommand/" 15 | let defaultHost = "http://localhost" 16 | var element: ComputerCommand! 17 | 18 | // MARK: - Lifecycle 19 | 20 | override func setUp() { 21 | try? SessionManager.instance.configure(for: defaultHost, username: "username", password: "password") 22 | 23 | let payload = self.payload(for: "computer_command", subfolder: subfolder)! 24 | element = ComputerCommand(json: payload)! 25 | } 26 | 27 | override func tearDown() { 28 | SessionManager.instance.clearConfiguration() 29 | } 30 | 31 | // MARK: - Tests 32 | 33 | func testShouldReturnReadAllRequest() { 34 | let actualValue = ComputerCommand.readAllRequest() 35 | 36 | XCTAssertNotNil(actualValue) 37 | XCTAssertEqual(actualValue?.httpMethod, HttpMethod.get.rawValue) 38 | XCTAssertEqual(actualValue?.url?.absoluteString, "\(defaultHost)/\(ComputerCommand.Endpoint)") 39 | XCTAssertNil(actualValue?.httpBody) 40 | } 41 | 42 | func testShouldReturnCreateRequest() { 43 | let actualValue = element.createRequest() 44 | 45 | XCTAssertNotNil(actualValue) 46 | XCTAssertEqual(actualValue?.httpMethod, HttpMethod.post.rawValue) 47 | XCTAssertEqual(actualValue?.url?.absoluteString, "\(defaultHost)/\(element.endpoint)/command/\(element.general.command)") 48 | XCTAssertNotNil(actualValue?.httpBody) 49 | } 50 | 51 | func testShouldNotReturnStaticReadRequestWithIdentifier() { 52 | let actualValue = ComputerCommand.readRequest(identifier: "12345") 53 | 54 | XCTAssertNil(actualValue) 55 | } 56 | 57 | func testShouldNotReturnReadRequestWithIdentifier() { 58 | let actualValue = element.readRequest() 59 | 60 | XCTAssertNil(actualValue) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/ComputerConfiguration/ComputerConfigurationManagement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKComputerConfigurationManagement) 7 | public final class ComputerConfigurationManagement: NSObject, Requestable { 8 | 9 | // MARK: - Constants 10 | 11 | static let UsernameKey = "username" 12 | static let PasswordKey = "password" 13 | static let CreateAccountKey = "create_account" 14 | static let HideAccountKey = "hide_account" 15 | static let AllowSSHForManagementOnlyKey = "allow_ssh_for_management_only" 16 | 17 | // MARK: - Properties 18 | 19 | @objc 20 | public var username: String 21 | 22 | @objc 23 | public var password: String 24 | 25 | @objc 26 | public var shouldCreateAccount: Bool 27 | 28 | @objc 29 | public var shouldHideAccount: Bool 30 | 31 | @objc 32 | public var isSSHAllowedForManagementOnly: Bool 33 | 34 | // MARK: - Initialization 35 | 36 | public init?(json: [String: Any], node: String = "") { 37 | username = json[ComputerConfigurationManagement.UsernameKey] as? String ?? "" 38 | password = json[ComputerConfigurationManagement.PasswordKey] as? String ?? "" 39 | shouldCreateAccount = json[ComputerConfigurationManagement.CreateAccountKey] as? Bool ?? false 40 | shouldHideAccount = json[ComputerConfigurationManagement.HideAccountKey] as? Bool ?? false 41 | isSSHAllowedForManagementOnly = json[ComputerConfigurationManagement.AllowSSHForManagementOnlyKey] as? Bool ?? false 42 | } 43 | 44 | // MARK: - Functions 45 | 46 | public func toJSON() -> [String: Any] { 47 | var json = [String: Any]() 48 | 49 | json[ComputerConfigurationManagement.UsernameKey] = username 50 | json[ComputerConfigurationManagement.PasswordKey] = password 51 | json[ComputerConfigurationManagement.CreateAccountKey] = shouldCreateAccount 52 | json[ComputerConfigurationManagement.HideAccountKey] = shouldHideAccount 53 | json[ComputerConfigurationManagement.AllowSSHForManagementOnlyKey] = isSSHAllowedForManagementOnly 54 | 55 | return json 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /JamfKit/Tests/Session/Requests/SessionManagerRequestsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class SessionManagerRequestsTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let defaultHost = "http://localhost" 15 | let defaultUsername = "username" 16 | let defaultPassword = "password" 17 | let defaultAuthorizationHeader = "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" 18 | 19 | // MARK: - Lifecycle 20 | 21 | override func setUp() { 22 | try? SessionManager.instance.configure(for: defaultHost, username: defaultUsername, password: defaultPassword) 23 | } 24 | 25 | override func tearDown() { 26 | SessionManager.instance.clearConfiguration() 27 | } 28 | 29 | // MARK: - Tests 30 | 31 | func testShouldComputeAuthorizationHeaderFromValidParameters() { 32 | let actualValue = SessionManager.computeAuthorizationHeader(from: defaultUsername, password: defaultPassword) 33 | 34 | XCTAssertEqual(actualValue, defaultAuthorizationHeader) 35 | } 36 | 37 | func testShouldNotComputeAuthorizationHeaderFromEmptyUsername() { 38 | let actualValue = SessionManager.computeAuthorizationHeader(from: "", password: defaultPassword) 39 | 40 | XCTAssertEqual(actualValue, "") 41 | } 42 | 43 | func testShouldNotComputeAuthorizationHeaderFromEmptyPassword() { 44 | let actualValue = SessionManager.computeAuthorizationHeader(from: defaultUsername, password: "") 45 | 46 | XCTAssertEqual(actualValue, "") 47 | } 48 | 49 | func testShouldReturnAuthentifiedURLRequest() { 50 | let defaultURL = URL(string: defaultHost)! 51 | let authorizationHeader = SessionManager.computeAuthorizationHeader(from: defaultUsername, password: defaultPassword) 52 | 53 | let actualValue = SessionManager.instance.authentifiedRequest(for: defaultURL, authorizationHeader: authorizationHeader, method: HttpMethod.get) 54 | 55 | XCTAssertNotNil(actualValue) 56 | XCTAssertEqual(actualValue.value(forHTTPHeaderField: HttpHeader.authorization.rawValue), defaultAuthorizationHeader) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/MobileDevice/mobile_device.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "display_name": "Mobile Device", 5 | "device_name": "mobile_device", 6 | "name": "Mobile Device", 7 | "asset_tag": "asset_tag", 8 | "last_inventory_update": "2017-07-07T18:37:04.000Z", 9 | "last_inventory_update_epoch": 1499470624555, 10 | "last_inventory_update_utc": "2017-07-07T18:37:04.555-0500", 11 | "capacity": 12159, 12 | "capacity_mb": 12159, 13 | "available": 11487, 14 | "available_mb": 11487, 15 | "percentage_used": 5, 16 | "os_type": "iOS", 17 | "os_version": "10.3.2", 18 | "os_build": "14F89", 19 | "serial_number": "C02Q7KHTGFWF", 20 | "udid": "270aae10800b6e61a2ee2bbc285eb967050b5984", 21 | "initial_entry_date_epoch": 1499470624555, 22 | "initial_entry_date_utc": "2017-07-07T18:37:04.555-0500", 23 | "phone_number": "123-555-6789", 24 | "ip_address": "192.0.0.1", 25 | "wifi_mac_address": "E0:AC:CB:97:36:G4", 26 | "bluetooth_mac_address": "E0:AC:CB:97:36:G6", 27 | "modem_firmware": "2.61.00", 28 | "model": "iPhone 6S", 29 | "model_identifier": "iPhone8,1", 30 | "model_number": "MKRY2LL", 31 | "model_display": "iPhone 6S", 32 | "device_ownership_level": "Institutional", 33 | "last_enrollment_epoch": 1499470624555, 34 | "last_enrollment_utc": "2017-07-07T18:37:04.555-0500", 35 | "managed": true, 36 | "supervised": true, 37 | "exchange_activesync_device_identifier": "TUCLLFJHPL779ACL9DCJQFN39F", 38 | "shared": "string", 39 | "tethered": "string", 40 | "battery_level": 95, 41 | "ble_capable": true, 42 | "device_locator_service_enabled": true, 43 | "do_not_disturb_enabled": true, 44 | "cloud_backup_enabled": true, 45 | "last_cloud_backup_date_epoch": 1499470624555, 46 | "last_cloud_backup_date_utc": "2017-07-07T18:37:04.555-0500", 47 | "location_services_enabled": true, 48 | "itunes_store_account_is_active": true, 49 | "last_backup_time_epoch": 1499470624555, 50 | "last_backup_time_utc": "2017-07-07T18:37:04.555-0500" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/ComputerCommand/ComputerCommandGeneralTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerCommandGeneralTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "ComputerCommand/" 15 | let defaultCommand = "command" 16 | let defaultPasscode: UInt = 123456 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = ComputerCommandGeneral(command: defaultCommand, passcode: defaultPasscode) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.command, defaultCommand) 25 | XCTAssertEqual(actualValue?.passcode, defaultPasscode) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = ComputerCommandGeneral(command: "", passcode: defaultPasscode) 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "computer_command_general_valid", subfolder: subfolder)! 36 | 37 | let actualValue = ComputerCommandGeneral(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.command, defaultCommand) 41 | XCTAssertEqual(actualValue?.passcode, defaultPasscode) 42 | } 43 | 44 | func testShouldNotInitializeFromInvalidJSON() { 45 | let payload = self.payload(for: "computer_command_general_invalid", subfolder: subfolder)! 46 | 47 | let actualValue = ComputerCommandGeneral(json: payload) 48 | 49 | XCTAssertNil(actualValue) 50 | } 51 | 52 | func testShouldEncodeToJSON() { 53 | let payload = self.payload(for: "computer_command_general_valid", subfolder: subfolder)! 54 | 55 | let actualValue = ComputerCommandGeneral(json: payload) 56 | let encodedObject = actualValue?.toJSON() 57 | 58 | XCTAssertNotNil(encodedObject) 59 | XCTAssertEqual(encodedObject?.count, 2) 60 | XCTAssertNotNil(encodedObject?[ComputerCommandGeneral.CommandKey]) 61 | XCTAssertNotNil(encodedObject?[ComputerCommandGeneral.PasscodeKey]) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/CategoryTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class CategoryTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Category/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "category" 17 | let defaultPriority: UInt = 10 18 | 19 | // MARK: - Tests 20 | 21 | func testShouldInstantiate() { 22 | let actualValue = Category(identifier: defaultIdentifier, name: defaultName) 23 | 24 | XCTAssertNotNil(actualValue) 25 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 26 | XCTAssertEqual(actualValue?.name, defaultName) 27 | } 28 | 29 | func testShouldNotInstantiateWithInvalidParameters() { 30 | let actualValue = Category(identifier: defaultIdentifier, name: "") 31 | 32 | XCTAssertNil(actualValue) 33 | } 34 | 35 | func testShouldInitializeFromJSON() { 36 | let payload = self.payload(for: "category_valid", subfolder: subfolder)! 37 | 38 | let actualValue = Category(json: payload) 39 | 40 | XCTAssertNotNil(actualValue) 41 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 42 | XCTAssertEqual(actualValue?.name, defaultName) 43 | XCTAssertEqual(actualValue?.priority, defaultPriority) 44 | } 45 | 46 | func testNotShouldInitializeFromInvalidJSON() { 47 | let payload = self.payload(for: "category_invalid", subfolder: subfolder)! 48 | 49 | let actualValue = Category(json: payload) 50 | 51 | XCTAssertNil(actualValue) 52 | } 53 | 54 | func testShouldEncodeToJSON() { 55 | let payload = self.payload(for: "category_valid", subfolder: subfolder)! 56 | 57 | let actualValue = Category(json: payload) 58 | let encodedObject = actualValue?.toJSON() 59 | 60 | XCTAssertNotNil(encodedObject) 61 | XCTAssertEqual(encodedObject?.count, 3) 62 | 63 | XCTAssertNotNil(encodedObject?[BaseObject.CodingKeys.identifier.rawValue]) 64 | XCTAssertNotNil(encodedObject?[BaseObject.CodingKeys.name.rawValue]) 65 | XCTAssertNotNil(encodedObject?[Category.PriorityKey]) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /JamfKit/Playgrounds/Examples.playground/Pages/Requests.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | //: # JamfKit - Requests 4 | 5 | //: 1. Import JamfKit 6 | 7 | import JamfKit 8 | 9 | //: 2. Configure the global instance of the `SessionManager` 10 | 11 | try SessionManager.instance.configure(for: "http://localhost/jss", username: "john", password: "appleseed") 12 | 13 | //: 3. Use any instanciated model that is conforming to `Requestable` 14 | 15 | let building = Building(json: ["id": UInt(12345), "name": "Some building"])! 16 | 17 | //: 4. Generate any request directly from the JSS class / object 18 | 19 | let readAllRequest = Building.readAllRequest() 20 | let createRequest = building.createRequest() 21 | let readStaticRequest = Building.readRequest(identifier: "12345") 22 | let readRequest = building.readRequest() 23 | let updateRequest = building.updateRequest() 24 | let deleteStaticRequest = Building.deleteRequest(identifier: "12345") 25 | let deleteRequest = building.deleteRequest() 26 | let deleteRequestWithName = building.deleteRequestWithName() 27 | 28 | //: #### Output 29 | 30 | print("\n##### CREATE") 31 | print(createRequest?.httpMethod) 32 | print(createRequest?.url) 33 | print(createRequest?.allHTTPHeaderFields) 34 | print(createRequest?.httpBody) 35 | print("\n##### READ ALL") 36 | print(readAllRequest?.httpMethod) 37 | print(readAllRequest?.url) 38 | print(readAllRequest?.allHTTPHeaderFields) 39 | print("\n##### READ STATIC") 40 | print(readStaticRequest?.httpMethod) 41 | print(readStaticRequest?.url) 42 | print(readStaticRequest?.allHTTPHeaderFields) 43 | print("\n##### READ") 44 | print(readRequest?.httpMethod) 45 | print(readRequest?.url) 46 | print(readRequest?.allHTTPHeaderFields) 47 | print("\n##### UPDATE") 48 | print(updateRequest?.httpMethod) 49 | print(updateRequest?.url) 50 | print(updateRequest?.allHTTPHeaderFields) 51 | print(updateRequest?.httpBody) 52 | print("\n##### DELETE STATIC") 53 | print(deleteStaticRequest?.httpMethod) 54 | print(deleteStaticRequest?.url) 55 | print(deleteStaticRequest?.allHTTPHeaderFields) 56 | print("\n##### DELETE") 57 | print(deleteRequest?.httpMethod) 58 | print(deleteRequest?.url) 59 | print(deleteRequest?.allHTTPHeaderFields) 60 | print("\n##### DELETE WITH NAME") 61 | print(deleteRequestWithName?.httpMethod) 62 | print(deleteRequestWithName?.url) 63 | print(deleteRequestWithName?.allHTTPHeaderFields) 64 | 65 | //: [Next](@next) 66 | -------------------------------------------------------------------------------- /JamfKit/Sources/Protocols/Requests/Readable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents an object that can be read with an URLRequest 7 | @objc(JMFKReadable) 8 | public protocol Readable { 9 | 10 | // MARK: - Functions 11 | 12 | /// Returns a GET **URLRequest** based on the JSS object type. 13 | static func readAllRequest() -> URLRequest? 14 | 15 | /// Returns a GET **URLRequest** based on the JSS object type & the supplied identifier. 16 | static func readRequest(identifier: String) -> URLRequest? 17 | 18 | /// Returns a GET **URLRequest** based on the identifier property of the supplied JSS object. 19 | func readRequest() -> URLRequest? 20 | } 21 | 22 | // MARK: - Implementation 23 | 24 | extension Readable where Self: Endpoint & Identifiable & Requestable { 25 | 26 | // MARK: - Functions 27 | 28 | static func getReadAllRequest() -> URLRequest? { 29 | return SessionManager.instance.readAllRequest(for: self.Endpoint) 30 | } 31 | 32 | static func getReadRequest(identifier: String) -> URLRequest? { 33 | return SessionManager.instance.readRequest(for: self, key: BaseObject.CodingKeys.identifier.rawValue, value: identifier) 34 | } 35 | 36 | func getReadRequest() -> URLRequest? { 37 | return SessionManager.instance.readRequest(for: self, key: BaseObject.CodingKeys.identifier.rawValue, value: String(identifier)) 38 | } 39 | 40 | static func getReadRequest(name: String) -> URLRequest? { 41 | return SessionManager.instance.readRequest(for: self, key: BaseObject.CodingKeys.name.rawValue, value: name) 42 | } 43 | 44 | func getReadRequestWithName() -> URLRequest? { 45 | return SessionManager.instance.readRequest(for: self, key: BaseObject.CodingKeys.name.rawValue, value: name) 46 | } 47 | } 48 | 49 | extension Readable where Self: Endpoint & Requestable & Subset { 50 | 51 | public static func getReadAllRequest() -> URLRequest? { 52 | return SessionManager.instance.readAllRequest(for: self.Endpoint) 53 | } 54 | 55 | static func getReadRequest(identifier: String) -> URLRequest? { 56 | return SessionManager.instance.readRequest(for: self, key: BaseObject.CodingKeys.identifier.rawValue, value: identifier) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Policy/PolicyDateTimeLimitations.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKPolicyDateTimeLimitations) 7 | public final class PolicyDateTimeLimitations: NSObject, Requestable { 8 | 9 | // MARK: - Constants 10 | 11 | static let ActivationDateKey = "activation_date" 12 | static let ExpirationDateKey = "expiration_date" 13 | static let NoExecuteOnKey = "no_execute_on" 14 | static let NoExecuteStartKey = "no_execute_start" 15 | static let NoExecuteEndKey = "no_execute_end" 16 | 17 | // MARK: - Properties 18 | 19 | @objc 20 | public var activationDate: PreciseDate? 21 | 22 | @objc 23 | public var expirationDate: PreciseDate? 24 | 25 | @objc 26 | public var noExecutionOn = [String: String]() 27 | 28 | @objc 29 | public var noExecutionStart = "" 30 | 31 | @objc 32 | public var noExecutionEnd = "" 33 | 34 | // MARK: - Initialization 35 | 36 | public init?(json: [String: Any], node: String = "") { 37 | activationDate = PreciseDate(json: json, node: PolicyDateTimeLimitations.ActivationDateKey) 38 | expirationDate = PreciseDate(json: json, node: PolicyDateTimeLimitations.ExpirationDateKey) 39 | noExecutionOn = json[PolicyDateTimeLimitations.NoExecuteOnKey] as? [String: String] ?? [String: String]() 40 | noExecutionStart = json[PolicyDateTimeLimitations.NoExecuteStartKey] as? String ?? "" 41 | noExecutionEnd = json[PolicyDateTimeLimitations.NoExecuteEndKey] as? String ?? "" 42 | } 43 | 44 | public override init() { 45 | super.init() 46 | } 47 | 48 | // MARK: - Functions 49 | 50 | public func toJSON() -> [String: Any] { 51 | var json = [String: Any]() 52 | 53 | if let activationDate = activationDate { 54 | json.merge(activationDate.toJSON()) { (_, new) in new } 55 | } 56 | 57 | if let expirationDate = expirationDate { 58 | json.merge(expirationDate.toJSON()) { (_, new) in new } 59 | } 60 | 61 | if !noExecutionOn.isEmpty { 62 | json[PolicyDateTimeLimitations.NoExecuteOnKey] = noExecutionOn 63 | } 64 | 65 | json[PolicyDateTimeLimitations.NoExecuteStartKey] = noExecutionStart 66 | json[PolicyDateTimeLimitations.NoExecuteEndKey] = noExecutionEnd 67 | 68 | return json 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Site.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents a physical location (building, office, etc.). 7 | @objc(JMFKSite) 8 | public final class Site: BaseObject, Endpoint { 9 | 10 | // MARK: - Constants 11 | 12 | public static let Endpoint = "sites" 13 | } 14 | 15 | // MARK: - Creatable 16 | 17 | extension Site: Creatable { 18 | 19 | public func createRequest() -> URLRequest? { 20 | return getCreateRequest() 21 | } 22 | } 23 | 24 | // MARK: - Readable 25 | 26 | extension Site: Readable { 27 | 28 | public static func readAllRequest() -> URLRequest? { 29 | return getReadAllRequest() 30 | } 31 | 32 | public static func readRequest(identifier: String) -> URLRequest? { 33 | return getReadRequest(identifier: identifier) 34 | } 35 | 36 | public func readRequest() -> URLRequest? { 37 | return getReadRequest() 38 | } 39 | 40 | /// Returns a GET **URLRequest** based on the supplied name. 41 | public static func readRequest(name: String) -> URLRequest? { 42 | return getReadRequest(name: name) 43 | } 44 | 45 | /// Returns a GET **URLRequest** based on the email. 46 | public func readRequestWithName() -> URLRequest? { 47 | return getReadRequestWithName() 48 | } 49 | } 50 | 51 | // MARK: - Updatable 52 | 53 | extension Site: Updatable { 54 | 55 | public func updateRequest() -> URLRequest? { 56 | return getUpdateRequest() 57 | } 58 | 59 | /// Returns a PUT **URLRequest** based on the name. 60 | public func updateRequestWithName() -> URLRequest? { 61 | return getUpdateRequestWithName() 62 | } 63 | } 64 | 65 | // MARK: - Deletable 66 | 67 | extension Site: Deletable { 68 | 69 | public static func deleteRequest(identifier: String) -> URLRequest? { 70 | return getDeleteRequest(identifier: identifier) 71 | } 72 | 73 | public func deleteRequest() -> URLRequest? { 74 | return getDeleteRequest() 75 | } 76 | 77 | /// Returns a DELETE **URLRequest** based on the supplied name. 78 | public static func deleteRequest(name: String) -> URLRequest? { 79 | return getDeleteRequest(name: name) 80 | } 81 | 82 | /// Returns a DELETE **URLRequest** based on the name. 83 | public func deleteRequestWithName() -> URLRequest? { 84 | return getDeleteRequestWithName() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Department.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents a physical department. 7 | @objc(JMFKDepartment) 8 | public final class Department: BaseObject, Endpoint { 9 | 10 | // MARK: - Constants 11 | 12 | public static let Endpoint = "departments" 13 | } 14 | 15 | // MARK: - Creatable 16 | 17 | extension Department: Creatable { 18 | 19 | public func createRequest() -> URLRequest? { 20 | return getCreateRequest() 21 | } 22 | } 23 | 24 | // MARK: - Readable 25 | 26 | extension Department: Readable { 27 | 28 | public static func readAllRequest() -> URLRequest? { 29 | return getReadAllRequest() 30 | } 31 | 32 | public static func readRequest(identifier: String) -> URLRequest? { 33 | return getReadRequest(identifier: identifier) 34 | } 35 | 36 | public func readRequest() -> URLRequest? { 37 | return getReadRequest() 38 | } 39 | 40 | /// Returns a GET **URLRequest** based on the supplied name. 41 | public static func readRequest(name: String) -> URLRequest? { 42 | return getReadRequest(name: name) 43 | } 44 | 45 | /// Returns a GET **URLRequest** based on the email. 46 | public func readRequestWithName() -> URLRequest? { 47 | return getReadRequestWithName() 48 | } 49 | } 50 | 51 | // MARK: - Updatable 52 | 53 | extension Department: Updatable { 54 | 55 | public func updateRequest() -> URLRequest? { 56 | return getUpdateRequest() 57 | } 58 | 59 | /// Returns a PUT **URLRequest** based on the name. 60 | public func updateRequestWithName() -> URLRequest? { 61 | return getUpdateRequestWithName() 62 | } 63 | } 64 | 65 | // MARK: - Deletable 66 | 67 | extension Department: Deletable { 68 | 69 | public static func deleteRequest(identifier: String) -> URLRequest? { 70 | return getDeleteRequest(identifier: identifier) 71 | } 72 | 73 | public func deleteRequest() -> URLRequest? { 74 | return getDeleteRequest() 75 | } 76 | 77 | /// Returns a DELETE **URLRequest** based on the supplied name. 78 | public static func deleteRequest(name: String) -> URLRequest? { 79 | return getDeleteRequest(name: name) 80 | } 81 | 82 | /// Returns a DELETE **URLRequest** based on the name. 83 | public func deleteRequestWithName() -> URLRequest? { 84 | return getDeleteRequestWithName() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/HardwareGroup/HardwareGroupCriterion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKHardwareGroupCriterion) 7 | public final class HardwareGroupCriterion: NSObject, Requestable { 8 | 9 | // MARK: - Constants 10 | 11 | static let NameKey = "name" 12 | static let PriorityKey = "priority" 13 | static let AndOrKey = "and_or" 14 | static let SearchTypeKey = "search_type" 15 | static let ValueKey = "value" 16 | static let OpeningParenKey = "opening_paren" 17 | static let ClosingParenKey = "closing_paren" 18 | 19 | // MARK: - Properties 20 | 21 | @objc 22 | public var name = "" 23 | 24 | @objc 25 | public var priority: UInt = 0 26 | 27 | @objc 28 | public var andOr = "" 29 | 30 | @objc 31 | public var searchType = "" 32 | 33 | @objc 34 | public var value: UInt = 0 35 | 36 | @objc 37 | public var openingParen = false 38 | 39 | @objc 40 | public var closingParen = false 41 | 42 | // MARK: - Initialization 43 | 44 | public init?(json: [String: Any], node: String = "") { 45 | name = json[HardwareGroupCriterion.NameKey] as? String ?? "" 46 | priority = json[HardwareGroupCriterion.PriorityKey] as? UInt ?? 0 47 | andOr = json[HardwareGroupCriterion.AndOrKey] as? String ?? "" 48 | searchType = json[HardwareGroupCriterion.SearchTypeKey] as? String ?? "" 49 | value = json[HardwareGroupCriterion.ValueKey] as? UInt ?? 0 50 | openingParen = json[HardwareGroupCriterion.OpeningParenKey] as? Bool ?? false 51 | closingParen = json[HardwareGroupCriterion.ClosingParenKey] as? Bool ?? false 52 | } 53 | 54 | public init?(name: String) { 55 | guard !name.isEmpty else { 56 | return nil 57 | } 58 | 59 | self.name = name 60 | 61 | super.init() 62 | } 63 | 64 | // MARK: - Functions 65 | 66 | public func toJSON() -> [String: Any] { 67 | var json = [String: Any]() 68 | 69 | json[HardwareGroupCriterion.NameKey] = name 70 | json[HardwareGroupCriterion.PriorityKey] = priority 71 | json[HardwareGroupCriterion.AndOrKey] = andOr 72 | json[HardwareGroupCriterion.SearchTypeKey] = searchType 73 | json[HardwareGroupCriterion.ValueKey] = value 74 | json[HardwareGroupCriterion.OpeningParenKey] = openingParen 75 | json[HardwareGroupCriterion.ClosingParenKey] = closingParen 76 | 77 | return json 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Computer/ComputerLocation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKComputerLocation) 7 | public final class ComputerLocation: NSObject, Requestable { 8 | 9 | // MARK: - Constants 10 | 11 | static let UsernameKey = "username" 12 | static let RealNameKey = "real_name" 13 | static let EmailAddressKey = "email_address" 14 | static let PositionKey = "position" 15 | static let PhoneNumberKey = "phone_number" 16 | static let DepartementKey = "department" 17 | static let BuildingKey = "building" 18 | static let RoomKey = "room" 19 | 20 | // MARK: - Properties 21 | 22 | @objc 23 | public var username = "" 24 | 25 | @objc 26 | public var realName = "" 27 | 28 | @objc 29 | public var emailAddress = "" 30 | 31 | @objc 32 | public var position = "" 33 | 34 | @objc 35 | public var phoneNumber = "" 36 | 37 | @objc 38 | public var department = "" 39 | 40 | @objc 41 | public var building = "" 42 | 43 | @objc 44 | public var room: UInt = 0 45 | 46 | // MARK: - Initialization 47 | 48 | public init?(json: [String: Any], node: String = "") { 49 | username = json[ComputerLocation.UsernameKey] as? String ?? "" 50 | realName = json[ComputerLocation.RealNameKey] as? String ?? "" 51 | emailAddress = json[ComputerLocation.EmailAddressKey] as? String ?? "" 52 | position = json[ComputerLocation.PositionKey] as? String ?? "" 53 | phoneNumber = json[ComputerLocation.PhoneNumberKey] as? String ?? "" 54 | department = json[ComputerLocation.DepartementKey] as? String ?? "" 55 | building = json[ComputerLocation.BuildingKey] as? String ?? "" 56 | room = json[ComputerLocation.RoomKey] as? UInt ?? 0 57 | } 58 | 59 | public override init() { 60 | super.init() 61 | } 62 | 63 | // MARK: - Functions 64 | 65 | public func toJSON() -> [String: Any] { 66 | var json = [String: Any]() 67 | 68 | json[ComputerLocation.UsernameKey] = username 69 | json[ComputerLocation.RealNameKey] = realName 70 | json[ComputerLocation.EmailAddressKey] = emailAddress 71 | json[ComputerLocation.PositionKey] = position 72 | json[ComputerLocation.PhoneNumberKey] = phoneNumber 73 | json[ComputerLocation.DepartementKey] = department 74 | json[ComputerLocation.BuildingKey] = building 75 | json[ComputerLocation.RoomKey] = room 76 | 77 | return json 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/Policy/PolicyOverrideDefaultSettingsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class PolicyOverrideDefaultSettingsTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Policy/" 15 | let defaultTargetDrive = "target_drive" 16 | let defaultDistributionPoint = "distribution_point" 17 | let defaultForceAfpSmb = true 18 | let defaultSus = "sus" 19 | let defaultNetbootServer = "netboot_server" 20 | 21 | // MARK: - Tests 22 | 23 | func testShouldInitializeFromJSON() { 24 | let payload = self.payload(for: "policy_override_default_settings", subfolder: subfolder)! 25 | 26 | let actualValue = PolicyOverrideDefaultSettings(json: payload) 27 | 28 | XCTAssertNotNil(actualValue) 29 | XCTAssertEqual(actualValue?.targetDrive, defaultTargetDrive) 30 | XCTAssertEqual(actualValue?.distributionPoint, defaultDistributionPoint) 31 | XCTAssertEqual(actualValue?.shouldForceAfpSmb, defaultForceAfpSmb) 32 | XCTAssertEqual(actualValue?.sus, defaultSus) 33 | XCTAssertEqual(actualValue?.netbootServer, defaultNetbootServer) 34 | } 35 | 36 | func testShouldInitializeFromEmptyJSON() { 37 | let actualValue = PolicyOverrideDefaultSettings(json: [String: Any]()) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.targetDrive, "") 41 | XCTAssertEqual(actualValue?.distributionPoint, "") 42 | XCTAssertEqual(actualValue?.shouldForceAfpSmb, false) 43 | XCTAssertEqual(actualValue?.sus, "") 44 | XCTAssertEqual(actualValue?.netbootServer, "") 45 | } 46 | 47 | func testShouldEncodeToJSON() { 48 | let payload = self.payload(for: "policy_override_default_settings", subfolder: subfolder)! 49 | 50 | let actualValue = PolicyOverrideDefaultSettings(json: payload) 51 | let encodedObject = actualValue?.toJSON() 52 | 53 | XCTAssertNotNil(encodedObject) 54 | XCTAssertEqual(encodedObject?.count, 5) 55 | XCTAssertNotNil(encodedObject?[PolicyOverrideDefaultSettings.TargetDriveKey]) 56 | XCTAssertNotNil(encodedObject?[PolicyOverrideDefaultSettings.DistributionPointKey]) 57 | XCTAssertNotNil(encodedObject?[PolicyOverrideDefaultSettings.ForceAfpSmbKey]) 58 | XCTAssertNotNil(encodedObject?[PolicyOverrideDefaultSettings.SusKey]) 59 | XCTAssertNotNil(encodedObject?[PolicyOverrideDefaultSettings.NetbootServerKey]) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/Policy/PolicyTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class PolicyTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Policy/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "Policy" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = Policy(identifier: defaultIdentifier, name: defaultName) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.general.identifier, defaultIdentifier) 25 | XCTAssertEqual(actualValue?.general.name, defaultName) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = Policy(identifier: defaultIdentifier, name: "") 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "policy", subfolder: subfolder)! 36 | 37 | let actualValue = Policy(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.description, "[Policy][\(defaultIdentifier) - \(defaultName)]") 41 | XCTAssertNotNil(actualValue?.general) 42 | } 43 | 44 | func testShouldInitializeFromIncompleteJSON() { 45 | let payload = self.payload(for: "policy_incomplete", subfolder: subfolder)! 46 | 47 | let actualValue = Policy(json: payload) 48 | 49 | XCTAssertNotNil(actualValue) 50 | XCTAssertEqual(actualValue?.description, "[Policy][\(defaultIdentifier) - \(defaultName)]") 51 | XCTAssertNotNil(actualValue?.general) 52 | } 53 | 54 | func testShouldNotInitializeFromEmptyJSON() { 55 | let actualValue = Computer(json: [String: Any]()) 56 | 57 | XCTAssertNil(actualValue) 58 | } 59 | 60 | func testShouldNotInitializeFromInvalidJSON() { 61 | let payload = self.payload(for: "policy_invalid", subfolder: subfolder)! 62 | 63 | let actualValue = Policy(json: payload) 64 | 65 | XCTAssertNil(actualValue) 66 | } 67 | 68 | func testShouldEncodeToJSON() { 69 | let payload = self.payload(for: "policy", subfolder: subfolder)! 70 | 71 | let actualValue = Policy(json: payload) 72 | let encodedObject = actualValue?.toJSON() 73 | 74 | XCTAssertNotNil(encodedObject) 75 | XCTAssertEqual(encodedObject?.count, 1) 76 | XCTAssertNotNil(encodedObject?[Policy.GeneralKey]) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/Computer/ComputerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Computer/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "computer" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = Computer(identifier: defaultIdentifier, name: defaultName) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.general.identifier, defaultIdentifier) 25 | XCTAssertEqual(actualValue?.general.name, defaultName) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = Computer(identifier: defaultIdentifier, name: "") 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "computer", subfolder: subfolder)! 36 | 37 | let actualValue = Computer(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.description, "[Computer][12345 - computer]") 41 | XCTAssertNotNil(actualValue?.general) 42 | XCTAssertNotNil(actualValue?.location) 43 | XCTAssertNotNil(actualValue?.purchasing) 44 | } 45 | 46 | func testShouldInitializeFromIncompleteJSON() { 47 | let payload = self.payload(for: "computer_incomplete", subfolder: subfolder)! 48 | 49 | let actualValue = Computer(json: payload) 50 | 51 | XCTAssertNotNil(actualValue) 52 | XCTAssertEqual(actualValue?.description, "[Computer][12345 - computer]") 53 | XCTAssertNotNil(actualValue?.general) 54 | XCTAssertNil(actualValue?.location) 55 | XCTAssertNil(actualValue?.purchasing) 56 | } 57 | 58 | func testShouldNotInitializeFromEmptyJSON() { 59 | let actualValue = Computer(json: [String: Any]()) 60 | 61 | XCTAssertNil(actualValue) 62 | } 63 | 64 | func testShouldEncodeToJSON() { 65 | let payload = self.payload(for: "computer", subfolder: subfolder)! 66 | 67 | let actualValue = Computer(json: payload) 68 | let encodedObject = actualValue?.toJSON() 69 | 70 | XCTAssertNotNil(encodedObject) 71 | XCTAssertEqual(encodedObject?.count, 3) 72 | XCTAssertNotNil(encodedObject?[Computer.GeneralKey]) 73 | XCTAssertNotNil(encodedObject?[Computer.LocationKey]) 74 | XCTAssertNotNil(encodedObject?[Computer.PurchasingKey]) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/ConfigurationProfile/ConfigurationProfileGeneral.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | @objc(JMFKConfigurationProfileGeneral) 7 | public class ConfigurationProfileGeneral: BaseObject { 8 | 9 | // MARK: - Constants 10 | 11 | static let DescriptionKey = "description" 12 | static let SiteKey = "site" 13 | static let CategoryKey = "category" 14 | static let UuidKey = "uuid" 15 | static let RedeployOnUpdateKey = "redeploy_on_update" 16 | static let PayloadsKey = "payloads" 17 | 18 | // MARK: - Properties 19 | 20 | @objc 21 | public var desc: String = "" 22 | 23 | @objc 24 | public var site: Site? 25 | 26 | @objc 27 | public var category: Category? 28 | 29 | @objc 30 | public var uuid: String = "" 31 | 32 | @objc 33 | public var redeployOnUpdate: String = "" 34 | 35 | @objc 36 | public var payloads: String = "" 37 | 38 | // MARK: - Initialization 39 | 40 | public required init?(json: [String: Any], node: String = "") { 41 | desc = json[ConfigurationProfileGeneral.DescriptionKey] as? String ?? "" 42 | 43 | if let siteNode = json[ConfigurationProfileGeneral.SiteKey] as? [String: Any] { 44 | site = Site(json: siteNode) 45 | } 46 | 47 | if let categoryNode = json[ConfigurationProfileGeneral.CategoryKey] as? [String: Any] { 48 | category = Category(json: categoryNode) 49 | } 50 | 51 | uuid = json[ConfigurationProfileGeneral.UuidKey] as? String ?? "" 52 | redeployOnUpdate = json[ConfigurationProfileGeneral.RedeployOnUpdateKey] as? String ?? "" 53 | payloads = json[ConfigurationProfileGeneral.PayloadsKey] as? String ?? "" 54 | 55 | super.init(json: json) 56 | } 57 | 58 | override init?(identifier: UInt, name: String) { 59 | super.init(identifier: identifier, name: name) 60 | } 61 | 62 | // MARK: - Functions 63 | 64 | public override func toJSON() -> [String: Any] { 65 | var json = super.toJSON() 66 | 67 | json[ConfigurationProfileGeneral.DescriptionKey] = desc 68 | 69 | if let site = site { 70 | json[ConfigurationProfileGeneral.SiteKey] = site.toJSON() 71 | } 72 | 73 | if let category = category { 74 | json[ConfigurationProfileGeneral.CategoryKey] = category.toJSON() 75 | } 76 | 77 | json[ConfigurationProfileGeneral.UuidKey] = uuid 78 | json[ConfigurationProfileGeneral.RedeployOnUpdateKey] = redeployOnUpdate 79 | json[ConfigurationProfileGeneral.PayloadsKey] = payloads 80 | 81 | return json 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/ConfigurationProfile/ComputerConfigurationProfile/ComputerConfigurationProfileTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerConfigurationProfileTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "ComputerConfigurationProfile/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "Corporate Wireless" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = ComputerConfigurationProfile(identifier: defaultIdentifier, name: defaultName) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.general.identifier, defaultIdentifier) 25 | XCTAssertEqual(actualValue?.general.name, defaultName) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = ComputerConfigurationProfile(identifier: defaultIdentifier, name: "") 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "computer_configuration_profile_valid", subfolder: subfolder)! 36 | 37 | let actualValue = ComputerConfigurationProfile(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.description, "[ComputerConfigurationProfile][\(defaultIdentifier) - \(defaultName)]") 41 | XCTAssertEqual(actualValue?.general.identifier, defaultIdentifier) 42 | XCTAssertEqual(actualValue?.general.name, defaultName) 43 | } 44 | 45 | func testShouldNotInitializeFromInvalidJSON() { 46 | let payload = self.payload(for: "computer_configuration_profile_invalid", subfolder: subfolder)! 47 | 48 | let actualValue = ComputerConfigurationProfile(json: payload) 49 | 50 | XCTAssertNil(actualValue) 51 | } 52 | 53 | func testShouldEncodeToJSON() { 54 | let payload = self.payload(for: "computer_configuration_profile_valid", subfolder: subfolder)! 55 | 56 | let actualValue = ComputerConfigurationProfile(json: payload) 57 | let encodedObject = actualValue?.toJSON() 58 | 59 | XCTAssertNotNil(encodedObject) 60 | XCTAssertEqual(encodedObject?.count, 1) 61 | XCTAssertNotNil(encodedObject?[ComputerConfigurationProfile.GeneralKey]) 62 | 63 | let generalNode = encodedObject?[ComputerConfigurationProfile.GeneralKey] as! [String: Any] 64 | XCTAssertNotNil(generalNode[BaseObject.CodingKeys.identifier.rawValue]) 65 | XCTAssertNotNil(generalNode[BaseObject.CodingKeys.name.rawValue]) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/BuildingTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class BuildingTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Building/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "Building" 17 | let defaultStreetAddress1 = "Doe Street" 18 | let defaultStreetAddress2 = "" 19 | let defaultCity = "Doeville" 20 | let defaultStateProvince = "Doe county" 21 | let defaultZipPostalCode = "012345" 22 | let defaultCountry = "Doeland" 23 | 24 | // MARK: - Tests 25 | 26 | func testShouldInstantiate() { 27 | let actualValue = Building(identifier: defaultIdentifier, name: defaultName) 28 | 29 | XCTAssertNotNil(actualValue) 30 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 31 | XCTAssertEqual(actualValue?.name, defaultName) 32 | } 33 | 34 | func testShouldNotInstantiateWithInvalidParameters() { 35 | let actualValue = Building(identifier: defaultIdentifier, name: "") 36 | 37 | XCTAssertNil(actualValue) 38 | } 39 | 40 | func testShouldInitializeFromJSON() { 41 | let payload = self.payload(for: "building_valid", subfolder: subfolder)! 42 | 43 | let actualValue = Building(json: payload) 44 | 45 | XCTAssertNotNil(actualValue) 46 | XCTAssertEqual(actualValue?.identifier, defaultIdentifier) 47 | XCTAssertEqual(actualValue?.name, defaultName) 48 | XCTAssertEqual(actualValue?.description, "[Building][\(defaultIdentifier) - \(defaultName)]") 49 | XCTAssertEqual(actualValue?.streetAddress1, defaultStreetAddress1) 50 | XCTAssertEqual(actualValue?.streetAddress2, defaultStreetAddress2) 51 | XCTAssertEqual(actualValue?.city, defaultCity) 52 | XCTAssertEqual(actualValue?.stateProvince, defaultStateProvince) 53 | XCTAssertEqual(actualValue?.zipPostalCode, defaultZipPostalCode) 54 | XCTAssertEqual(actualValue?.country, defaultCountry) 55 | } 56 | 57 | func testShouldNotInitializeFromInvalidJSON() { 58 | let payload = self.payload(for: "building_invalid", subfolder: subfolder)! 59 | 60 | let actualValue = Building(json: payload) 61 | 62 | XCTAssertNil(actualValue) 63 | } 64 | 65 | func testShouldEncodeToJSON() { 66 | let payload = self.payload(for: "building_valid", subfolder: subfolder)! 67 | 68 | let actualValue = Building(json: payload) 69 | let encodedObject = actualValue?.toJSON() 70 | 71 | XCTAssertNotNil(encodedObject) 72 | XCTAssertEqual(encodedObject?.count, 8) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/ComputerConfiguration/ComputerConfigurationManagementTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerConfigurationManagementTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "ComputerConfiguration/" 15 | let defaultUsername = "administrator" 16 | let defaultPassword = "password" 17 | let defaultShouldCreateAccount = true 18 | let defaultShouldHideAccount = true 19 | let defaultIsSSHAllowedOnlyForManagement = true 20 | 21 | // MARK: - Tests 22 | 23 | func testShouldInitializeFromJSON() { 24 | let payload = self.payload(for: "computer_configuration_management", subfolder: subfolder)! 25 | 26 | let actualValue = ComputerConfigurationManagement(json: payload) 27 | 28 | XCTAssertNotNil(actualValue) 29 | XCTAssertEqual(actualValue?.username, defaultUsername) 30 | XCTAssertEqual(actualValue?.password, defaultPassword) 31 | XCTAssertEqual(actualValue?.shouldCreateAccount, defaultShouldCreateAccount) 32 | XCTAssertEqual(actualValue?.shouldHideAccount, defaultShouldHideAccount) 33 | XCTAssertEqual(actualValue?.isSSHAllowedForManagementOnly, defaultIsSSHAllowedOnlyForManagement) 34 | } 35 | 36 | func testShouldInitializeFromEmptyJSON() { 37 | let actualValue = ComputerConfigurationManagement(json: [String: Any]()) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.username, "") 41 | XCTAssertEqual(actualValue?.password, "") 42 | XCTAssertEqual(actualValue?.shouldCreateAccount, false) 43 | XCTAssertEqual(actualValue?.shouldHideAccount, false) 44 | XCTAssertEqual(actualValue?.isSSHAllowedForManagementOnly, false) 45 | } 46 | 47 | func testShouldEncodeToJSON() { 48 | let payload = self.payload(for: "computer_configuration_management", subfolder: subfolder)! 49 | 50 | let actualValue = ComputerConfigurationManagement(json: payload) 51 | let encodedObject = actualValue?.toJSON() 52 | 53 | XCTAssertNotNil(encodedObject) 54 | XCTAssertEqual(encodedObject?.count, 5) 55 | XCTAssertNotNil(encodedObject?[ComputerConfigurationManagement.UsernameKey]) 56 | XCTAssertNotNil(encodedObject?[ComputerConfigurationManagement.PasswordKey]) 57 | XCTAssertNotNil(encodedObject?[ComputerConfigurationManagement.CreateAccountKey]) 58 | XCTAssertNotNil(encodedObject?[ComputerConfigurationManagement.HideAccountKey]) 59 | XCTAssertNotNil(encodedObject?[ComputerConfigurationManagement.AllowSSHForManagementOnlyKey]) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/PreciseDate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents a logical date within JSS api, contains 3 properties, the date itself, an epoch version of the date and an UTC version of the date. 7 | @objc(JMFKPreciseDate) 8 | public final class PreciseDate: NSObject, Requestable { 9 | 10 | // MARK: - Constants 11 | 12 | static let EpochKey = "_epoch" 13 | static let UTCKey = "_utc" 14 | 15 | // MARK: - Properties 16 | 17 | private let node: String 18 | 19 | @objc 20 | public var date: Date? 21 | 22 | @objc(epoch) 23 | public var internalEpoch: NSNumber? { 24 | guard let epoch = self.epoch else { 25 | return 0 26 | } 27 | 28 | return NSNumber(value: epoch) 29 | } 30 | 31 | @nonobjc 32 | public var epoch: UInt? 33 | 34 | @objc 35 | public var dateUTC: Date? 36 | 37 | // MARK: - Initialization 38 | 39 | public init?(json: [String: Any], node: String) { 40 | self.node = node 41 | 42 | if let rawDate = json[node] as? String { 43 | date = PreciseDate.getDateFormatter().date(from: rawDate) 44 | } 45 | 46 | epoch = json[node + PreciseDate.EpochKey] as? UInt 47 | 48 | if let rawDateUTC = json[node + PreciseDate.UTCKey] as? String { 49 | dateUTC = PreciseDate.getUTCDateFormatter().date(from: rawDateUTC) 50 | } 51 | } 52 | 53 | public func toJSON() -> [String: Any] { 54 | var json = [String: Any]() 55 | 56 | if let date = date { 57 | json[node] = PreciseDate.getDateFormatter().string(from: date) 58 | } 59 | 60 | json[node + PreciseDate.EpochKey] = epoch 61 | 62 | if let dateUTC = dateUTC { 63 | json[node + PreciseDate.UTCKey] = PreciseDate.getUTCDateFormatter().string(from: dateUTC) 64 | } 65 | 66 | return json 67 | } 68 | 69 | // MARK: - Helpers 70 | 71 | private static func getDateFormatter() -> DateFormatter { 72 | let dateFormatter = DateFormatter() 73 | dateFormatter.locale = Locale(identifier: "en_US_POSIX") 74 | dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" 75 | return dateFormatter 76 | } 77 | 78 | private static func getUTCDateFormatter() -> DateFormatter { 79 | let dateFormatter = DateFormatter() 80 | dateFormatter.locale = Locale(identifier: "en_US_POSIX") 81 | dateFormatter.timeZone = TimeZone(abbreviation: "UTC") 82 | dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZ" 83 | dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) 84 | return dateFormatter 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/ConfigurationProfile/MobileDeviceConfigurationProfile/MobileDeviceConfigurationProfileTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class MobileDeviceConfigurationProfileTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "MobileDeviceConfigurationProfile/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "Corporate Wireless" 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = MobileDeviceConfigurationProfile(identifier: defaultIdentifier, name: defaultName) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.general.identifier, defaultIdentifier) 25 | XCTAssertEqual(actualValue?.general.name, defaultName) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = MobileDeviceConfigurationProfile(identifier: defaultIdentifier, name: "") 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "mobile_device_configuration_profile_valid", subfolder: subfolder)! 36 | 37 | let actualValue = MobileDeviceConfigurationProfile(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.description, "[MobileDeviceConfigurationProfile][\(defaultIdentifier) - \(defaultName)]") 41 | XCTAssertEqual(actualValue?.general.identifier, defaultIdentifier) 42 | XCTAssertEqual(actualValue?.general.name, defaultName) 43 | } 44 | 45 | func testShouldNotInitializeFromInvalidJSON() { 46 | let payload = self.payload(for: "mobile_device_configuration_profile_invalid", subfolder: subfolder)! 47 | 48 | let actualValue = MobileDeviceConfigurationProfile(json: payload) 49 | 50 | XCTAssertNil(actualValue) 51 | } 52 | 53 | func testShouldEncodeToJSON() { 54 | let payload = self.payload(for: "mobile_device_configuration_profile_valid", subfolder: subfolder)! 55 | 56 | let actualValue = MobileDeviceConfigurationProfile(json: payload) 57 | let encodedObject = actualValue?.toJSON() 58 | 59 | XCTAssertNotNil(encodedObject) 60 | XCTAssertEqual(encodedObject?.count, 1) 61 | XCTAssertNotNil(encodedObject?[MobileDeviceConfigurationProfile.GeneralKey]) 62 | 63 | let generalNode = encodedObject?[MobileDeviceConfigurationProfile.GeneralKey] as! [String: Any] 64 | XCTAssertNotNil(generalNode[BaseObject.CodingKeys.identifier.rawValue]) 65 | XCTAssertNotNil(generalNode[BaseObject.CodingKeys.name.rawValue]) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /JamfKit/Tests/Resources/Mocks.bundle/Computer/computer.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "id": 12345, 4 | "name": "computer", 5 | "mac_address": "E0:AC:CB:97:36:G4", 6 | "alt_mac_address": "E0:AC:CB:97:36:G4", 7 | "ip_address": "10.1.1.1", 8 | "last_reported_ip": "192.0.0.1", 9 | "serial_number": "C02Q7KHTGFWF", 10 | "udid": "55900BDC-347C-58B1-D249-F32244B11D30", 11 | "jamf_version": "9.99.0-t1494340586", 12 | "platform": "Mac", 13 | "barcode_1": "string", 14 | "barcode_2": "string", 15 | "asset_tag": "string", 16 | "remote_management": { 17 | "managed": true, 18 | "management_username": "casperadmin" 19 | }, 20 | "mdm_capable": true, 21 | "mdm_capable_users": { 22 | "mdm_capable_user": "string" 23 | }, 24 | "report_date": "2017-07-07T18:37:04.000Z", 25 | "report_date_epoch": 1499470624555, 26 | "report_date_utc": "2017-07-07T18:37:04.555-0500", 27 | "last_contact_time": "2017-07-07T18:37:04.000Z", 28 | "last_contact_time_epoch": 1499470624555, 29 | "last_contact_time_utc": "2017-07-07T18:37:04.555-0500", 30 | "initial_entry_date": "2017-07-07T18:37:04.000Z", 31 | "initial_entry_date_epoch": 1499470624555, 32 | "initial_entry_date_utc": "2017-07-07T18:37:04.555-0500", 33 | "last_cloud_backup_date_epoch": 1499470624555, 34 | "last_cloud_backup_date_utc": "2017-07-07T18:37:04.555-0500", 35 | "last_enrolled_date_epoch": 1499470624555, 36 | "last_enrolled_date_utc": "2017-07-07T18:37:04.555-0500", 37 | "distribution_point": "string", 38 | "sus": "string", 39 | "netboot_server": "string", 40 | "site": { 41 | "id": 0, 42 | "name": "None" 43 | }, 44 | "itunes_store_account_is_active": true 45 | }, 46 | "location": { 47 | "username": "JBetty", 48 | "realname": "Betty Jackson", 49 | "real_name": "Betty Jackson", 50 | "email_address": "jbetty@company.com", 51 | "position": "Systems Engineer", 52 | "phone": "123-555-6789", 53 | "phone_number": "123-555-6789", 54 | "department": "Sales Staff", 55 | "building": "New York Office", 56 | "room": 1159 57 | }, 58 | "purchasing": { 59 | "is_purchased": true, 60 | "is_leased": true, 61 | "po_number": "string", 62 | "vendor": "string", 63 | "applecare_id": "string", 64 | "purchase_price": "string", 65 | "purchasing_account": "string", 66 | "po_date": "string", 67 | "po_date_epoch": 0, 68 | "po_date_utc": "string", 69 | "warranty_expires": "string", 70 | "warranty_expires_epoch": 0, 71 | "warranty_expires_utc": "string", 72 | "lease_expires": "string", 73 | "lease_expires_epoch": 0, 74 | "lease_expires_utc": "string", 75 | "life_expectancy": 0, 76 | "purchasing_contact": "string" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/Partition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents a logical partition for an hard drive installed inside an hardware element managed by Jamf. 7 | @objc(JMFKPartition) 8 | public final class Partition: NSObject, Requestable { 9 | 10 | // MARK: - Constants 11 | 12 | static let NameKey = "name" 13 | static let SizeGigabytesKey = "size_gb" 14 | static let MaximumPercentageKey = "maximum_percentage" 15 | static let FormatKey = "format" 16 | static let IsRestorePartitionKey = "is_restore_partition" 17 | static let ComputerConfigurationKey = "computer_configuration" 18 | static let ReimageKey = "reimage" 19 | static let AppendToNameKey = "append_to_name" 20 | 21 | // MARK: - Properties 22 | 23 | @objc 24 | public var name = "" 25 | 26 | @objc 27 | public var sizeInGigabytes: UInt = 0 28 | 29 | @objc 30 | public var maximumPercentage: UInt = 0 31 | 32 | @objc 33 | public var format = "" 34 | 35 | @objc 36 | public var isRestorePartition = false 37 | 38 | @objc 39 | public var computerConfiguration = "" 40 | 41 | @objc 42 | public var reimage = false 43 | 44 | @objc 45 | public var appendToName = "" 46 | 47 | @objc 48 | public override var description: String { 49 | return "[\(String(describing: type(of: self)))][\(name)]" 50 | } 51 | 52 | // MARK: - Initialization 53 | 54 | public init?(json: [String: Any], node: String = "") { 55 | name = json[Partition.NameKey] as? String ?? "" 56 | sizeInGigabytes = json[Partition.SizeGigabytesKey] as? UInt ?? 0 57 | maximumPercentage = json[Partition.MaximumPercentageKey] as? UInt ?? 0 58 | format = json[Partition.FormatKey] as? String ?? "" 59 | isRestorePartition = json[Partition.IsRestorePartitionKey] as? Bool ?? false 60 | computerConfiguration = json[Partition.ComputerConfigurationKey] as? String ?? "" 61 | reimage = json[Partition.ReimageKey] as? Bool ?? false 62 | appendToName = json[Partition.AppendToNameKey] as? String ?? "" 63 | } 64 | 65 | public init?(name: String) { 66 | guard !name.isEmpty else { 67 | return nil 68 | } 69 | 70 | self.name = name 71 | 72 | super.init() 73 | } 74 | 75 | // MARK: - Functions 76 | 77 | public func toJSON() -> [String: Any] { 78 | var json = [String: Any]() 79 | 80 | json[Partition.NameKey] = name 81 | json[Partition.SizeGigabytesKey] = sizeInGigabytes 82 | json[Partition.MaximumPercentageKey] = maximumPercentage 83 | json[Partition.FormatKey] = format 84 | json[Partition.IsRestorePartitionKey] = isRestorePartition 85 | json[Partition.ComputerConfigurationKey] = computerConfiguration 86 | json[Partition.ReimageKey] = reimage 87 | json[Partition.AppendToNameKey] = appendToName 88 | 89 | return json 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/BaseObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents the common denominator between all the JSS objects which must contains at least an `identifier` and a `name` properties. 7 | @objc 8 | public class BaseObject: NSObject, Requestable, Identifiable { 9 | 10 | // MARK: - Constants 11 | 12 | enum CodingKeys: String { 13 | case identifier = "id" 14 | case name = "name" 15 | } 16 | 17 | // MARK: - Properties 18 | 19 | @objc 20 | public let identifier: UInt 21 | 22 | @objc 23 | public var name: String 24 | 25 | public override var description: String { 26 | return "[\(String(describing: type(of: self)))][\(identifier) - \(self.name)]" 27 | } 28 | 29 | // MARK: - Initialization 30 | 31 | @objc 32 | public required init?(json: [String: Any], node: String = "") { 33 | guard 34 | let identifier = json[BaseObject.CodingKeys.identifier.rawValue] as? UInt, 35 | let name = json[BaseObject.CodingKeys.name.rawValue] as? String 36 | else { 37 | return nil 38 | } 39 | 40 | self.identifier = identifier 41 | self.name = name 42 | } 43 | 44 | @objc 45 | public init?(identifier: UInt, name: String) { 46 | guard !name.isEmpty else { 47 | return nil 48 | } 49 | 50 | self.identifier = identifier 51 | self.name = name 52 | 53 | super.init() 54 | } 55 | 56 | // MARK: - Functions 57 | 58 | @objc 59 | public func toJSON() -> [String: Any] { 60 | var json = [String: Any]() 61 | 62 | json[BaseObject.CodingKeys.identifier.rawValue] = identifier 63 | json[BaseObject.CodingKeys.name.rawValue] = name 64 | 65 | return json 66 | } 67 | 68 | /** 69 | * Parse the supplied JSON dictionary and extract a list of elements matching the supplied type. 70 | * 71 | * - Parameter json: The JSON payload to extract the list of elements from. 72 | * - Parameter nodeKey: The name of the main node to extract the element from. 73 | * - Parameter singleNodeKey: The string key used to identify a single element within the main node. 74 | * 75 | */ 76 | static func parseElements(from json: [String: Any], nodeKey: String, singleNodeKey: String) -> [Element] { 77 | var elements = [Element]() 78 | 79 | guard let elementsNode = json[nodeKey] as? [[String: [String: Any]]] else { 80 | return elements 81 | } 82 | 83 | let newElements = elementsNode.map { $0[singleNodeKey] }.compactMap { rawElementNode -> Element? in 84 | guard let rawElement = rawElementNode else { 85 | return nil 86 | } 87 | 88 | return Element(json: rawElement, node: "") 89 | } 90 | 91 | elements.append(contentsOf: newElements) 92 | 93 | return elements 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/Computer/ComputerLocationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerLocationTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Computer/" 15 | let defaultUsername = "JDoe" 16 | let defaultRealName = "John Doe" 17 | let defaultEmailAddress = "john.doe@doecorp.com" 18 | let defaultPosition = "Unknown" 19 | let defaultPhoneNumber = "123-456-7890" 20 | let defaultDepartment = "Unknown department" 21 | let defaultBuilding = "Unknown building" 22 | let defaultRoom: UInt = 1234 23 | 24 | // MARK: - Tests 25 | 26 | func testShouldInitializeFromJSON() { 27 | let payload = self.payload(for: "computer_location", subfolder: subfolder)! 28 | 29 | let actualValue = ComputerLocation(json: payload) 30 | 31 | XCTAssertNotNil(actualValue) 32 | XCTAssertEqual(actualValue?.username, defaultUsername) 33 | XCTAssertEqual(actualValue?.realName, defaultRealName) 34 | XCTAssertEqual(actualValue?.emailAddress, defaultEmailAddress) 35 | XCTAssertEqual(actualValue?.position, defaultPosition) 36 | XCTAssertEqual(actualValue?.phoneNumber, defaultPhoneNumber) 37 | XCTAssertEqual(actualValue?.department, defaultDepartment) 38 | XCTAssertEqual(actualValue?.building, defaultBuilding) 39 | XCTAssertEqual(actualValue?.room, defaultRoom) 40 | } 41 | 42 | func testShouldInitializeFromEmptyJSON() { 43 | let actualValue = ComputerLocation(json: [String: Any]()) 44 | 45 | XCTAssertNotNil(actualValue) 46 | XCTAssertEqual(actualValue?.username, "") 47 | XCTAssertEqual(actualValue?.realName, "") 48 | XCTAssertEqual(actualValue?.emailAddress, "") 49 | XCTAssertEqual(actualValue?.position, "") 50 | XCTAssertEqual(actualValue?.phoneNumber, "") 51 | XCTAssertEqual(actualValue?.department, "") 52 | XCTAssertEqual(actualValue?.building, "") 53 | XCTAssertEqual(actualValue?.room, 0) 54 | } 55 | 56 | func testShouldEncodeToJSON() { 57 | let payload = self.payload(for: "computer_location", subfolder: subfolder)! 58 | 59 | let actualValue = ComputerLocation(json: payload) 60 | let encodedObject = actualValue?.toJSON() 61 | 62 | XCTAssertNotNil(encodedObject) 63 | XCTAssertEqual(encodedObject?.count, 8) 64 | XCTAssertNotNil(encodedObject?[ComputerLocation.UsernameKey]) 65 | XCTAssertNotNil(encodedObject?[ComputerLocation.RealNameKey]) 66 | XCTAssertNotNil(encodedObject?[ComputerLocation.EmailAddressKey]) 67 | XCTAssertNotNil(encodedObject?[ComputerLocation.PositionKey]) 68 | XCTAssertNotNil(encodedObject?[ComputerLocation.PhoneNumberKey]) 69 | XCTAssertNotNil(encodedObject?[ComputerLocation.DepartementKey]) 70 | XCTAssertNotNil(encodedObject?[ComputerLocation.BuildingKey]) 71 | XCTAssertNotNil(encodedObject?[ComputerLocation.RoomKey]) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /JamfKit/Sources/Models/ComputerCommand/ComputerCommand.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | /// Represents a logical command that can be executed on any hardware element manageg by Jamf. 7 | @objc(JMFKComputerCommand) 8 | public final class ComputerCommand: NSObject, Requestable, Endpoint, Subset { 9 | 10 | // MARK: - Constants 11 | 12 | public static let Endpoint = "computercommands" 13 | static let GeneralKey = "general" 14 | static let ComputersKey = "computers" 15 | 16 | // MARK: - Properties 17 | 18 | @objc 19 | public var general: ComputerCommandGeneral 20 | 21 | @objc 22 | public var computers = [UInt]() 23 | 24 | public override var description: String { 25 | return "[\(String(describing: type(of: self)))][\(general.command)]" 26 | } 27 | 28 | // MARK: - Initialization 29 | 30 | public init?(json: [String: Any], node: String = "") { 31 | guard 32 | let generalNode = json[ComputerCommand.GeneralKey] as? [String: Any], 33 | let general = ComputerCommandGeneral(json: generalNode) 34 | else { 35 | return nil 36 | } 37 | 38 | self.general = general 39 | 40 | if let computersNode = json[ComputerCommand.ComputersKey] as? [String: [String: UInt]] { 41 | computers = computersNode.flatMap { $0.value }.compactMap { $1 } 42 | } else { 43 | computers = [UInt]() 44 | } 45 | } 46 | 47 | public init?(command: String, passcode: UInt) { 48 | guard let general = ComputerCommandGeneral(command: command, passcode: passcode) else { 49 | return nil 50 | } 51 | 52 | self.general = general 53 | } 54 | 55 | // MARK: - Functions 56 | 57 | public func toJSON() -> [String: Any] { 58 | var json = [String: Any]() 59 | 60 | json[ComputerCommand.GeneralKey] = general.toJSON() 61 | 62 | if !computers.isEmpty { 63 | let rawComputers = computers.map { computerIdentifier -> [String: [String: UInt]] in 64 | return [ 65 | "computer": [ 66 | "id": computerIdentifier 67 | ] 68 | ] 69 | } 70 | 71 | json[ComputerCommand.ComputersKey] = rawComputers 72 | } 73 | 74 | return json 75 | } 76 | } 77 | 78 | // MARK: - Creatable 79 | 80 | extension ComputerCommand: Creatable { 81 | 82 | public func createRequest() -> URLRequest? { 83 | return SessionManager.instance.createRequest(for: self, key: ComputerCommandGeneral.CommandKey, value: general.command) 84 | } 85 | } 86 | 87 | // MARK: - Readable 88 | 89 | extension ComputerCommand: Readable { 90 | 91 | public static func readAllRequest() -> URLRequest? { 92 | return getReadAllRequest() 93 | } 94 | 95 | public static func readRequest(identifier: String) -> URLRequest? { 96 | return nil 97 | } 98 | 99 | public func readRequest() -> URLRequest? { 100 | return nil 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/PreciseDateTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class PreciseDateTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "PreciseDate/" 15 | let defaultNode = "precise_date" 16 | let defaultDateValue = "2017-07-07T18:37:04.000Z" 17 | let defaultDateUTCValue = "2017-07-07T18:37:04.555-0500" 18 | 19 | var defaultDate: Date! 20 | let defaultEpoch: UInt = 1499470624555 21 | var defaultDateUTC: Date! 22 | 23 | // MARK: - Tests 24 | 25 | func testShouldInstantiateFromJSON() { 26 | let payload = self.payload(for: "precise_date", subfolder: subfolder)! 27 | 28 | let dateFormatter = DateFormatter() 29 | dateFormatter.locale = Locale(identifier: "en_US_POSIX") 30 | dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" 31 | defaultDate = dateFormatter.date(from: defaultDateValue) 32 | 33 | let dateFormatterUTC = DateFormatter() 34 | dateFormatterUTC.locale = Locale(identifier: "en_US_POSIX") 35 | dateFormatterUTC.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZ" 36 | dateFormatterUTC.timeZone = TimeZone(secondsFromGMT: 0) 37 | defaultDateUTC = dateFormatterUTC.date(from: defaultDateUTCValue) 38 | 39 | let actualValue = PreciseDate(json: payload, node: defaultNode) 40 | 41 | XCTAssertNotNil(actualValue) 42 | XCTAssertEqual(actualValue?.date, defaultDate) 43 | XCTAssertEqual(actualValue?.epoch, defaultEpoch) 44 | XCTAssertEqual(actualValue?.internalEpoch?.uintValue, defaultEpoch) 45 | XCTAssertEqual(actualValue?.dateUTC, defaultDateUTC) 46 | } 47 | 48 | func testShouldInstantiateFromIncompleteJSON() { 49 | let payload = self.payload(for: "precise_date_incomplete", subfolder: subfolder)! 50 | 51 | let dateFormatter = DateFormatter() 52 | dateFormatter.locale = Locale(identifier: "en_US_POSIX") 53 | dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" 54 | defaultDate = dateFormatter.date(from: defaultDateValue) 55 | 56 | let actualValue = PreciseDate(json: payload, node: defaultNode) 57 | 58 | XCTAssertNotNil(actualValue) 59 | XCTAssertEqual(actualValue?.date, defaultDate) 60 | XCTAssertNil(actualValue?.epoch) 61 | XCTAssertEqual(actualValue?.internalEpoch?.uintValue, 0) 62 | XCTAssertNil(actualValue?.dateUTC) 63 | } 64 | 65 | func testShouldEncodeToJSON() { 66 | let payload = self.payload(for: "precise_date", subfolder: subfolder)! 67 | 68 | let actualValue = PreciseDate(json: payload, node: defaultNode) 69 | let encodedObject = actualValue?.toJSON() 70 | 71 | XCTAssertNotNil(encodedObject) 72 | XCTAssertEqual(encodedObject?.count, 3) 73 | XCTAssertEqual(encodedObject?[defaultNode] as? String, defaultDateValue) 74 | XCTAssertEqual(encodedObject?[defaultNode + PreciseDate.EpochKey] as? UInt, defaultEpoch) 75 | // TOFIX: Output format is not exactly the same 76 | // XCTAssertEqual(encodedObject?[defaultNode + PreciseDate.UTCKey] as? String, defaultDateUTCValue) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/HardwareGroup/HardwareGroupCriterionTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class HardwareGroupCriterionTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "HardwareGroup/" 15 | let defaultName = "Last Inventory Update" 16 | let defaultPriority: UInt = 0 17 | let defaultAndOr = "and" 18 | let defaultSearchType = "more than x days ago" 19 | let defaultValue: UInt = 7 20 | let defaultOpeningParen = false 21 | let defaultClosingParen = false 22 | 23 | // MARK: - Tests 24 | 25 | func testShouldInstantiate() { 26 | let actualValue = HardwareGroupCriterion(name: defaultName) 27 | 28 | XCTAssertNotNil(actualValue) 29 | XCTAssertEqual(actualValue?.name, defaultName) 30 | } 31 | 32 | func testShouldNotInstantiateWithInvalidParameters() { 33 | let actualValue = HardwareGroupCriterion(name: "") 34 | 35 | XCTAssertNil(actualValue) 36 | } 37 | 38 | func testShouldInitializeFromJSON() { 39 | let payload = self.payload(for: "hardware_group_criterion", subfolder: subfolder)! 40 | 41 | let actualValue = HardwareGroupCriterion(json: payload) 42 | 43 | XCTAssertNotNil(actualValue) 44 | XCTAssertEqual(actualValue?.name, defaultName) 45 | XCTAssertEqual(actualValue?.priority, defaultPriority) 46 | XCTAssertEqual(actualValue?.andOr, defaultAndOr) 47 | XCTAssertEqual(actualValue?.searchType, defaultSearchType) 48 | XCTAssertEqual(actualValue?.value, defaultValue) 49 | XCTAssertEqual(actualValue?.openingParen, defaultOpeningParen) 50 | XCTAssertEqual(actualValue?.closingParen, defaultClosingParen) 51 | } 52 | 53 | func testShouldInitializeFromEmptyJSON() { 54 | let actualValue = HardwareGroupCriterion(json: [String: Any]()) 55 | 56 | XCTAssertNotNil(actualValue) 57 | XCTAssertEqual(actualValue?.name, "") 58 | XCTAssertEqual(actualValue?.priority, 0) 59 | XCTAssertEqual(actualValue?.andOr, "") 60 | XCTAssertEqual(actualValue?.searchType, "") 61 | XCTAssertEqual(actualValue?.value, 0) 62 | XCTAssertEqual(actualValue?.openingParen, false) 63 | XCTAssertEqual(actualValue?.closingParen, false) 64 | } 65 | 66 | func testShouldEncodeToJSON() { 67 | let payload = self.payload(for: "hardware_group_criterion", subfolder: subfolder)! 68 | 69 | let actualValue = HardwareGroupCriterion(json: payload) 70 | let encodedObject = actualValue?.toJSON() 71 | 72 | XCTAssertNotNil(encodedObject) 73 | XCTAssertEqual(encodedObject?.count, 7) 74 | XCTAssertNotNil(encodedObject?[HardwareGroupCriterion.NameKey]) 75 | XCTAssertNotNil(encodedObject?[HardwareGroupCriterion.PriorityKey]) 76 | XCTAssertNotNil(encodedObject?[HardwareGroupCriterion.AndOrKey]) 77 | XCTAssertNotNil(encodedObject?[HardwareGroupCriterion.SearchTypeKey]) 78 | XCTAssertNotNil(encodedObject?[HardwareGroupCriterion.ValueKey]) 79 | XCTAssertNotNil(encodedObject?[HardwareGroupCriterion.OpeningParenKey]) 80 | XCTAssertNotNil(encodedObject?[HardwareGroupCriterion.ClosingParenKey]) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/ComputerCommand/ComputerCommandTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ComputerCommandTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "ComputerCommand/" 15 | let defaultCommand = "command" 16 | let defaultPasscode: UInt = 123456 17 | 18 | // MARK: - Tests 19 | 20 | func testShouldInstantiate() { 21 | let actualValue = ComputerCommand(command: defaultCommand, passcode: defaultPasscode) 22 | 23 | XCTAssertNotNil(actualValue) 24 | XCTAssertEqual(actualValue?.general.command, defaultCommand) 25 | XCTAssertEqual(actualValue?.general.passcode, defaultPasscode) 26 | } 27 | 28 | func testShouldNotInstantiateWithInvalidParameters() { 29 | let actualValue = ComputerCommand(command: "", passcode: defaultPasscode) 30 | 31 | XCTAssertNil(actualValue) 32 | } 33 | 34 | func testShouldInitializeFromJSON() { 35 | let payload = self.payload(for: "computer_command", subfolder: subfolder)! 36 | 37 | let actualValue = ComputerCommand(json: payload) 38 | 39 | XCTAssertNotNil(actualValue) 40 | XCTAssertEqual(actualValue?.description, "[ComputerCommand][\(defaultCommand)]") 41 | XCTAssertEqual(actualValue?.general.command, defaultCommand) 42 | XCTAssertEqual(actualValue?.general.passcode, defaultPasscode) 43 | XCTAssertEqual(actualValue?.computers.count, 1) 44 | } 45 | 46 | func testShouldInitializeFromIncompleteJSON() { 47 | let payload = self.payload(for: "computer_command_incomplete", subfolder: subfolder)! 48 | 49 | let actualValue = ComputerCommand(json: payload) 50 | 51 | XCTAssertNotNil(actualValue) 52 | XCTAssertEqual(actualValue?.description, "[ComputerCommand][\(defaultCommand)]") 53 | XCTAssertEqual(actualValue?.general.command, defaultCommand) 54 | XCTAssertEqual(actualValue?.general.passcode, defaultPasscode) 55 | XCTAssertEqual(actualValue?.computers.count, 0) 56 | } 57 | 58 | func testShouldInitializeFromInvalidJSON() { 59 | let payload = self.payload(for: "computer_command_invalid", subfolder: subfolder)! 60 | 61 | let actualValue = ComputerCommand(json: payload) 62 | 63 | XCTAssertNil(actualValue) 64 | } 65 | 66 | func testShouldEncodeToJSON() { 67 | let payload = self.payload(for: "computer_command", subfolder: subfolder)! 68 | 69 | let actualValue = ComputerCommand(json: payload) 70 | let encodedObject = actualValue?.toJSON() 71 | 72 | XCTAssertNotNil(encodedObject) 73 | XCTAssertEqual(encodedObject?.count, 2) 74 | XCTAssertNotNil(encodedObject?[ComputerCommand.GeneralKey]) 75 | XCTAssertNotNil(encodedObject?[ComputerCommand.ComputersKey]) 76 | 77 | let generalNode = encodedObject?[ComputerCommand.GeneralKey] as! [String: Any] 78 | XCTAssertNotNil(generalNode[ComputerCommandGeneral.CommandKey]) 79 | XCTAssertNotNil(generalNode[ComputerCommandGeneral.PasscodeKey]) 80 | 81 | let computersNode = encodedObject?[ComputerCommand.ComputersKey] as! [[String: [String: UInt]]] 82 | XCTAssertEqual(computersNode.count, 1) 83 | XCTAssertEqual(computersNode[0]["computer"]!["id"], 1) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | education, socio-economic status, nationality, personal appearance, race, 10 | religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at damien.rivet@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/PartitionTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class PartitionTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "Partition/" 15 | let defaultName = "partition" 16 | let defaultSizeInGigabytes: UInt = 50 17 | let defaultMaximumPercentage: UInt = 25 18 | let defaultFormat = "Journaled HFS+" 19 | let defaultIsRestorePartition = true 20 | let defaultComputerConfiguration = "Recovery HD" 21 | let defaultReimage = true 22 | let defaultAppendToName = "suffix" 23 | 24 | // MARK: - Tests 25 | 26 | func testShouldInstantiate() { 27 | let actualValue = Partition(name: defaultName) 28 | 29 | XCTAssertNotNil(actualValue) 30 | XCTAssertEqual(actualValue?.name, defaultName) 31 | } 32 | 33 | func testShouldNotInstantiateWithInvalidParameters() { 34 | let actualValue = Partition(name: "") 35 | 36 | XCTAssertNil(actualValue) 37 | } 38 | 39 | func testShouldInitializeFromJSON() { 40 | let payload = self.payload(for: "partition", subfolder: subfolder)! 41 | 42 | let actualValue = Partition(json: payload) 43 | 44 | XCTAssertNotNil(actualValue) 45 | XCTAssertEqual(actualValue?.name, defaultName) 46 | XCTAssertEqual(actualValue?.sizeInGigabytes, defaultSizeInGigabytes) 47 | XCTAssertEqual(actualValue?.maximumPercentage, defaultMaximumPercentage) 48 | XCTAssertEqual(actualValue?.format, defaultFormat) 49 | XCTAssertEqual(actualValue?.isRestorePartition, defaultIsRestorePartition) 50 | XCTAssertEqual(actualValue?.computerConfiguration, defaultComputerConfiguration) 51 | XCTAssertEqual(actualValue?.reimage, defaultReimage) 52 | XCTAssertEqual(actualValue?.appendToName, defaultAppendToName) 53 | } 54 | 55 | func testShouldInitializeFromEmptyJSON() { 56 | let actualValue = Partition(json: [String: Any]()) 57 | 58 | XCTAssertNotNil(actualValue) 59 | XCTAssertEqual(actualValue?.name, "") 60 | XCTAssertEqual(actualValue?.sizeInGigabytes, 0) 61 | XCTAssertEqual(actualValue?.maximumPercentage, 0) 62 | XCTAssertEqual(actualValue?.format, "") 63 | XCTAssertEqual(actualValue?.isRestorePartition, false) 64 | XCTAssertEqual(actualValue?.computerConfiguration, "") 65 | XCTAssertEqual(actualValue?.reimage, false) 66 | XCTAssertEqual(actualValue?.appendToName, "") 67 | } 68 | 69 | func testShouldEncodeToJSON() { 70 | let payload = self.payload(for: "partition", subfolder: subfolder)! 71 | 72 | let actualValue = Partition(json: payload) 73 | let encodedObject = actualValue?.toJSON() 74 | 75 | XCTAssertNotNil(encodedObject) 76 | XCTAssertEqual(encodedObject?.count, 8) 77 | XCTAssertNotNil(encodedObject?[Partition.NameKey]) 78 | XCTAssertNotNil(encodedObject?[Partition.SizeGigabytesKey]) 79 | XCTAssertNotNil(encodedObject?[Partition.MaximumPercentageKey]) 80 | XCTAssertNotNil(encodedObject?[Partition.FormatKey]) 81 | XCTAssertNotNil(encodedObject?[Partition.IsRestorePartitionKey]) 82 | XCTAssertNotNil(encodedObject?[Partition.ComputerConfigurationKey]) 83 | XCTAssertNotNil(encodedObject?[Partition.ReimageKey]) 84 | XCTAssertNotNil(encodedObject?[Partition.AppendToNameKey]) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/ConfigurationProfile/ConfigurationProfileGeneralTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class ConfigurationProfileGeneralTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "ConfigurationProfileGeneral/" 15 | let defaultIdentifier: UInt = 12345 16 | let defaultName = "Configuration Profile" 17 | let defaultDescription = "Description" 18 | let defaultUuid = "88F8C1DB-D92A-4D10-95FB-CE7EDE82B93E" 19 | let defaultRedeployOnUpdate = "Newly Assigned" 20 | let defaultPayloads = "Payloads" 21 | 22 | 23 | // MARK: - Tests 24 | 25 | func testShouldInstantiate() { 26 | let actualValue = ConfigurationProfileGeneral(identifier: defaultIdentifier, name: defaultName) 27 | 28 | XCTAssertNotNil(actualValue) 29 | XCTAssertNil(actualValue?.site) 30 | XCTAssertNil(actualValue?.category) 31 | XCTAssertEqual(actualValue?.uuid, "") 32 | XCTAssertEqual(actualValue?.redeployOnUpdate, "") 33 | XCTAssertEqual(actualValue?.payloads, "") 34 | } 35 | 36 | func testShouldNotInstantiateWithInvalidParameters() { 37 | let actualValue = ConfigurationProfileGeneral(identifier: defaultIdentifier, name: "") 38 | 39 | XCTAssertNil(actualValue) 40 | } 41 | 42 | func testShouldInitializeFromJSON() { 43 | let payload = self.payload(for: "configuration_profile_general_valid", subfolder: subfolder)! 44 | 45 | let actualValue = ConfigurationProfileGeneral(json: payload) 46 | 47 | XCTAssertNotNil(actualValue) 48 | XCTAssertEqual(actualValue?.desc, defaultDescription) 49 | XCTAssertNotNil(actualValue?.site) 50 | XCTAssertNotNil(actualValue?.category) 51 | XCTAssertEqual(actualValue?.uuid, defaultUuid) 52 | XCTAssertEqual(actualValue?.redeployOnUpdate, defaultRedeployOnUpdate) 53 | XCTAssertEqual(actualValue?.payloads, defaultPayloads) 54 | } 55 | 56 | func testShouldNotInitializeFromInvalidJSON() { 57 | let payload = self.payload(for: "configuration_profile_general_invalid", subfolder: subfolder)! 58 | 59 | let actualValue = ConfigurationProfileGeneral(json: payload) 60 | 61 | XCTAssertNil(actualValue) 62 | } 63 | 64 | func testShouldNotInitializeFromEmptyJSON() { 65 | let actualValue = ConfigurationProfileGeneral(json: [String: Any]()) 66 | 67 | XCTAssertNil(actualValue) 68 | } 69 | 70 | func testShouldEncodeToJSON() { 71 | let payload = self.payload(for: "configuration_profile_general_valid", subfolder: subfolder)! 72 | 73 | let actualValue = ConfigurationProfileGeneral(json: payload) 74 | let encodedObject = actualValue?.toJSON() 75 | 76 | XCTAssertNotNil(encodedObject) 77 | XCTAssertEqual(encodedObject?.count, 8) 78 | XCTAssertNotNil(encodedObject?[BaseObject.CodingKeys.identifier.rawValue]) 79 | XCTAssertNotNil(encodedObject?[BaseObject.CodingKeys.name.rawValue]) 80 | XCTAssertNotNil(encodedObject?[ConfigurationProfileGeneral.DescriptionKey]) 81 | XCTAssertNotNil(encodedObject?[ConfigurationProfileGeneral.SiteKey]) 82 | XCTAssertNotNil(encodedObject?[ConfigurationProfileGeneral.CategoryKey]) 83 | XCTAssertNotNil(encodedObject?[ConfigurationProfileGeneral.UuidKey]) 84 | XCTAssertNotNil(encodedObject?[ConfigurationProfileGeneral.RedeployOnUpdateKey]) 85 | XCTAssertNotNil(encodedObject?[ConfigurationProfileGeneral.PayloadsKey]) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /JamfKit/Tests/Session/SessionManagerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class SessionManagerTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let defaultHost = "http://localhost" 15 | let defaultUsername = "username" 16 | let defaultPassword = "password" 17 | let defaultAuthorizationHeader = "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" 18 | 19 | // MARK: - Lifecycle 20 | 21 | override func tearDown() { 22 | SessionManager.instance.clearConfiguration() 23 | } 24 | 25 | // MARK: - Tests 26 | 27 | func testShouldConfigureWithValidParameters() { 28 | let defaultHost = URL(string: self.defaultHost)! 29 | 30 | try? SessionManager.instance.configure(for: self.defaultHost, username: defaultUsername, password: defaultPassword) 31 | 32 | XCTAssertEqual(SessionManager.instance.host, defaultHost) 33 | XCTAssertEqual(SessionManager.instance.username, defaultUsername) 34 | XCTAssertEqual(SessionManager.instance.password, defaultPassword) 35 | XCTAssertEqual(SessionManager.instance.authorizationHeader, defaultAuthorizationHeader) 36 | } 37 | 38 | func testShouldNotConfigureWithEmptyHost() { 39 | XCTAssertThrowsError(try SessionManager.instance.configure(for: "", username: defaultUsername, password: defaultPassword)) 40 | } 41 | 42 | func testShouldNotConfigureWithEmptyUsername() { 43 | XCTAssertThrowsError(try SessionManager.instance.configure(for: self.defaultHost, username: "", password: defaultPassword)) 44 | } 45 | 46 | func testShouldNotConfigureWithEmptyPassword() { 47 | XCTAssertThrowsError(try SessionManager.instance.configure(for: self.defaultHost, username: defaultUsername, password: "")) 48 | } 49 | 50 | func testShouldClearConfiguration() { 51 | try? SessionManager.instance.configure(for: self.defaultHost, username: defaultUsername, password: defaultPassword) 52 | 53 | SessionManager.instance.clearConfiguration() 54 | 55 | XCTAssertNil(SessionManager.instance.host) 56 | XCTAssertNil(SessionManager.instance.username) 57 | XCTAssertNil(SessionManager.instance.password) 58 | XCTAssertEqual(SessionManager.instance.authorizationHeader, "") 59 | } 60 | 61 | // func testShouldPerformThrowingConnectivityCheckWithEmptyConfiguration() { 62 | // SessionManager.instance.clearConfiguration() 63 | // 64 | // XCTAssertThrowsError(try SessionManager.instance.performConnectivityCheck { result in 65 | // XCTAssertFalse(result) 66 | // }) 67 | // } 68 | // 69 | // func testShouldPerformFailingConnectivityCheckWithEmptyHost() { 70 | // try? SessionManager.instance.configure(for: "", username: defaultUsername, password: defaultPassword) 71 | // 72 | // try? SessionManager.instance.performConnectivityCheck { result in 73 | // XCTAssertFalse(result) 74 | // } 75 | // } 76 | // 77 | // func testShouldPerformFailingConnectivityCheckWithEmptyUsername() { 78 | // try? SessionManager.instance.configure(for: self.defaultHost, username: "", password: defaultPassword) 79 | // 80 | // try? SessionManager.instance.performConnectivityCheck { result in 81 | // XCTAssertFalse(result) 82 | // } 83 | // } 84 | // 85 | // func testShouldPerformFailingConnectivityCheckWithEmptyPassword() { 86 | // try? SessionManager.instance.configure(for: self.defaultHost, username: defaultUsername, password: "") 87 | // 88 | // try? SessionManager.instance.performConnectivityCheck { result in 89 | // XCTAssertFalse(result) 90 | // } 91 | // } 92 | } 93 | -------------------------------------------------------------------------------- /JamfKit/Tests/Models/SMTPServerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2017-present JamfKit. All rights reserved. 3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information. 4 | // 5 | 6 | import XCTest 7 | 8 | @testable import JamfKit 9 | 10 | class SMTPServerTests: XCTestCase { 11 | 12 | // MARK: - Constants 13 | 14 | let subfolder = "SMTPServer/" 15 | let defaultIsEnabled = true 16 | let defaultHost = "smtp.jamfkit.com" 17 | let defaultPort: UInt = 12345 18 | let defaultTimeout: UInt = 5 19 | let defaultIsAuthorizationRequired = true 20 | let defaultUsername = "username" 21 | let defaultPassword = "password" 22 | let defaultIsSSLEnabled = true 23 | let defaultIsTLSEnabled = true 24 | let defaultSendFromName = "JamfKit SMTP Server" 25 | let defaultSendFromEmail = "smtp@jamfkit.com" 26 | 27 | // MARK: - Tests 28 | 29 | func testShouldInstantiate() { 30 | let actualValue = SMTPServer(host: defaultHost, port: defaultPort) 31 | 32 | XCTAssertNotNil(actualValue) 33 | XCTAssertEqual(actualValue?.host, defaultHost) 34 | XCTAssertEqual(actualValue?.port, defaultPort) 35 | } 36 | 37 | func testShouldNotInstantiateWithInvalidParameters() { 38 | let actualValue = SMTPServer(host: "", port: defaultPort) 39 | 40 | XCTAssertNil(actualValue) 41 | } 42 | 43 | func testShouldInitializeFromJSON() { 44 | let payload = self.payload(for: "smtp_server", subfolder: subfolder)! 45 | 46 | let actualValue = SMTPServer(json: payload) 47 | 48 | XCTAssertNotNil(actualValue) 49 | XCTAssertEqual(actualValue?.description, "[SMTPServer][\(defaultHost):\(defaultPort)]") 50 | XCTAssertEqual(actualValue?.isEnabled, defaultIsEnabled) 51 | XCTAssertEqual(actualValue?.host, defaultHost) 52 | XCTAssertEqual(actualValue?.port, defaultPort) 53 | XCTAssertEqual(actualValue?.timeout, defaultTimeout) 54 | XCTAssertEqual(actualValue?.isAuthorizationRequired, defaultIsAuthorizationRequired) 55 | XCTAssertEqual(actualValue?.username, defaultUsername) 56 | XCTAssertEqual(actualValue?.password, defaultPassword) 57 | XCTAssertEqual(actualValue?.isSSLEnabled, defaultIsSSLEnabled) 58 | XCTAssertEqual(actualValue?.isTLSEnabled, defaultIsTLSEnabled) 59 | XCTAssertEqual(actualValue?.sendFromName, defaultSendFromName) 60 | XCTAssertEqual(actualValue?.sendFromEmail, defaultSendFromEmail) 61 | } 62 | 63 | func testShouldInitializeFromEmptyJSON() { 64 | let actualValue = SMTPServer(json: [String: Any]()) 65 | 66 | XCTAssertNotNil(actualValue) 67 | XCTAssertEqual(actualValue?.description, "[SMTPServer]") 68 | } 69 | 70 | func testShouldEncodeToJSON() { 71 | let payload = self.payload(for: "smtp_server", subfolder: subfolder)! 72 | 73 | let actualValue = SMTPServer(json: payload) 74 | let encodedObject = actualValue?.toJSON() 75 | 76 | XCTAssertNotNil(encodedObject) 77 | XCTAssertEqual(encodedObject?.count, 11) 78 | XCTAssertNotNil(encodedObject?[SMTPServer.EnabledKey]) 79 | XCTAssertNotNil(encodedObject?[SMTPServer.HostKey]) 80 | XCTAssertNotNil(encodedObject?[SMTPServer.PortKey]) 81 | XCTAssertNotNil(encodedObject?[SMTPServer.TimeoutKey]) 82 | XCTAssertNotNil(encodedObject?[SMTPServer.AuthorizationRequiredKey]) 83 | XCTAssertNotNil(encodedObject?[SMTPServer.UsernameKey]) 84 | XCTAssertNotNil(encodedObject?[SMTPServer.PasswordKey]) 85 | XCTAssertNotNil(encodedObject?[SMTPServer.SslKey]) 86 | XCTAssertNotNil(encodedObject?[SMTPServer.TlsKey]) 87 | XCTAssertNotNil(encodedObject?[SMTPServer.SendFromNameKey]) 88 | XCTAssertNotNil(encodedObject?[SMTPServer.SendFromEmailKey]) 89 | } 90 | } 91 | --------------------------------------------------------------------------------