TmdUserController.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. using Azure.Cosmos;
  2. using Azure.Storage.Blobs.Models;
  3. using Azure.Storage.Sas;
  4. using Microsoft.AspNetCore.Http;
  5. using Microsoft.AspNetCore.Mvc;
  6. using Microsoft.Extensions.Options;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Dynamic;
  10. using System.IdentityModel.Tokens.Jwt;
  11. using System.IO;
  12. using System.Linq;
  13. using System.Text.Json;
  14. using System.Threading.Tasks;
  15. using TEAMModelOS.Models;
  16. using TEAMModelOS.SDK.Models;
  17. using TEAMModelOS.SDK.DI;
  18. using TEAMModelOS.SDK.Extension;
  19. using TEAMModelOS.Filter;
  20. using TEAMModelOS.SDK.Models.Cosmos;
  21. using HTEXLib.COMM.Helpers;
  22. using TEAMModelOS.SDK.Models.Service;
  23. using Microsoft.Extensions.Configuration;
  24. using System.Net.Http;
  25. using TEAMModelOS.SDK;
  26. using Microsoft.AspNetCore.Authorization;
  27. using System.Text;
  28. using static TEAMModelOS.SDK.Models.Teacher;
  29. namespace TEAMModelOS.Controllers
  30. {
  31. [ProducesResponseType(StatusCodes.Status200OK)]
  32. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  33. //
  34. [Route("tmduser/init")]
  35. [ApiController]
  36. public class TmdUserController : ControllerBase
  37. {
  38. private readonly AzureCosmosFactory _azureCosmos;
  39. private readonly AzureStorageFactory _azureStorage;
  40. private readonly AzureRedisFactory _azureRedis;
  41. private readonly DingDing _dingDing;
  42. private readonly Option _option;
  43. private readonly IConfiguration _configuration;
  44. private readonly CoreAPIHttpService _coreAPIHttpService;
  45. private readonly IPSearcher _searcher;
  46. private readonly HttpTrigger _httpTrigger;
  47. public TmdUserController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, IPSearcher searcher, AzureRedisFactory azureRedis, HttpTrigger httpTrigger)
  48. {
  49. _azureCosmos = azureCosmos;
  50. _azureStorage = azureStorage;
  51. _dingDing = dingDing;
  52. _option = option?.Value;
  53. _configuration = configuration;
  54. _coreAPIHttpService = coreAPIHttpService;
  55. _searcher = searcher;
  56. _azureRedis = azureRedis;
  57. _httpTrigger = httpTrigger;
  58. }
  59. [ProducesDefaultResponseType]
  60. [HttpPost("get-school-info")]
  61. [Authorize(Roles = "IES")]
  62. public async Task<IActionResult> GetSchoolInfo(JsonElement request)
  63. {
  64. if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  65. if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
  66. var jwt = new JwtSecurityToken(id_token.GetString());
  67. if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
  68. var id = jwt.Payload.Sub;
  69. var client = _azureCosmos.GetCosmosClient();
  70. //權限token
  71. jwt.Payload.TryGetValue("name", out object name);
  72. jwt.Payload.TryGetValue("picture", out object picture);
  73. return Ok();
  74. }
  75. [ProducesDefaultResponseType]
  76. [HttpPost("get-tmduser-info")]
  77. #if !DEBUG
  78. [Authorize(Roles = "IES")]
  79. #endif
  80. public async Task<IActionResult> GetTmdUserInfo(JsonElement request)
  81. {
  82. try
  83. {
  84. if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  85. var jwt = new JwtSecurityToken(id_token.GetString());
  86. if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.OrdinalIgnoreCase)) return BadRequest();
  87. var id = jwt.Payload.Sub;
  88. var Schoolid = jwt.Payload.Azp;
  89. jwt.Payload.TryGetValue("name", out object name);
  90. jwt.Payload.TryGetValue("picture", out object picture);
  91. (string ip, string region) = await LoginService.LoginIp(HttpContext, _searcher);
  92. List<object> schools = new List<object>();
  93. List<LoginInfo> loginInfos = new();
  94. string defaultschool = null;
  95. var client = _azureCosmos.GetCosmosClient();
  96. try
  97. {
  98. TmdUser tmdUser = await client.GetContainer("TEAMModelOS", "Student").ReadItemAsync<TmdUser>(id, new PartitionKey("Base"));
  99. tmdUser.name = $"{name}";
  100. tmdUser.picture = $"{picture}";
  101. if (tmdUser.schools.IsNotEmpty())
  102. {
  103. List<TmdUser.School> rm = new List<TmdUser.School>();
  104. foreach (var sc in tmdUser.schools)
  105. {
  106. dynamic schoolExtobj = new ExpandoObject();
  107. var schoolJson = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{sc.schoolId}", new PartitionKey("Base"));
  108. if (schoolJson.Status == 200)
  109. {
  110. var school = await JsonDocument.ParseAsync(schoolJson.ContentStream);
  111. schoolExtobj.schoolId = sc.schoolId;
  112. schoolExtobj.name = school.RootElement.GetProperty("name");
  113. schoolExtobj.status = sc.status;
  114. schoolExtobj.time = sc.time;
  115. schoolExtobj.picture = school.RootElement.GetProperty("picture");
  116. sc.name = $"{school.RootElement.GetProperty("name")}";
  117. }
  118. else
  119. {
  120. rm.Add(sc);
  121. }
  122. }
  123. rm.ForEach(x => { tmdUser.schools.Remove(x); });
  124. tmdUser.defaultSchool = string.IsNullOrEmpty(tmdUser.defaultSchool) ? tmdUser.schools[0].schoolId : tmdUser.defaultSchool;
  125. }
  126. loginInfos = tmdUser.loginInfos;
  127. tmdUser.pk="Base";
  128. await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync<TmdUser>(tmdUser, id, new PartitionKey("Base"));
  129. //預設學校ID
  130. defaultschool = tmdUser.defaultSchool;
  131. }
  132. catch (CosmosException ex)
  133. {
  134. if (ex.Status == 404)
  135. {
  136. //如果沒有,則初始化Teacher基本資料到Cosmos
  137. TmdUser teacher = new TmdUser
  138. {
  139. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  140. id = id,
  141. pk = "Base",
  142. code = "Base",
  143. name = name?.ToString(),
  144. picture = picture?.ToString(),
  145. defaultSchool = null,
  146. schools = new List<TmdUser.School>(),
  147. };
  148. var container = _azureStorage.GetBlobContainerClient(id);
  149. await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
  150. teacher = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Student").CreateItemAsync<TmdUser>(teacher, new PartitionKey("Base"));
  151. }
  152. }
  153. int timezone = 8;
  154. if (HttpContext.Request.Headers.TryGetValue("Time-Zone", out var Time_Zone) && int.TryParse(Time_Zone, out int tz))
  155. {
  156. timezone=tz;
  157. }
  158. //換取AuthToken,提供給前端
  159. var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", timezone: timezone, scope: Constant.ScopeTmdUser, roles: new[] { "student" }, expire: 1);
  160. //用户在线记录
  161. try
  162. {
  163. _ = _httpTrigger.RequestHttpTrigger(new { school = defaultschool, scope = $"{Constant.ScopeTmdUser}", id = $"{id}", ip = $"{ip}", expire = 1 }, _option.Location, "online-record");
  164. }
  165. catch { }
  166. if (!string.IsNullOrEmpty(defaultschool))
  167. {
  168. }
  169. var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
  170. blob_uri = blob_uri.Replace(id, "");
  171. blob_sas = "";
  172. await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new SDK.Models.Dtos.Accumulate { client="web", count=1, id="ies", key="tmdstudent_login", name="醍摩豆账号登录", scope="ies", target="ies" });
  173. return Ok(new { location = _option.Location, auth_token, schools, defaultschool, blob_uri, blob_sas, status = 200 });
  174. }
  175. catch (CosmosException ex)
  176. {
  177. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  178. return BadRequest();
  179. }
  180. catch (Exception ex)
  181. {
  182. request.TryGetProperty("id_token", out JsonElement id_token);
  183. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}\n{ex.StackTrace}\n{id_token}", GroupNames.醍摩豆服務運維群組);
  184. return BadRequest();
  185. }
  186. }
  187. private async Task<(string uri, string sas)> GetSchoolData(string shool)
  188. {
  189. // BLOB(學校,唯讀)
  190. var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(shool, BlobContainerSasPermissions.Read);
  191. return (blob_uri, blob_sas);
  192. }
  193. [ProducesDefaultResponseType]
  194. [HttpPost("get-tmd-info")]
  195. #if !DEBUG
  196. [Authorize(Roles = "IES")]
  197. #endif
  198. public async Task<ActionResult> getTmdInfo(JsonElement request)
  199. {
  200. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  201. List<string> ids = id.ToObject<List<string>>();
  202. List<ufo> tmds = new List<ufo>();
  203. try
  204. {
  205. var content = new StringContent(ids.ToJsonString(), Encoding.UTF8, "application/json");
  206. string json = await _coreAPIHttpService.GetUserInfos(content);
  207. if (!string.IsNullOrWhiteSpace(json))
  208. {
  209. try
  210. {
  211. tmds = json.ToObject<List<ufo>>();
  212. }
  213. catch (Exception ex)
  214. {
  215. await _dingDing.SendBotMsg($"{_coreAPIHttpService.options.location}用户转换失败:{_coreAPIHttpService.options.coreUrl}{json}\n ", GroupNames.醍摩豆服務運維群組);
  216. }
  217. }
  218. }
  219. catch (Exception e)
  220. {
  221. await _dingDing.SendBotMsg($"IES5,{_option.Location},tmduser/init/getTmdInfo()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  222. }
  223. return Ok(tmds);
  224. }
  225. }
  226. }