-
Notifications
You must be signed in to change notification settings - Fork 12
/
SubscriptionController.cs
191 lines (164 loc) · 7.25 KB
/
SubscriptionController.cs
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
182
183
184
185
186
187
188
189
190
191
/*
* Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license.
* See LICENSE in the source repository root for complete license information.
*/
using System;
using System.Configuration;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using Microsoft.OneDrive.Sdk;
using OneDriveWebhookTranslator.Models;
using System.Net.Http;
using Newtonsoft.Json;
namespace OneDriveWebhookTranslator.Controllers
{
public class SubscriptionController : Controller
{
// GET: Subscription
public ActionResult Index()
{
return View();
}
// Create webhook subscription
public async Task<ActionResult> CreateSubscription()
{
#region Create OneDriveClient for current user
OneDriveUser user = OneDriveUser.UserForRequest(this.Request);
if (null == user)
{
return Redirect(Url.Action("Index", "Home"));
}
var client = await GetOneDriveClientAsync(user);
#endregion
// Ensure the app folder is created first
var appFolder = await client.Drive.Special["approot"].Request().GetAsync();
// Create a subscription on the drive
var notificationUrl = ConfigurationManager.AppSettings["ida:NotificationUrl"];
Models.OneDriveSubscription subscription = new OneDriveSubscription
{
NotificationUrl = notificationUrl,
ClientState = "my client state"
};
FixPPESubscriptionBug(user, subscription);
// Because the OneDrive SDK does not support OneDrive subscriptions natively yet,
// we use BaseRequest to generate a request the SDK can understand. You could also use HttpClient
var request = new BaseRequest(client.BaseUrl + "/drive/root/subscriptions", client)
{
Method = "POST",
ContentType = "application/json"
};
try
{
var subscriptionResponse = await request.SendAsync<Models.OneDriveSubscription>(subscription);
if (null != subscriptionResponse)
{
// Store the subscription ID so we can keep track of which subscriptions are tied to which users
user.SubscriptionId = subscriptionResponse.SubscriptionId;
Models.SubscriptionViewModel viewModel = new Models.SubscriptionViewModel { Subscription = subscriptionResponse };
return View("Subscription", viewModel);
}
}
catch (Exception ex)
{
ViewBag.Message = ex.Message;
}
return View("Error");
}
private static void FixPPESubscriptionBug(OneDriveUser user, OneDriveSubscription subscription)
{
if (user.ClientType == ClientType.Business)
{
subscription.Scenarios = null;
}
else
{
subscription.SubscriptionExpirationDateTime = DateTime.Now.AddDays(3);
subscription.ClientState = null;
}
}
/// <summary>
/// Delete the user's active subscription and then redirect to logout
/// </summary>
/// <returns></returns>
public async Task<ActionResult> DeleteSubscription()
{
OneDriveUser user = OneDriveUser.UserForRequest(this.Request);
if (null == user)
{
return Redirect(Url.Action("Index", "Home"));
}
if (!string.IsNullOrEmpty(user.SubscriptionId))
{
var client = await GetOneDriveClientAsync(user);
// Because the OneDrive SDK does not support OneDrive subscriptions natively yet,
// we use BaseRequest to generate a request the SDK can understand
var request = new BaseRequest(client.BaseUrl + "/drive/root/subscriptions/" + user.SubscriptionId, client) { Method = "DELETE" };
try
{
var response = await request.SendRequestAsync(null);
if (!response.IsSuccessStatusCode)
{
ViewBag.Message = response.ReasonPhrase;
return View("Error");
}
else
{
user.SubscriptionId = null;
}
}
catch (Exception ex)
{
ViewBag.Message = ex.Message;
return View("Error");
}
}
return RedirectToAction("SignOut", "Account");
}
#region SDK helper methods
/// <summary>
/// Create a new instance of the OneDriveClient for the signed in user.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
internal static async Task<OneDriveClient> GetOneDriveClientAsync(OneDriveUser user)
{
if (string.IsNullOrEmpty(user.OneDriveBaseUrl))
{
// Resolve the API URL for this user
user.OneDriveBaseUrl = await LookupOneDriveUrl(user);
}
var client = new OneDriveClient(new AppConfig(), null, null, new OneDriveAccountServiceProvider(user), user.ClientType);
await client.AuthenticateAsync();
return client;
}
/// <summary>
/// Use the discovery API to resolve the base URL for the OneDrive API
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
internal static async Task<string> LookupOneDriveUrl(OneDriveUser user)
{
if (user.ClientType == ClientType.Consumer)
{
return "https://api.onedrive.com/v1.0";
}
var accessToken = await user.GetAccessTokenAsync("https://api.office.com/discovery/");
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.office.com/discovery/v2.0/me/services");
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
request.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException("Unable to determine OneDrive URL: " + response.ReasonPhrase);
}
var services = JsonConvert.DeserializeObject<DiscoveryServiceResponse>(await response.Content.ReadAsStringAsync());
var query = from s in services.Value
where s.Capability == "MyFiles" && s.ServiceApiVersion == "v2.0"
select s.ServiceEndpointUri;
return query.FirstOrDefault();
}
#endregion
}
}