123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- using Azure.Cosmos;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using System;
- using System.Collections.Generic;
- using System.IdentityModel.Tokens.Jwt;
- using System.Linq;
- using System.Text;
- using System.Text.Json;
- using System.Threading.Tasks;
- using TEAMModelOS.Models.Dto;
- using TEAMModelOS.SDK.Models;
- using TEAMModelOS.SDK;
- using TEAMModelOS.SDK.Context.Constant.Common;
- using TEAMModelOS.SDK.DI;
- using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
- using TEAMModelOS.SDK.Extension;
- using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
- using TEAMModelOS.SDK.Helper.Common.StringHelper;
- using TEAMModelOS.Models;
- using Microsoft.Extensions.Options;
- using TEAMModelOS.SDK.Models.Cosmos;
- using Microsoft.AspNetCore.Authorization;
- using TEAMModelOS.Filter;
- using StackExchange.Redis;
- using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
- using TEAMModelOS.Services.Common;
- using System.IO;
- using System.Dynamic;
- using Azure.Storage.Blobs.Models;
- using Azure.Storage.Sas;
- using Lib.AspNetCore.ServerSentEvents;
- using TEAMModelFunction;
- using TEAMModelOS.SDK.Models.Cosmos.Common;
- namespace TEAMModelOS.Controllers.Core
- {
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
- //[Authorize(Roles = "HiTool")]
- [Route("hiscan")]
- [ApiController]
- public class HiScanController : ControllerBase
- {
- private readonly AzureRedisFactory _azureRedis;
- private readonly AzureCosmosFactory _azureCosmos;
- private readonly SnowflakeId _snowflakeId;
- private readonly AzureServiceBusFactory _serviceBus;
- private readonly DingDing _dingDing;
- private readonly Option _option;
- private readonly AzureStorageFactory _azureStorage;
- private readonly ServerSentEventsService _sse;
- public HiScanController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option,
- AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, ServerSentEventsService sse)
- {
- _azureCosmos = azureCosmos;
- _serviceBus = serviceBus;
- _snowflakeId = snowflakeId;
- _dingDing = dingDing;
- _option = option?.Value;
- _azureRedis = azureRedis;
- _azureStorage = azureStorage;
- _sse = sse;
- }
- ///<summary>
- ///查询教师的阅卷任务列表
- /// </summary>
- /// <data>
- /// ! "code":"tmdid"
- /// </data>
- /// <param name="request"></param>
- /// <returns></returns>
- [ProducesDefaultResponseType]
- [HttpPost("verify-qrcode")]
- // [AuthToken(Roles = "teacher,admin")]
- public async Task<IActionResult> VerifyQrcode(JsonElement request)
- {
- try {
- if (!request.TryGetProperty("sid", out JsonElement sid)) return BadRequest();
- if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
-
- IServerSentEventsClient sseClient;
- if (Guid.TryParse($"{sid}", out Guid guid) && (sseClient = _sse.GetClient(guid)) != null) {
- //var clientName = sseClient.GetProperty<string>("NAME");
- //var clientDID= sseClient.GetProperty<string>("DID");
- // var isHiTeach = clientName.Contains("HiScan", StringComparison.OrdinalIgnoreCase);
- var jwt = new JwtSecurityToken(id_token.GetString());
- //TODO 此驗證IdToken先簡單檢查,後面需向Core ID新API,驗證Token
- if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.OrdinalIgnoreCase)) return BadRequest();
- var id = jwt.Payload.Sub;
- jwt.Payload.TryGetValue("name", out object name);
- jwt.Payload.TryGetValue("picture", out object picture);
- List<ScanSchool> schools = new List<ScanSchool>();
-
- //TODO 取得Teacher 個人相關數據(課程清單、虛擬教室清單、歷史紀錄清單等),學校數據另外API處理,多校切換時不同
- var client = _azureCosmos.GetCosmosClient();
- var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(id, new PartitionKey("Base"));
- int size = 0;
- //老師個人資料(含初始化)
- if (response.Status == 200)
- {
- var json = await JsonDocument.ParseAsync(response.ContentStream);
- if (json.RootElement.TryGetProperty("schools", out JsonElement value))
- {
- if (json.RootElement.TryGetProperty("size", out JsonElement _size) && _size.ValueKind.Equals(JsonValueKind.Number))
- {
- size = _size.GetInt32();
- }
- foreach (var obj in value.EnumerateArray())
- {
- string statusNow = obj.GetProperty("status").ToString();
- //正式加入才会有
- if (statusNow == "join")
- {
- //dynamic schoolExtobj = new ExpandoObject();
- var schoolJson = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{obj.GetProperty("schoolId")}", new PartitionKey("Base"));
- var school = await JsonDocument.ParseAsync(schoolJson.ContentStream);
- var schoolId = obj.GetProperty("schoolId");
- var schoolName = obj.GetProperty("name");
- var schoolStatus = obj.GetProperty("status");
- var schoolPicture = school.RootElement.GetProperty("picture");
- //检查学校购买的模组是否包含阅卷模组
- int count = 0;
- string sql = $" SELECT value(count(product)) FROM c join product in c.service.product where c.id ='{schoolId}' and c.pk='Product' and product.prodCode='YMPCVCIM' ";
- await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<int>(sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Product") })) {
- count = item;
- }
- if (count > 0) {
- //生成token
- var token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, roles: new[] { "teacher" }, schoolID: $"{schoolId}");
- //获取学校线下阅卷评测
- var sexams= await GetExam($"{schoolId}", "school", client);
- schools.Add(new ScanSchool { name = $"schoolName", picture = $"{schoolPicture}", code = $"{schoolId}", status = $"{schoolStatus}" ,token=token, datas = sexams });
- }
- }
- }
- }
- //获取个人线下阅卷评测
- var datas = await GetExam($"{id}", "private", client);
- //換取AuthToken,提供給前端
- var data = new { name, picture, id, schools , datas };
- await sseClient.SendEventAsync(data.ToJsonString());
- return Ok(data);
- }
- else
- {
- return Ok(new { status = 404 });
- }
- }
- } catch (Exception ex ) {
- await _dingDing.SendBotMsg($"IES5,{_option.Location},hiscan/verify-qrcode()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
- return BadRequest();
- }
- return Ok();
- }
- private async Task<List<ExamData>> GetExam(string code ,string scope, CosmosClient client)
- {
- List<ExamData> corrects = new List<ExamData>();
- if (scope.Equals("school"))
- {
- await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<Correct>(queryText: "SELECT * FROM c where c.source='2' and c.progress='going' order by c.createTime ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Correct-{code}") }))
- {
- ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(item.id, new PartitionKey($"Exam-{code}"));
- (List<string> tmdids, List<Students> students)stulist =await TriggerStuActivity.GetStuList(client, _dingDing, exam.classes, code);
- corrects.Add(new ExamData { exam = exam, correct = item,tmdids=stulist.tmdids,stulist=stulist.students });
- }
- }
- else if(scope.Equals("private")){
- await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<Correct>(queryText: "SELECT * FROM c where c.source='2' and c.progress='going' order by c.createTime ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Correct-{code}") }))
- {
- ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(item.id, new PartitionKey($"Exam-{code}"));
- (List<string> tmdids, List<Students> students) stulist = await TriggerStuActivity.GetStuList(client, _dingDing, exam.classes, code);
- corrects.Add(new ExamData { exam = exam, correct = item, tmdids = stulist.tmdids, stulist = stulist.students });
- }
- }
- return corrects;
- }
- }
- public class ScanSchool
- {
- public string name { get; set; }
- public string picture { get; set; }
- public string code { get; set; }
- public string status { get; set; }
- public string token { get; set; }
- // public List<(Correct,ExamInfo, (List<string> tmdids, List<Students> stulist))> exams{ get; set; }
- public List<ExamData> datas { get; set; }
- }
- public class ExamData
- {
- public Correct correct { get; set; }
- public ExamInfo exam { get; set; }
- public List<string> tmdids { get; set; }
- public List<Students> stulist { get; set; }
- }
- }
|