InitController.cs 59 KB

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