├── Graph-iOS-Swift-Snippets ├── SampleImage.png ├── Graph-iOS-Swift-Snippets.entitlements ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── AppDelegate.swift ├── EmailBody.html ├── ApplicationConstants.swift ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── MasterViewController.swift ├── Snippets.swift ├── DetailViewController.swift ├── ConnectViewController.swift ├── AuthenticationProvider.swift ├── GroupsSnippets.swift └── UserSnippets.swift ├── Podfile ├── Graph-iOS-Swift-SnippetsTests ├── testUserArgs.json ├── preTest.sh ├── Graph_iOS_Swift_SnippetsTests.swift ├── Info.plist ├── testAuthProvider.swift ├── GroupsSnippetsTest.swift └── UserSnippetsTest.swift ├── Graph-iOS-Swift-Snippets.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── Graph-iOS-Swift-Snippets.xcscheme └── project.pbxproj ├── Graph-iOS-Swift-Snippets.xcworkspace ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── contents.xcworkspacedata ├── .gitignore ├── Podfile.lock ├── License.txt ├── README-Localized ├── README-zh-cn.md ├── README-zh-tw.md ├── README-ja-jp.md ├── README-pt-br.md ├── README-es-es.md ├── README-ru-ru.md ├── README-de-de.md └── README-fr-fr.md ├── README.md └── CONTRIBUTING.md /Graph-iOS-Swift-Snippets/SampleImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/ios-swift-snippets-sample/master/Graph-iOS-Swift-Snippets/SampleImage.png -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '11.0' 2 | inhibit_all_warnings! 3 | use_frameworks! 4 | 5 | target 'Graph-iOS-Swift-Snippets' do 6 | pod 'MSGraphSDK' 7 | pod 'MSAL', '~> 0.4.0' 8 | end 9 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-SnippetsTests/testUserArgs.json: -------------------------------------------------------------------------------- 1 | { 2 | "test.clientId" : "ENTER_CLIENT_ID", 3 | "test.username" : "ENTER_USERNAME", 4 | "test.password" : "ENTER_PASSWORD" 5 | } 6 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/Graph-iOS-Swift-Snippets.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keychain-access-groups 6 | 7 | $(AppIdentifierPrefix)com.microsoft.adalcache 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-SnippetsTests/preTest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | get_script_dir () { 3 | SOURCE="${BASH_SOURCE[0]}" 4 | while [ -h "$SOURCE" ]; do 5 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 6 | SOURCE="$( readlink "$SOURCE" )" 7 | [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" 8 | done 9 | $( cd -P "$( dirname "$SOURCE" )" ) 10 | pwd 11 | } 12 | 13 | FILE="$(get_script_dir)/testUserArgs.json" 14 | 15 | /bin/cat <$FILE 16 | { 17 | "test.clientId" : "$1", 18 | "test.username" : "$2", 19 | "test.password" : "$3" 20 | } 21 | EOM 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | 3 | ## Build generated 4 | build/ 5 | DerivedData/ 6 | 7 | ## Various settings 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata/ 17 | 18 | ## Other 19 | *.moved-aside 20 | *.xcuserstate 21 | 22 | ## Obj-C/Swift specific 23 | *.hmap 24 | *.ipa 25 | *.dSYM.zip 26 | *.dSYM 27 | 28 | ## Playgrounds 29 | timeline.xctimeline 30 | playground.xcworkspace 31 | 32 | # Swift Package Manager 33 | # 34 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 35 | # Packages/ 36 | .build/ 37 | 38 | # CocoaPods 39 | # 40 | Pods/ 41 | 42 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Graph-iOS-Swift-SnippetsTests/Graph_iOS_Swift_SnippetsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Graph_iOS_Swift_SnippetsTests.swift 3 | // Graph-iOS-Swift-SnippetsTests 4 | // 5 | // Created by Jason Kim on 7/8/16. 6 | // Copyright © 2016 Jason Kim. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import Graph_iOS_Swift_Snippets 12 | 13 | class Graph_iOS_Swift_SnippetsTests: XCTestCase { 14 | 15 | override func setUp() { 16 | super.setUp() 17 | // Put setup code here. This method is called before the invocation of each test method in the class. 18 | 19 | } 20 | 21 | override func tearDown() { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | super.tearDown() 24 | } 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-SnippetsTests/Info.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 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | import UIKit 7 | import MSAL 8 | 9 | @UIApplicationMain 10 | class AppDelegate: UIResponder, UIApplicationDelegate 11 | { 12 | var window: UIWindow? 13 | 14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 15 | { 16 | return true 17 | } 18 | 19 | func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool 20 | { 21 | guard let sourceApplication = options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String else { return false } 22 | 23 | return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: sourceApplication) 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MSAL (0.4.0): 3 | - MSAL/app-lib (= 0.4.0) 4 | - MSAL/app-lib (0.4.0) 5 | - MSGraphSDK (0.10.1): 6 | - MSGraphSDK/Common (= 0.10.1) 7 | - MSGraphSDK/Extensions (= 0.10.1) 8 | - MSGraphSDK/Implementations (= 0.10.1) 9 | - MSGraphSDK/MSGraphCoreSDK (= 0.10.1) 10 | - MSGraphSDK/Common (0.10.1) 11 | - MSGraphSDK/Extensions (0.10.1): 12 | - MSGraphSDK/Implementations 13 | - MSGraphSDK/MSGraphCoreSDK 14 | - MSGraphSDK/Implementations (0.10.1): 15 | - MSGraphSDK/Common 16 | - MSGraphSDK/MSGraphCoreSDK (0.10.1): 17 | - MSGraphSDK/Common 18 | 19 | DEPENDENCIES: 20 | - MSAL (~> 0.4.0) 21 | - MSGraphSDK 22 | 23 | SPEC REPOS: 24 | https://github.com/cocoapods/specs.git: 25 | - MSAL 26 | - MSGraphSDK 27 | 28 | SPEC CHECKSUMS: 29 | MSAL: fb209227bd464771648206286eb2bcca46f438ec 30 | MSGraphSDK: 3c43eb632ca969593f1bdd5612b573e436bd3283 31 | 32 | PODFILE CHECKSUM: 3ad47728eb54cefdfb1d559e398f484d13aca6a9 33 | 34 | COCOAPODS: 1.6.1 35 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | 4 | Copyright (c) 2016 Microsoft 5 | 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/EmailBody.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Congratulations!

5 |

You just sent this email from the Snippets Sample for iOS Swift Using the Microsoft Graph SDK. How cool is that? You are well on your way to incorporating Microsoft Graph services in your apps.

6 |

Give us feedback

7 |

We'd love to get your feedback about the project. You can send your questions and suggestions to us in the issues section of the repository. 8 |

For more details on what else you can do with the Microsoft Graph endpoint in your iOS app, start with the 9 | Microsoft Graph page.

10 |

Thanks, and happy coding!

11 |

Your Microsoft Graph Development team

12 |
13 | 14 | 15 | 19 | 23 | 24 |
16 | See on GitHub 17 | 18 | 20 | Suggest on UserVoice 21 | 22 |
25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/ApplicationConstants.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | 7 | import Foundation 8 | 9 | struct ApplicationConstants 10 | { 11 | // You will set your application's clientId 12 | static let clientId = "YOUR CLIENT ID" 13 | static let authority = "https://login.microsoftonline.com/common" 14 | 15 | // Set scopes 16 | static let scopes = [ 17 | "https://graph.microsoft.com/User.Read", 18 | "https://graph.microsoft.com/User.ReadWrite", 19 | "https://graph.microsoft.com/User.ReadBasic.All", 20 | "https://graph.microsoft.com/Mail.Send", 21 | "https://graph.microsoft.com/Calendars.ReadWrite", 22 | "https://graph.microsoft.com/Mail.ReadWrite", 23 | "https://graph.microsoft.com/Files.ReadWrite", 24 | // Admin-only scopes. Uncomment these if you're running the sample with an admin work account. 25 | // You won't be able to sign in with a non-admin work account if you request these scopes. 26 | "https://graph.microsoft.com/Directory.AccessAsUser.All", 27 | "https://graph.microsoft.com/User.ReadWrite.All" 28 | ] 29 | } 30 | 31 | 32 | enum MSGraphError: Swift.Error 33 | { 34 | case NSErrorType(error: NSError) 35 | case UnexpectecError(errorString: String) 36 | } 37 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/Info.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 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | CFBundleURLTypes 50 | 51 | 52 | CFBundleTypeRole 53 | Editor 54 | CFBundleURLName 55 | $(PRODUCT_BUNDLE_IDENTIFIER) 56 | CFBundleURLSchemes 57 | 58 | msauth.com.microsoft.Graph-iOS-Swift-Snippets 59 | 60 | 61 | 62 | LSApplicationQueriesSchemes 63 | 64 | msauth 65 | msauthv2 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/MasterViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | 7 | import UIKit 8 | 9 | class MasterViewController: UITableViewController 10 | { 11 | var detailViewController: DetailViewController? 12 | var authenticationProvider: AuthenticationProvider! 13 | var snippets: Snippets! 14 | var objects = [AnyObject]() 15 | 16 | override func viewDidLoad() 17 | { 18 | super.viewDidLoad() 19 | 20 | snippets = Snippets(authenticationProvider: authenticationProvider) 21 | } 22 | 23 | override func viewWillAppear(_ animated: Bool) 24 | { 25 | super.viewWillAppear(animated) 26 | 27 | self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed 28 | } 29 | 30 | // MARK: - Segues 31 | 32 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) 33 | { 34 | if segue.identifier == "showDetail" { 35 | if let indexPath = self.tableView.indexPathForSelectedRow { 36 | let snippet = snippets[indexPath.section][indexPath.row] 37 | let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController 38 | 39 | controller.snippet = snippet 40 | controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem 41 | controller.navigationItem.leftItemsSupplementBackButton = true 42 | } 43 | } 44 | } 45 | 46 | @IBAction func disconnect(_ sender: Any) 47 | { 48 | authenticationProvider.disconnect() 49 | self.navigationController?.splitViewController?.dismiss(animated: true, completion: nil) 50 | } 51 | 52 | // MARK: - UITableViewController 53 | 54 | override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 55 | { 56 | return snippets[section].name 57 | } 58 | 59 | override func numberOfSections(in tableView: UITableView) -> Int 60 | { 61 | return snippets.count 62 | } 63 | 64 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 65 | { 66 | return snippets[section].count 67 | } 68 | 69 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 70 | { 71 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 72 | 73 | let snippet = snippets[indexPath.section][indexPath.row] 74 | 75 | cell.textLabel!.text = snippet.name 76 | if snippet.needAdminAccess { 77 | cell.detailTextLabel!.text = "Need admin access" 78 | } else { 79 | cell.detailTextLabel!.text = "" 80 | } 81 | 82 | return cell 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /README-Localized/README-zh-cn.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-365 5 | - office-outlook 6 | - ms-graph 7 | languages: 8 | - swift 9 | extensions: 10 | contentType: samples 11 | technologies: 12 | - Microsoft Graph 13 | services: 14 | - Office 365 15 | - Outlook 16 | - Groups 17 | platforms: 18 | - iOS 19 | createdDate: 5/26/2016 8:08:35 AM 20 | --- 21 | # Microsoft Graph iOS Swift 代码段示例 22 | 23 | ## 目录 24 | 25 | - [简介](#introduction) 26 | - [先决条件](#prerequisites) 27 | - [注册和配置应用](#register-and-configure-the-app) 28 | - [构建和调试](#build-and-debug) 29 | - [运行示例](#running-the-sample) 30 | 31 | ## 简介 32 | 33 | 本示例包含介绍如何使用 Microsoft Graph SDK 以发送电子邮件、管理组和使用 Office 365 数据执行其他活动的代码段存储库。它使用[适用于 iOS 的 Microsoft Graph SDK](https://github.com/microsoftgraph/msgraph-sdk-ios) 以结合使用由 Microsoft Graph 返回的数据。 34 | 35 | 此存储库介绍如何通过在 iOS 应用中向 Microsoft Graph API 生成 HTTP 请求来访问多个资源,包括 Microsoft Azure Active Directory (AD) 和 Office 365 API。 36 | 37 | 这些代码段简单且是自包含的,你可以在任何合适的时间将其复制并粘贴到你自己的代码中,或将其作为学习如何使用适用于 iOS 的 Microsoft Graph SDK 的资源。 38 | 39 | **注意:** 如果可能,请通过“非工作”或测试帐户使用该示例。该示例并非总能清理邮箱和日历中创建的对象。此时,需要手动删除示例邮件和日历事件。此外,请注意获取和发送邮件的代码段和其中的获取、创建、更新和删除事件在所有个人帐户中不可用。只有在这些帐户更新至使用 v2 身份验证终结点时,这些操作才可用。 40 | 41 | ## 先决条件 42 | 43 | 此示例要求如下: 44 | 45 | - [Xcode](https://developer.apple.com/xcode/downloads/) 版本 10.2.1 46 | - 安装 [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) 成为依存关系管理器。 47 | - Microsoft 工作或个人电子邮件帐户,例如 Office 365 或 outlook.com、hotmail.com 等。你可以注册 [Office 365 开发人员订阅](https://aka.ms/devprogramsignup),其中包含你开始构建 Office 365 应用所需的资源。 48 | 49 | ## 注册和配置应用 50 | 51 | 1. 打开浏览器,并导航到 [Azure Active Directory 管理中心](https://aad.portal.azure.com),然后使用**个人帐户**(亦称为“Microsoft 帐户”)或**工作/学校帐户**登录。 52 | 53 | 1. 选择左侧导航栏中的“Azure Active Directory”,再选择“管理”下的“应用注册”。 54 | 55 | 1. 选择“新注册”。在“注册应用”页上,按如下方式设置值。 56 | 57 | - 将“名称”设置为 `Swift 代码段示例`。 58 | - 将“受支持的帐户类型”设置为“任何组织目录中的帐户和个人 Microsoft 帐户”。 59 | - 在“重定向 URI”中,将下拉列表更改为“公共客户端(移动和桌面)”,然后将值设为 `msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth`. 60 | 61 | 1. 选择“注册”。在“Swift 代码段示例”页上,复制并保存“应用程序(客户端) ID”的值,将在下一步中用到它。 62 | 63 | ## 构建和调试 64 | 65 | 1. 克隆该存储库 66 | 67 | 1. 打开**终端**,然后导航到该项目的根。输入下面的命令来安装依赖项。 68 | 69 | ```Shell 70 | pod install 71 | ``` 72 | 73 | 1. 打开 Xcode 中的 **Graph-iOS-Swift-Snippets.xcworkspace**。 74 | 75 | 1. 打开 **ApplicationConstants.swift**。将 `ENTER_CLIENT_ID` 替换为你从注册应用中获得的应用程序 ID。 76 | 77 | ```swift 78 | // You will set your application's clientId 79 | static let clientId = "ENTER_CLIENT_ID" 80 | ``` 81 | 82 | 1. 运行示例。 83 | 84 | ## 运行示例 85 | 86 | 启动时,应用将显示常见用户任务列表。这些任务可以基于帐户类型和权限级别运行,并在注释中进行了说明: 87 | 88 | - 适用于工作或学校以及个人帐户的任务,如接收和发送电子邮件、创建文件等。 89 | - 仅适用于工作或学校帐户的任务,如获取用户的管理器或帐户照片。 90 | - 仅适用于具有管理权限的工作或学校帐户的任务,如获取组成员或新建用户帐户。 91 | 92 | 选择想要执行的任务并对其单击以运行。请注意,如果未使用对所选任务适用的权限的帐户进行登录,则会失败。例如,如果在组织中没有管理员特权的帐户中运行某个特定的代码段(如获取所有租户组),则该操作会失败。或者,如果使用个人帐户进行登录并尝试获取登录用户的管理器,则该操作会失败。 93 | 94 | ## 参与 95 | 96 | 如果想要参与本示例,请参阅 [CONTRIBUTING.MD](/CONTRIBUTING.md)。 97 | 98 | 此项目已采用 [Microsoft 开放源代码行为准则](https://opensource.microsoft.com/codeofconduct/)。有关详细信息,请参阅[行为准则常见问题解答](https://opensource.microsoft.com/codeofconduct/faq/)。如有其他任何问题或意见,也可联系 [opencode@microsoft.com](mailto:opencode@microsoft.com)。 99 | 100 | ## 版权信息 101 | 102 | 版权所有 (c) 2016 Microsoft。保留所有权利。 103 | -------------------------------------------------------------------------------- /README-Localized/README-zh-tw.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-365 5 | - office-outlook 6 | - ms-graph 7 | languages: 8 | - swift 9 | extensions: 10 | contentType: samples 11 | technologies: 12 | - Microsoft Graph 13 | services: 14 | - Office 365 15 | - Outlook 16 | - Groups 17 | platforms: 18 | - iOS 19 | createdDate: 5/26/2016 8:08:35 AM 20 | --- 21 | # Microsoft Graph iOS Swift 程式碼片段範例 22 | 23 | ## 目錄 24 | 25 | - [簡介](#introduction) 26 | - [必要條件](#prerequisites) 27 | - [註冊和設定應用程式](#register-and-configure-the-app) 28 | - [建置和偵錯](#build-and-debug) 29 | - [執行範例](#running-the-sample) 30 | 31 | ## 簡介 32 | 33 | 這個範例包含程式碼片段的儲存機制,顯示如何使用 Microsoft Graph SDK 來傳送電子郵件、管理群組,以及執行其他使用 Office 365 資料的活動。它會使用 [Microsoft Graph SDK for iOS](https://github.com/microsoftgraph/msgraph-sdk-ios),使用 Microsoft Graph 所傳回的資料。 34 | 35 | 這個儲存機制會示範如何在 iOS 應用程式中向 Microsoft Graph API 發出 HTTP 要求,以存取多個資源 (包括 Microsoft Azure Active Directory (AD) 和 Office 365 API)。 36 | 37 | 這些程式碼片段簡單且獨立,您可以適當地複製並貼到自己的程式碼,或使用它們做為資源來學習如何使用 Microsoft Graph SDK for iOS。 38 | 39 | **注意事項:** 請盡可能以「非工作」或測試帳戶來使用這個範例。範例不會一律清除您的信箱和行事曆中建立的物件。目前,您必須手動移除範例郵件及行事曆事件。另請注意取得和傳送訊息的程式碼片段,以及取得、建立、更新和刪除事件的程式碼片段不適用於所有個人帳戶。當這些帳戶升級為使用 v2 驗證端點時,這些作業最終可以運作。 40 | 41 | ## 必要條件 42 | 43 | 此範例需要下列項目: 44 | 45 | - [Xcode](https://developer.apple.com/xcode/downloads/)版本 10.2.1 46 | - 安裝 [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) 做為相依性管理員。 47 | - Microsoft 工作或個人電子郵件帳戶,例如 Office 365,或 outlook.com、hotmail.com 等等。您可以註冊 [Office 365 開發人員訂用帳戶](https://aka.ms/devprogramsignup),其中包含開始建置 Office 365 應用程式所需的資源。 48 | 49 | ## 註冊和設定應用程式 50 | 51 | 1. 開啟瀏覽器並瀏覽至[Azure Active Directory 管理中心](https://aad.portal.azure.com)並登入使用**個人帳戶**(也稱為:Microsoft 帳戶)或**公司或學校帳戶**。 52 | 53 | 1. 在左側導覽中選取 **Azure Active Directory**,然後在**管理**下選取**應用程式註冊**。 54 | 55 | 1. 選取 **新增註冊**。在**註冊應用程式**頁面上,如下所示設定數值。 56 | 57 | - 設定**名稱**到`迅速的程式碼片段範例`。 58 | - 在 **支援的帳戶類型**底下,選取 **任何組織目錄中的帳戶及個人的 Microsoft 帳戶**。 59 | - 在**重新導向 URI**,變更下拉式清單至**公用用戶端(行動裝置及電腦)**,並將值設定為`msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth`。 60 | 61 | 1. 選擇**註冊**。在**快速的程式碼片段範例**頁面上,複製**應用程式(用戶端)識別碼**的值,儲存起來,在下一個步驟會需要它。 62 | 63 | ## 建置和偵錯 64 | 65 | 1. 複製此儲存機制 66 | 67 | 1. 開啟**終端機**瀏覽至專案的根目錄。執行下列命令以安裝相依性。 68 | 69 | ```Shell 70 | pod install 71 | ``` 72 | 73 | 1. 在 Xcode 中開啟 **Graph-iOS-Swift-Snippets.xcworkspace**。 74 | 75 | 1. 開啟 **ApplicationConstants.swift**。用`ENTER_CLIENT_ID`取代註冊您的應用程式時所提供的應用程式識別碼。 76 | 77 | ```swift 78 | // You will set your application's clientId 79 | static let clientId = "ENTER_CLIENT_ID" 80 | ``` 81 | 82 | 1. 執行範例。 83 | 84 | ## 執行範例 85 | 86 | 啟動時,應用程式會顯示一般使用者工作的清單。這些工作可以根據帳戶類型和權限層級執行,並且在註解中附註︰ 87 | 88 | - 適用於工作或學校和個人帳戶的工作,例如取得和傳送電子郵件、建立檔案等等。 89 | - 只適用於工作或學校帳戶的工作,例如取得使用者的經理或帳戶相片。 90 | - 只適用於具有管理權限的工作或學校帳戶的工作,例如取得群組成員,或建立新的使用者帳戶。 91 | 92 | 選取您想要執行的工作,並且按一下它以執行。請注意,如果您登入沒有工作的適用權限的帳戶,您選取的工作就會失敗。例如,如果嘗試從組織中沒有系統管理權限的帳戶,執行特定的程式碼片段 (例如取得所有租用戶群組),則作業會失敗。或者,如果您登入個人帳戶,並且嘗試取得已登入使用者的主管,也會失敗。 93 | 94 | ## 參與 95 | 96 | 如果您想要參與這個範例,請參閱 [CONTRIBUTING.MD](/CONTRIBUTING.md)。 97 | 98 | 此專案已採用[Microsoft 開放原始碼管理辦法](https://opensource.microsoft.com/codeofconduct/)。如需詳細資訊,請參閱[管理辦法常見問題集](https://opensource.microsoft.com/codeofconduct/faq/),如果有其他問題或意見,請連絡 [opencode@microsoft.com](mailto:opencode@microsoft.com)。 99 | 100 | ## 著作權 101 | 102 | Copyright (c) 2016 Microsoft.著作權所有,並保留一切權利。 103 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/Snippets.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | 7 | import Foundation 8 | import MSGraphSDK 9 | 10 | // MARK: - Enum Result 11 | enum Result 12 | { 13 | case Success(displayText: String?) 14 | case SuccessDownloadImage(displayImage: UIImage?) 15 | case Failure(error: MSGraphError) 16 | } 17 | 18 | // MARK: - Protocol Snippet 19 | protocol Snippet 20 | { 21 | func execute(with completion: @escaping (_ result: Result) -> Void) 22 | 23 | var needAdminAccess: Bool { get } 24 | var name: String { get } 25 | } 26 | 27 | // MARK: - Snippet group 28 | struct SnippetSection 29 | { 30 | let name: String 31 | let snippets: [Snippet] 32 | 33 | var count: Int 34 | { 35 | get { return snippets.count } 36 | } 37 | 38 | subscript(index: Int) -> Snippet 39 | { 40 | get { return snippets[index] } 41 | } 42 | } 43 | 44 | // MARK: - Snippets 45 | struct Snippets 46 | { 47 | static var graphClient: MSGraphClient = { 48 | return MSGraphClient.defaultClient() 49 | }() 50 | 51 | let snippetSections: [SnippetSection] 52 | 53 | init(authenticationProvider: MSAuthenticationProvider) 54 | { 55 | let userArray = SnippetSection(name: "User", 56 | snippets: [ 57 | GetMe(), 58 | GetUsers(), 59 | GetDrive(), 60 | GetEvents(), 61 | CreateEvent(), 62 | UpdateEvent(), 63 | DeleteEevnt(), 64 | GetMessages(), 65 | SendMessage(), 66 | SendMessageHTML(), 67 | GetUserFiles(), 68 | CreateTextFile(), 69 | CreateFolder(), 70 | UploadFile(), 71 | DownloadFile(), 72 | UpdateFile(), 73 | RenameFile(), 74 | DeleteFile(), 75 | GetManager(), 76 | GetDirects(), 77 | GetPhoto(), 78 | GetPhotoValue(), 79 | ]) 80 | 81 | let groupsArray = SnippetSection(name: "Groups", 82 | snippets: [ 83 | CreateUser(), 84 | GetUserGroups(), 85 | GetAllGroups(), 86 | GetSingleGroup(), 87 | GetMembers(), 88 | GetOwners(), 89 | CreateGroup(), 90 | UpdateGroup(), 91 | DeleteGroup() 92 | ]) 93 | 94 | snippetSections = [userArray, groupsArray] 95 | MSGraphClient.setAuthenticationProvider(authenticationProvider) 96 | } 97 | 98 | var count: Int 99 | { 100 | get { return snippetSections.count } 101 | } 102 | 103 | subscript(index: Int) -> SnippetSection 104 | { 105 | get { return snippetSections[index] } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /README-Localized/README-ja-jp.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-365 5 | - office-outlook 6 | - ms-graph 7 | languages: 8 | - swift 9 | extensions: 10 | contentType: samples 11 | technologies: 12 | - Microsoft Graph 13 | services: 14 | - Office 365 15 | - Outlook 16 | - Groups 17 | platforms: 18 | - iOS 19 | createdDate: 5/26/2016 8:08:35 AM 20 | --- 21 | # Microsoft Graph iOS Swift スニペットのサンプル 22 | 23 | ## 目次 24 | 25 | - [はじめに](#introduction) 26 | - [前提条件](#prerequisites) 27 | - [アプリを登録して構成する](#register-and-configure-the-app) 28 | - [ビルドとデバッグ](#build-and-debug) 29 | - [サンプルの実行](#running-the-sample) 30 | 31 | ## はじめに 32 | 33 | このサンプルには、メールの送信、グループの管理、Office 365 データを使用した他のアクティビティの実行に Microsoft Graph SDK を使用する方法を示すコード スニペットのリポジトリが含まれています。[Microsoft Graph SDK for iOS](https://github.com/microsoftgraph/msgraph-sdk-ios) を使用して、Microsoft Graph が返すデータを操作します。 34 | 35 | このリポジトリでは、iOS アプリで Microsoft Graph API への HTTP 要求を実行して、Microsoft Azure Active Directory (AD) と Office 365 API などの複数のリソースにアクセスする方法を示します。 36 | 37 | これらのスニペットは、簡潔な自己完結型であり、必要に応じて、コピーして独自のコードに貼り付けたり、Microsoft Graph SDK for iOS の使用方法を学習するためのリソースとして使用したりすることができます。 38 | 39 | **注:** 可能であれば、"職場以外"のアカウントまたはテスト アカウントでこのサンプルを使用してください。サンプルでは、メールボックスと予定表で作成されたオブジェクトが常にクリーンアップされるとは限りません。現時点では、手動でサンプルのメールと予定表イベントを削除する必要があります。また、メッセージを送受信し、イベントを取得、作成、更新および削除するスニペットは、一部の個人用アカウントでは操作できないことにも注意してください。これらの操作は、それらのアカウントが更新されて v2 認証エンドポイントで操作できるようになったときに、最終的に機能するようになります。 40 | 41 | ## 前提条件 42 | 43 | このサンプルを実行するには次のものが必要です。 44 | 45 | - [Xcode](https://developer.apple.com/xcode/downloads/) バージョン 10.2.1 46 | - 依存関係マネージャーとしての [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) のインストール。 47 | - Office 365、outlook.com、hotmail.com などの、Microsoft の職場または個人用のメール アカウント。Office 365 アプリのビルドを開始するために必要なリソースを含む [Office 365 Developer サブスクリプション](https://aka.ms/devprogramsignup)にサインアップできます。 48 | 49 | ## アプリを登録して構成する 50 | 51 | 1. ブラウザーを開き、[Azure Active Directory 管理センター](https://aad.portal.azure.com)へ移動して、**個人用アカウント** (別名: Microsoft アカウント)、または**職場/学校アカウント**を使用してログインします。 52 | 53 | 1. 左側のナビゲーションで **\[Azure Active Directory]** を選択し、それから **\[管理]** で **\[アプリの登録]** を選択します。 54 | 55 | 1. **\[新規登録]** を選択します。**\[アプリケーションの登録]** ページで、次のように値を設定します。 56 | 57 | - **\[名前]** を `[Swift スニペットのサンプル]` に設定します。 58 | - **\[サポートされているアカウントの種類]** を **\[任意の組織のディレクトリ内のアカウントと個人用の Microsoft アカウント]** に設定します。 59 | - **\[リダイレクト URI]** で、ドロップ ダウンを **\[パブリック クライアント (モバイルとデスクトップ)]** に変更し、値を `msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth` に設定します。 60 | 61 | 1. **\[登録]** を選択します。**\[Swift スニペットのサンプル]** ページで、**\[アプリケーション (クライアント) ID]** の値をコピーして保存し、次の手順に移ります。 62 | 63 | ## ビルドとデバッグ 64 | 65 | 1. このリポジトリの複製を作成する 66 | 67 | 1. **\[ターミナル]** を開いて、プロジェクトのルート フォルダーに移動します。次のコマンドを実行して、依存関係をインストールします。 68 | 69 | ```Shell 70 | pod install 71 | ``` 72 | 73 | 1. Xcode で **Graph-iOS-Swift-Snippets.xcworkspace** を開きます。 74 | 75 | 1. **ApplicationConstants.swift** を開きます。`ENTER_CLIENT_ID` を、アプリを登録したときに取得したアプリケーション ID に置き換えます。 76 | 77 | ```swift 78 | // You will set your application's clientId 79 | static let clientId = "ENTER_CLIENT_ID" 80 | ``` 81 | 82 | 1. サンプルを実行します。 83 | 84 | ## サンプルの実行 85 | 86 | 起動すると、共通のユーザー タスクの一覧がアプリに表示されます。これらのタスクは、アカウントの種類とアクセス許可のレベルに基づいて実行でき、コメントに記載されています: 87 | 88 | - メールの送受信、ファイルの作成など、職場または学校のアカウントおよび個人用アカウントの両方に適用可能なタスク。 89 | - ユーザーの上司またはアカウントの写真の取得など、職場または学校のアカウントにのみ適用可能なタスク。 90 | - グループ メンバーの取得または新しいユーザーの作成など、管理アクセス許可を持つ職場または学校のアカウントにのみ適用可能なタスク。 91 | 92 | 実行するタスクを選択し、それをクリックして実行します。選択したタスクに適用可能なアクセス許可のないアカウントでログインすると、タスクが失敗しますので注意してください。たとえば、組織内の管理権限のないアカウントからすべてのテナント グループを取得するなど、特定のスニペットを実行しようとすると、その操作は失敗します。または、個人用アカウントでログインしている場合にサインインしているユーザーの上司を取得しようとすると、失敗します。 93 | 94 | ## 投稿 95 | 96 | このサンプルに投稿する場合は、[CONTRIBUTING.MD](/CONTRIBUTING.md) を参照してください。 97 | 98 | このプロジェクトでは、[Microsoft オープン ソース倫理規定](https://opensource.microsoft.com/codeofconduct/)が採用されています。詳細については、「[倫理規定の FAQ](https://opensource.microsoft.com/codeofconduct/faq/)」を参照してください。また、その他の質問やコメントがあれば、[opencode@microsoft.com](mailto:opencode@microsoft.com) までお問い合わせください。 99 | 100 | ## 著作権 101 | 102 | Copyright (c) 2016 Microsoft.All rights reserved. 103 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-SnippetsTests/testAuthProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // testAuthProvider.swift 3 | // Graph-iOS-Swift-Connect 4 | // 5 | // Created by Jason Kim on 6/23/16. 6 | // Copyright © 2016 Jason Kim. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @testable import Graph_iOS_Swift_Snippets 12 | 13 | class testAuthProvider: NSObject, MSAuthenticationProvider { 14 | 15 | var accessToken: String? 16 | var userEmail: String! 17 | var domainName: String! 18 | 19 | let contentType = "application/x-www-form-urlencoded" 20 | let grantType = "password" 21 | let tokenEndPoint = "https://login.microsoftonline.com/common/oauth2/token" 22 | let requestType = "POST" 23 | let resourceId = "https://graph.microsoft.com" 24 | 25 | let tokenType = "bearer" 26 | let apiHeaderAuthrization = "Authorization" 27 | 28 | override init() { 29 | super.init() 30 | let path = NSBundle(forClass: self.dynamicType).pathForResource("testUserArgs", ofType: "json") 31 | 32 | let jsonData = try! NSData(contentsOfFile: path!, options: .DataReadingMappedIfSafe) 33 | let jsonResult = try! NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! NSDictionary 34 | 35 | userEmail = jsonResult["test.username"] as! String 36 | domainName = userEmail.componentsSeparatedByString("@")[1] 37 | } 38 | 39 | @objc func appendAuthenticationHeaders(request: NSMutableURLRequest!, completion completionHandler: MSAuthenticationCompletion!) { 40 | 41 | if let _ = accessToken { 42 | let oauthAuthorizationHeader = String(format: "%@ %@", tokenType, accessToken!) 43 | request.setValue(oauthAuthorizationHeader, forHTTPHeaderField: self.apiHeaderAuthrization) 44 | completionHandler(request, nil) 45 | } 46 | else { 47 | let path = NSBundle(forClass: self.dynamicType).pathForResource("testUserArgs", ofType: "json") 48 | 49 | let jsonData = try! NSData(contentsOfFile: path!, options: .DataReadingMappedIfSafe) 50 | let jsonResult = try! NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! NSDictionary 51 | 52 | let username = jsonResult["test.username"] as! String 53 | let password = jsonResult["test.password"] as! String 54 | let clientId = jsonResult["test.clientId"] as! String 55 | 56 | userEmail = username 57 | 58 | let authRequest = NSMutableURLRequest() 59 | let bodyString = "grant_type=\(grantType)&resource=\(resourceId)&client_id=\(clientId)&username=\(username)&password=\(password)" 60 | 61 | authRequest.URL = NSURL(string: tokenEndPoint) 62 | authRequest.HTTPMethod = requestType 63 | authRequest.setValue(contentType, forHTTPHeaderField: "Content_Type") 64 | authRequest.HTTPBody = bodyString.dataUsingEncoding(NSUTF8StringEncoding) 65 | 66 | let session = NSURLSession.sharedSession() 67 | let task = session.dataTaskWithRequest(authRequest, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) in 68 | 69 | if let validData = data { 70 | let jsonDictionary = try! NSJSONSerialization.JSONObjectWithData(validData, options: .AllowFragments) as! NSDictionary 71 | if let accessTokenReturned = jsonDictionary["access_token"] { 72 | self.accessToken = accessTokenReturned as? String 73 | } 74 | else { 75 | self.accessToken = "WRONG_TOKEN" 76 | } 77 | } 78 | 79 | let oauthAuthorizationHeader = String(format: "%@ %@", self.tokenType, self.accessToken!) 80 | request.setValue(oauthAuthorizationHeader, forHTTPHeaderField: self.apiHeaderAuthrization) 81 | completionHandler(request, error) 82 | }) 83 | task.resume() 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/DetailViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | 7 | import UIKit 8 | 9 | class DetailViewController: UIViewController { 10 | 11 | @IBOutlet var activityIndicatorView: UIActivityIndicatorView! 12 | @IBOutlet var snippetNameLabel: UILabel! 13 | @IBOutlet var resultStackView: UIStackView! 14 | @IBOutlet var accessLevelLabel: UILabel! 15 | 16 | var snippet: Snippet? 17 | { 18 | didSet { configureView() } 19 | } 20 | 21 | override func viewDidLoad() 22 | { 23 | super.viewDidLoad() 24 | configureView() 25 | } 26 | 27 | override func viewDidAppear(_ animated: Bool) 28 | { 29 | super.viewDidAppear(animated) 30 | 31 | guard let _ = snippet else { return } 32 | 33 | executeSnippet() 34 | } 35 | 36 | // MARK: - Private 37 | 38 | private func executeSnippet() 39 | { 40 | guard let _ = snippet else { return } 41 | 42 | self.snippet!.execute { (result: Result) in 43 | switch result { 44 | case .Failure(let error): 45 | var displayText: String = "Failed\n\n" 46 | switch error { 47 | case .NSErrorType(let nsError): 48 | displayText = nsError.localizedDescription 49 | 50 | for (key, value) in nsError.userInfo.enumerated() { 51 | displayText += "\n\(key): \(value)" 52 | } 53 | 54 | break 55 | case.UnexpectecError(let errorString): 56 | displayText = errorString 57 | break 58 | } 59 | 60 | DispatchQueue.main.async { 61 | let result = UILabel() 62 | result.numberOfLines = 0 63 | result.text = displayText 64 | 65 | self.resultStackView.addArrangedSubview(result) 66 | self.accessLevelLabel.removeFromSuperview() 67 | 68 | self.hideActivityIndicator() 69 | } 70 | 71 | break 72 | case .Success(let displayText): 73 | if let text = displayText { 74 | DispatchQueue.main.async { 75 | let result = UILabel() 76 | result.numberOfLines = 0 77 | result.text = "Success\n\n\(text)" 78 | 79 | self.resultStackView.addArrangedSubview(result) 80 | self.hideActivityIndicator() 81 | } 82 | } 83 | break 84 | 85 | case .SuccessDownloadImage(let displayImage): 86 | DispatchQueue.main.async { 87 | let imageView = UIImageView(image: displayImage) 88 | 89 | self.resultStackView.addArrangedSubview(imageView) 90 | self.hideActivityIndicator() 91 | } 92 | break 93 | } 94 | } 95 | } 96 | 97 | private func hideActivityIndicator() 98 | { 99 | self.activityIndicatorView.stopAnimating() 100 | 101 | UIView.animate(withDuration: 0.35, animations: { 102 | self.activityIndicatorView.isHidden = true 103 | }) { (finished) in 104 | self.activityIndicatorView.stopAnimating() 105 | } 106 | } 107 | 108 | func configureView() 109 | { 110 | if let label = snippetNameLabel, let snippet = self.snippet { 111 | label.text = snippet.name 112 | accessLevelLabel.isHidden = !snippet.needAdminAccess 113 | } 114 | } 115 | 116 | func setResult(with string: String) 117 | { 118 | let label = UILabel() 119 | label.numberOfLines = 0 120 | label.text = string 121 | 122 | resultStackView.addArrangedSubview(label) 123 | } 124 | } 125 | 126 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets.xcodeproj/xcshareddata/xcschemes/Graph-iOS-Swift-Snippets.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/ConnectViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | 7 | import UIKit 8 | import MSAL 9 | 10 | class ConnectViewController: UIViewController, UISplitViewControllerDelegate 11 | { 12 | @IBOutlet var activityIndicator: UIActivityIndicatorView! 13 | @IBOutlet var connectButton: UIButton! 14 | 15 | let authenticationProvider: AuthenticationProvider? = { 16 | guard let authorityUrl = URL(string: ApplicationConstants.authority) else { return nil } 17 | 18 | var authenticationProvider: AuthenticationProvider? 19 | do { 20 | let authority = try MSALAADAuthority(url: authorityUrl) 21 | let clientId = ApplicationConstants.clientId 22 | authenticationProvider = try AuthenticationProvider(clientId: clientId, authority: authority) 23 | } catch let error as NSError { 24 | print("Error: ", error) 25 | } 26 | 27 | return authenticationProvider 28 | }() 29 | 30 | // MARK: - Split view 31 | 32 | func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController:UIViewController, ontoPrimaryViewController primaryViewController:UIViewController) -> Bool 33 | { 34 | guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false } 35 | guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false } 36 | if topAsDetailController.snippet == nil { 37 | // collapse when there is no snippet. i.e./ initial loading of the view controller. 38 | return true 39 | } 40 | return false 41 | } 42 | 43 | 44 | @IBAction func connectToGraph(_ sender: Any) 45 | { 46 | authenticate() 47 | } 48 | 49 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) 50 | { 51 | if segue.identifier == "showSnippets" { 52 | let splitViewController = segue.destination as! UISplitViewController 53 | 54 | let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController 55 | navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem 56 | 57 | let navController = splitViewController.viewControllers.first as! UINavigationController 58 | print(navController) 59 | 60 | let masterViewController = navController.topViewController as! MasterViewController 61 | masterViewController.authenticationProvider = self.authenticationProvider 62 | 63 | splitViewController.delegate = self 64 | } 65 | } 66 | 67 | // MARK: - Private 68 | 69 | private func authenticate() 70 | { 71 | guard let authenticationProvider = self.authenticationProvider else { return } 72 | let scopes = ApplicationConstants.scopes 73 | 74 | showLoadingView(show: true) 75 | authenticationProvider.acquireAuthToken(scopes: scopes) { (success, error) in 76 | self.showLoadingView(show: false) 77 | 78 | if success { 79 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 80 | self.performSegue(withIdentifier: "showSnippets", sender: nil) 81 | } 82 | 83 | return; 84 | } 85 | 86 | print("Error: ", error?.description ?? "nil error") 87 | self.showError(message: "Check print log for error details") 88 | } 89 | } 90 | 91 | private func showLoadingView(show: Bool) 92 | { 93 | if show { 94 | activityIndicator.startAnimating() 95 | connectButton.setTitle("Connecting...", for: .normal) 96 | connectButton.isEnabled = false 97 | } else { 98 | activityIndicator.stopAnimating() 99 | connectButton.setTitle("Connect", for: .normal) 100 | connectButton.isEnabled = true 101 | } 102 | } 103 | 104 | func showError(message: String) 105 | { 106 | DispatchQueue.main.async { 107 | let alertControl = UIAlertController(title: "Error", message: message, preferredStyle: .alert) 108 | alertControl.addAction(UIAlertAction(title: "Close", style: .default, handler: nil)) 109 | 110 | self.present(alertControl, animated: true, completion: nil) 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Microsoft Graph iOS Swift Snippets Sample 2 | 3 | ## Table of contents 4 | 5 | - [Introduction](#introduction) 6 | - [Prerequisites](#prerequisites) 7 | - [Register and configure the app](#register-and-configure-the-app) 8 | - [Build and debug](#build-and-debug) 9 | - [Running the sample](#running-the-sample) 10 | 11 | ## Introduction 12 | 13 | This sample contains a repository of code snippets that show how to use the Microsoft Graph SDK to send email, manage groups, and perform other activities with Office 365 data. It uses the [Microsoft Graph SDK for iOS](https://github.com/microsoftgraph/msgraph-sdk-ios) to work with data returned by Microsoft Graph. 14 | 15 | This repository shows you how to access multiple resources, including Microsoft Azure Active Directory (AD) and the Office 365 APIs, by making HTTP requests to the Microsoft Graph API in an iOS app. 16 | 17 | These snippets are simple and self-contained, and you can copy and paste them into your own code, whenever appropriate, or use them as a resource for learning how to use the Microsoft Graph SDK for iOS. 18 | 19 | **Note:** If possible, please use this sample with a "non-work" or test account. The sample does not always clean up the created objects in your mailbox and calendar. At this time you'll have to manually remove sample mails and calendar events. Also note that the snippets that get and send messages and that get, create, update, and delete events won't work with all personal accounts. These operations will eventually work when those accounts are updated to work with the v2 authentication endpoint. 20 | 21 | ## Prerequisites 22 | 23 | This sample requires the following: 24 | 25 | - [Xcode](https://developer.apple.com/xcode/downloads/) version 10.2.1 26 | - Installation of [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) as a dependency manager. 27 | - A Microsoft work or personal email account such as Office 365, or outlook.com, hotmail.com, etc. You can sign up for [an Office 365 Developer subscription](https://aka.ms/devprogramsignup) that includes the resources that you need to start building Office 365 apps. 28 | 29 | ## Register and configure the app 30 | 31 | 1. Open a browser and navigate to the [Azure Active Directory admin center](https://aad.portal.azure.com) and login using a **personal account** (aka: Microsoft Account) or **Work or School Account**. 32 | 33 | 1. Select **Azure Active Directory** in the left-hand navigation, then select **App registrations** under **Manage**. 34 | 35 | 1. Select **New registration**. On the **Register an application** page, set the values as follows. 36 | 37 | - Set **Name** to `Swift Snippets Sample`. 38 | - Set **Supported account types** to **Accounts in any organizational directory and personal Microsoft accounts**. 39 | - Under **Redirect URI**, change the drop down to **Public client (mobile & desktop)**, and set the value to `msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth`. 40 | 41 | 1. Choose **Register**. On the **Swift Snippets Sample** page, copy the value of the **Application (client) ID** and save it, you will need it in the next step. 42 | 43 | ## Build and debug 44 | 45 | 1. Clone this repository 46 | 47 | 1. Open **Terminal** and navigate to the root of the project. Run the following command to install dependencies. 48 | 49 | ```Shell 50 | pod install 51 | ``` 52 | 53 | 1. Open **Graph-iOS-Swift-Snippets.xcworkspace** in Xcode. 54 | 55 | 1. Open **ApplicationConstants.swift**. Replace `ENTER_CLIENT_ID` with the application ID you got from registering your app. 56 | 57 | ```swift 58 | // You will set your application's clientId 59 | static let clientId = "ENTER_CLIENT_ID" 60 | ``` 61 | 62 | 1. Run the sample. 63 | 64 | ## Running the sample 65 | 66 | When launched, the app displays a list of common user tasks. These tasks can be run based on account type and permission level, and are noted in comments: 67 | 68 | - Tasks that are applicable to both work or school and personal accounts, such as getting and sending email, creating files, etc. 69 | - Tasks that are only applicable to work or school accounts, such as getting a user's manager or account photo. 70 | - Tasks that are only applicable to a work or school account with administrative permissions, such as getting group members or creating new user accounts. 71 | 72 | Select the task that you want to perform and click on it to run. Be aware that if you log in with an account that doesn't have applicable permissions for the tasks you've selected they'll fail. For example if try to run a particular snippet, like get all tenant groups, from an account that doesn't not have admin privileges in the org the operation will fail. Or, if you log in with a personal account and attempt to get the manager of the signed in user, it will fail. 73 | 74 | ## Contributing 75 | 76 | If you'd like to contribute to this sample, see [CONTRIBUTING.MD](/CONTRIBUTING.md). 77 | 78 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 79 | 80 | ## Copyright 81 | 82 | Copyright (c) 2016 Microsoft. All rights reserved. 83 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/AuthenticationProvider.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | import Foundation 7 | import MSAL 8 | import MSGraphSDK 9 | 10 | class AuthenticationProvider: NSObject, MSAuthenticationProvider 11 | { 12 | var accessToken: String? 13 | var account: MSALAccount? 14 | var msalClient: MSALPublicClientApplication 15 | 16 | init(clientId: String, authority: MSALAuthority) throws 17 | { 18 | let config = MSALPublicClientApplicationConfig(clientId: clientId) 19 | msalClient = try MSALPublicClientApplication(configuration: config) 20 | } 21 | 22 | func acquireAuthToken(scopes: [String], completion:@escaping (_ success:Bool, _ error: NSError?) -> Void) 23 | { 24 | var completionBlock: MSALCompletionBlock? 25 | completionBlock = { (result, error) in 26 | 27 | if let error = error as NSError? 28 | { 29 | if (error.domain == MSALErrorDomain) 30 | { 31 | let msalError = MSALError(rawValue: error.code)! 32 | 33 | switch msalError { 34 | case MSALError.interactionRequired: 35 | let interactiveParameters = MSALInteractiveTokenParameters(scopes: scopes) 36 | self.msalClient.acquireToken(with: interactiveParameters, completionBlock: completionBlock!) 37 | 38 | case MSALError.serverDeclinedScopes: 39 | var declinedScopes = [String]() 40 | if let ds = error.userInfo[MSALDeclinedScopesKey] as? Array { declinedScopes = ds } 41 | print("The following scopes were declined: ", declinedScopes) 42 | 43 | var grantedScopes = [String]() 44 | if let gs = error.userInfo[MSALGrantedScopesKey] as? Array { grantedScopes = gs } 45 | print("Trying to acquire a token with granted scopes: ", grantedScopes) 46 | 47 | self.acquireTokenSilent(scopes: grantedScopes, msalCompletionBlock: completionBlock!, completion: completion) 48 | 49 | case MSALError.internal: 50 | 51 | // Log the error, then inspect the MSALInternalErrorCodeKey 52 | // in the userInfo dictionary. 53 | // More detailed information about the specific error 54 | // under MSALInternalErrorCodeKey can be found in MSALInternalError enum. 55 | print("Failed with internal MSAL error ", error) 56 | default: 57 | print("Failed with unknown MSAL error ", error) 58 | } 59 | } 60 | 61 | completion(false, error) 62 | 63 | } else if let result = result { 64 | self.accessToken = result.accessToken 65 | self.account = result.account 66 | completion(true, nil) 67 | 68 | return 69 | } else { 70 | assert(false, "result and error should never be nil at the same time.") 71 | } 72 | } 73 | 74 | var accounts = [MSALAccount]() 75 | do { 76 | accounts = try msalClient.allAccounts() 77 | } catch let error as NSError { 78 | print("Error: ", error) 79 | } 80 | 81 | if let account = accounts.first { 82 | let silentParameters = MSALSilentTokenParameters(scopes: scopes, account: account) 83 | msalClient.acquireTokenSilent(with: silentParameters, completionBlock: completionBlock!) 84 | } else { 85 | let interactiveParameters = MSALInteractiveTokenParameters(scopes: scopes) 86 | msalClient.acquireToken(with: interactiveParameters, completionBlock: completionBlock!) 87 | } 88 | } 89 | 90 | func disconnect() 91 | { 92 | guard let account = self.account else { return } 93 | 94 | do { 95 | try msalClient.remove(account) 96 | } catch let error as NSError { 97 | print("Error: ", error) 98 | } 99 | } 100 | 101 | // MARK: - MSAuthenticationProvider 102 | 103 | func appendAuthenticationHeaders(_ request: NSMutableURLRequest!, completion completionHandler: MSAuthenticationCompletion!) 104 | { 105 | if let accessToken = self.accessToken { 106 | let header = "Bearer \(accessToken)" 107 | request.setValue(header, forHTTPHeaderField:"Authorization") 108 | } 109 | 110 | completionHandler(request, nil); 111 | } 112 | 113 | // MARK: - Private 114 | 115 | private func acquireTokenSilent(scopes: [String], msalCompletionBlock: @escaping MSALCompletionBlock, completion:@escaping (_ success:Bool, _ error: NSError?) -> Void) 116 | { 117 | var accounts = [MSALAccount]() 118 | do { 119 | accounts = try self.msalClient.allAccounts() 120 | } catch let error as NSError { 121 | print("Error: ", error) 122 | completion(false, error) 123 | return 124 | } 125 | 126 | if let account = accounts.first { 127 | let silentParameters = MSALSilentTokenParameters(scopes: scopes, account: account) 128 | self.msalClient.acquireTokenSilent(with: silentParameters, completionBlock: msalCompletionBlock) 129 | } else { 130 | completion(false, nil) 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /README-Localized/README-pt-br.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-365 5 | - office-outlook 6 | - ms-graph 7 | languages: 8 | - swift 9 | extensions: 10 | contentType: samples 11 | technologies: 12 | - Microsoft Graph 13 | services: 14 | - Office 365 15 | - Outlook 16 | - Groups 17 | platforms: 18 | - iOS 19 | createdDate: 5/26/2016 8:08:35 AM 20 | --- 21 | # Exemplo de Trechos de Código do iOS Swift do Microsoft Graph 22 | 23 | ## Sumário 24 | 25 | - [Introdução](#introduction) 26 | - [Pré-requisitos](#prerequisites) 27 | - [Registrar e configurar o aplicativo](#register-and-configure-the-app) 28 | - [Criar e depurar](#build-and-debug) 29 | - [Execução do exemplo](#running-the-sample) 30 | 31 | ## Introdução 32 | 33 | Este exemplo contém um repositório de trechos de código que mostram como usar o SDK do Microsoft Graph SDK para enviar emails, gerenciar grupos e realizar outras atividades com os dados do Office 365. Ele usa o [SDK do Microsoft Graph para iOS](https://github.com/microsoftgraph/msgraph-sdk-ios) para trabalhar com dados retornados pelo Microsoft Graph. 34 | 35 | Este repositório mostra como acessar vários recursos, incluindo o Microsoft Azure Active Directory (AD) e APIs do Office 365, fazendo solicitações HTTP para a API do Microsoft Graph em um aplicativo iOS. 36 | 37 | Esses trechos são simples e autocontidos e você pode copiá-los e colá-los em seu próprio código, quando apropriado, ou usá-los como um recurso para aprender a usar o SDK do Microsoft Graph para iOS. 38 | 39 | **Observação:** Se possível, use este exemplo com uma conta "não comercial" ou de teste. O exemplo nem sempre limpa os objetos criados em sua caixa de correio e calendário. Neste momento, você terá que remover manualmente os exemplos de correios e eventos do calendário. Observe também que os trechos de código que recebem e enviam mensagens e que recebem, criam, atualizam e excluem eventos não funcionarão com todas as contas pessoais. Essas operações eventualmente funcionarão quando essas contas forem atualizadas para funcionar com o ponto de extremidade de autenticação v2. 40 | 41 | ## Pré-requisitos 42 | 43 | Esse exemplo requer o seguinte: 44 | 45 | - [Xcode](https://developer.apple.com/xcode/downloads/) versão 10.2.1 46 | - A instalação de [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) como um gerenciador de dependências. 47 | - Uma conta de email comercial ou pessoal da Microsoft como o Office 365, ou outlook.com, hotmail.com, etc. Inscreva-se para uma [Assinatura de Desenvolvedor do Office 365](https://aka.ms/devprogramsignup), que inclui os recursos necessários para começar a criação de aplicativos do Office 365. 48 | 49 | ## Registrar e configurar o aplicativo 50 | 51 | 1. Abra um navegador e navegue até o [centro de administração do Azure Active Directory](https://aad.portal.azure.com) e faça logon usando uma **conta pessoal** (também conhecida como: Conta da Microsoft) **Conta Corporativa ou de Estudante**. 52 | 53 | 1. Selecione **Azure Active Directory** na navegação à esquerda e, em seguida, selecione **Registros de aplicativos** em **Gerenciar**. 54 | 55 | 1. Selecione **Novo registro**. Na página **Registrar um aplicativo**, defina os valores da seguinte forma. 56 | 57 | - Defina o **Nome** para `Exemplo de Trechos Swift`. 58 | - Defina **Tipos de contas com suporte** para **Contas em qualquer diretório organizacional e contas pessoais da Microsoft**. 59 | - Em URI de Redirecionamento, altere a lista suspensa para Cliente público (celular & desktop), e defina o valor como `msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth`. 60 | 61 | 1. Escolha **Registrar**. Na página **Exemplo de Trechos Swift**, copie o valor da **ID do aplicativo (cliente)** e salve-o, você precisará dele na próxima etapa. 62 | 63 | ## Criar e depurar 64 | 65 | 1. Clonar este repositório 66 | 67 | 1. Abra o **Terminal** e navegue até a raiz do projeto. Execute o seguinte comando para instalar as dependências. 68 | 69 | ```Shell 70 | pod install 71 | ``` 72 | 73 | 1. Abra **Graph-Ios-Swift-Snippets. xcworkspace** no Xcode. 74 | 75 | 1. Abra **ApplicationConstants.swift**. Substitua `ENTER_CLIENT_ID` pela ID do aplicativo obtida do registro de seu aplicativo. 76 | 77 | ```swift 78 | // You will set your application's clientId 79 | static let clientId = "ENTER_CLIENT_ID" 80 | ``` 81 | 82 | 1. Execute o exemplo. 83 | 84 | ## Execução do exemplo 85 | 86 | Após ser iniciado, o aplicativo exibe uma lista de tarefas comuns de usuários. Essas tarefas podem ser executadas com base no nível de permissão e de tipo de conta e trazem uma anotação nos comentários: 87 | 88 | - Tarefas que são aplicáveis a contas comerciais ou escolares e contas pessoais, como receber e enviar emails, criar arquivos, etc. 89 | - Tarefas que só são aplicáveis a contas comerciais ou escolares, como receber a foto da conta e o gerenciador do usuário. 90 | - Tarefas que só são aplicáveis a contas comerciais ou escolares com permissões administrativas, como receber membros do grupo ou criar novas contas de usuário. 91 | 92 | Escolha a tarefa que você deseja realizar e clique nela para executar. Lembre-se de que se você fizer logon com uma conta que não tem permissões aplicáveis para as tarefas selecionadas, elas falharão. Por exemplo, se você tentar executar um determinado trecho de código, como obter todos os grupos de um locatário, de uma conta que não tem privilégios de administrador na organização, a operação falhará. Ou, se você entrar com uma conta pessoal do e tentar obter o gerenciador do usuário conectado, ele falhará. 93 | 94 | ## Colaboração 95 | 96 | Se quiser contribuir para esse exemplo, confira [CONTRIBUTING.MD](/CONTRIBUTING.md). 97 | 98 | Este projeto adotou o [Código de Conduta de Código Aberto da Microsoft](https://opensource.microsoft.com/codeofconduct/). Para saber mais, confira as [Perguntas frequentes sobre o Código de Conduta](https://opensource.microsoft.com/codeofconduct/faq/) ou entre em contato pelo [opencode@microsoft.com](mailto:opencode@microsoft.com) se tiver outras dúvidas ou comentários. 99 | 100 | ## Direitos autorais 101 | 102 | Copyright © 2016 Microsoft. Todos os direitos reservados. 103 | -------------------------------------------------------------------------------- /README-Localized/README-es-es.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-365 5 | - office-outlook 6 | - ms-graph 7 | languages: 8 | - swift 9 | extensions: 10 | contentType: samples 11 | technologies: 12 | - Microsoft Graph 13 | services: 14 | - Office 365 15 | - Outlook 16 | - Groups 17 | platforms: 18 | - iOS 19 | createdDate: 5/26/2016 8:08:35 AM 20 | --- 21 | # Ejemplo de fragmentos de código de muestra de iOS en Swift de Microsoft Graph 22 | 23 | ## Tabla de contenido 24 | 25 | - [Introducción](#introduction) 26 | - [Requisitos previos](#prerequisites) 27 | - [Registrar y configurar la aplicación](#register-and-configure-the-app) 28 | - [Compilar y depurar](#build-and-debug) 29 | - [Ejecución del ejemplo](#running-the-sample) 30 | 31 | ## Introducción 32 | 33 | Este ejemplo contiene un repositorio de fragmentos de código que muestran cómo usar el SDK de Microsoft Graph para enviar correos electrónicos, administrar grupos y realizar otras actividades con los datos de Office 365. Usa el [SDK de Microsoft Graph para iOS](https://github.com/microsoftgraph/msgraph-sdk-ios) para trabajar con los datos devueltos por Microsoft Graph. 34 | 35 | Este repositorio muestra cómo tener acceso a varios recursos, incluidos Microsoft Azure Active Directory (AD) y las API de Office 365, realizando solicitudes HTTP a la API de Microsoft Graph en una aplicación de iOS. 36 | 37 | Estos fragmentos de código son simples e independientes, y puede copiarlos y pegarlos en su propio código, cuando sea apropiado, o usarlos como un recurso para aprender a usar el SDK de Microsoft Graph para iOS. 38 | 39 | **Nota:** Si es posible, use este ejemplo con una cuenta de prueba o "no profesional". El ejemplo no siempre limpia los objetos creados en el buzón de correo y el calendario. En este momento, tendrá que eliminar manualmente los eventos del calendario y los correos del ejemplo. Tenga en cuenta que los fragmentos de código que reciben y envían mensajes, y que obtienen, crean, actualizan y eliminan eventos no funcionarán con todas las cuentas personales. Estas operaciones funcionarán finalmente cuando esas cuentas se actualicen para su funcionamiento con el modelo de autenticación v2. 40 | 41 | ## Requisitos previos 42 | 43 | Este ejemplo necesita lo siguiente: 44 | 45 | - La versión 10.2.1 de [Xcode](https://developer.apple.com/xcode/downloads/) 46 | - La instalación de [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) como administrador de dependencias. 47 | - Una cuenta de correo electrónico personal o profesional de Microsoft como Office 365, outlook.com, hotmail.com, etc. Puede realizar [una suscripción a Office 365 Developer](https://aka.ms/devprogramsignup) que incluye los recursos que necesita para comenzar a crear aplicaciones de Office 365. 48 | 49 | ## Registrar y configurar la aplicación 50 | 51 | 1. Abra un explorador y vaya al [Centro de administración de Azure Active Directory](https://aad.portal.azure.com) e inicie sesión con una **cuenta personal** (también conocida como: una cuenta de Microsoft) o una **cuenta profesional o educativa**. 52 | 53 | 1. Seleccione **Azure Active Directory** en el panel de navegación izquierdo y, después, **Registros de aplicaciones** en **Administrar**. 54 | 55 | 1. Seleccione **Nuevo registro**. En la página **Registrar una aplicación**, establezca los valores siguientes. 56 | 57 | - Establezca el **Nombre** en `Ejemplo de fragmentos de código de Swift`. 58 | - Establezca **Tipos de cuenta admitidos** en **Cuentas en cualquier directorio de organización y cuentas personales de Microsoft**. 59 | - En **URI de redirección**, cambie la lista desplegable a **Cliente público (móvil y escritorio)** y establezca el valor en `msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth`. 60 | 61 | 1. Elija **Registrar**. En la página **Ejemplo de fragmentos de código de Swift**, copie el valor del **Id. de aplicación (cliente)** y guárdelo. Lo necesitará en el paso siguiente. 62 | 63 | ## Compilar y depurar 64 | 65 | 1. Clone este repositorio. 66 | 67 | 1. Abra el **Terminal** y desplácese hasta la raíz del proyecto. Ejecute el siguiente comando para instalar dependencias. 68 | 69 | ```Shell 70 | pod install 71 | ``` 72 | 73 | 1. Abra **Graph-iOS-Swift-Snippets.xcworkspace** en Xcode. 74 | 75 | 1. Abra **ApplicationConstants.swift**. Reemplace `ESCRIBIR_ID_CLIENTE` por el id. de la aplicación que obtuvo al registrar la aplicación. 76 | 77 | ```swift 78 | // You will set your application's clientId 79 | static let clientId = "ENTER_CLIENT_ID" 80 | ``` 81 | 82 | 1. Ejecute el ejemplo. 83 | 84 | ## Ejecución del ejemplo 85 | 86 | Al iniciarse, la aplicación muestra una lista de tareas de usuario comunes. Estas tareas se pueden ejecutar basándose en el tipo de cuenta y nivel de permiso, y están marcadas en comentarios: 87 | 88 | - Tareas que son aplicables a cuentas profesionales, educativas y personales, como recibir y enviar correo electrónico, crear archivos, etc. 89 | - Tareas que solamente son aplicables a cuentas profesionales o educativas, como obtener fotos de administrador o de la cuenta de un usuario. 90 | - Tareas que solo son aplicables a una cuenta profesional o educativa con permisos administrativos, como obtener miembros del grupo o crear nuevas cuentas de usuario. 91 | 92 | Seleccione la tarea que desea realizar y haga clic en ella para ejecutarla. Tenga en cuenta que, si inicia una sesión con una cuenta que no tiene permisos aplicables para las tareas que ha seleccionado, no se realizarán correctamente. Por ejemplo, si intenta ejecutar un fragmento de código determinado, como obtener todos los grupos del inquilino a partir de una cuenta que no tiene privilegios de administrador en la organización, se producirá un error en la operación. Si inicia una sesión con una cuenta personal e intenta obtener el administrador del usuario con la sesión iniciada, se producirá un error. 93 | 94 | ## Colaboradores 95 | 96 | Si le gustaría contribuir a este ejemplo, vea [CONTRIBUTING.MD](/CONTRIBUTING.md). 97 | 98 | Este proyecto ha adoptado el [Código de conducta de código abierto de Microsoft](https://opensource.microsoft.com/codeofconduct/). Para obtener más información, vea [Preguntas frecuentes sobre el código de conducta](https://opensource.microsoft.com/codeofconduct/faq/) o póngase en contacto con [opencode@microsoft.com](mailto:opencode@microsoft.com) si tiene otras preguntas o comentarios. 99 | 100 | ## Copyright 101 | 102 | Copyright (c) 2016 Microsoft. Todos los derechos reservados. 103 | -------------------------------------------------------------------------------- /README-Localized/README-ru-ru.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-365 5 | - office-outlook 6 | - ms-graph 7 | languages: 8 | - swift 9 | extensions: 10 | contentType: samples 11 | technologies: 12 | - Microsoft Graph 13 | services: 14 | - Office 365 15 | - Outlook 16 | - Groups 17 | platforms: 18 | - iOS 19 | createdDate: 5/26/2016 8:08:35 AM 20 | --- 21 | # Пример фрагментов кода Microsoft Graph на Swift для iOS 22 | 23 | ## Содержание 24 | 25 | - [Введение](#introduction) 26 | - [Предварительные требования](#prerequisites) 27 | - [Регистрация и настройка приложения](#register-and-configure-the-app) 28 | - [Сборка и отладка](#build-and-debug) 29 | - [Запуск приложения](#running-the-sample) 30 | 31 | ## Введение 32 | 33 | Этот пример содержит репозиторий фрагментов кода, в которых показано, как использовать пакет SDK Microsoft Graph, чтобы отправлять электронные сообщения, управлять группами и выполнять другие действия с данными Office 365. Для работы с данными, возвращаемыми Microsoft Graph, используется [пакет SDK Microsoft Graph для iOS](https://github.com/microsoftgraph/msgraph-sdk-ios). 34 | 35 | Этот репозиторий показывает, как получить доступ к нескольким ресурсам, в том числе Microsoft Azure Active Directory (AD) и API Office 365, совершая HTTP-запросы в API Microsoft Graph в приложении iOS. 36 | 37 | Эти фрагменты простые и автономные. Вы можете копировать их в свой код или брать их за основу при изучении пакета SDK Microsoft Graph для iOS. 38 | 39 | **Примечание.** Если возможно, используйте этот пример с "нерабочей" или тестовой учетной записью. Если вы используете пример, созданные объекты в почтовом ящике и календаре не всегда очищаются. В настоящее время вам необходимо вручную удалить примеры сообщений и событий календаря. Обратите внимание, что фрагменты кода, которые используются для получения и отправки сообщений, а также получения, создания, обновления и удаления событий, работают не со всеми личными учетными записями. Настоящие операции будут поддерживаться в полном объеме, когда эти учетные записи будут обновлены для работы с конечной точкой проверки подлинности версии 2. 40 | 41 | ## Необходимые компоненты 42 | 43 | Для этого примера требуются приведенные ниже компоненты. 44 | 45 | - [Xcode](https://developer.apple.com/xcode/downloads/) версии 10.2.1. 46 | - Установка [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) в качестве диспетчера зависимостей. 47 | - Рабочая или личная учетная запись Майкрософт, например Office 365, outlook.com или hotmail.com. Вы можете [подписаться на план Office 365 для разработчиков](https://aka.ms/devprogramsignup), который включает ресурсы, необходимые для создания приложений Office 365. 48 | 49 | ## Регистрация и настройка приложения 50 | 51 | 1. Откройте браузер, перейдите в [Центр администрирования Azure Active Directory](https://aad.portal.azure.com) и войдите с помощью **личной учетной записи** (т. е. учетной записи Майкрософт) или **рабочей или учебной учетной записи**. 52 | 53 | 1. Выберите **Azure Active Directory** на панели навигации слева, затем выберите **Регистрация приложения** в разделе **Управление**. 54 | 55 | 1. Выберите **Новая регистрация**. На странице **Регистрация приложения** задайте необходимые значения следующим образом. 56 | 57 | - Задайте для параметра **Имя** значение `Swift Snippets Sample`. 58 | - Задайте для параметра **Поддерживаемые типы учетных записей** значение **Учетные записи в любом каталоге организации и личные учетные записи Майкрософт**. 59 | - В разделе **URI перенаправления** выберите в раскрывающемся списке **Общедоступный клиент (для мобильных и классических приложений)** и задайте значение `msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth`. 60 | 61 | 1. Нажмите кнопку **Зарегистрировать**. На странице **Пример фрагментов кода на Swift** скопируйте значение **Идентификатор приложения (клиента)** и сохраните его — оно потребуется на следующем шаге. 62 | 63 | ## Сборка и отладка 64 | 65 | 1. Клонируйте этот репозиторий 66 | 67 | 1. Откройте раздел **Терминал** и перейдите к корневой папке проекта. Чтобы установить зависимости, выполните указанную ниже команду. 68 | 69 | ```Shell 70 | pod install 71 | ``` 72 | 73 | 1. Откройте **Graph-iOS-Swift-Snippets.xcworkspace** в Xcode. 74 | 75 | 1. Откройте файл **ApplicationConstants.swift**. Замените `ENTER_CLIENT_ID` на идентификатор приложения, полученный при регистрации приложения. 76 | 77 | ```swift 78 | // You will set your application's clientId 79 | static let clientId = "ENTER_CLIENT_ID" 80 | ``` 81 | 82 | 1. Запустите пример. 83 | 84 | ## Запуск приложения 85 | 86 | Когда вы запустите приложение, в нем появится список типичных задач. Доступные задачи будут зависеть от типа учетной записи и уровня разрешений и отражены в примечаниях: 87 | 88 | - Задачи, доступные для рабочих, учебных и личных учетных записей, например получение и отправка электронной почты, создание файлов и т. д. 89 | - Задачи, доступные только для рабочих или учебных учетных записей, например получение фотографии учетной записи или сведений о руководителе пользователя. 90 | - Задачи, доступные только для рабочей или учебной учетной записи с административными разрешениями, например получение сведений о членах группы или создание учетных записей пользователей. 91 | 92 | Выберите задачу, которую необходимо выполнить, и щелчком запустите ее. Обратите внимание, что при входе в систему с помощью учетной записи, не имеющей соответствующих разрешений для выбранных задач, последние невозможно выполнить. Например, если вы попытаетесь выполнить определенный фрагмент кода (например, получить все клиентские группы) из учетной записи без прав администратора в организации, операция завершится ошибкой. Если вы войдете в систему с помощью личной учетной записи, вам не удастся получить сведения о руководителе пользователя, который вошел в систему. 93 | 94 | ## Участие 95 | 96 | Если вы хотите добавить код в этот пример, просмотрите статью [CONTRIBUTING.MD](/CONTRIBUTING.md). 97 | 98 | Этот проект соответствует [правилам поведения Майкрософт, касающимся обращения с открытым кодом](https://opensource.microsoft.com/codeofconduct/). Дополнительные сведения см. в разделе [Часто задаваемые вопросы о правилах поведения](https://opensource.microsoft.com/codeofconduct/faq/). Если у вас возникли вопросы или замечания, напишите нам по адресу [opencode@microsoft.com](mailto:opencode@microsoft.com). 99 | 100 | ## Авторское право 101 | 102 | (c) Корпорация Майкрософт (Microsoft Corporation), 2016. Все права защищены. 103 | -------------------------------------------------------------------------------- /README-Localized/README-de-de.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-365 5 | - office-outlook 6 | - ms-graph 7 | languages: 8 | - swift 9 | extensions: 10 | contentType: samples 11 | technologies: 12 | - Microsoft Graph 13 | services: 14 | - Office 365 15 | - Outlook 16 | - Groups 17 | platforms: 18 | - iOS 19 | createdDate: 5/26/2016 8:08:35 AM 20 | --- 21 | # Beispiel für iOS-Swift-Codeausschnitte für Microsoft Graph 22 | 23 | ## Inhaltsverzeichnis 24 | 25 | - [Einführung](#introduction) 26 | - [Voraussetzungen](#prerequisites) 27 | - [Registrieren und Konfigurieren der App](#register-and-configure-the-app) 28 | - [Erstellen und Debuggen](#build-and-debug) 29 | - [Ausführen des Beispiels](#running-the-sample) 30 | 31 | ## Einführung 32 | 33 | Dieses Beispiel enthält ein Repository von Codeausschnitten, die zeigen, wie das Microsoft Graph-SDK zum Senden von E-Mails, Verwalten von Gruppen und Ausführen anderer Aktivitäten mit Office 365-Daten verwendet wird. Es verwendet das [Microsoft Graph-SDK für iOS](https://github.com/microsoftgraph/msgraph-sdk-ios), um mit Daten zu arbeiten, die von Microsoft Graph zurückgegeben werden. 34 | 35 | In diesem Repository wird gezeigt, wie Sie auf mehrere Ressourcen, einschließlich Microsoft Azure Active Directory (AD) und die Office 365-APIs, zugreifen, indem Sie HTTP-Anforderungen an die Microsoft Graph-API in einer iOS-App ausführen. 36 | 37 | Diese Ausschnitte sind einfach und eigenständig, und Sie können sie ggf. in Ihren eigenen Code kopieren und einfügen oder als Ressource verwenden, um zu lernen, wie das Microsoft Graph-SDK für iOS verwendet wird. 38 | 39 | **Hinweis:** Verwenden Sie dieses Beispiel, wenn möglich, mit einem persönlichen Konto oder einem Testkonto. Das Beispiel bereinigt nicht immer die erstellten Objekte in Ihrem Postfach und Kalender. Derzeit müssen Sie Beispiel-E-Mails und -Kalenderereignisse manuell entfernen. Beachten Sie auch, dass die Codeausschnitte, die Nachrichten abrufen und senden und Ereignisse abrufen, erstellen, aktualisieren und löschen, nicht mit allen persönlichen Konten funktionieren. Diese Vorgänge funktionieren dann, wenn diese Konten so aktualisiert werden, dass sie mit dem v2-Authentifizierungsendpunkt arbeiten. 40 | 41 | ## Anforderungen 42 | 43 | Für dieses Beispiel ist Folgendes erforderlich: 44 | 45 | - [Xcode](https://developer.apple.com/xcode/downloads/), Version 10.2.1 46 | - Installation von [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) als ein Abhängigkeits-Manager. 47 | - Ein geschäftliches oder persönliches Microsoft-E-Mail-Konto, z. B. Office 365 oder outlook.com, hotmail.com usw. Sie können sich für ein [Office 365-Entwicklerabonnement](https://aka.ms/devprogramsignup) registrieren. Dieses umfasst die Ressourcen, die Sie zum Erstellen von Office 365-Apps benötigen. 48 | 49 | ## Registrieren und Konfigurieren der App 50 | 51 | 1. Öffnen Sie einen Browser, und navigieren Sie zum [Azure Active Directory Admin Center](https://aad.portal.azure.com). Melden Sie sich mit einem **persönlichen Konto** (auch: Microsoft-Konto) bzw. einem **Geschäfts-, Schul- oder Unikonto** an. 52 | 53 | 1. Wählen Sie in der linken Navigationsleiste **Azure Active Directory** aus, und wählen Sie dann **App-Registrierungen** unter **Verwalten** aus. 54 | 55 | 1. Wählen Sie **Neue Registrierungen** aus. Legen Sie auf der Seite **Anwendung registrieren** die Werte wie folgt fest. 56 | 57 | - Legen Sie **Name** auf `Swift-Codeausschnittbeispiel` fest. 58 | - Legen Sie **Unterstützte Kontotypen** auf **Konten in allen Organisationsverzeichnissen und persönliche Microsoft-Konten** fest. 59 | - Ändern Sie unter **Umleitungs-URI** die Dropdownliste auf **Öffentlicher Client (mobil & Desktop)**, und legen Sie den Wert auf `msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth` fest. 60 | 61 | 1. Wählen Sie **Registrieren** aus. Kopieren Sie auf der Seite **Swift-Codeausschnittbeispiel** den Wert von **Anwendungs-ID (Client-ID)**, und speichern Sie ihn. Sie benötigen ihn im nächsten Schritt. 62 | 63 | ## Erstellen und Debuggen 64 | 65 | 1. Klonen dieses Repositorys 66 | 67 | 1. Öffnen Sie ein **Terminal**, und navigieren Sie zum Stamm des Projekts. Führen Sie den folgenden Befehl aus, um Abhängigkeiten zu installieren. 68 | 69 | ```Shell 70 | pod install 71 | ``` 72 | 73 | 1. Öffnen Sie **Graph-iOS-Swift-Snippets.xcworkspace** in Xcode. 74 | 75 | 1. Öffnen **Sie ApplicationConstants.swift**. Ersetzen Sie `ENTER_CLIENT_ID` durch die Anwendungs-ID, die Sie durch die Registrierung Ihrer APP erhalten haben. 76 | 77 | ```swift 78 | // You will set your application's clientId 79 | static let clientId = "ENTER_CLIENT_ID" 80 | ``` 81 | 82 | 1. Führen Sie das Beispiel aus. 83 | 84 | ## Ausführen des Beispiels 85 | 86 | Nach dem Start wird in der App eine Liste allgemeiner Benutzeraufgaben angezeigt. Diese Aufgaben können basierend auf Kontotyp und Berechtigungsstufe ausgeführt werden und werden in Kommentaren notiert. 87 | 88 | - Aufgaben, die sowohl für Geschäfts- oder Schulkonten als auch für persönliche Konten gelten, z. B. das Abrufen und Seden von E-Mails, das Erstellen von Dateien usw. 89 | - Aufgaben, die nur für Geschäfts- oder Schulkonten gelten, z. B. das Abrufen eines Vorgesetzten eines Benutzers oder eines Kontofotos. 90 | - Aufgaben, die nur für Geschäfts- oder Schulkonten mit Administratorberechtigungen gelten, z. B. das Abrufen von Gruppenmitgliedern oder das Erstellen neuer Benutzerkonten. 91 | 92 | Wählen Sie die Aufgabe aus, die Sie ausführen möchten, und klicken Sie darauf, um sie auszuführen. Beachten Sie, dass die ausgewählten Aufgaben fehlschlagen, wenn Sie sich mit einem Konto anmelden, das nicht über die entsprechenden Berechtigungen für die Aufgaben verfügt. Wenn Sie beispielsweise versuchen, einen bestimmten Ausschnitt, z. B. das Abrufen aller Mandantengruppen, auf einem Konto auszuführen, das nicht über Administratorberechtigungen in der Organisation verfügt, schlägt der Vorgang fehl. Oder wenn Sie sich mit einem persönlichen Konto anmelden und versuchen, den Vorgesetzten des angemeldeten Benutzers abzurufen, schlägt dieser Vorgang fehl. 93 | 94 | ## Mitwirkung 95 | 96 | Wenn Sie einen Beitrag zu diesem Beispiel leisten möchten, finden Sie unter [CONTRIBUTING.MD](/CONTRIBUTING.md) weitere Informationen. 97 | 98 | In diesem Projekt wurden die [Microsoft Open Source-Verhaltensregeln](https://opensource.microsoft.com/codeofconduct/) übernommen. Weitere Informationen finden Sie unter [Häufig gestellte Fragen zu Verhaltensregeln](https://opensource.microsoft.com/codeofconduct/faq/), oder richten Sie Ihre Fragen oder Kommentare an [opencode@microsoft.com](mailto:opencode@microsoft.com). 99 | 100 | ## Copyright 101 | 102 | Copyright (c) 2016 Microsoft. Alle Rechte vorbehalten. 103 | -------------------------------------------------------------------------------- /README-Localized/README-fr-fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-365 5 | - office-outlook 6 | - ms-graph 7 | languages: 8 | - swift 9 | extensions: 10 | contentType: samples 11 | technologies: 12 | - Microsoft Graph 13 | services: 14 | - Office 365 15 | - Outlook 16 | - Groups 17 | platforms: 18 | - iOS 19 | createdDate: 5/26/2016 8:08:35 AM 20 | --- 21 | # Exemple d’extraits de code Microsoft Graph iOS Swift 22 | 23 | ## Table des matières 24 | 25 | - [Introduction](#introduction) 26 | - [Conditions préalables](#prerequisites) 27 | - [Enregistrement et configuration de l’application](#register-and-configure-the-app) 28 | - [Création et débogage](#build-and-debug) 29 | - [Exécution de l’exemple](#running-the-sample) 30 | 31 | ## Introduction 32 | 33 | Cet exemple contient un référentiel des extraits de code qui illustrent l’utilisation du kit de développement Microsoft Graph pour envoyer des messages électroniques, gérer les groupes et effectuer d’autres activités avec les données d’Office 365. Il utilise le [kit de développement logiciel Microsoft Graph pour iOS](https://github.com/microsoftgraph/msgraph-sdk-ios) pour exploiter les données renvoyées par Microsoft Graph. 34 | 35 | Ce référentiel vous montre comment accéder à plusieurs ressources, notamment Microsoft Azure Active Directory (AD) et les API d’Office 365, en envoyant des requêtes HTTP à l’API Microsoft Graph dans une application iOS. 36 | 37 | Ces extraits sont simples et autonomes, et vous pouvez les copier-coller dans votre propre code, le cas échéant, ou les utiliser comme ressource d’apprentissage sur l’utilisation du kit de développement logiciel Microsoft Graph pour iOS. 38 | 39 | **Remarque :** Si possible, utilisez cet exemple avec un compte de test ou non professionnel. L’exemple ne nettoie pas toujours les objets créés dans votre boîte aux lettres et votre calendrier. À ce stade, vous devrez supprimer manuellement les exemples de messages électroniques et les événements de calendrier. Notez également que les extraits de code qui obtiennent et envoient des messages et qui obtiennent, créent, mettent à jour et suppriment des événements ne fonctionnent pas avec tous les comptes personnels. Ces opérations fonctionneront finalement lorsque ces comptes seront mis à jour pour fonctionner avec le point de terminaison d’authentification v2. 40 | 41 | ## Conditions préalables 42 | 43 | Cet exemple nécessite les éléments suivants : 44 | 45 | - [Xcode](https://developer.apple.com/xcode/downloads/) version 10.2.1 46 | - Installation de [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html) comme gestionnaire de dépendances. 47 | - Un compte de messagerie professionnel ou personnel Microsoft comme Office 365 ou outlook.com, hotmail.com, etc. Vous pouvez vous inscrire à [Office 365 Developer](https://aka.ms/devprogramsignup) pour accéder aux ressources dont vous avez besoin pour commencer à créer des applications Office 365. 48 | 49 | ## Enregistrement et configuration de l’application 50 | 51 | 1. Ouvrez un navigateur, accédez au [Centre d’administration Azure Active Directory](https://aad.portal.azure.com) et connectez-vous à l’aide d’un **compte personnel** (ou compte Microsoft) ou d’un **compte professionnel ou scolaire**. 52 | 53 | 1. Sélectionnez **Azure Active Directory** dans le volet de navigation gauche, puis sélectionnez **Inscriptions d’applications** sous **Gérer**. 54 | 55 | 1. Sélectionnez **Nouvelle inscription**. Sur la page **Inscrire une application**, définissez les valeurs comme suit. 56 | 57 | - Définissez **Nom** sur `Exemple d'extraits de code Swift`. 58 | - Définissez **Types de comptes pris en charge** sur **Comptes figurant dans un annuaire organisationnel et comptes Microsoft personnels**. 59 | - Sous **URI de redirection**, remplacez la liste déroulante par **client public (mobile et bureau)** et définissez la valeur sur `msauth.com.microsoft.Graph-iOS-Swift-Snippets://auth`. 60 | 61 | 1. Choisissez **Inscrire**. Dans la page **Exemple d’extraits de code Swift**, copiez la valeur de **ID d’application (client)** et enregistrez-la, car vous en aurez besoin à l’étape suivante. 62 | 63 | ## Création et débogage 64 | 65 | 1. Cloner ce référentiel 66 | 67 | 1. Ouvrez **Terminal** et accédez au dossier racine du projet. Exécutez la commande suivante pour installer les dépendances. 68 | 69 | ```Shell 70 | pod install 71 | ``` 72 | 73 | 1. Ouvrez **Graph-iOS-Swift-Snippets.xcworkspace** dans Xcode. 74 | 75 | 1. Ouvrez **ApplicationConstants.swift**. Remplacez `ENTER_CLIENT_ID` par l’ID d’application que vous avez obtenu de l’inscription de votre application. 76 | 77 | ```swift 78 | // You will set your application's clientId 79 | static let clientId = "ENTER_CLIENT_ID" 80 | ``` 81 | 82 | 1. Exécutez l’exemple. 83 | 84 | ## Exécution de l’exemple 85 | 86 | Une fois lancée, l’application affiche une liste de tâches courantes de l’utilisateur. Ces tâches peuvent être exécutées en fonction du niveau d’autorisations et du type de compte et sont indiquées dans les commentaires : 87 | 88 | - Tâches qui s’appliquent à la fois aux comptes professionnels, scolaires et personnels, telles que l’obtention et l’envoi de messages électroniques, la création de fichiers, etc. 89 | - Tâches qui s’appliquent uniquement aux comptes professionnels ou scolaires, telles que l’obtention de la photo de compte ou du responsable d’un utilisateur. 90 | - Tâches qui s’appliquent uniquement aux comptes professionnels ou scolaires avec des autorisations administratives appropriées, telles que l’obtention de membres du groupe ou la création de comptes d’utilisateur. 91 | 92 | Sélectionnez la tâche que vous souhaitez effectuer et cliquez dessus pour l’exécuter. N’oubliez pas que si vous vous connectez avec un compte qui ne dispose pas des autorisations applicables pour les tâches sélectionnées, celles-ci échoueront. Par exemple si vous essayez d’exécuter un extrait spécifique, tel que l’obtention de tous les groupes du client, à partir d’un compte qui ne dispose pas de privilèges d’administrateur dans l’organigramme, l’opération échoue. Sinon, si vous vous connectez avec un compte personnel comme hotmail.com et essayez d’obtenir le responsable de l’utilisateur connecté, l’opération échoue. 93 | 94 | ## Contribution 95 | 96 | Si vous souhaitez contribuer à cet exemple, voir [CONTRIBUTING.MD](/CONTRIBUTING.md). 97 | 98 | Ce projet a adopté le [code de conduite Open Source de Microsoft](https://opensource.microsoft.com/codeofconduct/). Pour en savoir plus, reportez-vous à la [FAQ relative au code de conduite](https://opensource.microsoft.com/codeofconduct/faq/) ou contactez [opencode@microsoft.com](mailto:opencode@microsoft.com) pour toute question ou tout commentaire. 99 | 100 | ## Copyright 101 | 102 | Copyright (c) 2016 Microsoft. Tous droits réservés. 103 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-SnippetsTests/GroupsSnippetsTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GroupsSnippetsTest.swift 3 | // Graph-iOS-Swift-Snippets 4 | // 5 | // Created by Jason Kim on 7/18/16. 6 | // Copyright © 2016 Jason Kim. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import Graph_iOS_Swift_Snippets 12 | 13 | class GroupsSnippetsTest: XCTestCase { 14 | 15 | var authProvider: testAuthProvider! 16 | var graphClient: MSGraphClient! 17 | 18 | override func setUp() { 19 | super.setUp() 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | authProvider = testAuthProvider() 22 | 23 | MSGraphClient.setAuthenticationProvider(authProvider) 24 | graphClient = MSGraphClient.defaultClient() 25 | } 26 | 27 | override func tearDown() { 28 | // Put teardown code here. This method is called after the invocation of each test method in the class. 29 | super.tearDown() 30 | } 31 | 32 | 33 | func testCreateUser() { 34 | 35 | let userId = NSProcessInfo.processInfo().globallyUniqueString 36 | let domainName = authProvider.domainName 37 | let upn = userId + "@" + domainName 38 | 39 | let newUser = MSGraphUser() 40 | let passwordProfile = MSGraphPasswordProfile() 41 | passwordProfile.password = "!pass!word1" 42 | 43 | newUser.accountEnabled = true 44 | newUser.displayName = userId 45 | newUser.passwordProfile = passwordProfile 46 | newUser.mailNickname = userId 47 | newUser.userPrincipalName = upn 48 | 49 | var readyExpectation = expectationWithDescription("ready") 50 | 51 | var validCreatedUser: MSGraphUser! 52 | 53 | graphClient.users().request().addUser(newUser) { (createdUser: MSGraphUser?, error: NSError?) in 54 | 55 | XCTAssertNotNil(newUser) 56 | XCTAssertNil(error) 57 | 58 | validCreatedUser = createdUser 59 | 60 | readyExpectation.fulfill() 61 | } 62 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 63 | XCTAssertNil(error, "Timeout") 64 | return 65 | } 66 | 67 | readyExpectation = expectationWithDescription("ready") 68 | 69 | 70 | graphClient.users(validCreatedUser.entityId).request().deleteWithCompletion { (error: NSError?) in 71 | XCTAssertNil(error) 72 | readyExpectation.fulfill() 73 | } 74 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 75 | XCTAssertNil(error, "Timeout") 76 | return 77 | } 78 | } 79 | 80 | 81 | func testGetUserGroups() { 82 | 83 | let readyExpectation = expectationWithDescription("ready") 84 | 85 | graphClient.me().memberOf().request().getWithCompletion { (userGroupCollection: MSCollection?, 86 | nextRequest: MSGraphUserMemberOfCollectionWithReferencesRequest?, 87 | error: NSError?) in 88 | 89 | XCTAssertNotNil(userGroupCollection) 90 | XCTAssertNil(error) 91 | 92 | readyExpectation.fulfill() 93 | } 94 | 95 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 96 | XCTAssertNil(error, "Timeout") 97 | return 98 | } 99 | } 100 | 101 | func testGetAllGroups() { 102 | 103 | let readyExpectation = expectationWithDescription("ready") 104 | 105 | graphClient.groups().request().getWithCompletion { (allGroupsCollection: MSCollection?, nextRequest: MSGraphGroupsCollectionRequest?, error: NSError?) in 106 | XCTAssertNotNil(allGroupsCollection) 107 | XCTAssertNil(error) 108 | 109 | readyExpectation.fulfill() 110 | } 111 | 112 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 113 | XCTAssertNil(error, "Timeout") 114 | return 115 | } 116 | } 117 | 118 | func testGetSingleGroup() { 119 | 120 | var readyExpectation = expectationWithDescription("ready") 121 | var validGroupId: String? 122 | 123 | // get all groups first 124 | graphClient.groups().request().getWithCompletion { (allGroupsCollection: MSCollection?, nextRequest: MSGraphGroupsCollectionRequest?, error: NSError?) in 125 | XCTAssertNotNil(allGroupsCollection) 126 | XCTAssertNil(error) 127 | 128 | if let allGroups = allGroupsCollection { 129 | print((allGroups.value[0] as! MSGraphDirectoryObject).dictionaryFromItem()["id"]) 130 | 131 | validGroupId = (allGroups.value[0] as! MSGraphDirectoryObject).dictionaryFromItem()["id"] as? String 132 | } 133 | 134 | readyExpectation.fulfill() 135 | } 136 | 137 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 138 | XCTAssertNil(error, "Timeout") 139 | return 140 | } 141 | 142 | XCTAssertNotNil(validGroupId) 143 | 144 | 145 | readyExpectation = expectationWithDescription("ready") 146 | 147 | graphClient.groups(validGroupId).request().getWithCompletion { (singleGroup: MSGraphGroup?, error: NSError?) in 148 | 149 | XCTAssertNotNil(singleGroup) 150 | XCTAssertNil(error) 151 | 152 | readyExpectation.fulfill() 153 | } 154 | 155 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 156 | XCTAssertNil(error, "Timeout") 157 | return 158 | } 159 | 160 | } 161 | 162 | func testGetMembers() { 163 | 164 | var readyExpectation = expectationWithDescription("ready") 165 | var validGroupId: String? 166 | 167 | // get all groups first 168 | graphClient.groups().request().getWithCompletion { (allGroupsCollection: MSCollection?, nextRequest: MSGraphGroupsCollectionRequest?, error: NSError?) in 169 | XCTAssertNotNil(allGroupsCollection) 170 | XCTAssertNil(error) 171 | 172 | if let allGroups = allGroupsCollection { 173 | print((allGroups.value[0] as! MSGraphDirectoryObject).dictionaryFromItem()["id"]) 174 | 175 | validGroupId = (allGroups.value[0] as! MSGraphDirectoryObject).dictionaryFromItem()["id"] as? String 176 | } 177 | 178 | readyExpectation.fulfill() 179 | } 180 | 181 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 182 | XCTAssertNil(error, "Timeout") 183 | return 184 | } 185 | 186 | XCTAssertNotNil(validGroupId) 187 | 188 | 189 | readyExpectation = expectationWithDescription("ready") 190 | 191 | graphClient.groups(validGroupId).members().request().getWithCompletion { (memberCollection: MSCollection?, nextRequest: MSGraphGroupMembersCollectionWithReferencesRequest?, error: NSError?) in 192 | 193 | XCTAssertNotNil(memberCollection) 194 | XCTAssertNil(error) 195 | 196 | readyExpectation.fulfill() 197 | } 198 | 199 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 200 | XCTAssertNil(error, "Timeout") 201 | return 202 | } 203 | 204 | 205 | } 206 | 207 | func testGetOwners() { 208 | 209 | var readyExpectation = expectationWithDescription("ready") 210 | var validGroupId: String? 211 | 212 | // get all groups first 213 | graphClient.groups().request().getWithCompletion { (allGroupsCollection: MSCollection?, nextRequest: MSGraphGroupsCollectionRequest?, error: NSError?) in 214 | XCTAssertNotNil(allGroupsCollection) 215 | XCTAssertNil(error) 216 | 217 | if let allGroups = allGroupsCollection { 218 | print((allGroups.value[0] as! MSGraphDirectoryObject).dictionaryFromItem()["id"]) 219 | 220 | validGroupId = (allGroups.value[0] as! MSGraphDirectoryObject).dictionaryFromItem()["id"] as? String 221 | } 222 | 223 | readyExpectation.fulfill() 224 | } 225 | 226 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 227 | XCTAssertNil(error, "Timeout") 228 | return 229 | } 230 | 231 | XCTAssertNotNil(validGroupId) 232 | 233 | 234 | readyExpectation = expectationWithDescription("ready") 235 | 236 | graphClient.groups(validGroupId).owners().request().getWithCompletion { (memberCollection: MSCollection?, nextRequest: MSGraphGroupOwnersCollectionWithReferencesRequest?, error: NSError?) in 237 | 238 | XCTAssertNotNil(memberCollection) 239 | XCTAssertNil(error) 240 | 241 | readyExpectation.fulfill() 242 | } 243 | 244 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 245 | XCTAssertNil(error, "Timeout") 246 | return 247 | } 248 | 249 | 250 | } 251 | 252 | func testGroupOperations() { 253 | 254 | var validGroup: MSGraphGroup? 255 | var readyExpectation = expectationWithDescription("ready") 256 | 257 | // create group 258 | 259 | let group = Snippets.createGroupObject() 260 | graphClient.groups().request().addGroup(group) { (addedGroup: MSGraphGroup?, error: NSError?) in 261 | 262 | XCTAssertNotNil(addedGroup) 263 | XCTAssertNil(error) 264 | 265 | validGroup = addedGroup 266 | 267 | readyExpectation.fulfill() 268 | } 269 | 270 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 271 | XCTAssertNil(error, "Timeout") 272 | return 273 | } 274 | 275 | 276 | // update group 277 | 278 | guard let singleGroup = validGroup else { 279 | XCTAssertTrue(true) 280 | return 281 | } 282 | 283 | singleGroup.displayName = "Update namexxx" 284 | 285 | 286 | print("id", singleGroup.entityId) 287 | print("name", singleGroup.displayName) 288 | print("singleGroup", singleGroup) 289 | 290 | readyExpectation = expectationWithDescription("ready") 291 | 292 | graphClient.groups(singleGroup.entityId).request().update(singleGroup) { (updatedGroup: MSGraphGroup?, error: NSError?) in 293 | print(updatedGroup) 294 | print(error) 295 | 296 | XCTAssertNil(error) 297 | 298 | readyExpectation.fulfill() 299 | } 300 | 301 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 302 | XCTAssertNil(error, "Timeout") 303 | return 304 | } 305 | // delete group 306 | readyExpectation = expectationWithDescription("ready") 307 | 308 | graphClient.groups(validGroup!.entityId).request().deleteWithCompletion { (error: NSError?) in 309 | XCTAssertNil(error) 310 | readyExpectation.fulfill() 311 | } 312 | 313 | 314 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 315 | XCTAssertNil(error, "Timeout") 316 | return 317 | } 318 | } 319 | 320 | 321 | } 322 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/GroupsSnippets.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | import Foundation 7 | import MSGraphSDK 8 | 9 | // MARK: - Admin 10 | // Applicable to work accounts with admin rights 11 | 12 | // Creates a new user in the tenant. 13 | struct CreateUser: Snippet 14 | { 15 | let name = "Create user" 16 | let needAdminAccess: Bool = true 17 | 18 | func execute(with completion: @escaping (_ result: Result) -> Void) 19 | { 20 | let userId = ProcessInfo.processInfo.globallyUniqueString 21 | let domainName = "ENTER_DOMAIN_NAME" 22 | let upn = userId + "@" + domainName 23 | 24 | let newUser = MSGraphUser() 25 | let passwordProfile = MSGraphPasswordProfile() 26 | passwordProfile.password = "!pass!word1" 27 | 28 | newUser.accountEnabled = true 29 | newUser.displayName = userId 30 | newUser.passwordProfile = passwordProfile 31 | newUser.mailNickname = userId 32 | newUser.userPrincipalName = upn 33 | 34 | Snippets.graphClient.users().request()?.add(newUser, withCompletion: { (createdUser, error) in 35 | if let nsError = error as NSError? { 36 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 37 | return 38 | } else { 39 | guard let displayName = createdUser?.displayName else { 40 | completion(.Success(displayText: "User created - no user display name")) 41 | return 42 | } 43 | completion(.Success(displayText: "User created: \(displayName)")) 44 | } 45 | }) 46 | } 47 | } 48 | 49 | // Gets a collection of groups that the signed-in user is a member of. 50 | struct GetUserGroups: Snippet 51 | { 52 | let name = "Get user groups" 53 | let needAdminAccess: Bool = true 54 | 55 | func execute(with completion: @escaping (_ result: Result) -> Void) 56 | { 57 | Snippets.graphClient.me().memberOf().request()?.getWithCompletion({ (userGroupCollection, nextRequest, error) in 58 | if let nsError = error as NSError? { 59 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 60 | return 61 | } 62 | 63 | var displayString = "List of groups: \n" 64 | 65 | if let userGroups = userGroupCollection { 66 | for userGroup: MSGraphDirectoryObject in userGroups.value as! [MSGraphDirectoryObject] { 67 | guard let name = userGroup.dictionaryFromItem()["displayName"] else { 68 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Display name not found"))) 69 | return 70 | } 71 | displayString += "\(name)\n" 72 | } 73 | } 74 | if let _ = nextRequest { 75 | displayString += "Next request available for more groups" 76 | } 77 | 78 | completion(.Success(displayText: displayString)) 79 | }) 80 | } 81 | } 82 | 83 | // Returns all of the groups in your tenant's directory. 84 | struct GetAllGroups: Snippet 85 | { 86 | let name = "Get all groups" 87 | let needAdminAccess: Bool = true 88 | 89 | func execute(with completion: @escaping (_ result: Result) -> Void) 90 | { 91 | Snippets.graphClient.groups().request()?.getWithCompletion({ (allGroupsCollection, nextRequest, error) in 92 | if let nsError = error as NSError? { 93 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 94 | return 95 | } 96 | 97 | var displayString = "List of all groups: \n" 98 | 99 | if let allGroups = allGroupsCollection { 100 | for group: MSGraphDirectoryObject in allGroups.value as! [MSGraphDirectoryObject] { 101 | 102 | guard let name = group.dictionaryFromItem()["displayName"] else { 103 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Display name not found"))) 104 | return 105 | } 106 | displayString += "\(name)\n " 107 | } 108 | } 109 | if let _ = nextRequest { 110 | displayString += "Next request available for more groups" 111 | } 112 | 113 | completion(.Success(displayText: displayString)) 114 | }) 115 | } 116 | } 117 | 118 | // Gets a specified group. 119 | struct GetSingleGroup: Snippet 120 | { 121 | let name = "Get single group" 122 | let needAdminAccess: Bool = true 123 | 124 | func execute(with completion: @escaping (_ result: Result) -> Void) 125 | { 126 | // Enter a valid group ID, 127 | // This can be found from getting list of groups or creating a new group 128 | let groupId: String = "ENTER_GROUP_ID" 129 | 130 | Snippets.graphClient.groups(groupId).request().getWithCompletion({ (singleGroup, error) in 131 | if let nsError = error as NSError? { 132 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 133 | return 134 | } else { 135 | completion(.Success(displayText: "Retrieved group: \(singleGroup!)")) 136 | } 137 | }) 138 | } 139 | } 140 | 141 | //Gets a specific group's members. 142 | struct GetMembers: Snippet 143 | { 144 | let name = "Get members" 145 | let needAdminAccess: Bool = true 146 | 147 | func execute(with completion: @escaping (_ result: Result) -> Void) 148 | { 149 | // Enter a valid group ID, 150 | // This can be found from getting list of groups or creating a new group 151 | let groupId: String = "ENTER_GROUP_ID" 152 | 153 | Snippets.graphClient.groups(groupId).members().request().getWithCompletion({ (memberCollection, nextRequest, error) in 154 | if let nsError = error as NSError? { 155 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 156 | return 157 | } else { 158 | var displayString = "List of members:\n" 159 | 160 | for member: MSGraphDirectoryObject in memberCollection!.value as! [MSGraphDirectoryObject] { 161 | guard let name = member.dictionaryFromItem()["displayName"] else { 162 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Display name not found"))) 163 | return 164 | } 165 | displayString += name as! String + "\n" 166 | } 167 | 168 | if let _ = nextRequest { 169 | displayString += "Next request available for more members" 170 | } 171 | 172 | completion(.Success(displayText: "List of members:\n\(displayString)")) 173 | } 174 | }) 175 | } 176 | } 177 | 178 | // Gets a specific group's owners. 179 | struct GetOwners: Snippet 180 | { 181 | let name = "Get owners" 182 | let needAdminAccess: Bool = true 183 | 184 | func execute(with completion: @escaping (_ result: Result) -> Void) 185 | { 186 | // Enter a valid group ID, 187 | // This can be found from getting list of groups or creating a new group 188 | let groupId: String = "ENTER_GROUP_ID" //"047dc3cc-88ce-4f55-82f3-f8fe8c79f393" 189 | 190 | Snippets.graphClient.groups(groupId).owners().request().getWithCompletion({ (memberCollection, nextRequest, error) in 191 | if let nsError = error as NSError? { 192 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 193 | return 194 | } else { 195 | var displayString = "List of owners:\n" 196 | 197 | for member: MSGraphDirectoryObject in memberCollection!.value as! [MSGraphDirectoryObject] { 198 | guard let name = member.dictionaryFromItem()["displayName"] else { 199 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Display name not found"))) 200 | return 201 | } 202 | displayString += name as! String + "\n" 203 | } 204 | 205 | if let _ = nextRequest { 206 | displayString += "Next request available for more members" 207 | } 208 | 209 | completion(.Success(displayText: "List of owners:\n\(displayString)")) 210 | } 211 | }) 212 | } 213 | } 214 | 215 | // Creates a group in user's account. 216 | struct CreateGroup: Snippet 217 | { 218 | let name = "Create group" 219 | let needAdminAccess: Bool = true 220 | 221 | func execute(with completion: @escaping (_ result: Result) -> Void) 222 | { 223 | let group = Snippets.createGroupObject() 224 | 225 | Snippets.graphClient.groups().request().add(group) { (addedGroup, error) in 226 | if let nsError = error as NSError? { 227 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 228 | return 229 | } else { 230 | guard let _ = addedGroup else { 231 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Group ID not returned"))) 232 | return 233 | } 234 | print("id", addedGroup!.entityId) 235 | let displayName = addedGroup?.displayName ?? "" 236 | completion(.Success(displayText: "Group \(displayName) was added")) 237 | } 238 | } 239 | } 240 | } 241 | 242 | // Creates and updates a group in user's account. 243 | struct UpdateGroup: Snippet 244 | { 245 | let name = "Update group" 246 | let needAdminAccess: Bool = true 247 | func execute(with completion: @escaping (_ result: Result) -> Void) { 248 | 249 | // Enter a valid group ID, 250 | // This can be found from getting list of groups or creating a new group 251 | let groupId: String = "070fcdec-b187-498e-8c1e-663e3e7fb418" //"047dc3cc-88ce-4f55-82f3-f8fe8c79f393" 252 | 253 | Snippets.graphClient.groups(groupId).request().getWithCompletion { (group, error) in 254 | if let nsError = error as NSError? { 255 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 256 | return 257 | } else { 258 | guard let validGroup = group else { 259 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Group ID not returned"))) 260 | return 261 | } 262 | 263 | validGroup.displayName = "Updated group display name" 264 | Snippets.graphClient.groups(validGroup.entityId).request().update(validGroup, withCompletion: { (group, error) in 265 | if let nsError = error as NSError? { 266 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 267 | return 268 | } else { 269 | let displayName = group?.displayName ?? "" 270 | completion(.Success(displayText: "Group \(displayName) updated")) 271 | } 272 | }) 273 | } 274 | } 275 | } 276 | } 277 | 278 | // Creates and deletes a group in user's account. 279 | struct DeleteGroup: Snippet 280 | { 281 | let name = "Delete group" 282 | let needAdminAccess: Bool = true 283 | 284 | func execute(with completion: @escaping (_ result: Result) -> Void) { 285 | 286 | // Enter a valid group ID, 287 | // This can be found from getting list of groups or creating a new group 288 | let groupId: String = "ENTER_GROUP_ID" //"047dc3cc-88ce-4f55-82f3-f8fe8c79f393" 289 | 290 | Snippets.graphClient.groups(groupId).request().delete(completion: { (error) in 291 | if let nsError = error as NSError? { 292 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 293 | return 294 | } else { 295 | completion(.Success(displayText: "Group has been deleted")) 296 | } 297 | }) 298 | } 299 | } 300 | 301 | // MARK: - Helper methods 302 | 303 | extension Snippets { 304 | 305 | static func createGroupObject() -> MSGraphGroup { 306 | let group = MSGraphGroup() 307 | group.displayName = "New sample group" 308 | group.mailEnabled = true 309 | group.mailNickname = "samplemailnickname" 310 | group.securityEnabled = false 311 | group.groupTypes = ["Unified"] 312 | 313 | return group 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contribute to this documentation 2 | 3 | Thank you for your interest in our documentation! 4 | 5 | * [Ways to contribute](#ways-to-contribute) 6 | * [Contribute using GitHub](#contribute-using-github) 7 | * [Contribute using Git](#contribute-using-git) 8 | * [How to use Markdown to format your topic](#how-to-use-markdown-to-format-your-topic) 9 | * [FAQ](#faq) 10 | * [More resources](#more-resources) 11 | 12 | ## Ways to contribute 13 | 14 | Here are some ways you can contribute to this documentation: 15 | 16 | * To make small changes to an article, [Contribute using GitHub](#contribute-using-github). 17 | * To make large changes, or changes that involve code, [Contribute using Git](#contribute-using-git). 18 | * Report documentation bugs via GitHub Issues 19 | * Request new documentation at the [Office Developer Platform UserVoice](http://officespdev.uservoice.com) site. 20 | 21 | ## Contribute using GitHub 22 | 23 | Use GitHub to contribute to this documentation without having to clone the repo to your desktop. This is the easiest way to create a pull request in this repository. Use this method to make a minor change that doesn't involve code changes. 24 | 25 | **Note** Using this method allows you to contribute to one article at a time. 26 | 27 | ### To Contribute using GitHub 28 | 29 | 1. Find the article you want to contribute to on GitHub. 30 | 31 | If the article is in MSDN, choose the **suggest and submit changes** link in the **Contribute to this content** section and you'll be taken to the same article on GitHub. 32 | 2. Once you are on the article in GitHub, sign in to GitHub (get a free account [Join GitHub](https://github.com/join). 33 | 3. Choose the **pencil icon** (edit the file in your fork of this project) and make your changes in the **<>Edit file** window. 34 | 4. Scroll to the bottom and enter a description. 35 | 5. Choose **Propose file change**>**Create pull request**. 36 | 37 | You now have successfully submitted a pull request. Pull requests are typically reviewed within 10 business days. 38 | 39 | 40 | ## Contribute using Git 41 | 42 | Use Git to contribute substantive changes, such as: 43 | 44 | * Contributing code. 45 | * Contributing changes that affect meaning. 46 | * Contributing large changes to text. 47 | * Adding new topics. 48 | 49 | ### To Contribute using Git 50 | 51 | 1. If you don't have a GitHub account, set one up at [GitHub](https://github.com/join). 52 | 2. After you have an account, install Git on your computer. Follow the steps in [Setting up Git Tutorial](https://help.github.com/articles/set-up-git/). 53 | 3. To submit a pull request using Git, follow the steps in [Use GitHub, Git, and this repository](#use-github-git-and-this-repository). 54 | 4. You will be asked to sign the Contributor's License Agreement if you are: 55 | 56 | * A member of the Microsoft Open Technologies group. 57 | * A contributors who doesn't work for Microsoft. 58 | 59 | As a community member, you must sign the Contribution License Agreement (CLA) before you can contribute large submissions to a project. You only need to complete and submit the documentation once. Carefully review the document. You may be required to have your employer sign the document. 60 | 61 | Signing the CLA does not grant you rights to commit to the main repository, but it does mean that the Office Developer and Office Developer Content Publishing teams will be able to review and approve your contributions. You will be credited for your submissions. 62 | 63 | Pull requests are typically reviewed within 10 business days. 64 | 65 | ## Use GitHub, Git, and this repository 66 | 67 | **Note:** Most of the information in this section can be found in [GitHub Help] articles. If you're familiar with Git and GitHub, skip to the **Contribute and edit content** section for the specifics of the code/content flow of this repository. 68 | 69 | ### To set up your fork of the repository 70 | 71 | 1. Set up a GitHub account so you can contribute to this project. If you haven't done this, go to [GitHub](https://github.com/join) and do it now. 72 | 2. Install Git on your computer. Follow the steps in the [Setting up Git Tutorial] [Set Up Git]. 73 | 3. Create your own fork of this repository. To do this, at the top of the page, choose the **Fork** button. 74 | 4. Copy your fork to your computer. To do this, open Git Bash. At the command prompt enter: 75 | 76 | git clone https://github.com//.git 77 | 78 | Next, create a reference to the root repository by entering these commands: 79 | 80 | cd 81 | git remote add upstream https://github.com/microsoftgraph/.git 82 | git fetch upstream 83 | 84 | Congratulations! You've now set up your repository. You won't need to repeat these steps again. 85 | 86 | ### Contribute and edit content 87 | 88 | To make the contribution process as seamless as possible, follow these steps. 89 | 90 | #### To contribute and edit content 91 | 92 | 1. Create a new branch. 93 | 2. Add new content or edit existing content. 94 | 3. Submit a pull request to the main repository. 95 | 4. Delete the branch. 96 | 97 | **Important** Limit each branch to a single concept/article to streamline the work flow and reduce the chance of merge conflicts. Content appropriate for a new branch includes: 98 | 99 | * A new article. 100 | * Spelling and grammar edits. 101 | * Applying a single formatting change across a large set of articles (for example, applying a new copyright footer). 102 | 103 | #### To create a new branch 104 | 105 | 1. Open Git Bash. 106 | 2. At the Git Bash command prompt, type `git pull upstream master:`. This creates a new branch locally that is copied from the latest MicrosoftGraph master branch. 107 | 3. At the Git Bash command prompt, type `git push origin `. This alerts GitHub to the new branch. You should now see the new branch in your fork of the repository on GitHub. 108 | 4. At the Git Bash command prompt, type `git checkout ` to switch to your new branch. 109 | 110 | #### Add new content or edit existing content 111 | 112 | You navigate to the repository on your computer by using File Explorer. The repository files are in `C:\Users\\`. 113 | 114 | To edit files, open them in an editor of your choice and modify them. To create a new file, use the editor of your choice and save the new file in the appropriate location in your local copy of the repository. While working, save your work frequently. 115 | 116 | The files in `C:\Users\\` are a working copy of the new branch that you created in your local repository. Changing anything in this folder doesn't affect the local repository until you commit a change. To commit a change to the local repository, type the following commands in GitBash: 117 | 118 | git add . 119 | git commit -v -a -m "" 120 | 121 | The `add` command adds your changes to a staging area in preparation for committing them to the repository. The period after the `add` command specifies that you want to stage all of the files that you added or modified, checking subfolders recursively. (If you don't want to commit all of the changes, you can add specific files. You can also undo a commit. For help, type `git add -help` or `git status`.) 122 | 123 | The `commit` command applies the staged changes to the repository. The switch `-m` means you are providing the commit comment in the command line. The -v and -a switches can be omitted. The -v switch is for verbose output from the command, and -a does what you already did with the add command. 124 | 125 | You can commit multiple times while you are doing your work, or you can commit once when you're done. 126 | 127 | #### Submit a pull request to the main repository 128 | 129 | When you're finished with your work and are ready to have it merged into the main repository, follow these steps. 130 | 131 | #### To submit a pull request to the main repository 132 | 133 | 1. In the Git Bash command prompt, type `git push origin `. In your local repository, `origin` refers to your GitHub repository that you cloned the local repository from. This command pushes the current state of your new branch, including all commits made in the previous steps, to your GitHub fork. 134 | 2. On the GitHub site, navigate in your fork to the new branch. 135 | 3. Choose the **Pull Request** button at the top of the page. 136 | 4. Verify the Base branch is `microsoftgraph/@master` and the Head branch is `/@`. 137 | 5. Choose the **Update Commit Range** button. 138 | 6. Add a title to your pull request, and describe all the changes you're making. 139 | 7. Submit the pull request. 140 | 141 | One of the site administrators will process your pull request. Your pull request will surface on the microsoftgraph/ site under Issues. When the pull request is accepted, the issue will be resolved. 142 | 143 | #### Create a new branch after merge 144 | 145 | After a branch is successfully merged (that is, your pull request is accepted), don't continue working in that local branch. This can lead to merge conflicts if you submit another pull request. To do another update, create a new local branch from the successfully merged upstream branch, and then delete your initial local branch. 146 | 147 | For example, if your local branch X was successfully merged into the OfficeDev/microsoft-graph-docs master branch and you want to make additional updates to the content that was merged. Create a new local branch, X2, from the OfficeDev/microsoft-graph-docs master branch. To do this, open GitBash and execute the following commands: 148 | 149 | cd microsoft-graph-docs 150 | git pull upstream master:X2 151 | git push origin X2 152 | 153 | You now have local copies (in a new local branch) of the work that you submitted in branch X. The X2 branch also contains all the work other writers have merged, so if your work depends on others' work (for example, shared images), it is available in the new branch. You can verify that your previous work (and others' work) is in the branch by checking out the new branch... 154 | 155 | git checkout X2 156 | 157 | ...and verifying the content. (The `checkout` command updates the files in `C:\Users\\microsoft-graph-docs` to the current state of the X2 branch.) Once you check out the new branch, you can make updates to the content and commit them as usual. However, to avoid working in the merged branch (X) by mistake, it's best to delete it (see the following **Delete a branch** section). 158 | 159 | #### Delete a branch 160 | 161 | Once your changes are successfully merged into the main repository, delete the branch you used because you no longer need it. Any additional work should be done in a new branch. 162 | 163 | #### To delete a branch 164 | 165 | 1. In the Git Bash command prompt, type `git checkout master`. This ensures that you aren't in the branch to be deleted (which isn't allowed). 166 | 2. Next, at the command prompt, type `git branch -d `. This deletes the branch on your computer only if it has been successfully merged to the upstream repository. (You can override this behavior with the `–D` flag, but first be sure you want to do this.) 167 | 3. Finally, type `git push origin :` at the command prompt (a space before the colon and no space after it). This will delete the branch on your github fork. 168 | 169 | Congratulations, you have successfully contributed to the project! 170 | 171 | ## How to use Markdown to format your topic 172 | 173 | ### Article template 174 | 175 | The [markdown template](/articles/0-markdown-template-for-new-articles.md) contains the basic Markdown for a topic that includes a table of contents, sections with subheadings, links to other Office developer topics, links to other sites, bold text, italic text, numbered and bulleted lists, code snippets, and images. 176 | 177 | 178 | ### Standard Markdown 179 | 180 | All of the articles in this repository use Markdown. A complete introduction (and listing of all the syntax) can be found at [Markdown Home] []. 181 | 182 | ## FAQ 183 | 184 | ### How do I get a GitHub account? 185 | 186 | Fill out the form at [Join GitHub](https://github.com/join) to open a free GitHub account. 187 | 188 | ### Where do I get a Contributor's License Agreement? 189 | 190 | You will automatically be sent a notice that you need to sign the Contributor's License Agreement (CLA) if your pull request requires one. 191 | 192 | As a community member, **you must sign the Contribution License Agreement (CLA) before you can contribute large submissions to this project**. You only need complete and submit the documentation once. Carefully review the document. You may be required to have your employer sign the document. 193 | 194 | ### What happens with my contributions? 195 | 196 | When you submit your changes, via a pull request, our team will be notified and will review your pull request. You will receive notifications about your pull request from GitHub; you may also be notified by someone from our team if we need more information. We reserve the right to edit your submission for legal, style, clarity, or other issues. 197 | 198 | ### Can I become an approver for this repository's GitHub pull requests? 199 | 200 | Currently, we are not allowing external contributors to approve pull requests in this repository. 201 | 202 | ### How soon will I get a response about my change request or issue? 203 | 204 | We typically review pull requests and respond to issues within 10 business days. 205 | 206 | ## More resources 207 | 208 | * To learn more about Markdown, go to the Git creator's site [Daring Fireball]. 209 | * To learn more about using Git and GitHub, first check out the [GitHub Help section] [GitHub Help]. 210 | 211 | [GitHub Home]: http://github.com 212 | [GitHub Help]: http://help.github.com/ 213 | [Set Up Git]: http://help.github.com/win-set-up-git/ 214 | [Markdown Home]: http://daringfireball.net/projects/markdown/ 215 | [Daring Fireball]: http://daringfireball.net/ 216 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-SnippetsTests/UserSnippetsTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserSnippetsTest.swift 3 | // Graph-iOS-Swift-Snippets 4 | // 5 | // Created by Jason Kim on 7/11/16. 6 | // Copyright © 2016 Jason Kim. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import Graph_iOS_Swift_Snippets 12 | 13 | class UserSnippetsTest: XCTestCase { 14 | 15 | var authProvider: testAuthProvider! 16 | var graphClient: MSGraphClient! 17 | 18 | override func setUp() { 19 | super.setUp() 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | authProvider = testAuthProvider() 22 | 23 | MSGraphClient.setAuthenticationProvider(authProvider) 24 | graphClient = MSGraphClient.defaultClient() 25 | } 26 | 27 | // check for getting user information: GET ME 28 | func testGetMe() { 29 | let readyExpectation = expectationWithDescription("ready") 30 | graphClient.me().request().getWithCompletion({ (user: MSGraphUser?, error: NSError?) in 31 | XCTAssertNotNil(user, "User data should not be nil") 32 | XCTAssertNil(error, "Error should be nil") 33 | 34 | readyExpectation.fulfill() 35 | }) 36 | 37 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 38 | XCTAssertNil(error, "Timeout") 39 | return 40 | } 41 | } 42 | 43 | 44 | func testUsers() { 45 | let readyExpectation = expectationWithDescription("ready") 46 | graphClient.users().request().getWithCompletion { 47 | (userCollection: MSCollection?, nextRequest: MSGraphUsersCollectionRequest?, error: NSError?) in 48 | XCTAssertNotNil(userCollection, "Users data should not be nil") 49 | XCTAssertNil(error, "Error should be nil") 50 | 51 | readyExpectation.fulfill() 52 | } 53 | 54 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 55 | XCTAssertNil(error, "Timeout") 56 | return 57 | } 58 | } 59 | 60 | func testDrive() { 61 | let readyExpectation = expectationWithDescription("ready") 62 | graphClient.me().drive().request().getWithCompletion { 63 | (drive: MSGraphDrive?, error: NSError?) in 64 | XCTAssertNil(error, "Error should be nil") 65 | XCTAssertNotNil(drive) 66 | readyExpectation.fulfill() 67 | } 68 | 69 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 70 | XCTAssertNil(error, "Timeout") 71 | return 72 | } 73 | } 74 | 75 | 76 | 77 | func testEvent() { 78 | 79 | var readyExpectation = expectationWithDescription("ready") 80 | 81 | // Create event 82 | var event = Snippets.createEventObject(isSeries: false) 83 | 84 | graphClient.me().calendar().events().request().addEvent(event) { (newEvent: MSGraphEvent?, error: NSError?) in 85 | XCTAssertNotNil(newEvent) 86 | XCTAssertNil(error) 87 | 88 | event = newEvent! 89 | readyExpectation.fulfill() 90 | } 91 | 92 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 93 | XCTAssertNil(error, "Timeout") 94 | return 95 | } 96 | XCTAssertNotNil(event) 97 | 98 | // Update event 99 | readyExpectation = expectationWithDescription("ready") 100 | event.subject = "NEW NAME" 101 | graphClient.me().events(event.entityId).request().update(event) { (newEvent: MSGraphEvent?, error: NSError?) in 102 | XCTAssertNotNil(newEvent) 103 | XCTAssertNil(error) 104 | 105 | readyExpectation.fulfill() 106 | } 107 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 108 | XCTAssertNil(error, "Timeout") 109 | return 110 | } 111 | XCTAssertNotNil(event) 112 | 113 | // Delete event 114 | readyExpectation = expectationWithDescription("ready") 115 | event.subject = "NEW NAME" 116 | graphClient.me().events(event.entityId).request().deleteWithCompletion({ (error: NSError?) in 117 | XCTAssertNil(error) 118 | 119 | readyExpectation.fulfill() 120 | }) 121 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 122 | XCTAssertNil(error, "Timeout") 123 | return 124 | } 125 | 126 | } 127 | 128 | 129 | func testGetMessage() { 130 | 131 | let readyExpectation = expectationWithDescription("ready") 132 | 133 | graphClient.me().messages().request().getWithCompletion { (collection: MSCollection?, nextRequest: MSGraphUserMessagesCollectionRequest?, error: NSError?) in 134 | XCTAssertNil(error) 135 | XCTAssertNotNil(collection) 136 | 137 | readyExpectation.fulfill() 138 | } 139 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 140 | XCTAssertNil(error, "Timeout") 141 | return 142 | } 143 | } 144 | 145 | 146 | func testSendMessage() { 147 | 148 | // set message 149 | let message = MSGraphMessage() 150 | 151 | let toRecipient = MSGraphRecipient() 152 | let msEmailAddress = MSGraphEmailAddress() 153 | msEmailAddress.address = authProvider.userEmail 154 | toRecipient.emailAddress = msEmailAddress 155 | let toRecipientList = [toRecipient] 156 | message.toRecipients = toRecipientList 157 | message.subject = "Test mail from unit testing" 158 | let messageBody = MSGraphItemBody() 159 | messageBody.contentType = MSGraphBodyType.text() 160 | messageBody.content = "Mail received from the Office 365 iOS Microsoft Graph Snippets unit testing" 161 | message.body = messageBody 162 | 163 | // send message 164 | let readyExpectation = expectationWithDescription("ready") 165 | 166 | let mailRequest = graphClient.me().sendMailWithMessage(message, saveToSentItems: true).request() 167 | mailRequest.executeWithCompletion { (response: [NSObject : AnyObject]?, error: NSError?) in 168 | print(response?.keys) 169 | XCTAssertNotNil(response) 170 | XCTAssertNil(error) 171 | readyExpectation.fulfill() 172 | 173 | } 174 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 175 | XCTAssertNil(error, "Timeout") 176 | return 177 | } 178 | } 179 | 180 | 181 | func testGetUserFiles() { 182 | let readyExpectation: XCTestExpectation = expectationWithDescription("ready") 183 | 184 | 185 | graphClient.me().drive().root().children().request().getWithCompletion { (collection: MSCollection?, next: MSGraphDriveItemChildrenCollectionRequest?, error: NSError?) in 186 | XCTAssertNotNil(collection) 187 | XCTAssertNil(error) 188 | 189 | readyExpectation.fulfill() 190 | } 191 | 192 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 193 | XCTAssertNil(error, "Timeout") 194 | return 195 | } 196 | } 197 | 198 | func testFolderOperations() { 199 | var readyExpectation: XCTestExpectation 200 | 201 | // Create folder 202 | readyExpectation = expectationWithDescription("ready") 203 | 204 | // bug on conflictBehavior 205 | // https://github.com/OneDrive/onedrive-api-docs/issues/391 206 | var driveItem = MSGraphDriveItem(dictionary: [MSNameConflict.rename().key: MSNameConflict.rename().value]) 207 | driveItem.name = "TestFolder" 208 | driveItem.folder = MSGraphFolder() 209 | 210 | graphClient.me().drive().root().children().request().addDriveItem(driveItem) { (item: MSGraphDriveItem?, error: NSError?) in 211 | XCTAssertNotNil(item) 212 | XCTAssertNil(error) 213 | 214 | driveItem = item 215 | 216 | readyExpectation.fulfill() 217 | } 218 | 219 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 220 | XCTAssertNil(error, "Timeout") 221 | return 222 | } 223 | 224 | 225 | // Delete folder 226 | readyExpectation = expectationWithDescription("ready") 227 | 228 | graphClient.me().drive().items(driveItem.entityId).request().deleteWithCompletion { (error :NSError?) in 229 | XCTAssertNil(error) 230 | readyExpectation.fulfill() 231 | 232 | } 233 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 234 | XCTAssertNil(error, "Timeout") 235 | return 236 | } 237 | } 238 | 239 | func testFileOperations() { 240 | var readyExpectation: XCTestExpectation 241 | var driveItem: MSGraphDriveItem! 242 | 243 | // Create file 244 | readyExpectation = expectationWithDescription("ready") 245 | 246 | let uploadData = "Test".dataUsingEncoding(NSUTF8StringEncoding) 247 | 248 | graphClient.me().drive().root().itemByPath("/testFile.txt").contentRequest().uploadFromData(uploadData) { (item: MSGraphDriveItem?, error: NSError?) in 249 | XCTAssertNotNil(item) 250 | XCTAssertNil(error) 251 | 252 | driveItem = item! 253 | 254 | readyExpectation.fulfill() 255 | } 256 | 257 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 258 | XCTAssertNil(error, "Timeout") 259 | return 260 | } 261 | 262 | // rename file 263 | readyExpectation = expectationWithDescription("ready") 264 | 265 | driveItem.name = "testFile2.txt" 266 | graphClient.me().drive().items(driveItem.entityId).request().update(driveItem) { (item: MSGraphDriveItem?, error: NSError?) in 267 | XCTAssertNotNil(item) 268 | XCTAssertNil(error) 269 | 270 | XCTAssertTrue(item!.name == "testFile2.txt") 271 | 272 | driveItem = item! 273 | 274 | readyExpectation.fulfill() 275 | } 276 | 277 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 278 | XCTAssertNil(error, "Timeout") 279 | return 280 | } 281 | 282 | 283 | // download file 284 | readyExpectation = expectationWithDescription("ready") 285 | 286 | graphClient.me().drive().items(driveItem.entityId).contentRequest().downloadWithCompletion { (url: NSURL?, response: NSURLResponse?, error: NSError?) in 287 | XCTAssertNotNil(url) 288 | XCTAssertNil(error) 289 | 290 | do { 291 | try NSFileManager.defaultManager().removeItemAtURL(url!) 292 | } catch let error as NSError { 293 | XCTAssertNil(error, "Timeout") 294 | } 295 | 296 | readyExpectation.fulfill() 297 | } 298 | 299 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 300 | XCTAssertNil(error, "Timeout") 301 | return 302 | } 303 | 304 | 305 | // delete file 306 | readyExpectation = expectationWithDescription("ready") 307 | 308 | graphClient.me().drive().items(driveItem.entityId).request().deleteWithCompletion { (error :NSError?) in 309 | XCTAssertNil(error) 310 | readyExpectation.fulfill() 311 | } 312 | 313 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 314 | XCTAssertNil(error, "Timeout") 315 | return 316 | } 317 | 318 | } 319 | 320 | func testGetManager() { 321 | let readyExpectation: XCTestExpectation = expectationWithDescription("ready") 322 | 323 | graphClient.me().manager().request().getWithCompletion { (directoryObject: MSGraphDirectoryObject?, error: NSError?) in 324 | XCTAssertNotNil(directoryObject) 325 | XCTAssertNil(error) 326 | 327 | readyExpectation.fulfill() 328 | 329 | } 330 | 331 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 332 | XCTAssertNil(error, "Timeout") 333 | return 334 | } 335 | } 336 | 337 | func testGetDirects() { 338 | let readyExpectation: XCTestExpectation = expectationWithDescription("ready") 339 | 340 | 341 | graphClient.me().directReports().request().getWithCompletion { (directCollection: MSCollection?, nextRequest: MSGraphUserDirectReportsCollectionWithReferencesRequest?, error: NSError?) in 342 | XCTAssertNotNil(directCollection) 343 | XCTAssertNil(error) 344 | 345 | readyExpectation.fulfill() 346 | } 347 | 348 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 349 | XCTAssertNil(error, "Timeout") 350 | return 351 | } 352 | } 353 | 354 | func testGetPhoto() { 355 | let readyExpectation: XCTestExpectation = expectationWithDescription("ready") 356 | 357 | 358 | graphClient.me().photo().request().getWithCompletion { (photo: MSGraphProfilePhoto?, error: NSError?) in 359 | XCTAssertNotNil(photo) 360 | XCTAssertNil(error) 361 | 362 | readyExpectation.fulfill() 363 | } 364 | 365 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 366 | XCTAssertNil(error, "Timeout") 367 | return 368 | } 369 | } 370 | 371 | func testGetPhotoValue() { 372 | let readyExpectation: XCTestExpectation = expectationWithDescription("ready") 373 | 374 | 375 | graphClient.me().photoValue().downloadWithCompletion { (url: NSURL?, response: NSURLResponse?, error: NSError?) in 376 | XCTAssertNotNil(url) 377 | XCTAssertNil(error) 378 | 379 | do { 380 | try NSFileManager.defaultManager().removeItemAtURL(url!) 381 | } catch let error as NSError { 382 | XCTAssertNil(error, "Timeout") 383 | } 384 | 385 | readyExpectation.fulfill() 386 | } 387 | 388 | waitForExpectationsWithTimeout(10) { (error: NSError?) in 389 | XCTAssertNil(error, "Timeout") 390 | return 391 | } 392 | 393 | } 394 | 395 | 396 | 397 | 398 | } 399 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 960EBA121CEA8472007B8171 /* ConnectViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960EBA111CEA8472007B8171 /* ConnectViewController.swift */; }; 11 | 9682B8C31CEA92B500EEA064 /* AuthenticationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9682B8C21CEA92B500EEA064 /* AuthenticationProvider.swift */; }; 12 | 96B34CD41CE548C500B6F4E8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B34CD31CE548C500B6F4E8 /* AppDelegate.swift */; }; 13 | 96B34CD61CE548C500B6F4E8 /* MasterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B34CD51CE548C500B6F4E8 /* MasterViewController.swift */; }; 14 | 96B34CD81CE548C500B6F4E8 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B34CD71CE548C500B6F4E8 /* DetailViewController.swift */; }; 15 | 96B34CDB1CE548C500B6F4E8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96B34CD91CE548C500B6F4E8 /* Main.storyboard */; }; 16 | 96B34CDD1CE548C500B6F4E8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96B34CDC1CE548C500B6F4E8 /* Assets.xcassets */; }; 17 | 96B34CE01CE548C500B6F4E8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96B34CDE1CE548C500B6F4E8 /* LaunchScreen.storyboard */; }; 18 | 96B34CE81CE54D1000B6F4E8 /* Snippets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B34CE71CE54D1000B6F4E8 /* Snippets.swift */; }; 19 | 96C4ED931CF6165A00B97245 /* SampleImage.png in Resources */ = {isa = PBXBuildFile; fileRef = 96C4ED921CF6165A00B97245 /* SampleImage.png */; }; 20 | 96C4ED971CF6707600B97245 /* UserSnippets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C4ED961CF6707600B97245 /* UserSnippets.swift */; }; 21 | 96C4ED991CF6709D00B97245 /* GroupsSnippets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C4ED981CF6709D00B97245 /* GroupsSnippets.swift */; }; 22 | 96C80A781CEA93AA005D8FC4 /* ApplicationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C80A771CEA93AA005D8FC4 /* ApplicationConstants.swift */; }; 23 | 96E8E3761CF3D5CE00E3795C /* EmailBody.html in Resources */ = {isa = PBXBuildFile; fileRef = 96E8E3751CF3D5CE00E3795C /* EmailBody.html */; }; 24 | BDBB226ADB67255D4C8ED655 /* Pods_Graph_iOS_Swift_Snippets.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7636C72C1EBF480F90E6E63E /* Pods_Graph_iOS_Swift_Snippets.framework */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 1A6FD9F3B470B571895415AF /* Pods-Graph-iOS-Swift-Snippets.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Graph-iOS-Swift-Snippets.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Graph-iOS-Swift-Snippets/Pods-Graph-iOS-Swift-Snippets.debug.xcconfig"; sourceTree = ""; }; 29 | 238BA009227BB16D00A5BACD /* Graph-iOS-Swift-Snippets.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Graph-iOS-Swift-Snippets.entitlements"; sourceTree = ""; }; 30 | 7636C72C1EBF480F90E6E63E /* Pods_Graph_iOS_Swift_Snippets.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Graph_iOS_Swift_Snippets.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 88338EAC202F86B11BFC9413 /* Pods-Graph-iOS-Swift-Snippets.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Graph-iOS-Swift-Snippets.release.xcconfig"; path = "Pods/Target Support Files/Pods-Graph-iOS-Swift-Snippets/Pods-Graph-iOS-Swift-Snippets.release.xcconfig"; sourceTree = ""; }; 32 | 960EBA111CEA8472007B8171 /* ConnectViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectViewController.swift; sourceTree = ""; }; 33 | 9682B8C21CEA92B500EEA064 /* AuthenticationProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationProvider.swift; sourceTree = ""; }; 34 | 96B34CD01CE548C500B6F4E8 /* Graph-iOS-Swift-Snippets.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Graph-iOS-Swift-Snippets.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 96B34CD31CE548C500B6F4E8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 36 | 96B34CD51CE548C500B6F4E8 /* MasterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterViewController.swift; sourceTree = ""; }; 37 | 96B34CD71CE548C500B6F4E8 /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = ""; }; 38 | 96B34CDA1CE548C500B6F4E8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 39 | 96B34CDC1CE548C500B6F4E8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 40 | 96B34CDF1CE548C500B6F4E8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 41 | 96B34CE11CE548C500B6F4E8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | 96B34CE71CE54D1000B6F4E8 /* Snippets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Snippets.swift; sourceTree = ""; }; 43 | 96C4ED921CF6165A00B97245 /* SampleImage.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SampleImage.png; sourceTree = ""; }; 44 | 96C4ED961CF6707600B97245 /* UserSnippets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserSnippets.swift; sourceTree = ""; }; 45 | 96C4ED981CF6709D00B97245 /* GroupsSnippets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupsSnippets.swift; sourceTree = ""; }; 46 | 96C80A771CEA93AA005D8FC4 /* ApplicationConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationConstants.swift; sourceTree = ""; }; 47 | 96E8E3751CF3D5CE00E3795C /* EmailBody.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = EmailBody.html; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 96B34CCD1CE548C500B6F4E8 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | BDBB226ADB67255D4C8ED655 /* Pods_Graph_iOS_Swift_Snippets.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXFrameworksBuildPhase section */ 60 | 61 | /* Begin PBXGroup section */ 62 | 7C1FBF706E7B6E2D09FCBD79 /* Pods */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 1A6FD9F3B470B571895415AF /* Pods-Graph-iOS-Swift-Snippets.debug.xcconfig */, 66 | 88338EAC202F86B11BFC9413 /* Pods-Graph-iOS-Swift-Snippets.release.xcconfig */, 67 | ); 68 | name = Pods; 69 | sourceTree = ""; 70 | }; 71 | 96B34CC71CE548C500B6F4E8 = { 72 | isa = PBXGroup; 73 | children = ( 74 | 96B34CD21CE548C500B6F4E8 /* Graph-iOS-Swift-Snippets */, 75 | 96B34CD11CE548C500B6F4E8 /* Products */, 76 | 7C1FBF706E7B6E2D09FCBD79 /* Pods */, 77 | 9F04E14C6BD42E60D6DC42D4 /* Frameworks */, 78 | ); 79 | sourceTree = ""; 80 | }; 81 | 96B34CD11CE548C500B6F4E8 /* Products */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 96B34CD01CE548C500B6F4E8 /* Graph-iOS-Swift-Snippets.app */, 85 | ); 86 | name = Products; 87 | sourceTree = ""; 88 | }; 89 | 96B34CD21CE548C500B6F4E8 /* Graph-iOS-Swift-Snippets */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 238BA009227BB16D00A5BACD /* Graph-iOS-Swift-Snippets.entitlements */, 93 | 96C4ED9D1CF6716D00B97245 /* Application */, 94 | 96C4ED9C1CF6715600B97245 /* Views */, 95 | 96C4ED9B1CF6713300B97245 /* Authentication */, 96 | 96C4ED9A1CF6712200B97245 /* Controllers */, 97 | 96C4ED951CF6705D00B97245 /* Snippets */, 98 | 96C4ED941CF66BFD00B97245 /* Resources */, 99 | ); 100 | path = "Graph-iOS-Swift-Snippets"; 101 | sourceTree = ""; 102 | }; 103 | 96C4ED941CF66BFD00B97245 /* Resources */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 96B34CE11CE548C500B6F4E8 /* Info.plist */, 107 | 96B34CDC1CE548C500B6F4E8 /* Assets.xcassets */, 108 | 96C4ED921CF6165A00B97245 /* SampleImage.png */, 109 | 96E8E3751CF3D5CE00E3795C /* EmailBody.html */, 110 | ); 111 | name = Resources; 112 | sourceTree = ""; 113 | }; 114 | 96C4ED951CF6705D00B97245 /* Snippets */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 96B34CE71CE54D1000B6F4E8 /* Snippets.swift */, 118 | 96C4ED961CF6707600B97245 /* UserSnippets.swift */, 119 | 96C4ED981CF6709D00B97245 /* GroupsSnippets.swift */, 120 | ); 121 | name = Snippets; 122 | sourceTree = ""; 123 | }; 124 | 96C4ED9A1CF6712200B97245 /* Controllers */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 96B34CD31CE548C500B6F4E8 /* AppDelegate.swift */, 128 | 960EBA111CEA8472007B8171 /* ConnectViewController.swift */, 129 | 96B34CD51CE548C500B6F4E8 /* MasterViewController.swift */, 130 | 96B34CD71CE548C500B6F4E8 /* DetailViewController.swift */, 131 | ); 132 | name = Controllers; 133 | sourceTree = ""; 134 | }; 135 | 96C4ED9B1CF6713300B97245 /* Authentication */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 9682B8C21CEA92B500EEA064 /* AuthenticationProvider.swift */, 139 | ); 140 | name = Authentication; 141 | sourceTree = ""; 142 | }; 143 | 96C4ED9C1CF6715600B97245 /* Views */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 96B34CD91CE548C500B6F4E8 /* Main.storyboard */, 147 | 96B34CDE1CE548C500B6F4E8 /* LaunchScreen.storyboard */, 148 | ); 149 | name = Views; 150 | sourceTree = ""; 151 | }; 152 | 96C4ED9D1CF6716D00B97245 /* Application */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 96C80A771CEA93AA005D8FC4 /* ApplicationConstants.swift */, 156 | ); 157 | name = Application; 158 | sourceTree = ""; 159 | }; 160 | 9F04E14C6BD42E60D6DC42D4 /* Frameworks */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 7636C72C1EBF480F90E6E63E /* Pods_Graph_iOS_Swift_Snippets.framework */, 164 | ); 165 | name = Frameworks; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 96B34CCF1CE548C500B6F4E8 /* Graph-iOS-Swift-Snippets */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 96B34CE41CE548C500B6F4E8 /* Build configuration list for PBXNativeTarget "Graph-iOS-Swift-Snippets" */; 174 | buildPhases = ( 175 | 8548920E38D8B76ACEB030AB /* [CP] Check Pods Manifest.lock */, 176 | 96B34CCC1CE548C500B6F4E8 /* Sources */, 177 | 96B34CCD1CE548C500B6F4E8 /* Frameworks */, 178 | 96B34CCE1CE548C500B6F4E8 /* Resources */, 179 | 47FD35A13F916C6982C087C5 /* [CP] Embed Pods Frameworks */, 180 | ); 181 | buildRules = ( 182 | ); 183 | dependencies = ( 184 | ); 185 | name = "Graph-iOS-Swift-Snippets"; 186 | productName = "Graph-iOS-Swift-Snippets"; 187 | productReference = 96B34CD01CE548C500B6F4E8 /* Graph-iOS-Swift-Snippets.app */; 188 | productType = "com.apple.product-type.application"; 189 | }; 190 | /* End PBXNativeTarget section */ 191 | 192 | /* Begin PBXProject section */ 193 | 96B34CC81CE548C500B6F4E8 /* Project object */ = { 194 | isa = PBXProject; 195 | attributes = { 196 | LastSwiftUpdateCheck = 0730; 197 | LastUpgradeCheck = 1020; 198 | ORGANIZATIONNAME = "Jason Kim"; 199 | TargetAttributes = { 200 | 96B34CCF1CE548C500B6F4E8 = { 201 | CreatedOnToolsVersion = 7.3.1; 202 | SystemCapabilities = { 203 | com.apple.Keychain = { 204 | enabled = 1; 205 | }; 206 | }; 207 | }; 208 | }; 209 | }; 210 | buildConfigurationList = 96B34CCB1CE548C500B6F4E8 /* Build configuration list for PBXProject "Graph-iOS-Swift-Snippets" */; 211 | compatibilityVersion = "Xcode 3.2"; 212 | developmentRegion = en; 213 | hasScannedForEncodings = 0; 214 | knownRegions = ( 215 | en, 216 | Base, 217 | ); 218 | mainGroup = 96B34CC71CE548C500B6F4E8; 219 | productRefGroup = 96B34CD11CE548C500B6F4E8 /* Products */; 220 | projectDirPath = ""; 221 | projectRoot = ""; 222 | targets = ( 223 | 96B34CCF1CE548C500B6F4E8 /* Graph-iOS-Swift-Snippets */, 224 | ); 225 | }; 226 | /* End PBXProject section */ 227 | 228 | /* Begin PBXResourcesBuildPhase section */ 229 | 96B34CCE1CE548C500B6F4E8 /* Resources */ = { 230 | isa = PBXResourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | 96B34CE01CE548C500B6F4E8 /* LaunchScreen.storyboard in Resources */, 234 | 96C4ED931CF6165A00B97245 /* SampleImage.png in Resources */, 235 | 96B34CDD1CE548C500B6F4E8 /* Assets.xcassets in Resources */, 236 | 96B34CDB1CE548C500B6F4E8 /* Main.storyboard in Resources */, 237 | 96E8E3761CF3D5CE00E3795C /* EmailBody.html in Resources */, 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | }; 241 | /* End PBXResourcesBuildPhase section */ 242 | 243 | /* Begin PBXShellScriptBuildPhase section */ 244 | 47FD35A13F916C6982C087C5 /* [CP] Embed Pods Frameworks */ = { 245 | isa = PBXShellScriptBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | inputFileListPaths = ( 250 | ); 251 | inputPaths = ( 252 | "${PODS_ROOT}/Target Support Files/Pods-Graph-iOS-Swift-Snippets/Pods-Graph-iOS-Swift-Snippets-frameworks.sh", 253 | "${BUILT_PRODUCTS_DIR}/MSAL/MSAL.framework", 254 | "${BUILT_PRODUCTS_DIR}/MSGraphSDK/MSGraphSDK.framework", 255 | ); 256 | name = "[CP] Embed Pods Frameworks"; 257 | outputFileListPaths = ( 258 | ); 259 | outputPaths = ( 260 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MSAL.framework", 261 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MSGraphSDK.framework", 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | shellPath = /bin/sh; 265 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Graph-iOS-Swift-Snippets/Pods-Graph-iOS-Swift-Snippets-frameworks.sh\"\n"; 266 | showEnvVarsInLog = 0; 267 | }; 268 | 8548920E38D8B76ACEB030AB /* [CP] Check Pods Manifest.lock */ = { 269 | isa = PBXShellScriptBuildPhase; 270 | buildActionMask = 2147483647; 271 | files = ( 272 | ); 273 | inputPaths = ( 274 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 275 | "${PODS_ROOT}/Manifest.lock", 276 | ); 277 | name = "[CP] Check Pods Manifest.lock"; 278 | outputPaths = ( 279 | "$(DERIVED_FILE_DIR)/Pods-Graph-iOS-Swift-Snippets-checkManifestLockResult.txt", 280 | ); 281 | runOnlyForDeploymentPostprocessing = 0; 282 | shellPath = /bin/sh; 283 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 284 | showEnvVarsInLog = 0; 285 | }; 286 | /* End PBXShellScriptBuildPhase section */ 287 | 288 | /* Begin PBXSourcesBuildPhase section */ 289 | 96B34CCC1CE548C500B6F4E8 /* Sources */ = { 290 | isa = PBXSourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | 960EBA121CEA8472007B8171 /* ConnectViewController.swift in Sources */, 294 | 96B34CD81CE548C500B6F4E8 /* DetailViewController.swift in Sources */, 295 | 96C4ED971CF6707600B97245 /* UserSnippets.swift in Sources */, 296 | 96B34CD61CE548C500B6F4E8 /* MasterViewController.swift in Sources */, 297 | 96C4ED991CF6709D00B97245 /* GroupsSnippets.swift in Sources */, 298 | 96B34CD41CE548C500B6F4E8 /* AppDelegate.swift in Sources */, 299 | 96B34CE81CE54D1000B6F4E8 /* Snippets.swift in Sources */, 300 | 9682B8C31CEA92B500EEA064 /* AuthenticationProvider.swift in Sources */, 301 | 96C80A781CEA93AA005D8FC4 /* ApplicationConstants.swift in Sources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | /* End PBXSourcesBuildPhase section */ 306 | 307 | /* Begin PBXVariantGroup section */ 308 | 96B34CD91CE548C500B6F4E8 /* Main.storyboard */ = { 309 | isa = PBXVariantGroup; 310 | children = ( 311 | 96B34CDA1CE548C500B6F4E8 /* Base */, 312 | ); 313 | name = Main.storyboard; 314 | sourceTree = ""; 315 | }; 316 | 96B34CDE1CE548C500B6F4E8 /* LaunchScreen.storyboard */ = { 317 | isa = PBXVariantGroup; 318 | children = ( 319 | 96B34CDF1CE548C500B6F4E8 /* Base */, 320 | ); 321 | name = LaunchScreen.storyboard; 322 | sourceTree = ""; 323 | }; 324 | /* End PBXVariantGroup section */ 325 | 326 | /* Begin XCBuildConfiguration section */ 327 | 96B34CE21CE548C500B6F4E8 /* Debug */ = { 328 | isa = XCBuildConfiguration; 329 | buildSettings = { 330 | ALWAYS_SEARCH_USER_PATHS = NO; 331 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 332 | CLANG_ANALYZER_NONNULL = YES; 333 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 334 | CLANG_CXX_LIBRARY = "libc++"; 335 | CLANG_ENABLE_MODULES = YES; 336 | CLANG_ENABLE_OBJC_ARC = YES; 337 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 338 | CLANG_WARN_BOOL_CONVERSION = YES; 339 | CLANG_WARN_COMMA = YES; 340 | CLANG_WARN_CONSTANT_CONVERSION = YES; 341 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 342 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 343 | CLANG_WARN_EMPTY_BODY = YES; 344 | CLANG_WARN_ENUM_CONVERSION = YES; 345 | CLANG_WARN_INFINITE_RECURSION = YES; 346 | CLANG_WARN_INT_CONVERSION = YES; 347 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 348 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 349 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 350 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 351 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 352 | CLANG_WARN_STRICT_PROTOTYPES = YES; 353 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 354 | CLANG_WARN_UNREACHABLE_CODE = YES; 355 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 356 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 357 | COPY_PHASE_STRIP = NO; 358 | DEBUG_INFORMATION_FORMAT = dwarf; 359 | ENABLE_STRICT_OBJC_MSGSEND = YES; 360 | ENABLE_TESTABILITY = YES; 361 | GCC_C_LANGUAGE_STANDARD = gnu99; 362 | GCC_DYNAMIC_NO_PIC = NO; 363 | GCC_NO_COMMON_BLOCKS = YES; 364 | GCC_OPTIMIZATION_LEVEL = 0; 365 | GCC_PREPROCESSOR_DEFINITIONS = ( 366 | "DEBUG=1", 367 | "$(inherited)", 368 | ); 369 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 370 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 371 | GCC_WARN_UNDECLARED_SELECTOR = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 373 | GCC_WARN_UNUSED_FUNCTION = YES; 374 | GCC_WARN_UNUSED_VARIABLE = YES; 375 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 376 | MTL_ENABLE_DEBUG_INFO = YES; 377 | ONLY_ACTIVE_ARCH = YES; 378 | SDKROOT = iphoneos; 379 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 380 | }; 381 | name = Debug; 382 | }; 383 | 96B34CE31CE548C500B6F4E8 /* Release */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ALWAYS_SEARCH_USER_PATHS = NO; 387 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 388 | CLANG_ANALYZER_NONNULL = YES; 389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 390 | CLANG_CXX_LIBRARY = "libc++"; 391 | CLANG_ENABLE_MODULES = YES; 392 | CLANG_ENABLE_OBJC_ARC = YES; 393 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 394 | CLANG_WARN_BOOL_CONVERSION = YES; 395 | CLANG_WARN_COMMA = YES; 396 | CLANG_WARN_CONSTANT_CONVERSION = YES; 397 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 398 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 399 | CLANG_WARN_EMPTY_BODY = YES; 400 | CLANG_WARN_ENUM_CONVERSION = YES; 401 | CLANG_WARN_INFINITE_RECURSION = YES; 402 | CLANG_WARN_INT_CONVERSION = YES; 403 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 404 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 405 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 406 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 407 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 408 | CLANG_WARN_STRICT_PROTOTYPES = YES; 409 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 410 | CLANG_WARN_UNREACHABLE_CODE = YES; 411 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 412 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 413 | COPY_PHASE_STRIP = NO; 414 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 415 | ENABLE_NS_ASSERTIONS = NO; 416 | ENABLE_STRICT_OBJC_MSGSEND = YES; 417 | GCC_C_LANGUAGE_STANDARD = gnu99; 418 | GCC_NO_COMMON_BLOCKS = YES; 419 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 420 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 421 | GCC_WARN_UNDECLARED_SELECTOR = YES; 422 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 423 | GCC_WARN_UNUSED_FUNCTION = YES; 424 | GCC_WARN_UNUSED_VARIABLE = YES; 425 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 426 | MTL_ENABLE_DEBUG_INFO = NO; 427 | SDKROOT = iphoneos; 428 | SWIFT_COMPILATION_MODE = wholemodule; 429 | VALIDATE_PRODUCT = YES; 430 | }; 431 | name = Release; 432 | }; 433 | 96B34CE51CE548C500B6F4E8 /* Debug */ = { 434 | isa = XCBuildConfiguration; 435 | baseConfigurationReference = 1A6FD9F3B470B571895415AF /* Pods-Graph-iOS-Swift-Snippets.debug.xcconfig */; 436 | buildSettings = { 437 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 438 | CLANG_ENABLE_MODULES = YES; 439 | CODE_SIGN_ENTITLEMENTS = "Graph-iOS-Swift-Snippets/Graph-iOS-Swift-Snippets.entitlements"; 440 | DEVELOPMENT_TEAM = ""; 441 | INFOPLIST_FILE = "Graph-iOS-Swift-Snippets/Info.plist"; 442 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 443 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 444 | PRODUCT_BUNDLE_IDENTIFIER = "com.microsoft.Graph-iOS-Swift-Snippets"; 445 | PRODUCT_NAME = "$(TARGET_NAME)"; 446 | SWIFT_OBJC_BRIDGING_HEADER = ""; 447 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 448 | SWIFT_VERSION = 4.2; 449 | TARGETED_DEVICE_FAMILY = "1,2"; 450 | }; 451 | name = Debug; 452 | }; 453 | 96B34CE61CE548C500B6F4E8 /* Release */ = { 454 | isa = XCBuildConfiguration; 455 | baseConfigurationReference = 88338EAC202F86B11BFC9413 /* Pods-Graph-iOS-Swift-Snippets.release.xcconfig */; 456 | buildSettings = { 457 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 458 | CLANG_ENABLE_MODULES = YES; 459 | CODE_SIGN_ENTITLEMENTS = "Graph-iOS-Swift-Snippets/Graph-iOS-Swift-Snippets.entitlements"; 460 | DEVELOPMENT_TEAM = ""; 461 | INFOPLIST_FILE = "Graph-iOS-Swift-Snippets/Info.plist"; 462 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 463 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 464 | PRODUCT_BUNDLE_IDENTIFIER = "com.microsoft.Graph-iOS-Swift-Snippets"; 465 | PRODUCT_NAME = "$(TARGET_NAME)"; 466 | SWIFT_OBJC_BRIDGING_HEADER = ""; 467 | SWIFT_VERSION = 4.2; 468 | TARGETED_DEVICE_FAMILY = "1,2"; 469 | }; 470 | name = Release; 471 | }; 472 | /* End XCBuildConfiguration section */ 473 | 474 | /* Begin XCConfigurationList section */ 475 | 96B34CCB1CE548C500B6F4E8 /* Build configuration list for PBXProject "Graph-iOS-Swift-Snippets" */ = { 476 | isa = XCConfigurationList; 477 | buildConfigurations = ( 478 | 96B34CE21CE548C500B6F4E8 /* Debug */, 479 | 96B34CE31CE548C500B6F4E8 /* Release */, 480 | ); 481 | defaultConfigurationIsVisible = 0; 482 | defaultConfigurationName = Release; 483 | }; 484 | 96B34CE41CE548C500B6F4E8 /* Build configuration list for PBXNativeTarget "Graph-iOS-Swift-Snippets" */ = { 485 | isa = XCConfigurationList; 486 | buildConfigurations = ( 487 | 96B34CE51CE548C500B6F4E8 /* Debug */, 488 | 96B34CE61CE548C500B6F4E8 /* Release */, 489 | ); 490 | defaultConfigurationIsVisible = 0; 491 | defaultConfigurationName = Release; 492 | }; 493 | /* End XCConfigurationList section */ 494 | }; 495 | rootObject = 96B34CC81CE548C500B6F4E8 /* Project object */; 496 | } 497 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 60 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 188 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 256 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | -------------------------------------------------------------------------------- /Graph-iOS-Swift-Snippets/UserSnippets.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the project root for license information. 4 | */ 5 | 6 | import Foundation 7 | import MSGraphSDK 8 | 9 | // MARK: - User snippets 10 | 11 | // Returns select information about the signed-in user from Azure Active Directory. Applies to personal or work accounts 12 | struct GetMe: Snippet 13 | { 14 | let name = "Get me" 15 | let needAdminAccess: Bool = false 16 | 17 | func execute(with completion: @escaping (_ result: Result) -> Void) 18 | { 19 | Snippets.graphClient.me().request()?.getWithCompletion({ (user, error) in 20 | if let nsError = error as NSError? { 21 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 22 | } 23 | else { 24 | let displayName = user?.displayName ?? "" 25 | let displayString = "Retrieval of user account information succeeded for \(displayName)" 26 | completion(.Success(displayText: displayString)) 27 | } 28 | }) 29 | 30 | } 31 | } 32 | 33 | // Returns all of the users in your tenant's directory. 34 | // Applies to personal or work accounts. 35 | // nextRequest is a subsequent request if there are more users to be loaded. 36 | struct GetUsers: Snippet 37 | { 38 | let name = "Get users" 39 | let needAdminAccess: Bool = false 40 | 41 | func execute(with completion: @escaping (_ result: Result) -> Void) 42 | { 43 | Snippets.graphClient.users().request()?.getWithCompletion({ (userCollection, nextRequest, error) in 44 | if let nsError = error as NSError? { 45 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 46 | } 47 | else { 48 | var displayString = "List of users:\n" 49 | if let users = userCollection { 50 | 51 | for user: MSGraphUser in users.value as! [MSGraphUser] { 52 | displayString += user.displayName + "\n" 53 | } 54 | } 55 | 56 | if let _ = nextRequest { 57 | displayString += "Next request available for more users" 58 | } 59 | completion(.Success(displayText: displayString)) 60 | } 61 | }) 62 | } 63 | } 64 | 65 | // Gets the signed-in user's drive from OneDrive. 66 | // Applies to personal or work accounts 67 | struct GetDrive: Snippet 68 | { 69 | let name = "Get drive" 70 | let needAdminAccess: Bool = false 71 | 72 | func execute(with completion: @escaping (_ result: Result) -> Void) 73 | { 74 | Snippets.graphClient.me().drive().request()?.getWithCompletion({ (drive, error) in 75 | if let nsError = error as NSError? { 76 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 77 | } 78 | else { 79 | var displayString = "Drive information:\n" 80 | if let userDrive = drive { 81 | displayString += "Drive type is " + userDrive.driveType + "\n" 82 | displayString += "Total Quote is " + String(userDrive.quota.total) 83 | } 84 | completion(.Success(displayText: displayString)) 85 | } 86 | }) 87 | } 88 | 89 | } 90 | 91 | // Gets the signed-in user's events. 92 | // Applies to personal or work accounts 93 | struct GetEvents: Snippet 94 | { 95 | let name = "Get events" 96 | let needAdminAccess: Bool = false 97 | 98 | func execute(with completion: @escaping (_ result: Result) -> Void) 99 | { 100 | Snippets.graphClient.me().events().request()?.getWithCompletion({ (eventCollection, nextRequest, error) in 101 | if let nsError = error as NSError? { 102 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 103 | } 104 | else { 105 | var displayString = "List of events (subjects):\n" 106 | if let events = eventCollection { 107 | for event: MSGraphEvent in events.value as! [MSGraphEvent] { 108 | displayString += event.subject + "\n\n" 109 | } 110 | } 111 | 112 | if let _ = nextRequest { 113 | displayString += "Next request available for more users" 114 | } 115 | 116 | completion(.Success(displayText: displayString)) 117 | } 118 | }) 119 | } 120 | } 121 | 122 | 123 | // Create an event in the signed in user's calendar. 124 | // Applies to personal or work accounts 125 | struct CreateEvent: Snippet 126 | { 127 | let name = "Create event" 128 | let needAdminAccess: Bool = false 129 | 130 | func execute(with completion: @escaping (_ result: Result) -> Void) 131 | { 132 | let event = Snippets.createEventObject(isSeries: false) 133 | 134 | Snippets.graphClient.me().calendar().events()?.request()?.add(event, withCompletion: { (event, error) in 135 | if let nsError = error as NSError? { 136 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 137 | } else { 138 | let entityId = event?.entityId ?? "" 139 | let displayString = "Event created with id \(entityId)" 140 | completion(.Success(displayText: displayString)) 141 | } 142 | }) 143 | } 144 | } 145 | 146 | // 147 | // Updates an event in the signed in user's calendar. 148 | // Applies to personal or work accounts 149 | struct UpdateEvent: Snippet 150 | { 151 | let name = "Update event" 152 | let needAdminAccess: Bool = false 153 | 154 | func execute(with completion: @escaping (_ result: Result) -> Void) 155 | { 156 | // Enter a valid event id 157 | let eventId = "ENTER_VALID_EVENT_ID" 158 | 159 | // Get an event and then update 160 | 161 | Snippets.graphClient.me().events(eventId).request()?.getWithCompletion({ (event, error) in 162 | if let nsError = error as NSError? { 163 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 164 | } 165 | else { 166 | guard let validEvent = event else { 167 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Event ID not returned"))) 168 | return 169 | } 170 | validEvent.subject = "New Name" 171 | 172 | Snippets.graphClient.me().events(validEvent.entityId).request()?.update(validEvent, withCompletion: { (updatedEvent, error) in 173 | if let nsError = error as NSError? { 174 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 175 | } 176 | else { 177 | let displayString = "Event updated with a new subject" 178 | completion(.Success(displayText: displayString)) 179 | } 180 | }) 181 | } 182 | }) 183 | } 184 | } 185 | 186 | 187 | // Deletes an event in the signed in user's calendar. 188 | // Applies to personal or work accounts 189 | struct DeleteEevnt: Snippet 190 | { 191 | let name = "Delete event" 192 | let needAdminAccess: Bool = false 193 | 194 | func execute(with completion: @escaping (_ result: Result) -> Void) 195 | { 196 | // Enter a valid event id 197 | let eventId = "ENTER_VALID_EVENT_ID" 198 | 199 | Snippets.graphClient.me().events(eventId)?.request()?.delete(completion: { (error) in 200 | if let nsError = error as NSError? { 201 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 202 | } 203 | else { 204 | completion(.Success(displayText: "Deleted calendar event id: \(eventId)")) 205 | } 206 | }) 207 | } 208 | } 209 | 210 | 211 | // Gets the signed-in user's messages. 212 | // Applies to personal or work accounts 213 | struct GetMessages: Snippet 214 | { 215 | let name = "Get messages" 216 | let needAdminAccess: Bool = false 217 | 218 | func execute(with completion: @escaping (_ result: Result) -> Void) 219 | { 220 | Snippets.graphClient.me().messages().request()?.getWithCompletion({ (messageCollection, nextRequest, error) in 221 | if let nsError = error as NSError? { 222 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 223 | } 224 | else { 225 | var displayString = "List of messages:\n" 226 | if let messages = messageCollection { 227 | 228 | for message: MSGraphMessage in messages.value as! [MSGraphMessage] { 229 | displayString += message.subject + "\n\n" 230 | } 231 | } 232 | 233 | if let _ = nextRequest { 234 | displayString += "Next request available for more messages" 235 | } 236 | 237 | completion(.Success(displayText: displayString)) 238 | } 239 | }) 240 | 241 | } 242 | } 243 | 244 | 245 | // Create and send a message as the signed-in user. 246 | // Applies to personal or work accounts 247 | struct SendMessage: Snippet 248 | { 249 | let name = "Send mail" 250 | let needAdminAccess: Bool = false 251 | 252 | func execute(with completion: @escaping (_ result: Result) -> Void) 253 | { 254 | // ENTER EMAIL ADDRESS 255 | let recipientEmailAddress = "ENTER_EMAIL_ADDRESS" 256 | 257 | // =================================================================== 258 | // Set message 259 | // =================================================================== 260 | let message = MSGraphMessage() 261 | 262 | // Set recipients 263 | let toRecipient = MSGraphRecipient() 264 | let msEmailAddress = MSGraphEmailAddress() 265 | msEmailAddress.address = recipientEmailAddress 266 | toRecipient.emailAddress = msEmailAddress 267 | let toRecipientList = [toRecipient] 268 | message.toRecipients = toRecipientList 269 | 270 | // Subject 271 | message.subject = "Mail received from the Office 365 iOS Microsoft Graph Snippets Sample" 272 | 273 | // Body 274 | let messageBody = MSGraphItemBody() 275 | messageBody.contentType = MSGraphBodyType.text() 276 | messageBody.content = "Mail received from the Office 365 iOS Microsoft Graph Snippets Sample" 277 | 278 | message.body = messageBody 279 | 280 | // =================================================================== 281 | // Send message 282 | // =================================================================== 283 | 284 | guard let mailRequest = Snippets.graphClient.me()?.sendMail(with: message, saveToSentItems: true)?.request() else { return } 285 | mailRequest.execute { (response, error) in 286 | if let nsError = error as NSError? { 287 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 288 | } 289 | else { 290 | completion(.Success(displayText: "Message sent")) 291 | } 292 | } 293 | } 294 | } 295 | 296 | 297 | // Create and send a message as the signed-in user. 298 | // This one uses HTML message. 299 | // Applies to personal or work accounts 300 | struct SendMessageHTML: Snippet 301 | { 302 | let name = "Send HTML mail" 303 | let needAdminAccess: Bool = false 304 | func execute(with completion: @escaping (_ result: Result) -> Void) 305 | { 306 | // ENTER EMAIL ADDRESS 307 | let recipientEmailAddress = "ENTER_EMAIL_ADDRESS" 308 | 309 | // =================================================================== 310 | // Set message 311 | // =================================================================== 312 | let message = MSGraphMessage() 313 | 314 | // Set recipients 315 | let toRecipient = MSGraphRecipient() 316 | let msEmailAddress = MSGraphEmailAddress() 317 | msEmailAddress.address = recipientEmailAddress 318 | toRecipient.emailAddress = msEmailAddress 319 | let toRecipientList = [toRecipient] 320 | message.toRecipients = toRecipientList 321 | 322 | // Subject 323 | message.subject = "Mail received from the Office 365 iOS Microsoft Graph Snippets Sample" 324 | 325 | // Body 326 | let messageBody = MSGraphItemBody() 327 | messageBody.contentType = MSGraphBodyType.html() 328 | 329 | guard let emailBodyFilePath = Bundle.main.path(forResource: "EmailBody", ofType: "html") else { 330 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "EmailBody.html not found in resources"))) 331 | return 332 | } 333 | messageBody.content = try! String(contentsOfFile: emailBodyFilePath, encoding: String.Encoding.utf8) 334 | message.body = messageBody 335 | 336 | // =================================================================== 337 | // Send message 338 | // =================================================================== 339 | let mailRequest = Snippets.graphClient.me().sendMail(with: message, saveToSentItems: true).request() 340 | mailRequest?.execute(completion: { (response, error) in 341 | if let nsError = error as NSError? { 342 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 343 | } 344 | else { 345 | completion(.Success(displayText: "Message sent")) 346 | } 347 | }) 348 | } 349 | } 350 | 351 | // Returns all of the user's files. 352 | // Applies to personal or work accounts 353 | struct GetUserFiles: Snippet 354 | { 355 | let name = "Get user files" 356 | let needAdminAccess: Bool = false 357 | 358 | func execute(with completion: @escaping (_ result: Result) -> Void) 359 | { 360 | Snippets.graphClient.me().drive().root().children()?.request()?.getWithCompletion({ (fileCollection, nextRequest, error) in 361 | if let nsError = error as NSError? { 362 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 363 | } else { 364 | var displayString = "List of files: \n" 365 | if let files = fileCollection { 366 | 367 | for file: MSGraphDriveItem in files.value as! [MSGraphDriveItem] { 368 | let name = file.name ?? "" 369 | displayString += "\(name): \(file.size) \n" 370 | } 371 | } 372 | 373 | if let _ = nextRequest { 374 | displayString += "Next request available for more files" 375 | } 376 | 377 | completion(.Success(displayText: displayString)) 378 | } 379 | }) 380 | } 381 | } 382 | 383 | // Create a text file in the signed in user's OneDrive account. 384 | // If a file already exists it will be overwritten. 385 | // Applies to personal or work accounts 386 | struct CreateTextFile: Snippet 387 | { 388 | let name = "Create text file" 389 | let needAdminAccess: Bool = false 390 | func execute(with completion: @escaping (_ result: Result) -> Void) 391 | { 392 | let uploadData = "Test".data(using: String.Encoding.utf8) 393 | 394 | Snippets.graphClient.me().drive().root().item(byPath: "Test Folder/testTextfile.text").contentRequest()?.upload(from: uploadData, completion: { (item, error) in 395 | if let nsError = error as NSError? { 396 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 397 | } else { 398 | completion(.Success(displayText: "File created at Test Folder/testTextfile.text")) 399 | } 400 | }) 401 | } 402 | } 403 | 404 | // Upload an image file in the signed in user's OneDrive account. 405 | // Applies to personal or work accounts 406 | struct UploadFile: Snippet 407 | { 408 | let name = "Upload image file" 409 | let needAdminAccess: Bool = false 410 | func execute(with completion: @escaping (_ result: Result) -> Void) 411 | { 412 | let urlpath = Bundle.main.path(forResource: "SampleImage", ofType: "png") 413 | let url = NSURL.fileURL(withPath: urlpath!) 414 | 415 | Snippets.graphClient.me().drive().root().item(byPath: "sampleImage.png").contentRequest()?.upload(fromFile: url, completion: { (item, error) in 416 | if let nsError = error as NSError? { 417 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 418 | } else { 419 | completion(.Success(displayText: "File uploaded (sampleImage.png)")) 420 | } 421 | }) 422 | } 423 | } 424 | 425 | // Creates a new folder in the signed in user's OneDrive account. 426 | // Applies to personal or work accounts 427 | struct CreateFolder: Snippet 428 | { 429 | let name = "Create folder" 430 | let needAdminAccess: Bool = false 431 | func execute(with completion: @escaping (_ result: Result) -> Void) 432 | { 433 | let driveItem = MSGraphDriveItem(dictionary: [MSNameConflict.rename().key: MSNameConflict.rename().value]) 434 | driveItem?.name = "TestFolder" 435 | driveItem?.folder = MSGraphFolder() 436 | 437 | // Use itemByPath as below to create a subfolder under an existing folder 438 | // Snippets.graphClient.me().drive().root().itemByPath("existingFolder").request().getWithCompletion( 439 | Snippets.graphClient.me().drive().root().request()?.getWithCompletion({ (item, error) in 440 | if let nsError = error as NSError? { 441 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 442 | } 443 | 444 | guard let validItem = item else { 445 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Valid item not returned for a path"))) 446 | return 447 | } 448 | 449 | Snippets.graphClient.me().drive().items(validItem.entityId).children().request()?.add(driveItem, withCompletion: { (item, error) in 450 | if let nsError = error as NSError? { 451 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 452 | } else { 453 | let name = item?.name ?? "" 454 | completion(.Success(displayText: "Created a folder \(name)")) 455 | } 456 | }) 457 | }) 458 | } 459 | } 460 | 461 | 462 | // Downloads a file into the signed in user's OneDrive account. 463 | // Applies to personal or work accounts 464 | struct DownloadFile: Snippet 465 | { 466 | let name = "Download file" 467 | let needAdminAccess: Bool = false 468 | func execute(with completion: @escaping (_ result: Result) -> Void) { 469 | 470 | // Enter a valid event id 471 | let fileId = "ENTER_VALID_ID" 472 | 473 | Snippets.graphClient.me().drive().items(fileId).contentRequest()?.download(completion: { (url, response, error) in 474 | if let nsError = error as NSError? { 475 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 476 | } else { 477 | guard let downloadedUrl = url else { 478 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Downloaded URL not found"))) 479 | return 480 | } 481 | completion(.Success(displayText: "Downloaded file at \(downloadedUrl.absoluteString)")) 482 | } 483 | }) 484 | } 485 | } 486 | 487 | // Uploads a file in the signed in user's OneDrive account. 488 | // Applies to personal or work accounts 489 | struct UpdateFile: Snippet 490 | { 491 | let name = "Update file" 492 | let needAdminAccess: Bool = false 493 | func execute(with completion: @escaping (_ result: Result) -> Void) { 494 | 495 | // Enter a valid event id 496 | let fileId = "ENTER_VALID_ID" 497 | 498 | let uploadData = "newTextValue".data(using: String.Encoding.utf8) 499 | Snippets.graphClient.me().drive().items(fileId).contentRequest()?.upload(from: uploadData, completion: { (updatedItem, error) in 500 | if let nsError = error as NSError? { 501 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 502 | } else { 503 | let name = updatedItem?.name ?? "" 504 | completion(.Success(displayText: "File \(name) contents updated")) 505 | } 506 | }) 507 | } 508 | } 509 | 510 | // Renames a file in the signed in user's OneDrive account. 511 | // Applies to personal or work accounts 512 | struct RenameFile: Snippet 513 | { 514 | let name = "Rename file" 515 | let needAdminAccess: Bool = false 516 | func execute(with completion: @escaping (_ result: Result) -> Void) { 517 | 518 | // Enter a valid event id 519 | let fileId = "ENTER_VALID_ID" 520 | 521 | Snippets.graphClient.me().drive().items(fileId).request()?.getWithCompletion({ (file, error) in 522 | if let nsError = error as NSError? { 523 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 524 | } 525 | else { 526 | guard let validFile = file else { 527 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Valid file not returned"))) 528 | return 529 | } 530 | 531 | validFile.name = "NewTextFileName" 532 | Snippets.graphClient.me().drive().items(validFile.entityId).request()?.update(validFile, withCompletion: { (updateItem, error) in 533 | if let nsError = error as NSError? { 534 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 535 | } else { 536 | let name = updateItem?.name ?? "" 537 | completion(.Success(displayText: "New name is \(name)")) 538 | } 539 | }) 540 | } 541 | }) 542 | } 543 | } 544 | 545 | 546 | // Deletes a file in the signed in user's OneDrive account. 547 | // Applies to personal or work accounts 548 | struct DeleteFile: Snippet 549 | { 550 | let name = "Delete file" 551 | let needAdminAccess: Bool = false 552 | func execute(with completion: @escaping (_ result: Result) -> Void) { 553 | 554 | // Enter a valid event id 555 | let fileId = "ENTER_VALID_ID" 556 | 557 | Snippets.graphClient.me().drive().items(fileId).request()?.delete(completion: { (error) in 558 | if let nsError = error as NSError? { 559 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 560 | } else { 561 | completion(.Success(displayText: "File deleted")) 562 | } 563 | }) 564 | } 565 | } 566 | 567 | 568 | // Get user's manager if they have one. 569 | // Applies to work accounts only 570 | struct GetManager: Snippet 571 | { 572 | let name = "Get manager" 573 | let needAdminAccess: Bool = false 574 | func execute(with completion: @escaping (_ result: Result) -> Void) 575 | { 576 | Snippets.graphClient.me().manager().request()?.getWithCompletion({ (directoryObject, error) in 577 | if let nsError = error as NSError? { 578 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 579 | } else { 580 | var displayString: String = "Manager information: \n" 581 | 582 | if let manager = directoryObject { 583 | if let managerName = manager.dictionaryFromItem()["displayName"] { 584 | displayString += "Manager is \(managerName)\n\n" 585 | } 586 | else { 587 | displayString += "No manager" 588 | } 589 | displayString += "Full object is\n\(manager)" 590 | } 591 | completion(.Success(displayText: "\(displayString)")) 592 | } 593 | }) 594 | } 595 | } 596 | 597 | 598 | // Get user's direct reports 599 | // Applies to work accounts only 600 | struct GetDirects: Snippet 601 | { 602 | let name = "Get directs" 603 | let needAdminAccess: Bool = false 604 | func execute(with completion: @escaping (_ result: Result) -> Void) 605 | { 606 | Snippets.graphClient.me().directReports().request()?.getWithCompletion({ (directCollection, nextRequest, error) in 607 | if let nsError = error as NSError? { 608 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 609 | } else { 610 | var displayString = "List of directs: \n" 611 | if let directs = directCollection { 612 | 613 | for direct: MSGraphDirectoryObject in directs.value as! [MSGraphDirectoryObject] { 614 | guard let name = direct.dictionaryFromItem()["displayName"] else { 615 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Display name not found"))) 616 | return 617 | } 618 | displayString += "\(name)\n" 619 | } 620 | } 621 | 622 | if let _ = nextRequest { 623 | displayString += "Next request available for more users" 624 | } 625 | 626 | completion(.Success(displayText: "\(displayString)")) 627 | } 628 | }) 629 | } 630 | } 631 | 632 | // Gets the signed-in user's photo data if they have a photo. 633 | // This snippet will return metadata for the user photo. 634 | // Applies to work accounts only 635 | struct GetPhoto: Snippet 636 | { 637 | let name = "Get photo" 638 | let needAdminAccess: Bool = false 639 | func execute(with completion: @escaping (_ result: Result) -> Void) 640 | { 641 | Snippets.graphClient.me().photo().request()?.getWithCompletion({ (photo, error) in 642 | if let nsError = error as NSError? { 643 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 644 | } else { 645 | guard let photoMetric = photo else { 646 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "Photo width and height not found"))) 647 | return 648 | } 649 | let displayString = "Photo size is \(photoMetric.height) x \(photoMetric.width)" 650 | completion(.Success(displayText: "\(displayString)")) 651 | } 652 | }) 653 | } 654 | } 655 | 656 | // Creates a new user in the tenant. 657 | // Applicable to work accounts with admin rights 658 | struct GetPhotoValue: Snippet 659 | { 660 | let name = "Get photo value" 661 | let needAdminAccess: Bool = false 662 | func execute(with completion: @escaping (_ result: Result) -> Void) 663 | { 664 | Snippets.graphClient.me().photoValue()?.download(completion: { (url, response, error) in 665 | if let nsError = error as NSError? { 666 | completion(.Failure(error: MSGraphError.NSErrorType(error: nsError))) 667 | return 668 | } 669 | 670 | guard let picUrl = url else { 671 | completion(.Failure(error: MSGraphError.UnexpectecError(errorString: "No downloaded URL"))) 672 | return 673 | } 674 | 675 | let picData = try! Data(contentsOf: picUrl) 676 | let picImage = UIImage(data: picData) 677 | 678 | completion(.SuccessDownloadImage(displayImage: picImage)) 679 | }) 680 | } 681 | } 682 | 683 | // MARK: - Helper methods 684 | 685 | extension Snippets 686 | { 687 | // Helper for creating a event object. 688 | // Set series to true to create a recurring event. 689 | static func createEventObject(isSeries series: Bool) -> MSGraphEvent 690 | { 691 | let event = MSGraphEvent() 692 | event.subject = "Event Subject" 693 | event.body = MSGraphItemBody() 694 | event.body.contentType = MSGraphBodyType.text() 695 | event.body.content = "Sample event body" 696 | event.importance = MSGraphImportance.normal() 697 | 698 | let startDate: Date = Date(timeInterval: 30 * 60, since: Date()) 699 | let endDate: Date = Date(timeInterval: 30 * 60, since: startDate) 700 | 701 | let dateFormatter = DateFormatter() 702 | dateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss" 703 | 704 | event.start = MSGraphDateTimeTimeZone() 705 | event.start.dateTime = dateFormatter.string(from: startDate) 706 | 707 | // For more timezone settings, visit this link 708 | // http://graph.microsoft.io/en-us/docs/api-reference/v1.0/resources/datetimetimezone 709 | event.start.timeZone = "Pacific/Honolulu" 710 | 711 | event.end = MSGraphDateTimeTimeZone() 712 | event.end.dateTime = dateFormatter.string(from: endDate) 713 | event.end.timeZone = "Pacific/Honolulu" 714 | 715 | if !series { 716 | event.type = MSGraphEventType.singleInstance() 717 | } 718 | else { 719 | event.type = MSGraphEventType.seriesMaster() 720 | 721 | event.recurrence = MSGraphPatternedRecurrence() 722 | event.recurrence.pattern = MSGraphRecurrencePattern() 723 | event.recurrence.pattern.interval = 1 724 | event.recurrence.pattern.type = MSGraphRecurrencePatternType.weekly() 725 | event.recurrence.pattern.daysOfWeek = [MSGraphDayOfWeek.friday()] 726 | event.recurrence.range = MSGraphRecurrenceRange() 727 | event.recurrence.range.type = MSGraphRecurrenceRangeType.noEnd() 728 | event.recurrence.range.startDate = MSDate(nsDate: startDate) 729 | } 730 | return event 731 | } 732 | } 733 | --------------------------------------------------------------------------------