|
@@ -0,0 +1,360 @@
|
|
|
+using Azure.Cosmos;
|
|
|
+using Azure.Storage.Blobs.Models;
|
|
|
+using Azure.Storage.Sas;
|
|
|
+using Microsoft.AspNetCore.Http;
|
|
|
+using Microsoft.AspNetCore.Mvc;
|
|
|
+using Microsoft.Extensions.Options;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Dynamic;
|
|
|
+using System.IdentityModel.Tokens.Jwt;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using System.Text.Json;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using TEAMModelOS.Models;
|
|
|
+using TEAMModelOS.SDK.Models;
|
|
|
+using TEAMModelOS.SDK.DI;
|
|
|
+using TEAMModelOS.SDK.Extension;
|
|
|
+using TEAMModelOS.Filter;
|
|
|
+using TEAMModelOS.SDK.Models.Cosmos;
|
|
|
+using HTEXLib.COMM.Helpers;
|
|
|
+using TEAMModelOS.SDK.Models.Service;
|
|
|
+using Microsoft.Extensions.Configuration;
|
|
|
+using System.Net.Http;
|
|
|
+using TEAMModelOS.SDK;
|
|
|
+using static TEAMModelOS.SDK.Models.Teacher;
|
|
|
+using TEAMModelOS.Services;
|
|
|
+using Microsoft.AspNetCore.Authorization;
|
|
|
+
|
|
|
+namespace TEAMModelOS.Controllers
|
|
|
+{
|
|
|
+ [ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
+
|
|
|
+ [Route("teacher-init")]
|
|
|
+ [ApiController]
|
|
|
+ public class TeacherInitController : ControllerBase
|
|
|
+ {
|
|
|
+ private readonly AzureCosmosFactory _azureCosmos;
|
|
|
+ private readonly AzureStorageFactory _azureStorage;
|
|
|
+ private readonly DingDing _dingDing;
|
|
|
+ private readonly Option _option;
|
|
|
+ private readonly IConfiguration _configuration;
|
|
|
+ private readonly NotificationService _notificationService;
|
|
|
+ private readonly CoreAPIHttpService _coreAPIHttpService;
|
|
|
+ public TeacherInitController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
|
|
|
+ {
|
|
|
+ _azureCosmos = azureCosmos;
|
|
|
+ _azureStorage = azureStorage;
|
|
|
+ _dingDing = dingDing;
|
|
|
+ _option = option?.Value;
|
|
|
+ _configuration = configuration;
|
|
|
+ _notificationService = notificationService;
|
|
|
+ _coreAPIHttpService = coreAPIHttpService;
|
|
|
+ }
|
|
|
+ //TODO 此API需處理對應前端返回的相關數據
|
|
|
+ [ProducesDefaultResponseType]
|
|
|
+ [Authorize(Roles = "IES")]
|
|
|
+ [HttpPost("get-teacher-info")]
|
|
|
+ public async Task<IActionResult> GetTeacherInfo(JsonElement request)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
|
|
|
+ var jwt = new JwtSecurityToken(id_token.GetString());
|
|
|
+ //TODO 此驗證IdToken先簡單檢查,後面需向Core ID新API,驗證Token
|
|
|
+ var id = jwt.Payload.Sub;
|
|
|
+ jwt.Payload.TryGetValue("name", out object name);
|
|
|
+ jwt.Payload.TryGetValue("picture", out object picture);
|
|
|
+ Teacher teacher = null;
|
|
|
+ TeacherInfo teacherInfo = await TeacherInfo(_azureCosmos, teacher, $"{name}", $"{picture}", id, _azureStorage, _option);
|
|
|
+ return Ok(new
|
|
|
+ {
|
|
|
+ location = _option.Location,
|
|
|
+ teacherInfo.auth_token,
|
|
|
+ teacherInfo.blob_uri,
|
|
|
+ teacherInfo.blob_sas,
|
|
|
+ teacherInfo.schools,
|
|
|
+ teacherInfo.defaultschool,
|
|
|
+ teacherInfo.courses,
|
|
|
+ teacherInfo.total,
|
|
|
+ teacherInfo.osblob_uri,
|
|
|
+ teacherInfo.osblob_sas,
|
|
|
+ teacherInfo.tsize,
|
|
|
+ status = 200,
|
|
|
+ teacherInfo.areas
|
|
|
+ });
|
|
|
+ }
|
|
|
+ catch (CosmosException ex)
|
|
|
+ {
|
|
|
+ await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
|
|
|
+ return BadRequest();
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
|
|
|
+ return BadRequest();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static async Task<TeacherInfo> TeacherInfo(AzureCosmosFactory _azureCosmos, Teacher teacher, string name, string picture, string id, AzureStorageFactory _azureStorage, Option _option)
|
|
|
+ {
|
|
|
+ List<object> schools = new List<object>();
|
|
|
+ List<AreaDto> areas = new List<AreaDto>();
|
|
|
+ List<Area> areasd = new List<Area>();
|
|
|
+ string defaultschool = null;
|
|
|
+ //TODO 取得Teacher 個人相關數據(課程清單、虛擬教室清單、歷史紀錄清單等),學校數據另外API處理,多校切換時不同
|
|
|
+ var client = _azureCosmos.GetCosmosClient();
|
|
|
+ int total = 0;
|
|
|
+ int tsize = 0;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (teacher == null)
|
|
|
+ {
|
|
|
+ teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
|
|
|
+ teacher.name = $"{name}";
|
|
|
+ teacher.picture = $"{picture}";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ name = teacher.name;
|
|
|
+ picture = teacher.picture;
|
|
|
+ id = teacher.id;
|
|
|
+ }
|
|
|
+ ///教师的个人空间
|
|
|
+ tsize = teacher.size;
|
|
|
+ ///教师的总空间 包含 个人空间和学校赠送的空间累加
|
|
|
+ total = teacher.size;
|
|
|
+ //areas = teacher.areas;
|
|
|
+ if (teacher.areas.IsNotEmpty())
|
|
|
+ {
|
|
|
+ //teacher.areas.Select(x => x.areaId);
|
|
|
+ //await foreach (var item client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>($"{areat.areaId}", new PartitionKey("Base-Area"))) {
|
|
|
+
|
|
|
+ //}
|
|
|
+ //https://test.teammodel.cn/hita/join-school?ts=1644291704907&school=cdxcwgy
|
|
|
+ foreach (var areat in teacher.areas)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ Area area = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{areat.areaId}", new PartitionKey("Base-Area"));
|
|
|
+ areasd.Add(area);
|
|
|
+ AreaSetting setting = null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>($"{areat.areaId}", new PartitionKey("AreaSetting"));
|
|
|
+ }
|
|
|
+ catch (CosmosException ex)
|
|
|
+ {
|
|
|
+ setting = null;
|
|
|
+ }
|
|
|
+ int access = 0;
|
|
|
+ if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
|
|
|
+ {
|
|
|
+ access = 1;
|
|
|
+ }
|
|
|
+ if (setting != null)
|
|
|
+ {
|
|
|
+ setting.accessConfig = null;
|
|
|
+ }
|
|
|
+ areas.Add(new AreaDto { areaId = area.id, name = area.name, standard = area.standard, standardName = area.standardName, setting = setting, access = access });
|
|
|
+ }
|
|
|
+ catch (CosmosException)
|
|
|
+ {
|
|
|
+ //数据库捞不到数据
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //检查是否有加入学校,如果加入学校,则当个人空间size是0G的时候,则免费获得一个G空间,但无论加入多少个学校,只能获取一次 1G的免费空间。没有加入学校则默认0G空间,除非自己购买空间
|
|
|
+ if (teacher.schools.IsNotEmpty())
|
|
|
+ {
|
|
|
+ foreach (var sc in teacher.schools)
|
|
|
+ {
|
|
|
+ string statusNow = sc.status != null ? sc.status : "";
|
|
|
+ if (statusNow.Equals("join") || statusNow.Equals("invite") || statusNow.Equals("request"))
|
|
|
+ {
|
|
|
+ dynamic schoolExtobj = new ExpandoObject();
|
|
|
+ // var schoolJson = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{sc.schoolId}", new PartitionKey("Base"));
|
|
|
+ //var school = await JsonDocument.ParseAsync(schoolJson.ContentStream);
|
|
|
+ schoolExtobj.schoolId = sc.schoolId;
|
|
|
+ schoolExtobj.name = sc.name;
|
|
|
+ schoolExtobj.status = sc.status;
|
|
|
+ schoolExtobj.time = sc.time;
|
|
|
+ schoolExtobj.picture = sc.picture;
|
|
|
+ schoolExtobj.areaId = $"{sc.areaId}";
|
|
|
+ Area area = null;
|
|
|
+ int access = 0;
|
|
|
+ if (!string.IsNullOrEmpty($"{sc.areaId}"))
|
|
|
+ {
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+
|
|
|
+ area = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{sc.areaId}", new PartitionKey("Base-Area"));
|
|
|
+ AreaSetting setting = null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>($"{area.id}", new PartitionKey("AreaSetting"));
|
|
|
+ }
|
|
|
+ catch (CosmosException ex)
|
|
|
+ {
|
|
|
+ setting = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
|
|
|
+ {
|
|
|
+ access = 1;
|
|
|
+ }
|
|
|
+ areasd.Add(area);
|
|
|
+
|
|
|
+ }
|
|
|
+ catch (CosmosException)
|
|
|
+ {
|
|
|
+ area = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (area != null)
|
|
|
+ {
|
|
|
+ schoolExtobj.area = new { area.name, area.id, area.institution, area.provName, area.code, area.cityCode, area.cityName, area.standard, area.provCode, area.pk, access };
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ schoolExtobj.area = area;
|
|
|
+ }
|
|
|
+ var sctch = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{sc.schoolId}"));
|
|
|
+ if (sctch.Status == 200)
|
|
|
+ {
|
|
|
+ var jsonDoc = await JsonDocument.ParseAsync(sctch.ContentStream);
|
|
|
+ SchoolTeacher schoolTeacher = jsonDoc.RootElement.ToObject<SchoolTeacher>();
|
|
|
+ schoolTeacher.name = $"{name}";
|
|
|
+ schoolTeacher.picture = $"{picture}";
|
|
|
+ await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(schoolTeacher, id, new PartitionKey($"Teacher-{sc.schoolId}"));
|
|
|
+ if (jsonDoc.RootElement.TryGetProperty("size", out JsonElement _size) && _size.ValueKind.Equals(JsonValueKind.Number))
|
|
|
+ {
|
|
|
+ total += _size.GetInt32();
|
|
|
+ schoolExtobj.size = _size.GetInt32();
|
|
|
+ }
|
|
|
+ else { schoolExtobj.size = 0; }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ schoolExtobj.size = 0;
|
|
|
+ }
|
|
|
+ if (statusNow.Equals("join"))
|
|
|
+ {
|
|
|
+ //初始化
|
|
|
+ await TmdUserService.JoinSchool(client, teacher.id, teacher.picture, teacher.name, sc.schoolId, sc.name);
|
|
|
+ }
|
|
|
+ schools.Add(schoolExtobj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //如果包含任何申请,邀请,加入学校的记录 且个人空间未分配2G 则默认分配个人空间至2G.
|
|
|
+ if (teacher.size < 2 && teacher.schools.Count > 0)
|
|
|
+ {
|
|
|
+ teacher.size = 2;
|
|
|
+ }
|
|
|
+ //如果未包含任何申请,邀请,加入学校的记录 且 个人空间没有分配1G 则默认赠送一个G
|
|
|
+ if (teacher.schools.Count == 0 && teacher.size < 1)
|
|
|
+ {
|
|
|
+ teacher.size = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (string.IsNullOrEmpty(teacher.defaultSchool) && teacher.schools.IsNotEmpty())
|
|
|
+ {
|
|
|
+ var tech = teacher.schools.FindAll(x => x.status.Equals("join"));
|
|
|
+ if (tech.IsNotEmpty())
|
|
|
+ {
|
|
|
+ teacher.defaultSchool = teacher.schools[0].schoolId;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
|
|
|
+ //預設學校ID
|
|
|
+ defaultschool = teacher.defaultSchool;
|
|
|
+ }
|
|
|
+ catch (CosmosException ex)
|
|
|
+ {
|
|
|
+ if (ex.Status == 404)
|
|
|
+ {
|
|
|
+ //如果沒有,則初始化Teacher基本資料到Cosmos
|
|
|
+ teacher = new Teacher
|
|
|
+ {
|
|
|
+ id = id,
|
|
|
+ pk = "Base",
|
|
|
+ code = "Base",
|
|
|
+ name = name?.ToString(),
|
|
|
+ picture = picture?.ToString(),
|
|
|
+ //创建账号并第一次登录IES5则默认赠送1G
|
|
|
+ size = 1,
|
|
|
+ defaultSchool = null,
|
|
|
+ schools = new List<Teacher.TeacherSchool>(),
|
|
|
+ };
|
|
|
+ var container = _azureStorage.GetBlobContainerClient(id);
|
|
|
+ await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
|
|
|
+ teacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey("Base"));
|
|
|
+ total = teacher.size;
|
|
|
+ tsize = teacher.size;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex) {
|
|
|
+ throw new Exception($"{ex.Message}{ex.StackTrace}");
|
|
|
+ }
|
|
|
+ //私人課程
|
|
|
+ List<object> courses = new List<object>();
|
|
|
+ await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{id}") }))
|
|
|
+ {
|
|
|
+ using var json = await JsonDocument.ParseAsync(item.ContentStream);
|
|
|
+ if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
|
|
|
+ {
|
|
|
+ foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
|
|
|
+ {
|
|
|
+ courses.Add(obj.ToObject<object>());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ List<string> roles = new List<string>() { "teacher" };
|
|
|
+ Area areaa = null;
|
|
|
+ if (areas.Count > 0)
|
|
|
+ {
|
|
|
+ roles.Add("area");
|
|
|
+ if (!string.IsNullOrEmpty($"{areas[0]}"))
|
|
|
+ {
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ areaa = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{areas[0].areaId}", new PartitionKey("Base-Area"));
|
|
|
+ }
|
|
|
+ catch (CosmosException)
|
|
|
+ {
|
|
|
+ areaa = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //換取AuthToken,提供給前端
|
|
|
+ var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, standard: areaa != null ? areaa.standard : "", roles: roles.ToArray());
|
|
|
+ //取得Teacher Blob 容器位置及SAS
|
|
|
+ await _azureStorage.GetBlobContainerClient(id).CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
|
|
|
+ var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);
|
|
|
+ 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);
|
|
|
+ return new TeacherInfo
|
|
|
+ {
|
|
|
+ auth_token = auth_token,
|
|
|
+ blob_uri = blob_uri,
|
|
|
+ blob_sas = blob_sas,
|
|
|
+ schools = schools,
|
|
|
+ defaultschool = defaultschool,
|
|
|
+ courses = courses,
|
|
|
+ total = total,
|
|
|
+ osblob_sas = osblob_sas,
|
|
|
+ osblob_uri = osblob_uri,
|
|
|
+ tsize = tsize,
|
|
|
+ areas = areas,
|
|
|
+ teacher = teacher
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|