Explorar o código

研修平台对接登录调整接口。

CrazyIter_Bin %!s(int64=3) %!d(string=hai) anos
pai
achega
61efa9e6a1

+ 2 - 2
TEAMModelOS.SDK/Helper/Security/Md5Hash/Md5Hash.cs

@@ -1,9 +1,9 @@
-using System;
+using System;
 using System.IO;
 using System.Security.Cryptography;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Helper.Security.Md5Hash
+namespace TEAMModelOS.SDK
 {
     public  class Md5Hash
     {

+ 8 - 0
TEAMModelOS.SDK/Models/Cosmos/Teacher/Teacher.cs

@@ -13,6 +13,7 @@ namespace TEAMModelOS.SDK.Models
         public string defaultSchool { get; set; }
         public List<TeacherSchool> schools { get; set; }= new List<TeacherSchool>();
         public List<TeacherArea> areas { get; set; } = new List<TeacherArea>();
+        public List<ThirdBind> binds { get; set; } = new List<ThirdBind>();
         public class TeacherSchool
         {
             public string schoolId { get; set; }
@@ -28,5 +29,12 @@ namespace TEAMModelOS.SDK.Models
             public string name { get; set; }
             public string status { get; set; }
         }
+        public class ThirdBind
+        {
+            public string webid { get; set; }
+            public string pxid { get; set; }
+            public string tid { get; set; }
+
+        }
     }
 }

+ 1 - 1
TEAMModelOS/ClientApp/package.json

@@ -21,7 +21,7 @@
 		"@vue/eslint-config-standard": "^4.0.0",
 		"animate.css": "^3.7.2",
 		"apexcharts": "^3.26.1",
-		"axios": "^0.21.1",
+		"axios": "^0.21.4",
 		"bcryptjs": "^2.4.3",
 		"core-js": "^3.1.2",
 		"d3": "^5.9.2",

+ 2 - 1
TEAMModelOS/Controllers/Core/CoreController.cs

@@ -54,6 +54,7 @@ namespace TEAMModelOS.Controllers.Core
             //var v2 = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
             var description = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyDescriptionAttribute>().Description;
             var version = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
+            long nowtime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
             //Console.WriteLine($"Assembly.GetEntryAssembly().GetName().Version: " +
 
             //                  $"{Assembly.GetEntryAssembly().GetName().Version}");5.2107.12.1
@@ -64,7 +65,7 @@ namespace TEAMModelOS.Controllers.Core
             //Console.WriteLine($"Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion:" +
 
             //                  $"{Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion}");5.2107.12
-            return Ok(new { version, description });
+            return Ok(new { version, description, nowtime });
         }
         /// <summary>
         /// 等待P1V3,啟動Dcoker,支持EMF GDI+

+ 2 - 2
TEAMModelOS/Controllers/Item/ItemController.cs

@@ -702,8 +702,8 @@ namespace TEAMModelOS.Controllers
             }
             catch (Exception e)
             {
-                await _dingDing.SendBotMsg($"OS,{_option.Location},item/Find()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
-                return BadRequest(e.StackTrace);
+                await _dingDing.SendBotMsg($"OS,{_option.Location},item/Find()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest();
             }
 
         }

+ 15 - 15
TEAMModelOS/Controllers/School/GroupListController.cs

@@ -51,10 +51,7 @@ namespace TEAMModelOS.Controllers
         {
             try
             {
-              
                 var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
-                
-                
                 if (!json.TryGetProperty("type", out JsonElement _type))
                 {
                     return BadRequest();
@@ -69,12 +66,12 @@ namespace TEAMModelOS.Controllers
                     list.school = school;
                     list.pk = "GroupList";
                     list.code =  !list.code.StartsWith("GroupList-")?$"GroupList-{list.code}":list.code;
-
                     switch (true)
                     {
                         //普通学生名单(包含学校教学班名单,个人课程名单),其中学生成员账号类型可以是学校学生账号和醍摩豆ID,分区键为GroupList-hbcn  分区键为GroupList-tmdid
                         case bool when $"{_type}".Equals("student", StringComparison.OrdinalIgnoreCase):
                             list.type = "student";
+                            list = await CheckListNo(list);
                             break;
                         //教研组名单,只有加入学校的老师名单 成员账号类型是醍摩豆ID,保存在学校表,分区键为GroupList-hbcn
                         case bool when $"{_type}".Equals("research", StringComparison.OrdinalIgnoreCase):
@@ -87,6 +84,7 @@ namespace TEAMModelOS.Controllers
                         //社交群组类型(包含学校交流群组,个人交流群组),成员账号类型可以是学校学生账号和醍摩豆ID,,分区键为GroupList-hbcn  分区键为GroupList-tmdid
                         case bool when $"{_type}".Equals("group", StringComparison.OrdinalIgnoreCase):
                             list.type = "group";
+                            list = await CheckListNo(list);
                             break;
                     }
                 }
@@ -99,26 +97,28 @@ namespace TEAMModelOS.Controllers
             }
         }
 
-        private async Task<GroupList> UpsertList(GroupList list ) {
+        private async Task<GroupList> CheckListNo(GroupList list ) {
             try {
                 var client = _azureCosmos.GetCosmosClient();
                 if (string.IsNullOrEmpty(list.no)) {
                     list.no = $"{Utils.CreatSaltString(6, "0123456789")}";
                     for (int i = 0; i < 10; i++)
                     {
-                        var queryNo = $"SELECT  c.no  FROM c where  c.no ='{list.no}'";
                         List<string> noStus = new();
-                        await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: queryNo,
-                                requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"{list.code}") }))
-                        {
-                            using var jsonNo = await JsonDocument.ParseAsync(item.ContentStream);
-                            if (jsonNo.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                        var queryNo = $"SELECT  c.no  FROM c where  c.no ='{list.no}'";
+                        if (list.scope.Equals("school")) {
+                            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: queryNo,
+                                    requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"{list.code}") }))
                             {
-                                var accounts = jsonNo.RootElement.GetProperty("Documents").EnumerateArray();
-                                while (accounts.MoveNext())
+                                using var jsonNo = await JsonDocument.ParseAsync(item.ContentStream);
+                                if (jsonNo.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                                 {
-                                    JsonElement account = accounts.Current;
-                                    noStus.Add(account.GetProperty("no").GetString());
+                                    var accounts = jsonNo.RootElement.GetProperty("Documents").EnumerateArray();
+                                    while (accounts.MoveNext())
+                                    {
+                                        JsonElement account = accounts.Current;
+                                        noStus.Add(account.GetProperty("no").GetString());
+                                    }
                                 }
                             }
                         }

+ 10 - 189
TEAMModelOS/Controllers/Teacher/InitController.cs

@@ -24,6 +24,7 @@ using Microsoft.Extensions.Configuration;
 using System.Net.Http;
 using TEAMModelOS.SDK;
 using static TEAMModelOS.SDK.Models.Teacher;
+using TEAMModelOS.Services;
 
 namespace TEAMModelOS.Controllers
 {
@@ -157,195 +158,15 @@ namespace TEAMModelOS.Controllers
                 var id = jwt.Payload.Sub;
                 jwt.Payload.TryGetValue("name", out object name);
                 jwt.Payload.TryGetValue("picture", out object picture);
-                List<object> schools = new List<object>();
-                List<dynamic> areas = new List<dynamic>();
-                List<Area> areasd = new List<Area>();
-                string defaultschool = null;
-                //TODO 取得Teacher 個人相關數據(課程清單、虛擬教室清單、歷史紀錄清單等),學校數據另外API處理,多校切換時不同
-                var client = _azureCosmos.GetCosmosClient();
-                int total = 0;
-                int tsize = 0;
-                try
-                {
-                    Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
-                    teacher.name = $"{name}";
-                    teacher.picture = $"{picture}";
-                    ///教师的个人空间
-                    tsize = teacher.size;
-                    ///教师的总空间 包含 个人空间和学校赠送的空间累加
-                    total = teacher.size;
-                    //areas = teacher.areas;
-                    if (teacher.areas.IsNotEmpty())
-                    {
-                        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);
-                                areas.Add(new { areaId = area.id, name = area.name, area.standard, area.standardName });
-                            }
-                            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;
-                                if (!string.IsNullOrEmpty($"{sc.areaId}"))
-                                {
-
-                                    try
-                                    {
-                                        var ar= areasd.Find(x => x.id.Equals(sc.areaId));
-                                        if (ar == null)
-                                        {
-                                            area = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{sc.areaId}", new PartitionKey("Base-Area"));
-                                            areasd.Add(area);
-                                        }
-                                        else {
-                                            area = ar;
-                                        }
-                                    }
-                                    catch (CosmosException)
-                                    {
-                                        area = null;
-                                    }
-                                }
-                                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 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;
-                    }
-                }
-                //私人課程
-                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>());
-                        }
-                    }
-                }
-
-                //老師個人課綱  TODO 暂时不取
-                List<SyllabusRole> syllabus = new List<SyllabusRole>();
-                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, 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 Ok(new { location = _option.Location, auth_token, blob_uri, blob_sas, schools, defaultschool, courses, total, osblob_uri, osblob_sas, tsize, status = 200, areas });
+                Teacher teacher = null;
+
+                TeacherInfo teacherInfo= await TeacherService.GetTeacherInfo(_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)
             {

+ 174 - 0
TEAMModelOS/Controllers/Third/ScTrainController.cs

@@ -0,0 +1,174 @@
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.DI;
+using System.Text.Json;
+using TEAMModelOS.SDK.Models;
+using Microsoft.AspNetCore.Http;
+using TEAMModelOS.SDK.Extension;
+using Azure.Cosmos;
+using System.Text;
+using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
+using Microsoft.Extensions.Options;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Extensions.Configuration;
+using TEAMModelOS.Services.Common;
+using HTEXLib.COMM.Helpers;
+using TEAMModelOS.SDK;
+using System.IdentityModel.Tokens.Jwt;
+using TEAMModelOS.Services;
+
+namespace TEAMModelOS.Controllers
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    ///  
+    [ProducesResponseType(StatusCodes.Status200OK)]
+    [ProducesResponseType(StatusCodes.Status400BadRequest)]
+    //[Authorize(Roles = "IES5")]
+    [Route("third/sctrain")]
+    //[Route("api/[controller]")]
+    [ApiController]
+    public class ScTrainController : ControllerBase
+    {
+        private readonly SnowflakeId _snowflakeId;
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly AzureRedisFactory _azureRedis;
+        public IConfiguration _configuration { get; set; }
+        public ScTrainController(AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage,
+          AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IConfiguration configuration)
+        {
+            _azureCosmos = azureCosmos;
+            _snowflakeId = snowflakeId;
+            _dingDing = dingDing;
+            _option = option?.Value;
+            _azureStorage = azureStorage;
+            _serviceBus = serviceBus;
+            _configuration = configuration;
+            _azureRedis = azureRedis;
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("opt-tmdid-tid")]
+        public async Task<IActionResult> OptTmdidTid(JsonElement request) {
+
+            try {
+                if (!request.TryGetProperty("opt", out JsonElement _opt))
+                {
+                    return BadRequest();
+                }
+                if (request.TryGetProperty("Pxid", out JsonElement _Pxid) &&
+                            request.TryGetProperty("Webid", out JsonElement _Webid) &&
+                            request.TryGetProperty("tid", out JsonElement _tid) &&
+                            request.TryGetProperty("time", out JsonElement _time) &&
+                            request.TryGetProperty("Encrypt", out JsonElement _Encrypt))
+                {
+                    string parmas = $"Pxid={_Pxid}&Webid={_Webid}&tid={_tid}&time={_time}";
+                    if (Md5Hash.GetMd5String(parmas).Equals($"{_Encrypt}"))
+                    {
+                        long ssotime = long.Parse($"{_time}");
+                        long nowtime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+                        if (nowtime - ssotime > 60 * 10)//10分钟有效期
+                        { 
+                          //  return Ok(new { status = 2, msg = "登录超时!" });
+                        }
+                    }
+                    else
+                    {
+                        return Ok(new { status = 1, msg = "参数异常!" });
+                    }
+                }
+                else
+                {
+                    return Ok(new { status = 1, msg = "参数异常!" });
+                }
+                Teacher teacher = null;
+                TeacherInfo teacherInfo = null;
+                switch (true) {
+                    case bool when $"{_opt}".Equals("CheckBindInfo", StringComparison.OrdinalIgnoreCase):
+                        string sql = $"SELECT distinct value(c) FROM c join A1 in  c.binds where A1.pxid='{_Pxid}' and A1.webid='{_Webid}' and A1.tid='{_tid}'";
+                        await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Teacher>(queryText: sql,
+                            requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
+                        {
+                            teacher = item;
+                            break;
+                        }
+                        if (teacher == null)
+                        {
+                            return Ok(new { status = 0, msg = "没有绑定!" });
+                        }
+                        else
+                        {
+                            teacherInfo = await TeacherService.GetTeacherInfo(_azureCosmos, teacher, null, null, null, _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
+                            });
+                        }
+                    case bool when $"{_opt}".Equals("BindTmdidTidInfo", StringComparison.OrdinalIgnoreCase):
+                        if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
+                        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);
+                        teacherInfo = await TeacherService.GetTeacherInfo(_azureCosmos, teacher, $"{name}", $"{picture}", id, _azureStorage, _option);
+                        var client = _azureCosmos.GetCosmosClient();
+                        if (teacherInfo.teacher == null)
+                        {
+                            teacherInfo.teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
+                        }
+                        teacherInfo.teacher.binds.Add(new Teacher.ThirdBind { pxid = $"{_Pxid}", tid = $"{_tid}" ,webid=$"{_Webid}"});
+                        await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacherInfo.teacher, id, new PartitionKey("Base"));
+                        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 (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest();
+
+            }
+            return Ok(new { status = 1, msg = "参数异常!" });
+        }
+    }
+}

+ 4 - 0
TEAMModelOS/Program.cs

@@ -1,6 +1,8 @@
 
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.Extensions.Hosting;
+using System;
+using TEAMModelOS.SDK;
 
 namespace TEAMModelOS
 {
@@ -8,6 +10,8 @@ namespace TEAMModelOS
     {
         public static void Main(string[] args)
         {
+
+            
             CreateHostBuilder(args).Build().Run();
         }
 

+ 262 - 0
TEAMModelOS/Services/Common/TeacherService.cs

@@ -0,0 +1,262 @@
+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;
+
+namespace TEAMModelOS.Services
+{
+    public static class TeacherService
+    {
+        public static async Task<TeacherInfo> GetTeacherInfo (AzureCosmosFactory _azureCosmos,Teacher teacher,string name,string picture,string id , AzureStorageFactory _azureStorage, Option _option)
+        {
+            List<object> schools = new List<object>();
+            List<dynamic> areas = new List<dynamic>();
+            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())
+                {
+                    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);
+                            areas.Add(new { areaId = area.id, name = area.name, area.standard, area.standardName });
+                        }
+                        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;
+                            if (!string.IsNullOrEmpty($"{sc.areaId}"))
+                            {
+
+                                try
+                                {
+                                    var ar = areasd.Find(x => x.id.Equals(sc.areaId));
+                                    if (ar == null)
+                                    {
+                                        area = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{sc.areaId}", new PartitionKey("Base-Area"));
+                                        areasd.Add(area);
+                                    }
+                                    else
+                                    {
+                                        area = ar;
+                                    }
+                                }
+                                catch (CosmosException)
+                                {
+                                    area = null;
+                                }
+                            }
+                            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;
+                }
+            }
+            //私人課程
+            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, 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
+            };
+        }
+    }
+    public record TeacherInfo { 
+        public string auth_token { get; set; }
+        public string blob_uri { get; set; }
+        public string blob_sas { get; set; }
+        public List<object> schools { get; set; }= new List<object> ();
+        public string defaultschool { get; set; }
+        public List<object> courses { get; set; }= new List<object>();
+        public int total { get; set; }
+        public string osblob_uri { get; set; }
+        public string osblob_sas { get; set; }
+        public int tsize { get; set; }
+        public List<dynamic> areas { get; set; } = new List<dynamic>();
+        public Teacher teacher { get; set; }
+       
+    }
+}

+ 1 - 1
TEAMModelOS/Startup.cs

@@ -145,7 +145,7 @@ namespace TEAMModelOS
                 };
             });
             //等保安全性验证。
-            services.AddScoped<SecurityHeadersAttribute>();
+          //  services.AddScoped<SecurityHeadersAttribute>();
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

+ 3 - 3
TEAMModelOS/TEAMModelOS.csproj

@@ -37,9 +37,9 @@
     <SpaRoot>ClientApp\</SpaRoot>
     <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
     <UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-    <Version>5.2110.18</Version>
-    <AssemblyVersion>5.2110.18.1</AssemblyVersion>
-    <FileVersion>5.2110.18.1</FileVersion>
+    <Version>5.2110.21</Version>
+    <AssemblyVersion>5.2110.21.1</AssemblyVersion>
+    <FileVersion>5.2110.21.1</FileVersion>
     <Description>TEAMModelOS(IES5)</Description>
     <PackageReleaseNotes>版本说明</PackageReleaseNotes>
   </PropertyGroup>