ScController.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. using Microsoft.AspNetCore.Mvc;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using TEAMModelOS.Models;
  7. using TEAMModelOS.SDK.DI;
  8. using System.Text.Json;
  9. using TEAMModelOS.SDK.Models;
  10. using Microsoft.AspNetCore.Http;
  11. using TEAMModelOS.SDK.Extension;
  12. using Azure.Cosmos;
  13. using System.Text;
  14. using TEAMModelOS.SDK.DI;
  15. using Microsoft.Extensions.Options;
  16. using Azure.Messaging.ServiceBus;
  17. using Microsoft.Extensions.Configuration;
  18. using HTEXLib.COMM.Helpers;
  19. using TEAMModelOS.SDK;
  20. using System.IdentityModel.Tokens.Jwt;
  21. using TEAMModelOS.Services;
  22. using TEAMModelOS.SDK.Models.Service;
  23. using System.IO;
  24. using System.Dynamic;
  25. using Microsoft.AspNetCore.Authorization;
  26. using Azure.Storage.Blobs.Models;
  27. using static TEAMModelOS.SDK.Models.Teacher;
  28. using System.Web;
  29. using static TEAMModelOS.Controllers.FixDataController;
  30. using static TEAMModelOS.SDK.SchoolService;
  31. using Microsoft.AspNetCore.Hosting;
  32. using Microsoft.Azure.Cosmos.Table;
  33. using System.Net.Http;
  34. namespace TEAMModelOS.Controllers
  35. {
  36. /// <summary>
  37. ///
  38. /// </summary>
  39. ///
  40. [ProducesResponseType(StatusCodes.Status200OK)]
  41. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  42. //
  43. //[Route("")]
  44. //[Route("api/[controller]")]
  45. [ApiController]
  46. public class ScController : ControllerBase
  47. {
  48. private readonly SnowflakeId _snowflakeId;
  49. private readonly AzureCosmosFactory _azureCosmos;
  50. private readonly DingDing _dingDing;
  51. private readonly Option _option;
  52. private readonly AzureStorageFactory _azureStorage;
  53. private readonly AzureServiceBusFactory _serviceBus;
  54. private readonly AzureRedisFactory _azureRedis;
  55. private readonly CoreAPIHttpService _coreAPIHttpService;
  56. public readonly string type = "scsyxpt";
  57. public readonly IHttpClientFactory _httpClientFactory;
  58. public IConfiguration _configuration { get; set; }
  59. public ScController( IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage,
  60. AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService,IHttpClientFactory httpClientFactory)
  61. {
  62. _azureCosmos = azureCosmos;
  63. _snowflakeId = snowflakeId;
  64. _dingDing = dingDing;
  65. _option = option?.Value;
  66. _azureStorage = azureStorage;
  67. _serviceBus = serviceBus;
  68. _configuration = configuration;
  69. _azureRedis = azureRedis;
  70. _coreAPIHttpService = coreAPIHttpService;
  71. _httpClientFactory = httpClientFactory;
  72. }
  73. /// <summary>
  74. /// 检查教师绑定
  75. /// </summary>
  76. /// <param name="request"></param>
  77. /// <returns></returns>
  78. [ProducesDefaultResponseType]
  79. [HttpPost("sc/check-teacher-bind")]
  80. [AllowAnonymous]
  81. public async Task<IActionResult> CheckTeacherBind(JsonElement request)
  82. {
  83. if (!request.TryGetProperty("schoolId", out JsonElement _schoolId)) return BadRequest();
  84. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  85. List<ScSchool> schools = await table.FindListByDict<ScSchool>(new Dictionary<string, object>() { { "PartitionKey", "ScSchool" }, { "schoolCode", $"{_schoolId}" } });
  86. if (schools.IsNotEmpty())
  87. {
  88. List<ScTeacher> teachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object>() { { "PartitionKey", "ScTeacher" }, { "SchoolID", schools[0].schoolid } });
  89. return Ok(new { teachers = teachers });
  90. }
  91. else
  92. {
  93. return Ok();
  94. }
  95. }
  96. /// <summary>
  97. /// 检查醍摩豆id存在多个学校的情况
  98. /// </summary>
  99. /// <param name="request"></param>
  100. /// <returns></returns>
  101. [ProducesDefaultResponseType]
  102. [HttpPost("sc/check-bind")]
  103. [AllowAnonymous]
  104. public async Task<IActionResult> CheckBlobBinds(JsonElement json)
  105. {
  106. List<GroupList> teachers = new List<GroupList>();
  107. string sqs = "select c.members from c where c.pk='GroupList' and c.type='yxtrain' and c.school in ('pjsyzx','pjzx','pjsazx','pjbjxx','pjxnxx','pjthxx','pjcyxx','pjfxxx','pjwjxx','pjzyzx','psywgy','hscjzx','cyhjnz','psasmx','psacjz','pwxjnx','pptsfx','pjjysx','xlzjnx','pdtjnx','pgxjnx','pcjjnx','pdxjnx','pnjyey','pbjyey','pcbyey','pcxyey','pcnyey','xjwhye','pxlyey','sazxye','saxcye','pthyey','psmyey','pshyey','pwxyey','pjysye','pfxyey','pgxyey','pcjyey','pcyhye','pbyyey','pdtyey','xyheye','xhyey','xbeyey','hhzyey','xxyey','saxgye','xllxye','dxxmye','dtxmye','dtydye','pnjdxy','pcxgmy','pcbgqy','saxccq','pjjsjx') ";
  108. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<GroupList>(queryText: sqs))
  109. {
  110. teachers.Add(item);
  111. }
  112. var a = teachers.SelectMany(x => x.members).GroupBy(y => y.id).ToList();
  113. var ae = a.Select(x => new { key = x.Key, val = x.ToList().Count() });
  114. ae = ae.Where(x => x.val > 1);
  115. return Ok(new { ae });
  116. }
  117. /// <summary>
  118. ///
  119. /// </summary>
  120. /// <param name="request"></param>
  121. /// <returns></returns>
  122. [ProducesDefaultResponseType]
  123. [HttpPost("sc/fix-bind")]
  124. [AllowAnonymous]
  125. public async Task<IActionResult> FixBlobBinds(JsonElement json)
  126. {
  127. List<string> teacherids = new List<string>();
  128. string sql = $" SELECT value(c.id) FROM c where ARRAY_LENGTH(c.binds)>0 ";
  129. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<string>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  130. {
  131. teacherids.Add(item);
  132. }
  133. var bloblist = await _azureStorage.GetBlobContainerClient("teammodelos").List($"yxpt/scpjx/scbind");
  134. bloblist = bloblist.Select(x => x.Substring(18, 10)).ToList();
  135. List<string> tmdids = teacherids.Except(bloblist).ToList();
  136. List<Teacher> teachers = new List<Teacher>();
  137. sql = $" SELECT value(c) FROM c where ARRAY_LENGTH(c.binds)>0 ";
  138. if (tmdids != null)
  139. {
  140. sql = $"{sql} and c.id in ( {string.Join(",", tmdids.Select(x => $"'{x}'"))} )";
  141. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Teacher>(queryText: sql,
  142. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  143. {
  144. teachers.Add(item);
  145. }
  146. }
  147. List<string> unbind = new List<string>();
  148. List<string> list = new List<string>();
  149. HashSet<string> schoolIds = teachers.Where(z => z.schools.IsNotEmpty()).SelectMany(x => x.schools).Where(m => m.status.Equals("join")).Select(y => y.schoolId).ToHashSet();
  150. List<GroupList> groupLists = new List<GroupList>();
  151. foreach (var schoolid in schoolIds)
  152. {
  153. StringBuilder queryText = new StringBuilder($"SELECT distinct value(c) FROM c where c.type='yxtrain'");
  154. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<GroupList>(queryText: queryText.ToString(),
  155. requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList-{schoolid}") }))
  156. {
  157. groupLists.Add(item);
  158. }
  159. }
  160. foreach (var teacher in teachers)
  161. {
  162. var a = teacher.binds.SelectMany(y => y.data).ToList().Find(x => !string.IsNullOrWhiteSpace(x));
  163. if (a != null)
  164. {
  165. await _azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(a, $"yxpt/scpjx/scbind", $"{teacher.id}.json");
  166. }
  167. else
  168. {
  169. unbind.Add(teacher.id);
  170. }
  171. if (teacher.schools.IsNotEmpty())
  172. {
  173. foreach (var school in teacher.schools)
  174. {
  175. if (!string.IsNullOrWhiteSpace(school.schoolId))
  176. {
  177. if (school.status.Equals("join"))
  178. {
  179. List<GroupList> yxtrain = groupLists.FindAll(x => x.code.Equals($"GroupList-{school.schoolId}"));
  180. if (yxtrain.IsNotEmpty())
  181. {
  182. var meber = yxtrain.SelectMany(x => x.members).Where(y => y.id.Equals(teacher.id));
  183. //不在研修名单
  184. if (meber == null || meber.Count() <= 0)
  185. {
  186. yxtrain[0].members.Add(new Member { id = teacher.id, type = 1 });
  187. await GroupListService.UpsertList(yxtrain[0], _azureCosmos, _configuration, _serviceBus, _client: "web");
  188. }
  189. }
  190. else
  191. {
  192. GroupList groupList = new GroupList()
  193. {
  194. id = Guid.NewGuid().ToString(),
  195. code = $"GroupList-{school.schoolId}",
  196. creatorId = teacher.id,
  197. type = "yxtrain",
  198. year = DateTimeOffset.UtcNow.Year,
  199. members = new List<Member> { new Member { id = teacher.id, type = 1 } },
  200. scope = "school",
  201. school = school.schoolId,
  202. name = "研修名单",
  203. pk = "GroupList",
  204. ttl = -1,
  205. expire=0,
  206. };
  207. await GroupListService.UpsertList(groupList, _azureCosmos, _configuration, _serviceBus, _client: "web");
  208. }
  209. }
  210. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(teacher.id, new PartitionKey($"Teacher-{school.schoolId}"));
  211. if (response.Status != 200)
  212. {
  213. SchoolTeacher schoolTeacher = new SchoolTeacher
  214. {
  215. id = teacher.id,
  216. code = $"Teacher-{school.schoolId}",
  217. pk = "Teacher",
  218. name = teacher.name,
  219. picture = teacher.picture,
  220. size = 0,
  221. roles = new List<string> { "teacher" },
  222. permissions = new List<string>(),
  223. status = school.status,
  224. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  225. ttl = -1
  226. };
  227. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(teacher.id, new PartitionKey($"Teacher-{school.schoolId}"));
  228. }
  229. else
  230. {
  231. JsonDocument document = await JsonDocument.ParseAsync(response.ContentStream);
  232. SchoolTeacher schoolTeacher = document.RootElement.ToObject<SchoolTeacher>();
  233. schoolTeacher.status = school.status;
  234. schoolTeacher.pk = "Teacher";
  235. schoolTeacher.name = teacher.name;
  236. schoolTeacher.picture = teacher.picture;
  237. if (!schoolTeacher.roles.IsEmpty())
  238. {
  239. if (!schoolTeacher.roles.Contains("teacher"))
  240. {
  241. schoolTeacher.roles .Add("teacher");
  242. }
  243. }
  244. else {
  245. schoolTeacher.roles = new List<string> { "teacher" };
  246. }
  247. schoolTeacher.permissions = schoolTeacher.permissions.IsNotEmpty() ? schoolTeacher.permissions : new List<string>();
  248. schoolTeacher.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  249. schoolTeacher.ttl = -1;
  250. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(schoolTeacher, schoolTeacher.id, new PartitionKey($"Teacher-{school.schoolId}"));
  251. }
  252. }
  253. }
  254. }
  255. }
  256. return Ok(new { unbind, list });
  257. }
  258. /// <summary>
  259. ///
  260. /// </summary>
  261. /// <param name="request"></param>
  262. /// <returns></returns>
  263. [ProducesDefaultResponseType]
  264. [HttpPost("sc/bind")]
  265. [AllowAnonymous]
  266. public async Task<IActionResult> Bind(SSO sso)
  267. {
  268. try
  269. {
  270. Teacher teacher = null;
  271. TmdidImplicit tmdidImplicit = null;
  272. if (!string.IsNullOrWhiteSpace(sso.mobile))
  273. {
  274. var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", sso.mobile } }, _option.Location, _configuration);
  275. if (coreUser != null)
  276. {
  277. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  278. tmdidImplicit = await _coreAPIHttpService.Implicit(new Dictionary<string, string> { { "grant_type", "implicit" },
  279. { "client_id",clientID },
  280. { "account",coreUser.id },
  281. { "nonce",Guid.NewGuid().ToString()} }, _option.Location, _configuration);
  282. if (tmdidImplicit != null && !string.IsNullOrWhiteSpace(tmdidImplicit.id_token))
  283. {
  284. sso.id_token = tmdidImplicit.id_token;
  285. }
  286. else
  287. {
  288. return Ok(new
  289. {
  290. location = _option.Location,
  291. status = 2,
  292. });
  293. }
  294. }
  295. else {
  296. return Ok(new
  297. {
  298. location = _option.Location,
  299. status = 2,
  300. });
  301. }
  302. }
  303. if (string.IsNullOrWhiteSpace(sso.id_token))
  304. {
  305. return Ok(new
  306. {
  307. location = _option.Location,
  308. status = 2,
  309. });
  310. }
  311. JwtSecurityToken jwt = null;
  312. try
  313. {
  314. jwt = new JwtSecurityToken(sso.id_token);
  315. }
  316. catch (Exception ex)
  317. {
  318. await _dingDing.SendBotMsg($"OS,{_option.Location}\n绑定失败,出现的原因可能是 参数异常:\n{sso.ToJsonString()},{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  319. return BadRequest();
  320. }
  321. var id = jwt.Payload.Sub;
  322. CoreUser coreUserById= await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{id}" } }, _option.Location, _configuration);
  323. if (coreUserById == null|| string.IsNullOrWhiteSpace(coreUserById.mobile)|| coreUserById.mobile.Length!=11)
  324. {
  325. return Ok(new
  326. {
  327. location = _option.Location,
  328. status = 2,
  329. });
  330. }
  331. jwt.Payload.TryGetValue("name", out object name);
  332. jwt.Payload.TryGetValue("picture", out object picture);
  333. ScSSOData scsso = HttpUtility.UrlDecode(sso.param, Encoding.UTF8).ToObject<ScSSOData>();
  334. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  335. List<ScTeacher> scTeachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object> { { Constant.PartitionKey, "ScTeacher" }, { "tmdid", id } });
  336. if (scTeachers.Count > 0 && !string.IsNullOrWhiteSpace(scTeachers[0].RowKey) && !scTeachers[0].RowKey.Equals(scsso.Pxid))
  337. {
  338. return Ok(new
  339. {
  340. location = _option.Location,
  341. //账号已被别的醍摩豆id绑定
  342. status = 3,
  343. tmdid = $"{id}",
  344. name = name.Equals(scTeachers[0].TeacherName) ? $"{name}" : $"{name}({scTeachers[0].TeacherName})",
  345. tid = scsso.tid
  346. });
  347. }
  348. var client = _azureCosmos.GetCosmosClient();
  349. try
  350. {
  351. teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
  352. //先检查绑定的平台是否已经被绑定
  353. //四川研训平台跳转隐式登录/或者绑定IES平台接入规范
  354. string sql = $"SELECT distinct value(c) FROM c join A1 in c.binds where A1.tid='{scsso.tid}'";
  355. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Teacher>(queryText: sql,
  356. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  357. {
  358. teacher = item;
  359. break;
  360. }
  361. if (teacher != null)
  362. {
  363. if (teacher.id.Equals(id))
  364. {
  365. var bindData = scsso.data.ToObject<ScBindData>();
  366. //var bind = teacher.binds.Find(x => x.source.Equals($"{scsso.Webid}") && x.userid.Equals($"{scsso.tid}"));
  367. var bind = teacher.binds.Find(x => x.userid.Equals($"{scsso.tid}"));
  368. if (bind == null)
  369. {
  370. teacher.binds = new List<Teacher.ThirdBind> { new Teacher.ThirdBind { data = new List<string> { scsso.data }, userid = $"{scsso.tid}", account = scsso.account, username = scsso.username, type = type } };
  371. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey(teacher.code));
  372. }
  373. else
  374. {
  375. bind.username = scsso.username;
  376. bind.account = scsso.account;
  377. bool isnew = true;
  378. for (int index = 0; index < bind.data.Count; index++)
  379. {
  380. ScBindData scBind = bind.data[index].ToObject<ScBindData>();
  381. if (scBind.pxid.Equals(bindData.pxid))
  382. {
  383. bind.data[index] = bindData.ToJsonString();
  384. isnew = false;
  385. }
  386. }
  387. if (isnew)
  388. {
  389. bind.data.Add(bindData.ToJsonString());
  390. }
  391. if (bindData != null)
  392. {
  393. bindData.userid = scsso.tid;
  394. bindData.username = scsso.username;
  395. bindData.account = scsso.account;
  396. }
  397. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey(teacher.code));
  398. }
  399. await _azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(bindData.ToJsonString(), $"yxpt/{scsso.path}/scbind", $"{teacher.id}.json");
  400. await ThirdService.GetScTeacher(bindData, teacher, _azureStorage, _azureCosmos, _serviceBus, _configuration, _dingDing);
  401. }
  402. else
  403. {
  404. return Ok(new
  405. {
  406. location = _option.Location,
  407. //账号已被别的醍摩豆id绑定
  408. status = 3,
  409. tmdid = teacher.id,
  410. name = teacher.name,
  411. tid = scsso.tid
  412. });
  413. }
  414. }
  415. }
  416. catch (CosmosException ex) when (ex.Status ==404)
  417. {
  418. teacher = new Teacher
  419. {
  420. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  421. id = id,
  422. pk = "Teacher",
  423. code = "Base",
  424. name = name?.ToString(),
  425. picture = picture?.ToString(),
  426. //创建账号并第一次登录IES5则默认赠送1G
  427. size = 1,
  428. defaultSchool = null,
  429. schools = new List<Teacher.TeacherSchool>(),
  430. binds = new List<Teacher.ThirdBind> { new Teacher.ThirdBind { username = scsso.username, account = scsso.account, data = new List<string> { scsso.data }, userid = $"{scsso.tid}", /*source = $"{scsso.Webid}",*/ type = type } }
  431. };
  432. var container = _azureStorage.GetBlobContainerClient(id);
  433. await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
  434. teacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey("Base"));
  435. ScBindData bindData = scsso.data.ToObject<ScBindData>();
  436. await ThirdService.GetScTeacher(bindData, teacher, _azureStorage, _azureCosmos, _serviceBus, _configuration, _dingDing);
  437. if (bindData != null)
  438. {
  439. bindData.userid = scsso.tid;
  440. bindData.username = scsso.username;
  441. bindData.account = scsso.account;
  442. await _azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(bindData.ToJsonString(), $"yxpt/{scsso.path}/scbind", $"{teacher.id}.json");
  443. }
  444. else
  445. {
  446. await _azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(scsso.data.ToJsonString(), $"yxpt/{scsso.path}/scbind", $"{teacher.id}.json");
  447. }
  448. }
  449. catch (Exception ex)
  450. {
  451. await _dingDing.SendBotMsg($"OS,{_option.Location}\n绑定失败:\n{sso.ToJsonString()},{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  452. return Ok(new
  453. {
  454. location = _option.Location,
  455. status = 2,
  456. });
  457. }
  458. return Ok(new
  459. {
  460. tmdidImplicit = tmdidImplicit,
  461. location = _option.Location,
  462. status = 200,
  463. });
  464. }
  465. catch (Exception ex)
  466. {
  467. await _dingDing.SendBotMsg($"OS,{_option.Location}\n绑定失败:\n{sso.ToJsonString()},{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  468. return Ok(new
  469. {
  470. location = _option.Location,
  471. status = 2,
  472. });
  473. }
  474. }
  475. /// <summary>
  476. /// 动态地址路由。"config":"scsyxpt","path":"sc{pjx/jinniu}"
  477. /// </summary>
  478. /// <param name="request"></param>
  479. /// <returns></returns>
  480. [HttpGet("sc/gen-sso")]
  481. [AllowAnonymous]
  482. public async Task<IActionResult> GenSso([FromQuery] ScTchTmd tmd) {
  483. if (tmd != null && !string.IsNullOrWhiteSpace(tmd.tmdid))
  484. {
  485. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  486. List<ScTeacher> scTeachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object> { { "PartitionKey", "ScTeacher" }, { "tmdid", $"{tmd.tmdid}" } });
  487. if (scTeachers.Any())
  488. {
  489. string ep = $"Pxid={scTeachers[0].PXID}&Webid=1001&tid={scTeachers[0].TID}&time=1646617519";
  490. string Encrypt = Md5Hash.GetMd5String(ep);
  491. string url = $"https://www.teammodel.cn/sc/sso?{ep}&Encrypt={Encrypt}";
  492. return Ok(new { url });
  493. }
  494. else
  495. {
  496. return Ok("暂无ID的数据");
  497. }
  498. }
  499. else
  500. {
  501. return Ok("参数错误!");
  502. }
  503. }
  504. /// <summary>
  505. /// 动态地址路由。"config":"scsyxpt","path":"sc{pjx/jinniu}"
  506. /// </summary>
  507. /// <param name="request"></param>
  508. /// <returns></returns>
  509. [HttpGet("{path}/sso")]
  510. [AllowAnonymous]
  511. public async Task<IActionResult> Sso([FromQuery] ScSSO scsso, string path)
  512. {
  513. string HostName = HttpContext.GetHostName();
  514. if (!string.IsNullOrWhiteSpace(_option.HostName))
  515. {
  516. HostName = _option.HostName;
  517. }
  518. if (path.Equals("jinniu"))
  519. {
  520. if (!_option.Location.Contains("Dep"))
  521. {
  522. HostName = "jinniu.teammodel.cn";
  523. }
  524. }
  525. if (HostName.Equals("www.teammodel.cn")) {
  526. HostName = "scyx.teammodel.cn";
  527. }
  528. //var rurl = new StringBuilder($"https://{_option.HostName}/sso");
  529. var rurl = new StringBuilder($"https://{HostName}/sso");
  530. try
  531. {
  532. string parmas = $"Pxid={scsso.Pxid}&Webid={scsso.Webid}&tid={scsso.tid}&time={scsso.time}";
  533. if (Md5Hash.GetMd5String(parmas).Equals($"{scsso.Encrypt}"))
  534. {
  535. //四川研训平台跳转隐式登录/或者绑定IES平台接入规范
  536. long ssotime = long.Parse($"{scsso.time}");
  537. long nowtime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
  538. if (nowtime - ssotime > 60 * 10)//10分钟有效期
  539. {
  540. // return Ok(new { status = 2, msg = "登录超时!" });
  541. }
  542. }
  543. else
  544. {
  545. return Redirect(rurl.Append($"?status=1").ToString());
  546. }
  547. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  548. string qurey = $"PartitionKey {QueryComparisons.Equal} 'ScTeacher' and TID {QueryComparisons.Equal} {scsso.tid} and RowKey {QueryComparisons.Equal} '{scsso.Pxid}' ";
  549. var result = await table.ExecuteQuerySegmentedAsync(new TableQuery<ScTeacher>().Where(qurey), null);
  550. List<ScTeacher> scTeachers = result.Results;
  551. // List<ScTeacher> scTeachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object> { { "PartitionKey", "ScTeacher" }, { "TID", scsso.tid }, { "RowKey", $"{scsso.Pxid}" } });
  552. if (!scTeachers.IsNotEmpty())
  553. {
  554. //没有同步省平台
  555. string enurl = $"status=5&param={HttpUtility.UrlEncode(new { scsso.Pxid, scsso.tid }.ToJsonString(), Encoding.UTF8)}";
  556. return Redirect(rurl.Append($"?{enurl}").ToString());
  557. }
  558. string setsql = $"select value(c) from c where c.id ='{scTeachers[0].areaId}' and contains(c.accessConfig,'{ scTeachers[0].ProjectID}') and contains(c.accessConfig,'{ scTeachers[0].ProjectItemID}') and contains(c.accessConfig,'scsyxpt') ";
  559. AreaSetting setting = null;
  560. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AreaSetting>(queryText: setsql,
  561. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AreaSetting") }))
  562. {
  563. setting = item;
  564. break;
  565. }
  566. if (setting == null || (setting != null && string.IsNullOrWhiteSpace(setting.accessConfig)))
  567. {
  568. return Redirect(rurl.Append($"?status=1").ToString());
  569. }
  570. string accessConfig = setting.accessConfig;
  571. Dictionary<string, object> dict = new() { { "accessConfig", accessConfig }, { "pxid", scsso.Pxid }, { "tid", scsso.tid }, { "areaId", $"{setting.id}" } };
  572. string SchoolName = "", SchoolID = "", ProjectID = "", ProjectItemID = "", TeacherName = "", Account = "";
  573. if (scTeachers.IsNotEmpty())
  574. {
  575. ScTeacher scTeacher = scTeachers[0];
  576. if (scTeacher != null && $"{scTeacher.PXID}".Equals(scsso.Pxid) && $"{scTeacher.TID}".Equals(scsso.tid))
  577. {
  578. SchoolName = scTeacher.SchoolName;
  579. SchoolID = $"{scTeacher.SchoolID}";
  580. ProjectID = $"{ scTeacher.ProjectID}";
  581. ProjectItemID = $"{ scTeacher.ProjectItemID}";
  582. TeacherName = $"{ scTeacher.TeacherName}";
  583. Account = $"{ scTeacher.Account}";
  584. }
  585. }
  586. if (string.IsNullOrWhiteSpace(SchoolID))
  587. {
  588. //(int status, string json) = await _httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetSingleTeacherByProject");
  589. (int status, string json) = await ScsStudyApisService.GetSingleTeacherByProject(_httpClientFactory.CreateClient(), _dingDing, _azureStorage, accessConfig, scsso.Pxid, scsso.tid);
  590. if (status == 200)
  591. {
  592. ScTeacher scTeacher = json.ToObject<ScTeacher>(new JsonSerializerOptions { PropertyNameCaseInsensitive = false });
  593. if (scTeacher != null && $"{scTeacher.PXID}".Equals(scsso.Pxid) && $"{scTeacher.TID}".Equals(scsso.tid))
  594. {
  595. SchoolName = scTeacher.SchoolName;
  596. SchoolID = $"{scTeacher.SchoolID}";
  597. ProjectID = $"{ scTeacher.ProjectID}";
  598. ProjectItemID = $"{ scTeacher.ProjectItemID}";
  599. TeacherName = $"{ scTeacher.TeacherName}";
  600. Account = $"{ scTeacher.Account}";
  601. }
  602. }
  603. else
  604. {
  605. await _dingDing.SendBotMsg($"OS,{_option.Location}\n省平台教师信息:\nstatus:{status}{json}\n{dict.ToJsonString()} \nGetSingleTeacherByProject", GroupNames.醍摩豆服務運維群組);
  606. }
  607. }
  608. ScBindData bindData = new()
  609. {
  610. sn = SchoolName,
  611. sid = SchoolID,
  612. pd = ProjectID,
  613. pid = ProjectItemID,
  614. pxid = scsso.Pxid,
  615. userid = scsso.tid,
  616. username = TeacherName,
  617. account = Account,
  618. path = path,
  619. };
  620. var data = bindData.ToJsonString();
  621. ScSSOData sso = new ScSSOData
  622. {
  623. username = TeacherName,
  624. account = Account,
  625. path = path,
  626. Pxid = scsso.Pxid,
  627. Encrypt = scsso.Encrypt,
  628. tid = scsso.tid,
  629. time = scsso.time,
  630. data = data
  631. };
  632. Teacher teacher = null;
  633. //四川研训平台跳转隐式登录/或者绑定IES平台接入规范
  634. //string sql = $"SELECT distinct value(c) FROM c join A1 in c.binds where A1.pxid='{sso.Pxid}' and A1.webid='{sso.Webid}' and A1.tid='{sso.tid}'";
  635. string sql = $"SELECT distinct value(c) FROM c join A1 in c.binds where A1.userid='{sso.tid}'";
  636. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Teacher>(queryText: sql,
  637. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  638. {
  639. teacher = item;
  640. break;
  641. }
  642. if (teacher == null)
  643. {
  644. //string enurl = HttpUtility.UrlEncode(rurl.Append($"?status=4&param={sso.ToJsonString()}&type={type}&bindurl=sc/bind").ToString());
  645. string enurl = $"status=4&param={HttpUtility.UrlEncode(sso.ToJsonString(), Encoding.UTF8)}&type={type}&bindurl=sc/bind";
  646. return Redirect(rurl.Append($"?{enurl}").ToString());
  647. }
  648. else
  649. {
  650. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  651. var location = _option.Location;
  652. TmdidImplicit implicit_token = await _coreAPIHttpService.Implicit(
  653. new Dictionary<string, string>()
  654. {
  655. { "grant_type", "implicit" },
  656. { "client_id",clientID },
  657. { "account",teacher.id },
  658. { "nonce",Guid.NewGuid().ToString()}
  659. }, location, _configuration);
  660. if (implicit_token != null)
  661. {
  662. if (string.IsNullOrWhiteSpace(implicit_token.id_token))
  663. {
  664. await _dingDing.SendBotMsg($"OS,隐式登录获得信息为空:{_option.Location}-\n{scsso.ToJsonString()} \npath:{path}\n{implicit_token.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  665. return Redirect(rurl.Append($"?status=1").ToString());
  666. }
  667. //处理自动加入学校,加入培训名单
  668. await ThirdService.GetScTeacher(bindData, teacher, _azureStorage, _azureCosmos, _serviceBus, _configuration, _dingDing);
  669. var bind = teacher.binds.Find(x => x.userid.Equals(sso.tid));
  670. //var bind = teacher.binds.Find(x => x.userid.Equals(sso.tid) && x.source.Equals(sso.Webid));
  671. if (bind != null)
  672. {
  673. bool isnew = true;
  674. for (int index = 0; index < bind.data.Count; index++)
  675. {
  676. ScBindData scBind = bind.data[index].ToObject<ScBindData>();
  677. if (scBind.pxid.Equals(bindData.pxid))
  678. {
  679. bind.data[index] = bindData.ToJsonString();
  680. isnew = false;
  681. }
  682. }
  683. if (isnew)
  684. {
  685. bind.data.Add(bindData.ToJsonString());
  686. }
  687. bind.username = TeacherName;
  688. bind.account = Account;
  689. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey(teacher.code));
  690. }
  691. try
  692. {
  693. await _azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(bindData.ToJsonString(), $"yxpt/{sso.path}/scbind", $"{teacher.id}.json");
  694. }
  695. catch (Exception ex)
  696. {
  697. await _dingDing.SendBotMsg($"OS,{_option.Location}-\n文件失败 \npath:{path}\n\n{ex.Message}\n{ex.StackTrace}\n yxpt/{sso.path}/scbind/{teacher.id}.json", GroupNames.醍摩豆服務運維群組);
  698. }
  699. rurl.Append($"?status=200&id_token={implicit_token.id_token}&access_token={implicit_token.access_token}&expires_in={HttpUtility.UrlEncode(implicit_token.expires_in)}&token_type={HttpUtility.UrlEncode(implicit_token.token_type)}").ToString();
  700. string uri = rurl.ToString();
  701. return Redirect(uri);
  702. }
  703. else
  704. {
  705. //绑定失效
  706. //if (teacher.binds.IsNotEmpty())
  707. //{
  708. // teacher.binds.RemoveAll(x => x.userid.Equals(sso.tid));
  709. // await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey(teacher.code));
  710. //}
  711. //string enurl = $"status=4&param={HttpUtility.UrlEncode(sso.ToJsonString(), Encoding.UTF8)}&type={type}&bindurl=sc/bind";
  712. // return Redirect(rurl.Append($"?{enurl}").ToString());
  713. return Redirect(rurl.Append($"?status=1").ToString());
  714. }
  715. }
  716. }
  717. catch (Exception ex)
  718. {
  719. await _dingDing.SendBotMsg($"OS,{_option.Location}-\n{scsso.ToJsonString()} \npath:{path}\n\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  720. return Redirect(rurl.Append($"?status=1").ToString());
  721. }
  722. }
  723. public class DbBind
  724. {
  725. public string id { get; set; }
  726. public string userid { get; set; }
  727. public List<string> data { get; set; }
  728. }
  729. }
  730. }