You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
13 KiB

2 years ago
  1. using EasyBL;
  2. using Microsoft.Graph;
  3. using Newtonsoft.Json;
  4. using Newtonsoft.Json.Linq;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Net.Http;
  8. using System.Threading.Tasks;
  9. using WebApp.Outlook.Models;
  10. namespace WebApp.Outlook
  11. {
  12. public static class Statics
  13. {
  14. public static T Deserialize<T>(this string result)
  15. {
  16. return JsonConvert.DeserializeObject<T>(result);
  17. }
  18. }
  19. public class GraphService
  20. {
  21. private static string GraphRootUri = Common.GetAppSettings("ida:GraphRootUri");
  22. /// <summary>
  23. /// Get the current user's id from their profile.
  24. /// </summary>
  25. /// <param name="accessToken">Access token to validate user</param>
  26. /// <returns></returns>
  27. public async Task<string> GetMyIdAsync(String accessToken)
  28. {
  29. //string endpoint = "https://graph.microsoft.com/v1.0/me";
  30. var endpoint = $"{GraphRootUri}/me";
  31. var queryParameter = "?$select=id";
  32. var userId = "";
  33. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Get, endpoint + queryParameter, accessToken);
  34. if (response != null && response.IsSuccessStatusCode)
  35. {
  36. var json = JObject.Parse(await response.Content.ReadAsStringAsync());
  37. userId = json.GetValue("id").ToString();
  38. }
  39. return userId?.Trim();
  40. }
  41. // Get the current user's email address from their profile.
  42. public async Task<string> GetMyEmailAddressAsync(GraphServiceClient graphClient)
  43. {
  44. // Get the current user. This sample only needs the user's email address, so select the
  45. // mail and userPrincipalName properties. If the mail property isn't defined,
  46. // userPrincipalName should map to the email for all account types.
  47. var me = await graphClient.Me.Request().Select("mail,userPrincipalName").GetAsync();
  48. return me.Mail ?? me.UserPrincipalName;
  49. }
  50. public async Task<IUserEventsCollectionPage> GetMyCalendarEventsAsync(GraphServiceClient graphClient)
  51. {
  52. var Events = await graphClient.Me.Events.Request().GetAsync();
  53. return Events;
  54. }
  55. public async Task<string> UpdateMyEventsAsync(string accessToken, string eventId, Event _event)
  56. {
  57. var endpoint = $"{GraphRootUri}/me/events/{eventId}";
  58. var response = await ServiceHelper.SendRequestAsync(new HttpMethod("PATCH"), endpoint, accessToken, _event);
  59. if (!response.IsSuccessStatusCode)
  60. throw new Exception(response.ReasonPhrase) { Source = JsonConvert.SerializeObject(response) };
  61. return response.ReasonPhrase;
  62. }
  63. public async Task<bool> DeleteMyEventsAsync(string accessToken, string eventId)
  64. {
  65. var endpoint = $"{GraphRootUri}/me/events/{eventId}";
  66. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Delete, endpoint, accessToken);
  67. if (!response.IsSuccessStatusCode)
  68. throw new Exception(response.ReasonPhrase) { Source = JsonConvert.SerializeObject(response) };
  69. return response.ReasonPhrase == "No Content";
  70. }
  71. /// <summary>
  72. /// Create new channel.
  73. /// </summary>
  74. /// <param name="accessToken">Access token to validate user</param>
  75. /// <param name="teamId">Id of the team in which new channel needs to be created</param>
  76. /// <param name="channelName">New channel name</param>
  77. /// <param name="channelDescription">New channel description</param>
  78. /// <returns></returns>
  79. public async Task<HttpResponseMessage> CreateChannelAsync(string accessToken, string teamId, string channelName, string channelDescription)
  80. {
  81. var endpoint = $"{GraphRootUri}/teams/{teamId}/channels";
  82. var content = new Channel()
  83. {
  84. Description = channelDescription,
  85. DisplayName = channelName
  86. };
  87. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Post, endpoint, accessToken, content);
  88. return response;//.ReasonPhrase;
  89. }
  90. /// <summary>
  91. /// Get all channels of the given.
  92. /// </summary>
  93. /// <param name="accessToken">Access token to validate user</param>
  94. /// <param name="teamId">Id of the team to get all associated channels</param>
  95. /// <param name="resourcePropId">todo: describe resourcePropId parameter on GetChannelsAsync</param>
  96. /// <returns></returns>
  97. public async Task<IEnumerable<ResultsItem>> GetChannelsAsync(string accessToken, string teamId, string resourcePropId)
  98. {
  99. var endpoint = $"{GraphRootUri}/teams/{teamId}/channels";
  100. var items = new List<ResultsItem>();
  101. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Get, endpoint, accessToken);
  102. if (response != null && response.IsSuccessStatusCode)
  103. {
  104. items = await ServiceHelper.GetResultsItemAsync(response, "id", "displayName", resourcePropId);
  105. }
  106. return items;
  107. }
  108. /// <summary>
  109. /// Get all teams which user is the member of.
  110. /// </summary>
  111. /// <param name="accessToken">Access token to validate user</param>
  112. /// <param name="resourcePropId">todo: describe resourcePropId parameter on GetMyTeamsAsync</param>
  113. /// <returns></returns>
  114. public async Task<IEnumerable<ResultsItem>> GetMyTeamsAsync(string accessToken, string resourcePropId)
  115. {
  116. var endpoint = $"{GraphRootUri}/me/joinedTeams";
  117. var items = new List<ResultsItem>();
  118. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Get, endpoint, accessToken);
  119. if (response != null && response.IsSuccessStatusCode)
  120. {
  121. items = await ServiceHelper.GetResultsItemAsync(response, "id", "displayName", resourcePropId);
  122. }
  123. return items;
  124. }
  125. /// <summary>
  126. /// </summary>
  127. /// <param name="accessToken"></param>
  128. /// <param name="teamId"></param>
  129. /// <param name="channelId"></param>
  130. /// <param name="message"></param>
  131. /// <returns></returns>
  132. public async Task<HttpResponseMessage> PostMessageAsync(string accessToken, string teamId, string channelId, string message)
  133. {
  134. var endpoint = $"{GraphRootUri}/teams/{teamId}/channels/{channelId}/chatThreads";
  135. var content = new PostMessage()
  136. {
  137. RootMessage = new RootMessage()
  138. {
  139. body = new MSG()
  140. {
  141. Content = message
  142. }
  143. }
  144. };
  145. var items = new List<ResultsItem>();
  146. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Post, endpoint, accessToken, content);
  147. return response;//response.ReasonPhrase;
  148. }
  149. /// <summary>
  150. /// </summary>
  151. /// <param name="accessToken"></param>
  152. /// <param name="group"></param>
  153. /// <returns></returns>
  154. public async Task<string> CreateNewTeamAndGroupAsync(string accessToken, Models.Group group)
  155. {
  156. // create group
  157. var endpoint = $"{GraphRootUri}/groups";
  158. if (group != null)
  159. {
  160. group.GroupTypes = new string[] { "Unified" };
  161. group.MailEnabled = true;
  162. group.SecurityEnabled = false;
  163. group.Visibility = "Private";
  164. }
  165. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Post, endpoint, accessToken, group);
  166. if (!response.IsSuccessStatusCode)
  167. {
  168. return await response.Content.ReadAsStringAsync();
  169. }
  170. var responseBody = await response.Content.ReadAsStringAsync(); ;
  171. var groupId = responseBody.Deserialize<Models.Group>().Id; // groupId is the same as teamId
  172. // add me as member
  173. var me = await GetMyIdAsync(accessToken);
  174. var payload = $"{{ '@odata.id': '{GraphRootUri}/users/{me}' }}";
  175. var responseRef = await ServiceHelper.SendRequestAsync(HttpMethod.Post,
  176. $"{GraphRootUri}/groups/{groupId}/members/$ref",
  177. accessToken, payload);
  178. // create team
  179. await AddTeamToGroupAsync(groupId, accessToken);
  180. return $"Created {groupId}";
  181. }
  182. /// <summary>
  183. /// </summary>
  184. /// <param name="groupId"></param>
  185. /// <param name="accessToken"></param>
  186. /// <returns></returns>
  187. public async Task<String> AddTeamToGroupAsync(string groupId, string accessToken)
  188. {
  189. var endpoint = $"{GraphRootUri}/groups/{groupId}/team";
  190. var team = new Team
  191. {
  192. guestSettings = new Models.TeamGuestSettings() { AllowCreateUpdateChannels = false, AllowDeleteChannels = false }
  193. };
  194. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Put, endpoint, accessToken, team);
  195. if (!response.IsSuccessStatusCode)
  196. throw new Exception(response.ReasonPhrase) { Source = JsonConvert.SerializeObject(response) };
  197. return response.ReasonPhrase;
  198. }
  199. /// <summary>
  200. /// </summary>
  201. /// <param name="teamId"></param>
  202. /// <param name="accessToken"></param>
  203. /// <returns></returns>
  204. public async Task<String> UpdateTeamAsync(string teamId, string accessToken)
  205. {
  206. var endpoint = $"{GraphRootUri}/teams/{teamId}";
  207. var team = new Team
  208. {
  209. guestSettings = new Models.TeamGuestSettings() { AllowCreateUpdateChannels = true, AllowDeleteChannels = false }
  210. };
  211. var response = await ServiceHelper.SendRequestAsync(new HttpMethod("PATCH"), endpoint, accessToken, team);
  212. if (!response.IsSuccessStatusCode)
  213. throw new Exception(response.ReasonPhrase) { Source = JsonConvert.SerializeObject(response) };
  214. return response.ReasonPhrase;
  215. }
  216. /// <summary>
  217. /// </summary>
  218. /// <param name="teamId"></param>
  219. /// <param name="member"></param>
  220. /// <param name="accessToken"></param>
  221. /// <returns></returns>
  222. public async Task AddMemberAsync(string teamId, Member member, string accessToken)
  223. {
  224. // If you have a user's UPN, you can add it directly to a group, but then there will be a
  225. // significant delay before Microsoft Teams reflects the change. Instead, we find the
  226. // user object's id, and add the ID to the group through the Graph beta endpoint, which
  227. // is recognized by Microsoft Teams much more quickly. See
  228. // https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/teams_api_overview
  229. // for more about delays with adding members.
  230. // Step 1 -- Look up the user's id from their UPN
  231. var endpoint = $"{GraphRootUri}/users/{member.Upn}";
  232. var response = await ServiceHelper.SendRequestAsync(HttpMethod.Get, endpoint, accessToken);
  233. var responseBody = await response.Content.ReadAsStringAsync();
  234. if (!response.IsSuccessStatusCode)
  235. throw new Exception(response.ReasonPhrase) { Source = JsonConvert.SerializeObject(response) };
  236. var userId = responseBody.Deserialize<Member>().Id;
  237. // Step 2 -- add that id to the group
  238. var payload = $"{{ '@odata.id': '{GraphRootUri}/users/{userId}' }}";
  239. endpoint = $"{GraphRootUri}/groups/{teamId}/members/$ref";
  240. var responseRef = await ServiceHelper.SendRequestAsync(HttpMethod.Post, endpoint, accessToken, payload);
  241. if (!response.IsSuccessStatusCode)
  242. throw new Exception(response.ReasonPhrase) { Source = JsonConvert.SerializeObject(response) };
  243. if (member.Owner)
  244. {
  245. endpoint = $"{GraphRootUri}/groups/{teamId}/owners/$ref";
  246. var responseOwner = await ServiceHelper.SendRequestAsync(HttpMethod.Post, endpoint, accessToken, payload);
  247. if (!response.IsSuccessStatusCode)
  248. throw new Exception(response.ReasonPhrase) { Source = JsonConvert.SerializeObject(response) };
  249. }
  250. }
  251. /// <summary>
  252. /// </summary>
  253. /// <param name="accessToken"></param>
  254. /// <param name="teamId"></param>
  255. /// <param name="resourcePropId"></param>
  256. /// <returns></returns>
  257. public async Task<IEnumerable<ResultsItem>> ListAppsAsync(string accessToken, string teamId, string resourcePropId)
  258. {
  259. var response = await ServiceHelper.SendRequestAsync(
  260. HttpMethod.Get,
  261. $"{GraphRootUri}/teams/{teamId}/apps",
  262. accessToken);
  263. var responseBody = await response.Content.ReadAsStringAsync();
  264. var items = new List<ResultsItem>();
  265. if (response != null && response.IsSuccessStatusCode)
  266. {
  267. items = await ServiceHelper.GetResultsItemAsync(response, "id", "displayName", resourcePropId);
  268. }
  269. return items;
  270. }
  271. }
  272. }