TeacherService.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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 static TEAMModelOS.SDK.Models.Teacher;
  27. namespace TEAMModelOS.Services
  28. {
  29. public static class TeacherService
  30. {
  31. public static async Task<TeacherInfo> GetTeacherInfo (AzureCosmosFactory _azureCosmos,Teacher teacher,string name,string picture,string id , AzureStorageFactory _azureStorage, Option _option)
  32. {
  33. List<object> schools = new List<object>();
  34. List<AreaDto> areas = new List<AreaDto>();
  35. List<Area> areasd = new List<Area>();
  36. string defaultschool = null;
  37. //TODO 取得Teacher 個人相關數據(課程清單、虛擬教室清單、歷史紀錄清單等),學校數據另外API處理,多校切換時不同
  38. var client = _azureCosmos.GetCosmosClient();
  39. int total = 0;
  40. int tsize = 0;
  41. try
  42. {
  43. if (teacher == null)
  44. {
  45. teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
  46. teacher.name = $"{name}";
  47. teacher.picture = $"{picture}";
  48. }
  49. else {
  50. name = teacher.name;
  51. picture = teacher.picture;
  52. id = teacher.id;
  53. }
  54. ///教师的个人空间
  55. tsize = teacher.size;
  56. ///教师的总空间 包含 个人空间和学校赠送的空间累加
  57. total = teacher.size;
  58. //areas = teacher.areas;
  59. if (teacher.areas.IsNotEmpty())
  60. {
  61. foreach (var areat in teacher.areas)
  62. {
  63. try
  64. {
  65. Area area = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{areat.areaId}", new PartitionKey("Base-Area"));
  66. areasd.Add(area);
  67. AreaSetting setting= null;
  68. try
  69. {
  70. setting= await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>($"{areat.areaId}", new PartitionKey("AreaSetting"));
  71. } catch (CosmosException ex) {
  72. setting = null;
  73. }
  74. int access = 0;
  75. if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig)) {
  76. access = 1;
  77. }
  78. if (setting != null) {
  79. setting.accessConfig = null;
  80. }
  81. areas.Add(new AreaDto { areaId = area.id, name = area.name,standard= area.standard,standardName= area.standardName,setting=setting, access= access });
  82. }
  83. catch (CosmosException)
  84. {
  85. //数据库捞不到数据
  86. continue;
  87. }
  88. }
  89. }
  90. //检查是否有加入学校,如果加入学校,则当个人空间size是0G的时候,则免费获得一个G空间,但无论加入多少个学校,只能获取一次 1G的免费空间。没有加入学校则默认0G空间,除非自己购买空间
  91. if (teacher.schools.IsNotEmpty())
  92. {
  93. foreach (var sc in teacher.schools)
  94. {
  95. string statusNow = sc.status != null ? sc.status : "";
  96. if (statusNow.Equals("join") || statusNow.Equals("invite") || statusNow.Equals("request"))
  97. {
  98. dynamic schoolExtobj = new ExpandoObject();
  99. // var schoolJson = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{sc.schoolId}", new PartitionKey("Base"));
  100. //var school = await JsonDocument.ParseAsync(schoolJson.ContentStream);
  101. schoolExtobj.schoolId = sc.schoolId;
  102. schoolExtobj.name = sc.name;
  103. schoolExtobj.status = sc.status;
  104. schoolExtobj.time = sc.time;
  105. schoolExtobj.picture = sc.picture;
  106. schoolExtobj.areaId = $"{sc.areaId}";
  107. Area area = null;
  108. int access = 0;
  109. if (!string.IsNullOrEmpty($"{sc.areaId}"))
  110. {
  111. try
  112. {
  113. area = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{sc.areaId}", new PartitionKey("Base-Area"));
  114. AreaSetting setting = null;
  115. try
  116. {
  117. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>($"{area.id}", new PartitionKey("AreaSetting"));
  118. }
  119. catch (CosmosException ex)
  120. {
  121. setting = null;
  122. }
  123. if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
  124. {
  125. access = 1;
  126. }
  127. areasd.Add(area);
  128. }
  129. catch (CosmosException)
  130. {
  131. area = null;
  132. }
  133. }
  134. if (area != null)
  135. {
  136. schoolExtobj.area = new {area.name, area.id, area.institution, area.provName, area.code, area.cityCode, area.cityName, area.standard, area.provCode, area.pk, access };
  137. }
  138. else {
  139. schoolExtobj.area = area;
  140. }
  141. var sctch = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{sc.schoolId}"));
  142. if (sctch.Status == 200)
  143. {
  144. var jsonDoc = await JsonDocument.ParseAsync(sctch.ContentStream);
  145. SchoolTeacher schoolTeacher = jsonDoc.RootElement.ToObject<SchoolTeacher>();
  146. schoolTeacher.name = $"{name}";
  147. schoolTeacher.picture = $"{picture}";
  148. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(schoolTeacher, id, new PartitionKey($"Teacher-{sc.schoolId}"));
  149. if (jsonDoc.RootElement.TryGetProperty("size", out JsonElement _size) && _size.ValueKind.Equals(JsonValueKind.Number))
  150. {
  151. total += _size.GetInt32();
  152. schoolExtobj.size = _size.GetInt32();
  153. }
  154. else { schoolExtobj.size = 0; }
  155. }
  156. else
  157. {
  158. schoolExtobj.size = 0;
  159. }
  160. if (statusNow.Equals("join"))
  161. {
  162. //初始化
  163. await TmdUserService.JoinSchool(client, teacher.id, teacher.picture, teacher.name, sc.schoolId, sc.name);
  164. }
  165. schools.Add(schoolExtobj);
  166. }
  167. }
  168. //如果包含任何申请,邀请,加入学校的记录 且个人空间未分配2G 则默认分配个人空间至2G.
  169. if (teacher.size < 2 && teacher.schools.Count > 0)
  170. {
  171. teacher.size = 2;
  172. }
  173. //如果未包含任何申请,邀请,加入学校的记录 且 个人空间没有分配1G 则默认赠送一个G
  174. if (teacher.schools.Count == 0 && teacher.size < 1)
  175. {
  176. teacher.size = 1;
  177. }
  178. }
  179. if (string.IsNullOrEmpty(teacher.defaultSchool) && teacher.schools.IsNotEmpty())
  180. {
  181. var tech = teacher.schools.FindAll(x => x.status.Equals("join"));
  182. if (tech.IsNotEmpty())
  183. {
  184. teacher.defaultSchool = teacher.schools[0].schoolId;
  185. }
  186. }
  187. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
  188. //預設學校ID
  189. defaultschool = teacher.defaultSchool;
  190. }
  191. catch (CosmosException ex)
  192. {
  193. if (ex.Status == 404)
  194. {
  195. //如果沒有,則初始化Teacher基本資料到Cosmos
  196. teacher = new Teacher
  197. {
  198. id = id,
  199. pk = "Base",
  200. code = "Base",
  201. name = name?.ToString(),
  202. picture = picture?.ToString(),
  203. //创建账号并第一次登录IES5则默认赠送1G
  204. size = 1,
  205. defaultSchool = null,
  206. schools = new List<Teacher.TeacherSchool>(),
  207. };
  208. var container = _azureStorage.GetBlobContainerClient(id);
  209. await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
  210. teacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey("Base"));
  211. total = teacher.size;
  212. tsize = teacher.size;
  213. }
  214. }
  215. //私人課程
  216. List<object> courses = new List<object>();
  217. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{id}") }))
  218. {
  219. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  220. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  221. {
  222. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  223. {
  224. courses.Add(obj.ToObject<object>());
  225. }
  226. }
  227. }
  228. List<string> roles = new List<string>() { "teacher" };
  229. Area areaa = null;
  230. if (areas.Count > 0)
  231. {
  232. roles.Add("area");
  233. if (!string.IsNullOrEmpty($"{areas[0]}"))
  234. {
  235. try
  236. {
  237. areaa = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{areas[0].areaId}", new PartitionKey("Base-Area"));
  238. }
  239. catch (CosmosException)
  240. {
  241. areaa = null;
  242. }
  243. }
  244. }
  245. //換取AuthToken,提供給前端
  246. var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, standard: areaa != null ? areaa.standard : "", roles: roles.ToArray());
  247. //取得Teacher Blob 容器位置及SAS
  248. await _azureStorage.GetBlobContainerClient(id).CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
  249. var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);
  250. var (osblob_uri, osblob_sas) = roles.Contains("area") ? _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete) : _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
  251. return new TeacherInfo {
  252. auth_token = auth_token,
  253. blob_uri = blob_uri,
  254. blob_sas = blob_sas,
  255. schools = schools,
  256. defaultschool = defaultschool,
  257. courses = courses,
  258. total=total,
  259. osblob_sas=osblob_sas,
  260. osblob_uri = osblob_uri,
  261. tsize=tsize,
  262. areas= areas,
  263. teacher=teacher
  264. };
  265. }
  266. }
  267. public record AreaDto
  268. {
  269. //areaId = area.id, name = area.name, area.standard, area.standardName
  270. public string areaId { get; set; }
  271. public string name { get; set; }
  272. public string standard { get; set; }
  273. public string standardName { get; set; }
  274. //public string accessConfig { get; set; }
  275. public AreaSetting setting { get; set; }
  276. public int access { get; set; } = 0;
  277. }
  278. public record TeacherInfo {
  279. public string auth_token { get; set; }
  280. public string blob_uri { get; set; }
  281. public string blob_sas { get; set; }
  282. public List<object> schools { get; set; }= new List<object> ();
  283. public string defaultschool { get; set; }
  284. public List<object> courses { get; set; }= new List<object>();
  285. public int total { get; set; }
  286. public string osblob_uri { get; set; }
  287. public string osblob_sas { get; set; }
  288. public int tsize { get; set; }
  289. public List<AreaDto> areas { get; set; } = new List<AreaDto>();
  290. public Teacher teacher { get; set; }
  291. }
  292. }