InitController.cs 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  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. using TEAMModelOS.Services;
  28. using Microsoft.AspNetCore.Authorization;
  29. using System.Diagnostics;
  30. using Microsoft.Extensions.Logging;
  31. using System.Text;
  32. using Microsoft.Azure.Cosmos.Table;
  33. namespace TEAMModelOS.Controllers
  34. {
  35. [ProducesResponseType(StatusCodes.Status200OK)]
  36. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  37. [Route("teacher/init")]
  38. [ApiController]
  39. public class InitController : ControllerBase
  40. {
  41. private readonly AzureCosmosFactory _azureCosmos;
  42. private readonly AzureStorageFactory _azureStorage;
  43. private readonly AzureRedisFactory _azureRedis;
  44. private readonly DingDing _dingDing;
  45. private readonly Option _option;
  46. private readonly IConfiguration _configuration;
  47. private readonly NotificationService _notificationService;
  48. private readonly CoreAPIHttpService _coreAPIHttpService;
  49. private readonly IPSearcher _searcher;
  50. private readonly ILogger<InitController> _logger;
  51. private readonly HttpTrigger _httpTrigger;
  52. public InitController(ILogger<InitController> logger, IPSearcher searcher, CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService, HttpTrigger httpTrigger)
  53. {
  54. _searcher = searcher;
  55. _azureCosmos = azureCosmos;
  56. _azureStorage = azureStorage;
  57. _azureRedis = azureRedis;
  58. _dingDing = dingDing;
  59. _option = option?.Value;
  60. _configuration = configuration;
  61. _notificationService = notificationService;
  62. _coreAPIHttpService = coreAPIHttpService;
  63. _logger = logger;
  64. _httpTrigger = httpTrigger;
  65. }
  66. /// <summary>
  67. /// 修改教师信息
  68. /// </summary>
  69. /// <param name="request"></param>
  70. /// <returns></returns>
  71. [ProducesDefaultResponseType]
  72. [HttpPost("GetUserInfo")]
  73. //[Authorize(Roles = "IES")]
  74. public async Task<IActionResult> GetUserInfo(JsonElement request)
  75. {
  76. if (!request.TryGetProperty("key", out JsonElement key)) return BadRequest();
  77. var location = _option.Location;
  78. //https://api2-rc.teammodel.cn
  79. CoreUser core = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string>()
  80. { { "key",$"{key}" }
  81. }, location, _configuration
  82. );
  83. if (core != null)
  84. {
  85. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  86. TmdidImplicit tmdidImplicit = await _coreAPIHttpService.Implicit(new Dictionary<string, string> { { "grant_type", "implicit" },
  87. { "client_id",clientID },
  88. { "account",core.id },
  89. { "nonce",Guid.NewGuid().ToString()} }, _option.Location, _configuration);
  90. if (tmdidImplicit != null && !string.IsNullOrEmpty(tmdidImplicit.id_token))
  91. {
  92. return Ok(new { coreUser = core, tmdidImplicit });
  93. }
  94. }
  95. return Ok(new { coreUser = core });
  96. }
  97. /// <summary>
  98. /// 修改教师信息
  99. /// </summary>
  100. /// <param name="request"></param>
  101. /// <returns></returns>
  102. [ProducesDefaultResponseType]
  103. [HttpPost("set-teacher-info")]
  104. [AuthToken(Roles = "admin,teacher,area")]
  105. [Authorize(Roles = "IES")]
  106. public async Task<IActionResult> SetTeacherInfo(JsonElement request)
  107. {
  108. var client = _azureCosmos.GetCosmosClient();
  109. if (!request.TryGetProperty("opt", out JsonElement _opt))
  110. {
  111. return BadRequest();
  112. }
  113. var (userid, name, _, school) = HttpContext.GetAuthTokenInfo();
  114. try
  115. {
  116. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(userid, new PartitionKey("Base"));
  117. switch (true)
  118. {
  119. //修改默认学校
  120. case bool when $"{_opt}".Equals("UpdateDefaultSchool", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("defaultSchool", out JsonElement _defaultSchool)):
  121. if (teacher.schools.Select(x => x.schoolId).Contains($"{_defaultSchool}") && !string.IsNullOrEmpty($"{_defaultSchool}"))
  122. {
  123. teacher.defaultSchool = $"{_defaultSchool}";
  124. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, userid, new PartitionKey("Base"));
  125. return Ok(new { teacher, status = 1 });
  126. }
  127. else
  128. {
  129. return BadRequest(new { status = -1, msg = "您未加入该学校!" });
  130. }
  131. //修改教师的最大课例保存数量
  132. case bool when $"{_opt}".Equals("UpdateLessonLimit", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("lessonLimit", out JsonElement _lessonLimit)):
  133. teacher.lessonLimit = int.Parse($"{_lessonLimit}");
  134. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, userid, new PartitionKey("Base"));
  135. return Ok(new { teacher, status = 1 });
  136. //修改教师设置自动将课例发布给谁的设置
  137. case bool when $"{_opt}".Equals("UpdateLessonShow", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("lessonShow", out JsonElement _lessonShow)):
  138. teacher.lessonShow = _lessonShow.Deserialize<List<string>>();
  139. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, userid, new PartitionKey("Base"));
  140. return Ok(new { teacher, status = 1 });
  141. //设置教师的科目信息
  142. case bool when $"{_opt}".Equals("SetTeacherSubject", StringComparison.OrdinalIgnoreCase) && request.TryGetProperty("targerTecher", out JsonElement _targetTecher)
  143. && request.TryGetProperty("subjectIds", out JsonElement _subjectIds):
  144. if (_subjectIds.ValueKind.Equals(JsonValueKind.Array))
  145. {
  146. if (_targetTecher.ValueKind.Equals(JsonValueKind.Array))
  147. {
  148. List<string> targetTechers = _targetTecher.ToObject<List<string>>();
  149. List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
  150. foreach (string targetTecher in targetTechers)
  151. {
  152. try
  153. {
  154. SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>($"{targetTecher}", new PartitionKey($"Teacher-{school}"));
  155. schoolTeacher.subjectIds = _subjectIds.ToObject<List<string>>();
  156. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, $"{targetTecher}", new PartitionKey($"Teacher-{school}"));
  157. schoolTeachers.Add(schoolTeacher);
  158. }
  159. catch (Exception ex)
  160. {
  161. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info:SetTeacherSubject()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}-{targetTecher}", GroupNames.醍摩豆服務運維群組);
  162. }
  163. }
  164. return Ok(new { status = 1, schoolTeachers });
  165. }
  166. else
  167. {
  168. try
  169. {
  170. SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>($"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
  171. schoolTeacher.subjectIds = _subjectIds.ToObject<List<string>>();
  172. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, $"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
  173. return Ok(new { status = 1, schoolTeacher });
  174. }
  175. catch (Exception ex)
  176. {
  177. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info:SetTeacherSubject()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  178. return Ok(new { error = -1, msg = "设置失败" });
  179. }
  180. }
  181. }
  182. else
  183. {
  184. return Ok(new { error = -1, msg = "设置失败" });
  185. }
  186. ///移交管理员
  187. case bool when $"{_opt}".Equals("TransferAdminRole", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("targerTecher", out JsonElement _targetTecher)):
  188. if (!string.IsNullOrEmpty(school) && !string.IsNullOrEmpty($"{_targetTecher}"))
  189. {
  190. SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>(userid, new PartitionKey($"Teacher-{school}"));
  191. if (schoolTeacher.roles.IsNotEmpty() && schoolTeacher.roles.Contains("admin"))
  192. {
  193. schoolTeacher.roles.Remove("admin");
  194. SchoolTeacher newSchoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>($"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
  195. if (!newSchoolTeacher.roles.Contains("admin"))
  196. {
  197. newSchoolTeacher.roles.Add("admin");
  198. newSchoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(newSchoolTeacher, $"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
  199. }
  200. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, userid, new PartitionKey($"Teacher-{school}"));
  201. string code = "transfer-admin";
  202. School schoolBase = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey($"Base"));
  203. Notification notification = new Notification
  204. {
  205. hubName = "hita",
  206. type = "msg",
  207. from = $"ies5:{_option.Location}:{school}",
  208. to = new List<string> { $"{_targetTecher}" },
  209. label = $"{code}_school",
  210. body = new { location = _option.Location, biz = code, tmdid = userid, tmdname = name, schoolcode = $"{school}", schoolname = $"{schoolBase.name}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
  211. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  212. };
  213. if (notification != null)
  214. {
  215. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  216. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  217. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  218. var location = _option.Location;
  219. await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
  220. }
  221. _ = _azureStorage.SaveLog("transfer-admin-role", new { request, userid, name, school, schoolName = schoolBase.name, targetTecher = _targetTecher, }.ToJsonString(), bizId: $"{userid}-{schoolBase.id}-{_targetTecher}", httpContext: HttpContext, dingDing: _dingDing, scope: "school");
  222. return Ok(new { status = 1 });
  223. }
  224. else
  225. {
  226. return BadRequest(new { status = -1, msg = "当前登录账号没有admin权限" });
  227. }
  228. }
  229. else
  230. {
  231. return BadRequest(new { status = -1, msg = "参数异常!" });
  232. }
  233. }
  234. }
  235. catch (Exception ex)
  236. {
  237. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  238. return BadRequest("teacher not exist");
  239. }
  240. return BadRequest();
  241. }
  242. //TODO 此API需處理對應前端返回的相關數據
  243. [ProducesDefaultResponseType]
  244. [Authorize(Roles = "IES")]
  245. [HttpPost("get-teacher-info")]
  246. public async Task<IActionResult> GetTeacherInfo(JsonElement request)
  247. {
  248. string domain = HttpContext?.Request?.Host.Host;
  249. if (domain.Equals("teammodelos.chinacloudsites.cn"))
  250. {
  251. domain = _option.HostName;
  252. }
  253. if (_option.Location.Equals("China"))
  254. {
  255. domain = _option.HostName;
  256. }
  257. if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  258. var jwt = new JwtSecurityToken(id_token.GetString());
  259. //TODO 此驗證IdToken先簡單檢查,後面需向Core ID新API,驗證Token
  260. var id = jwt.Payload.Sub;
  261. jwt.Payload.TryGetValue("name", out object name);
  262. jwt.Payload.TryGetValue("picture", out object picture);
  263. (string ip, string region) = await LoginService.LoginIp(HttpContext, _searcher);
  264. try
  265. {
  266. Teacher teacher = null;
  267. TeacherInfo teacherInfo = await TeacherService.TeacherInfo(_azureCosmos, teacher, $"{name}", $"{picture}", id, _azureStorage, _option, _azureRedis, ip, _httpTrigger);
  268. teacherInfo.areas.ForEach(x => { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } });
  269. LoginService.LoginLog(HttpContext, _option, _logger, _dingDing, ip, region, id, $"{name}", 200);
  270. int lessonLimit = teacherInfo.teacher.lessonLimit;
  271. if (teacherInfo.teacher.lessonLimit == 0)
  272. {
  273. //未设置的的采用系统设置的默认值30
  274. lessonLimit = Constant.private_lesson_limit;
  275. }
  276. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOAuth");
  277. List<string> Codes = new List<string>();
  278. if (!string.IsNullOrWhiteSpace(id))
  279. {
  280. Codes.Add($" Code {QueryComparisons.Equal} '{id}' ");
  281. }
  282. string qurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow' and Domain {QueryComparisons.Equal} '{domain}' and ( { string.Join(" or ", Codes)} ) ";
  283. var result = await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(qurey), null);
  284. List<OAuthShow> shows = result.Results;
  285. return Ok(new
  286. {
  287. privateShows = shows?.FindAll(x => x.Scope.Equals("private")).Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
  288. location = _option.Location,
  289. teacherInfo.auth_token,
  290. teacherInfo.blob_uri,
  291. teacherInfo.blob_sas,
  292. teacherInfo.schools,
  293. teacherInfo.defaultschool,
  294. teacherInfo.courses,
  295. teacherInfo.total,
  296. teacherInfo.osblob_uri,
  297. teacherInfo.osblob_sas,
  298. teacherInfo.tsize,
  299. status = 200,
  300. teacherInfo.areas,
  301. lessonLimit,
  302. teacherInfo.teacher.lessonShow
  303. });
  304. }
  305. catch (CosmosException ex)
  306. {
  307. LoginService.LoginLog(HttpContext, _option, _logger, _dingDing, ip, region, id, $"{name}", 500);
  308. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  309. return BadRequest();
  310. }
  311. catch (Exception ex)
  312. {
  313. LoginService.LoginLog(HttpContext, _option, _logger, _dingDing, ip, region, id, $"{name}", 500);
  314. _ = _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  315. return BadRequest();
  316. }
  317. }
  318. //TODO 此API需處理對應前端返回的相關數據
  319. [ProducesDefaultResponseType]
  320. [Authorize(Roles = "IES")]
  321. [HttpPost("get-school-info")]
  322. public async Task<IActionResult> GetSchoolInfo(JsonElement request)
  323. {
  324. string domain = HttpContext?.Request?.Host.Host;
  325. if (domain.Equals("teammodelos.chinacloudsites.cn") ) {
  326. domain = _option.HostName;
  327. }
  328. if (_option.Location.Equals("China"))
  329. {
  330. domain = _option.HostName;
  331. }
  332. try
  333. {
  334. if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  335. if (!request.TryGetProperty("school_code", out JsonElement _school_code)) return BadRequest();
  336. string school_code = $"{_school_code}";
  337. var jwt = new JwtSecurityToken(id_token.GetString());
  338. var id = jwt.Payload.Sub;
  339. var client = _azureCosmos.GetCosmosClient();
  340. //權限token
  341. jwt.Payload.TryGetValue("name", out object name);
  342. jwt.Payload.TryGetValue("picture", out object picture);
  343. List<string> roles = new List<string>();
  344. List<string> permissions = new List<string>();
  345. int size = 0;
  346. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
  347. List<AreaDto> areas = new List<AreaDto>();
  348. HashSet<string> areaIds = new HashSet<string>();
  349. if (teacher.areas.IsNotEmpty())
  350. {
  351. teacher.areas.ForEach(x => {
  352. areaIds.Add(x.areaId);
  353. });
  354. }
  355. if (teacher.schools.IsNotEmpty())
  356. {
  357. teacher.schools.ForEach(x => {
  358. if (!string.IsNullOrEmpty(x.areaId))
  359. {
  360. areaIds.Add(x.areaId);
  361. }
  362. });
  363. }
  364. List<Area> areasDbs = new List<Area>();
  365. List<AreaSetting> areaSettings = new List<AreaSetting>();
  366. if (areaIds.Count > 0)
  367. {
  368. string queryText = $"select value(c) from c where c.id in ({string.Join(",", areaIds.Select(x => $"'{x}'"))})";
  369. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base-Area") }))
  370. {
  371. areasDbs.Add(item);
  372. }
  373. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AreaSetting>(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("AreaSetting") }))
  374. {
  375. areaSettings.Add(item);
  376. }
  377. }
  378. if (teacher.areas.IsNotEmpty())
  379. {
  380. foreach (var areat in teacher.areas)
  381. {
  382. Area area = areasDbs.Find(x => x.id.Equals(areat.areaId));
  383. AreaSetting setting = null;
  384. if (area != null)
  385. {
  386. setting = areaSettings.Find(x => x.id.Equals(areat.areaId));
  387. }
  388. int access = 0;
  389. if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
  390. {
  391. access = 1;
  392. }
  393. //if (setting != null)
  394. //{
  395. // setting.accessConfig = null;
  396. //}
  397. areas.Add(new AreaDto { areaId = area.id, name = area.name, standard = area.standard, standardName = area.standardName, setting = setting, access = access });
  398. }
  399. }
  400. if (school_code.Equals(teacher.defaultSchool) && teacher.schools.IsNotEmpty() && !teacher.schools.Select(x => x.schoolId).Contains(school_code))
  401. {
  402. school_code = teacher.schools[0].schoolId;
  403. teacher.defaultSchool = school_code;
  404. teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
  405. }
  406. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{school_code}"));
  407. if (response.Status == 200)
  408. {
  409. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  410. if (json.RootElement.TryGetProperty("size", out JsonElement _size) && _size.ValueKind == JsonValueKind.Number)
  411. {
  412. size = _size.GetInt32();
  413. }
  414. if (json.RootElement.TryGetProperty("roles", out JsonElement _roles) && _roles.ValueKind != JsonValueKind.Null)
  415. {
  416. foreach (var obj in _roles.EnumerateArray())
  417. {
  418. roles.Add(obj.GetString());
  419. }
  420. }
  421. if (json.RootElement.TryGetProperty("permissions", out JsonElement _permissions) && _permissions.ValueKind != JsonValueKind.Null)
  422. {
  423. foreach (var obj in _permissions.EnumerateArray())
  424. {
  425. permissions.Add(obj.GetString());
  426. }
  427. }
  428. }
  429. else //無此學校資料
  430. {
  431. }
  432. if (roles.Count == 0)
  433. {
  434. //助理,管家
  435. //roles.Add("assist");
  436. roles.Add("teacher");
  437. }
  438. //TODO JJ,调整为取得学校基础设置数据,取代下方學校學制、年級
  439. School school_base = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
  440. foreach (var period in school_base.period)
  441. {
  442. try
  443. {
  444. await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemCond>($"{period.id}", new PartitionKey($"ItemCond-{school_code}"));
  445. }
  446. catch (CosmosException)
  447. {
  448. ItemCond itemCond = new ItemCond
  449. {
  450. id = period.id,
  451. pk = "ItemCond",
  452. code = $"ItemCond-{school_code}",
  453. ttl = -1,
  454. };
  455. try
  456. {
  457. await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<ItemCond>(itemCond, new PartitionKey($"ItemCond-{school_code}"));
  458. }
  459. catch (CosmosException ex) when (ex.Status == 409)
  460. {
  461. continue;
  462. }
  463. }
  464. }
  465. string currAreaId = "";
  466. dynamic currArea = new ExpandoObject();
  467. if (!string.IsNullOrEmpty(school_base.areaId))
  468. {
  469. try
  470. {
  471. Area area = areasDbs.Find(x => x.id.Equals(school_base.areaId));
  472. AreaSetting setting = null;
  473. if (area != null)
  474. {
  475. //setting =await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(school_base.areaId, new PartitionKey("AreaSetting"));
  476. setting = areaSettings.Find(x => x.id.Equals(school_base.areaId));
  477. }
  478. int access = 0;
  479. AccessConfig accessConfig = null;
  480. if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
  481. {
  482. access = 1;
  483. accessConfig = setting.accessConfig.ToObject<AccessConfig>();
  484. }
  485. //if (setting!=null&& !string.IsNullOrEmpty(setting.accessConfig)) {
  486. // setting.accessConfig = null;
  487. //}
  488. currArea = new
  489. {
  490. areaId = area?.id,
  491. name = area?.name,
  492. standard = area?.standard,
  493. standardName = area?.standardName,
  494. setting = setting,
  495. access = access,
  496. //submitType=accessConfig?.submitType,
  497. homeworkType = accessConfig != null && accessConfig.homeworkType.IsNotEmpty() ? accessConfig.homeworkType : new List<string> { "pdf" },
  498. };
  499. currAreaId = area?.id;
  500. }
  501. catch (CosmosException)
  502. {
  503. //数据库捞不到数据
  504. }
  505. }
  506. if (areas.Count > 0)
  507. {
  508. roles.Add("area");
  509. }
  510. //TODO JJ,更新Token时,在取得学校资讯时,没有传入schoolId
  511. var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, schoolID: school_code.ToString(), areaId: currAreaId, standard: school_base.standard, roles: roles.ToArray(), permissions: permissions.ToArray(), expire: 1);
  512. //取得班级
  513. List<object> school_classes = new List<object>();
  514. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator
  515. (queryText: $"SELECT c.id,c.x,c.y,c.name,c.year,c.teacher,c.periodId,c.gradeId,c.room,c.sn,c.no,c.style,c.status,c.openType,c.school, ARRAY_LENGTH(c.students) AS studCount FROM c",
  516. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school_code}") }))
  517. {
  518. var jsonc = await JsonDocument.ParseAsync(item.ContentStream);
  519. foreach (var classeinfo in jsonc.RootElement.GetProperty("Documents").EnumerateArray())
  520. {
  521. school_classes.Add(classeinfo.ToObject<object>());
  522. }
  523. }
  524. //取得教室
  525. List<Room> school_rooms = new List<Room>();
  526. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Room>(queryText: $"select value(c) from c ",
  527. requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Room-{school_code}") }))
  528. {
  529. school_rooms.Add(item);
  530. }
  531. //該老師排定的學校課程
  532. List<object> school_courses = new List<object>();
  533. var query = $"SELECT distinct value(c) FROM c JOIN A1 IN c.schedule where A1.teacherId='{id}'";
  534. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school_code}") }))
  535. {
  536. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  537. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  538. {
  539. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  540. {
  541. school_courses.Add(obj.ToObject<object>());
  542. }
  543. }
  544. }
  545. List<SchoolProductSumData> services = new List<SchoolProductSumData>();
  546. //获取HiTeachCC的授权
  547. int cc_avaliable = 0;
  548. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<int>("select value count(1) from c where c.prodCode='LZLL6ZEI'",
  549. requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Product-{school_code}") }))
  550. {
  551. cc_avaliable = item;
  552. }
  553. services.Add(new SchoolProductSumData { prodCode = "LZLL6ZEI", avaliable = cc_avaliable });
  554. Azure.Response productSumResponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(school_code, new PartitionKey("ProductSum"));
  555. if (productSumResponse.Status == 200)
  556. {
  557. var doc = JsonDocument.Parse(productSumResponse.Content);
  558. //if (doc.RootElement.TryGetProperty("serial", out JsonElement serial))
  559. //{
  560. // serials = serial.ToObject<List<SchoolProductSumData>>();
  561. //}
  562. if (doc.RootElement.TryGetProperty("service", out JsonElement service))
  563. {
  564. services .AddRange(service.ToObject<List<SchoolProductSumData>>());
  565. }
  566. }
  567. //校本課綱 [式樣未定 先不取]
  568. //取得School Blob 容器位置及SAS
  569. string school_code_blob = school_code.ToLower();
  570. var container = _azureStorage.GetBlobContainerClient(school_code_blob);
  571. await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建School容器,如存在則不做任何事,保障容器一定存在
  572. var (blob_uri, blob_sas) = (roles.Contains("admin") || permissions.Contains("schoolAc-upd")) ? _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete) : _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Write);
  573. ///https://teammodelstorage.blob.core.chinacloudapi.cn/teammodelos
  574. 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);
  575. areas.ForEach(x => { { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } } });
  576. int lessonLimit = teacher.lessonLimit;
  577. if (teacher.lessonLimit == 0)
  578. {
  579. //未设置的的采用系统设置的默认值30
  580. lessonLimit = Constant.private_lesson_limit;
  581. }
  582. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOAuth");
  583. List<string> Codes = new List<string>();
  584. if (!string.IsNullOrWhiteSpace(id))
  585. {
  586. Codes.Add($" Code {QueryComparisons.Equal} '{id}' ");
  587. }
  588. if (!string.IsNullOrWhiteSpace(school_code))
  589. {
  590. Codes.Add($" Code {QueryComparisons.Equal} '{school_code}' ");
  591. }
  592. if (!string.IsNullOrWhiteSpace(currAreaId))
  593. {
  594. Codes.Add($" Code {QueryComparisons.Equal} '{currAreaId}' ");
  595. }
  596. string tbqurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow' and Domain {QueryComparisons.Equal} '{domain}' and ( { string.Join(" or ", Codes)} ) ";
  597. var result = await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(tbqurey), null);
  598. List<OAuthShow> shows = result.Results;
  599. List<OAuthShow> schoolShow = new List<OAuthShow>();
  600. var schoolShows = shows?.Where(y => !y.Scope.Equals("private"));
  601. if (schoolShows.Any())
  602. {
  603. schoolShows.ToList().ForEach(y => { y.Scope = "school"; y.Code = school_code; });
  604. schoolShows.GroupBy(x => $"{x.Type}{x.Scope}").Select(s => new { key = s.Key, list = s.ToList() }).ToList().ForEach(z => {
  605. schoolShow.Add(z.list.First());
  606. });
  607. }
  608. return Ok(new
  609. {
  610. privateShows = shows?.FindAll(x => x.Scope.Equals("private")).Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
  611. schoolShows = schoolShow.Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
  612. auth_token,
  613. blob_uri,
  614. blob_sas,
  615. school_base,
  616. school_courses,
  617. school_classes,
  618. school_rooms,
  619. size,
  620. osblob_uri,
  621. osblob_sas,
  622. status = 200,
  623. areas,
  624. currArea,
  625. lessonLimit,
  626. teacher.lessonShow,
  627. productSum = new
  628. {
  629. //serial = serials,
  630. service = services
  631. }
  632. });
  633. }
  634. catch (CosmosException ex)
  635. {
  636. HttpContext.Request.Headers.TryGetValue("referer", out var referer);
  637. HttpContext.Request.Headers.TryGetValue("sec-ch-ua", out var chua);
  638. HttpContext.Request.Headers.TryGetValue("sec-ch-ua-platform", out var platform);
  639. HttpContext.Request.Headers.TryGetValue("user-agent", out var useragent);
  640. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/get-school-info()\n{ex.Message}\n{ex.StackTrace}\n{request.ToJsonString()}\nreferer:{referer}\nsec-ch-ua:{chua}\nsec-ch-ua-platform:{platform}\nuser-agent:{useragent}", GroupNames.醍摩豆服務運維群組);
  641. return BadRequest(new { status = ex.Status });
  642. }
  643. catch (Exception ex)
  644. {
  645. HttpContext.Request.Headers.TryGetValue("referer", out var referer);
  646. HttpContext.Request.Headers.TryGetValue("sec-ch-ua", out var chua);
  647. HttpContext.Request.Headers.TryGetValue("sec-ch-ua-platform", out var platform);
  648. HttpContext.Request.Headers.TryGetValue("user-agent", out var useragent);
  649. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/get-school-info()\n{ex.Message}\n{ex.StackTrace}\n{request.ToJsonString()}\nreferer:{referer}\nsec-ch-ua:{chua}\nsec-ch-ua-platform:{platform}\nuser-agent:{useragent}", GroupNames.醍摩豆服務運維群組);
  650. return BadRequest(new { status = 500 });
  651. }
  652. }
  653. /// <summary>
  654. /// 取得學校所有列表
  655. /// </summary>
  656. /// <param name="request"></param>
  657. /// <returns></returns>
  658. [ProducesDefaultResponseType]
  659. //[AuthToken(Roles = "teacher")]
  660. [HttpPost("get-school-list")]
  661. public async Task<IActionResult> GetSchoolList(JsonElement request)
  662. {
  663. try
  664. {
  665. //輸入值
  666. string sqlSchoolId = (request.TryGetProperty("schoolId", out JsonElement reqSchoolId)) ? reqSchoolId.GetString() : string.Empty;
  667. bool sqlHasManager = (request.TryGetProperty("manager", out JsonElement reqHasManager)) ? reqHasManager.GetBoolean() : false;
  668. bool sqlHasMBaseModule = (request.TryGetProperty("base", out JsonElement reqHasBaseModule)) ? reqHasBaseModule.GetBoolean() : false;
  669. var client = _azureCosmos.GetCosmosClient();
  670. //有管理者的學校
  671. Dictionary<string, List<Dictionary<string, string>>> managerSchDic = new Dictionary<string, List<Dictionary<string, string>>>();
  672. string managerWhereOption = (!string.IsNullOrWhiteSpace(sqlSchoolId)) ? $" AND c.code = 'Teacher-{sqlSchoolId}'" : string.Empty;
  673. string managerSql = $"SELECT DISTINCT REPLACE(c.code, 'Teacher-', '') AS schoolId, c.id, c.name FROM c WHERE ARRAY_CONTAINS(c.roles, 'admin', true) AND c.pk = 'Teacher' AND c.status = 'join'{managerWhereOption}";
  674. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: managerSql, requestOptions: new QueryRequestOptions() { }))
  675. {
  676. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  677. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  678. {
  679. string id = obj.GetProperty("id").GetString(); //管理者ID
  680. string name = obj.GetProperty("name").GetString(); //管理者姓名
  681. string schoolId = obj.GetProperty("schoolId").GetString(); //學校ID
  682. Dictionary<string, string> managerDic = new Dictionary<string, string>();
  683. managerDic.Add("id", id);
  684. managerDic.Add("name", name);
  685. if (managerSchDic.ContainsKey(schoolId))
  686. {
  687. managerSchDic[schoolId].Add(managerDic);
  688. }
  689. else
  690. {
  691. List<Dictionary<string, string>> managerList = new List<Dictionary<string, string>>();
  692. managerList.Add(managerDic);
  693. managerSchDic.Add(schoolId, managerList);
  694. }
  695. }
  696. }
  697. //有管理模組的學校
  698. List<string> baseModuleSchList = new List<string>();
  699. string baseModuleWhereOption = (!string.IsNullOrWhiteSpace(sqlSchoolId)) ? $" AND c.id = '{sqlSchoolId}'" : string.Empty;
  700. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id FROM c JOIN serviceProduct IN c.service.product WHERE serviceProduct.prodCode = 'IPDYZYLC'{baseModuleWhereOption}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Product") }))
  701. {
  702. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  703. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  704. {
  705. string schoolId = obj.GetProperty("id").GetString(); //學校ID
  706. baseModuleSchList.Add(schoolId);
  707. }
  708. }
  709. //學校資料
  710. List<object> schools = new List<object>();
  711. string schoolWhereOption = (!string.IsNullOrWhiteSpace(sqlSchoolId)) ? $" WHERE c.id = '{sqlSchoolId}'" : string.Empty;
  712. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.region, c.province, c.city, c.picture FROM c {schoolWhereOption}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  713. {
  714. var jsons = await JsonDocument.ParseAsync(item.ContentStream);
  715. if (jsons.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  716. {
  717. foreach (var obj in jsons.RootElement.GetProperty("Documents").EnumerateArray())
  718. {
  719. dynamic schoolExtobj = new ExpandoObject();
  720. schoolExtobj.id = obj.GetProperty("id").GetString(); //學校ID
  721. schoolExtobj.name = obj.GetProperty("name");
  722. schoolExtobj.region = obj.GetProperty("region");
  723. schoolExtobj.province = obj.GetProperty("province");
  724. schoolExtobj.city = obj.GetProperty("city");
  725. schoolExtobj.picture = obj.GetProperty("picture");
  726. if (managerSchDic.ContainsKey(schoolExtobj.id))
  727. {
  728. schoolExtobj.hasManager = true;
  729. schoolExtobj.managers = managerSchDic[schoolExtobj.id];
  730. }
  731. else
  732. {
  733. schoolExtobj.hasManager = false;
  734. schoolExtobj.managers = new List<object>();
  735. }
  736. schoolExtobj.hasBaseModule = (baseModuleSchList.Contains(schoolExtobj.id)) ? true : false;
  737. //學校輸出結果加入篩選
  738. if ((sqlHasManager && sqlHasMBaseModule) && (schoolExtobj.hasManager && schoolExtobj.hasBaseModule))
  739. {
  740. schools.Add(schoolExtobj);
  741. }
  742. else if (sqlHasManager && schoolExtobj.hasManager)
  743. {
  744. schools.Add(schoolExtobj);
  745. }
  746. else if (sqlHasMBaseModule && schoolExtobj.hasBaseModule)
  747. {
  748. schools.Add(schoolExtobj);
  749. }
  750. else if (!sqlHasManager && !sqlHasMBaseModule)
  751. {
  752. schools.Add(schoolExtobj);
  753. }
  754. }
  755. }
  756. }
  757. return Ok(new { schools });
  758. }
  759. catch (Exception ex)
  760. {
  761. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/get-school-info()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  762. return BadRequest();
  763. }
  764. }
  765. /// <summary>
  766. /// 申請或同意邀請加入學校
  767. /// </summary>
  768. ///
  769. /// <param name="requert"></param>
  770. /// <returns></returns>
  771. [ProducesDefaultResponseType]
  772. [AuthToken(Roles = "teacher")]
  773. [HttpPost("join-school")]
  774. [Authorize(Roles = "IES")]
  775. public async Task<IActionResult> JoinSchool(JsonElement requert)
  776. {
  777. try
  778. {
  779. if (!requert.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest(); //"invite":學校邀請 "request":老師申請 "join":"成為學校老師",leave 离开,cancel 取消。
  780. if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
  781. if (!requert.TryGetProperty("school_name", out JsonElement school_name)) return BadRequest();
  782. ///当邀请某个老师加入学校则需要知道是谁邀请的
  783. //if (!requert.TryGetProperty("school_admin", out JsonElement school_admin)) return BadRequest();
  784. string authtoken = HttpContext.GetXAuth("AuthToken");
  785. if (string.IsNullOrEmpty(authtoken)) return BadRequest();
  786. var jwt = new JwtSecurityToken(authtoken);
  787. var id = jwt.Payload.Sub;
  788. var schoolcode = jwt.Payload.Azp;
  789. var Claims = jwt.Payload.Claims;
  790. jwt.Payload.TryGetValue("name", out object name);
  791. jwt.Payload.TryGetValue("picture", out object picture);
  792. var client = _azureCosmos.GetCosmosClient();
  793. //在老師表找出老師,處理該學校狀態 (老師基本資料應該要存在)
  794. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
  795. if (teacher.schools == null)
  796. teacher.schools = new List<Teacher.TeacherSchool>();
  797. var school = teacher.schools?.FirstOrDefault(x => x.schoolId.Equals(school_code.GetString(), StringComparison.OrdinalIgnoreCase));
  798. School schoolBase = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
  799. if (school != null)
  800. school.status = grant_type.GetString();
  801. else
  802. {
  803. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  804. teacher.schools.Add(new Teacher.TeacherSchool() { areaId = schoolBase.areaId, picture = schoolBase.picture, schoolId = school_code.GetString(), name = school_name.GetString(), status = grant_type.GetString(), time = now });
  805. }
  806. if (grant_type.GetString().Equals("leave") || grant_type.GetString().Equals("cancel"))
  807. {
  808. if (teacher.schools.IsNotEmpty())
  809. {
  810. //获取之前已经加入的学校或者申请的学校
  811. var inSchools = teacher.schools.Where(x => x.schoolId == school_code.GetString()).ToList();
  812. if (inSchools.IsNotEmpty())
  813. {
  814. inSchools.ForEach(x => teacher.schools.Remove(x));
  815. }
  816. }
  817. if (teacher.schools.Count > 0 && teacher.size <= 1)
  818. {
  819. teacher.size = 2;
  820. }
  821. if (!string.IsNullOrEmpty(teacher.defaultSchool) && teacher.defaultSchool.Equals($"{school_code}"))
  822. {
  823. if (teacher.schools.IsNotEmpty())
  824. {
  825. teacher.defaultSchool = teacher.schools[0].schoolId;
  826. }
  827. else
  828. {
  829. teacher.defaultSchool = null;
  830. }
  831. }
  832. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
  833. var sresponse = await client.GetContainer(Constant.TEAMModelOS, "School").DeleteItemStreamAsync(id, new PartitionKey($"Teacher-{school_code}"));
  834. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{school_code}", new PartitionKey("TeacherImport"));
  835. TeacherImport teacherImport = null;
  836. if (response.Status == 200)
  837. {
  838. teacherImport = JsonDocument.Parse(response.Content).RootElement.Deserialize<TeacherImport>();
  839. var tchs = teacherImport?.teachers?.RemoveAll(x => !string.IsNullOrWhiteSpace(x.id) && x.id.Equals(id));
  840. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
  841. }
  842. return Ok(new { stauts = 1 });
  843. }
  844. else
  845. {
  846. var dft = new List<string>() { "content-read", "exercise-read", "knowledge-read", "syllabus-read" };
  847. if (teacher.schools.Count > 0 && teacher.size <= 1)
  848. {
  849. teacher.size = 2;
  850. }
  851. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
  852. //在學校表處理該學校教師帳號的狀態
  853. var sresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{school_code}"));
  854. if (sresponse.Status == 200)
  855. {
  856. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  857. SchoolTeacher steacher = json.ToObject<SchoolTeacher>();
  858. steacher.status = grant_type.GetString();
  859. if (grant_type.ToString().Equals("join"))
  860. {
  861. if (steacher.permissions.IsNotEmpty())
  862. {
  863. foreach (var d in dft)
  864. {
  865. if (!steacher.permissions.Contains(d))
  866. {
  867. steacher.permissions.Add(d);
  868. }
  869. }
  870. }
  871. else
  872. {
  873. steacher.permissions = dft;
  874. }
  875. }
  876. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(steacher, id, new PartitionKey($"Teacher-{school_code}"));
  877. }
  878. else
  879. {
  880. SchoolTeacher st = new SchoolTeacher()
  881. {
  882. pk = "Teacher",
  883. code = $"Teacher-{school_code}",
  884. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  885. id = id,
  886. name = name.ToString(),
  887. picture = picture?.ToString(),
  888. permissions = grant_type.ToString().Equals("join") ? dft : null,
  889. roles = new List<string>() { "teacher" },
  890. size = 0,
  891. status = grant_type.GetString()
  892. };
  893. var response = await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(st, new PartitionKey($"Teacher-{school_code}"));
  894. }
  895. Azure.Response responseImport = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{school_code}", new PartitionKey("TeacherImport"));
  896. TeacherImport teacherImport = null;
  897. if ($"{grant_type}".Equals("request"))
  898. {
  899. if (responseImport.Status == 200)
  900. {
  901. teacherImport = JsonDocument.Parse(responseImport.Content).RootElement.Deserialize<TeacherImport>();
  902. var tchs = teacherImport?.teachers?.FindAll(x => string.IsNullOrWhiteSpace(x.iname) && x.iname.Equals($"{name}") && string.IsNullOrWhiteSpace(x.id));
  903. if (tchs.IsNotEmpty())
  904. {
  905. var tch = tchs[0];
  906. string ujson = null;
  907. var content = new StringContent(new List<string> { $"{id}" }.ToJsonString(), Encoding.UTF8, "application/json");
  908. ujson = await _coreAPIHttpService.GetUserInfos(content);
  909. List<CoreUser> coreUsers = new List<CoreUser>();
  910. if (!string.IsNullOrWhiteSpace(ujson))
  911. {
  912. coreUsers = ujson.ToObject<List<CoreUser>>();
  913. }
  914. if (coreUsers.IsNotEmpty())
  915. {
  916. tch.phone = coreUsers[0].mobile;
  917. tch.email = coreUsers[0].mail;
  918. }
  919. tch.id = $"{id}";
  920. tch.picture = $"{picture}";
  921. tch.status = $"{grant_type}";
  922. tch.time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  923. tch.tmdid = id;
  924. tch.name = $"{name }";
  925. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
  926. }
  927. }
  928. }
  929. if (grant_type.ToString().Equals("join"))
  930. {
  931. if (responseImport.Status == 200)
  932. {
  933. teacherImport = JsonDocument.Parse(responseImport.Content).RootElement.Deserialize<TeacherImport>();
  934. teacherImport?.teachers.ForEach(x => {
  935. if (!string.IsNullOrWhiteSpace(x.id) && !string.IsNullOrWhiteSpace(teacher.id) && x.id.Equals(teacher.id))
  936. {
  937. x.name = teacher.name;
  938. x.status = "join";
  939. x.time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  940. x.picture = teacher.picture;
  941. }
  942. });
  943. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
  944. await TmdUserService.JoinSchool(client, teacher.id, teacher.picture, teacher.name, school.schoolId, school.name);
  945. }
  946. }
  947. Notification notification = null;
  948. List<SchoolTeacher> teachers = new List<SchoolTeacher>();
  949. var queryslt = $"SELECT value(c) FROM c join A1 in c.roles where A1 in ('admin')";
  950. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<SchoolTeacher>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school_code}") }))
  951. {
  952. teachers.Add(item);
  953. }
  954. if (teachers.IsNotEmpty())
  955. {
  956. string code = grant_type.GetString();
  957. if (grant_type.GetString().Equals("join"))
  958. {
  959. code = "invite-join";
  960. }
  961. notification = new Notification
  962. {
  963. hubName = "hita",
  964. type = "msg",
  965. from = $"ies5:{_option.Location}:private",
  966. to = teachers.Select(x => x.id).ToList(),
  967. label = $"{code}_school",
  968. body = new { location = _option.Location, biz = code, tmdid = id, tmdname = name.ToString(), schoolcode = $"{school_code}", schoolname = $"{school_name}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
  969. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  970. };
  971. }
  972. if (notification != null)
  973. {
  974. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  975. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  976. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  977. var location = _option.Location;
  978. var code = await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
  979. }
  980. return Ok(new { stauts = 1 });
  981. }
  982. }
  983. catch (Exception ex)
  984. {
  985. await _dingDing.SendBotMsg($"TEAMModel,{_option.Location},Init/JoinSchool()\n{ex.Message}\n{ex.StackTrace}\n{requert.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  986. return BadRequest();
  987. }
  988. }
  989. //課綱的model先記在下面,待式樣確定後再轉換
  990. private List<SyllabusNode> CreateSyllabusTree(List<Syllabus> syllabuses)
  991. {
  992. List<SyllabusNode> nodes = new List<SyllabusNode>();
  993. foreach (var syllabus in syllabuses)
  994. {
  995. if (syllabus.pid.Equals(""))
  996. nodes.Add(new SyllabusNode { id = syllabus.id, name = syllabus.name });
  997. else
  998. {
  999. CreateNode(nodes, syllabus);
  1000. }
  1001. }
  1002. return nodes;
  1003. }
  1004. private void CreateNode(List<SyllabusNode> nodes, Syllabus parent)
  1005. {
  1006. foreach (var node in nodes)
  1007. {
  1008. if (node.id == parent.pid)
  1009. {
  1010. node.children.Add(new SyllabusNode { id = parent.id, name = parent.name });
  1011. }
  1012. else
  1013. {
  1014. CreateNode(node.children, parent);
  1015. }
  1016. }
  1017. }
  1018. public class SyllabusRole
  1019. {
  1020. public string id { get; set; }
  1021. public string name { get; set; }
  1022. public object period { get; set; }
  1023. public object semester { get; set; }
  1024. public object grade { get; set; }
  1025. public object subject { get; set; }
  1026. public int resourceCount { get; set; }
  1027. public int itemCount { get; set; }
  1028. public object structure { get; set; }
  1029. }
  1030. public class Syllabus
  1031. {
  1032. public string id { get; set; }
  1033. public string name { get; set; }
  1034. public string pid { get; set; }
  1035. public int order { get; set; }
  1036. }
  1037. public class SyllabusNode
  1038. {
  1039. public string id { get; set; }
  1040. public string name { get; set; }
  1041. public List<SyllabusNode> children { get; set; }
  1042. public SyllabusNode()
  1043. {
  1044. children = new List<SyllabusNode>();
  1045. }
  1046. }
  1047. }
  1048. }