Kaynağa Gözat

作业活动,政策文件,精品课堂接口。

CrazyIter_Bin 3 yıl önce
ebeveyn
işleme
ce7f7144d3

+ 3 - 0
TEAMModelOS.SDK/Context/Constant/Constant.cs

@@ -9,5 +9,8 @@ namespace TEAMModelOS.SDK.DI
         public static readonly List<string> BlobPrefix = new List<string> { "exam", "vote", "survey", "item", "paper", "syllabus", "records", "doc", "image", "res", "video", "audio", "other", "thum", "train", "temp", "jyzx" };
         public static readonly List<string> ContentPrefix = new List<string> { "doc", "image", "res", "video", "audio", "other"};
         public static string TEAMModelOS = "TEAMModelOS";
+        public static string ScopeTeacher = "teacher";
+        public static string ScopeTmdUser = "tmduser";
+        public static string ScopeStudent = "student";
     }
 }

+ 3 - 2
TEAMModelOS.SDK/Extension/JwtAuthExtension.cs

@@ -14,7 +14,7 @@ namespace TEAMModelOS.SDK.Extension
 {
     public static class JwtAuthExtension
     {
-        public static string CreateAuthToken(string issuer, string id,string name,string picture, string salt, string schoolID = "",string standard="", string[] roles = null, string[] permissions = null, int expire = 1)
+        public static string CreateAuthToken(string issuer, string id,string name,string picture, string salt,string scope, string schoolID = "",string standard="", string[] roles = null, string[] permissions = null, int expire = 1)
         {
             // 設定要加入到 JWT Token 中的聲明資訊(Claims)  
             var payload = new JwtPayload {
@@ -26,7 +26,8 @@ namespace TEAMModelOS.SDK.Extension
                 { "picture",picture}, // 用戶頭像
                 { "roles",roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student) 
                 { "permissions",permissions}, //登入者的權限請求
-                { "standard",standard} //登入者的權限請求
+                { "standard",standard} ,//登入者的能力点标准
+                { "scope",scope}  //登入者的入口类型。 (teacher 教师端登录的醍摩豆ID、tmduser学生端登录的醍摩豆ID、student学生端登录校内账号的学生ID) 
             };
 
             // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用

+ 4 - 7
TEAMModelOS.SDK/Models/Cosmos/Common/Inner/Attachment.cs

@@ -14,19 +14,15 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// 文件名字
         /// </summary>
-     
         public string name { get; set; }
         /// <summary>
         /// 
         /// </summary>
-
         public string url { get; set; }
         
-//public int order { get; set; }
         /// <summary>
         /// 文件大小
         /// </summary>
-        
         public long size { get; set; }
         /// <summary>
         /// 创建时间
@@ -36,15 +32,16 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// 文件后缀
         /// </summary>
-        
         public string extension { get; set; }
-
         /// <summary>
         /// 文件类型
         /// </summary>
-        
         public string type { get; set; }
         public string blob { get; set; }
+        /// <summary>
+        /// 设置为主要提交文档。
+        /// </summary>
+        public bool prime { get; set; } = false;
 
     }
 }

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/Common/StuActivity.cs

@@ -2,7 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Models.Cosmos.Common
+namespace TEAMModelOS.SDK.Models
 {
 
     /*

+ 24 - 3
TEAMModelOS.SDK/Models/Cosmos/School/StandardFile.cs

@@ -24,12 +24,33 @@ namespace TEAMModelOS.SDK.Models
         public List<Link> links { get; set; }
     }
     public class Link { 
-        public string link { get; set; }
         public string thum { get; set; }
-        public string title { get; set; }
         public string subtitle { get; set; }
         public string content { get; set; }
+        /// <summary>
+        /// 文件名字
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public string url { get; set; }
+        /// <summary>
+        /// 文件大小
+        /// </summary>
+        public long size { get; set; }
+        /// <summary>
+        /// 创建时间
+        /// </summary>
 
-        public string time { get; set; }
+        public long createTime { get; set; }
+        /// <summary>
+        /// 文件后缀
+        /// </summary>
+        public string extension { get; set; }
+        /// <summary>
+        /// 文件类型
+        /// </summary>
+        public string type { get; set; }
     }
 }

+ 2 - 0
TEAMModelOS.SDK/Models/Cosmos/Student/HomeworkRecord.cs

@@ -13,6 +13,8 @@ namespace TEAMModelOS.SDK.Models
     /// </summary>    
     public class HomeworkRecord : CosmosEntity
     {
+        public string school { get; set; }
+        public string teacher { get; set; }
         /// <summary>
         /// 提交时间
         /// </summary>

+ 143 - 11
TEAMModelOS/Controllers/Common/HomeworkController.cs

@@ -397,24 +397,156 @@ namespace TEAMModelOS.Controllers.Learn
         [AuthToken(Roles = "teacher,student,admin")]
         public async Task<IActionResult> Interact(JsonElement request)
         {
-
+            if (!HttpContext.Items.TryGetValue("Scope", out object _scope)) return BadRequest();
+            var client = _azureCosmos.GetCosmosClient();
+            var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
+            long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             if (!request.TryGetProperty("opt", out JsonElement _opt)) return BadRequest();
-            if (!request.TryGetProperty("tmdid", out JsonElement _tmdid)) return BadRequest();
+            if (!request.TryGetProperty("id", out JsonElement _id)) return BadRequest();
+            if (!request.TryGetProperty("code", out JsonElement _code)) return BadRequest();
+            if (!request.TryGetProperty("targetType", out JsonElement _targetType)) return BadRequest();
+            string tbname = "Student";
+            if ($"{_targetType}".Equals("research", StringComparison.OrdinalIgnoreCase))
+            {
+                tbname = "Teacher";
+
+            }
+            else if ($"{_targetType}".Equals("student", StringComparison.OrdinalIgnoreCase))
+            {
+                tbname = "Student";
+
+            }
+           
             try
             {
                 switch (true)
-                {
-                        //提交答案
+                {   
+                    //作答记录
+                    case bool when $"{_opt}".Equals("AnswerRecord", StringComparison.OrdinalIgnoreCase):
+                        if (!request.TryGetProperty("userid", out JsonElement _userid)) return BadRequest();
+                        if (!request.TryGetProperty("userType", out JsonElement _userType)) return BadRequest();
+                        
+                        string partition = $"HomeworkRecord-{userid}";
+                        if ($"{_userType}".Equals("student"))
+                        {
+                            request.TryGetProperty("userSchool", out JsonElement _userSchool);
+                            partition = $"HomeworkRecord-{_userSchool}-{userid}";
+                        }
+                       
+                        try
+                        {
+                            HomeworkRecord record = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<HomeworkRecord>($"{_id}", new PartitionKey(partition));
+                            await client.GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<HomeworkRecord>(record, $"{_id}", new PartitionKey(partition));
+                            return Ok(new { record });
+                        }
+                        catch (CosmosException ex) {
+                            return Ok(new {error=404 });
+                        }
+                    //提交答案
                     case bool when $"{_opt}".Equals("SubmitAnswer", StringComparison.OrdinalIgnoreCase):
+                        if (!request.TryGetProperty("content", out JsonElement _content)) return BadRequest();
+                        string partitionKey = $"HomeworkRecord-{userid}";
+                        if ($"{_scope}".Equals(Constant.ScopeStudent))
+                        {
+                            partitionKey = $"HomeworkRecord-{school}-{userid}";
+                        }
+                        Content content = _content.ToObject<Content>();
+                        int taskStatus = -1;
+                        byte msgid = 0;
+                        if (content != null)
+                        {
 
-
-                        break;
-                        //评论
+                            try
+                            {
+                                HomeworkRecord record = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<HomeworkRecord>($"{_id}", new PartitionKey(partitionKey));
+                                record.content = content;
+                                await client.GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<HomeworkRecord>(record, $"{_id}", new PartitionKey(partitionKey));
+                                taskStatus = 1;
+                                msgid = 1;
+                            }
+                            catch (CosmosException ex)
+                            {
+                                if (ex.Status == 404)
+                                {
+                                    HomeworkRecord record = new HomeworkRecord
+                                    {
+                                        teacher = $"{_code}",
+                                        school = school,
+                                        id = $"{_id}",
+                                        code = partitionKey,
+                                        content = content,
+                                        pk = "HomeworkRecord",
+                                        ttl = -1,
+                                        time = now
+                                    };
+                                    record = await client.GetContainer(Constant.TEAMModelOS, tbname).CreateItemAsync<HomeworkRecord>(record, new PartitionKey(partitionKey));
+                                    taskStatus = 1;
+                                    msgid = 1;
+                                }
+                            }
+                            try
+                            {
+                                if ($"{_scope}".Equals(Constant.ScopeStudent)) {
+                                    StuActivity activity = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<StuActivity>($"{_id}", new PartitionKey($"Activity-{school}-{userid}"));
+                                    activity.taskStatus = taskStatus;
+                                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync<StuActivity>(activity, $"{_id}", new PartitionKey($"Activity-{school}-{userid}"));
+                                }
+                                if ($"{_scope}".Equals(Constant.ScopeTmdUser))
+                                {
+                                    StuActivity activity = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<StuActivity>($"{_id}", new PartitionKey($"Activity-{userid}"));
+                                    activity.taskStatus = taskStatus;
+                                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync<StuActivity>(activity, $"{_id}", new PartitionKey($"Activity-{userid}"));
+                                }
+                                if ($"{_scope}".Equals(Constant.ScopeTeacher))
+                                {
+                                    StuActivity activity = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<StuActivity>($"{_id}", new PartitionKey($"Activity-{userid}"));
+                                    activity.taskStatus = taskStatus;
+                                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<StuActivity>(activity, $"{_id}", new PartitionKey($"Activity-{userid}"));
+                                }
+                            }
+                            catch (CosmosException ex)
+                            {
+                                taskStatus = -1;
+                            }
+                            return Ok(new { msgid, taskStatus });
+                        }
+                        else {
+                            return Ok(new { msgid, taskStatus ,error =400});
+                        }
+                    //评论
                     case bool when $"{_opt}".Equals("Comment", StringComparison.OrdinalIgnoreCase):
-                        break;
-                        //打分
-                    case bool when $"{_opt}".Equals("Score", StringComparison.OrdinalIgnoreCase):
-                        break;
+                        try
+                        {
+                            string partitionkey = "";
+                            HomeworkRecord record = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<HomeworkRecord>($"{_id}", new PartitionKey(partitionkey));
+                            return Ok(new { error = 404 });
+                        }
+                        catch (CosmosException ex)
+                        {
+                            return Ok(new { error = 404 });
+                        }
+                        catch (Exception ex) {
+                            return BadRequest(new { error = 400 });
+                        }
+                    //打分
+                    case bool when $"{_opt}".Equals("MarkScore", StringComparison.OrdinalIgnoreCase):
+                        try
+                        {
+                            string pkey = "";
+                            HomeworkRecord record = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<HomeworkRecord>($"{_id}", new PartitionKey(pkey));
+                            if (!request.TryGetProperty("score", out JsonElement _score)) return BadRequest();
+                            record.score = double.Parse($"{_score}");
+                            await client.GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<HomeworkRecord>(record, $"{_id}", new PartitionKey(pkey));
+                            return Ok(new { status = true });
+                        }
+                        catch (CosmosException ex)
+                        {
+                            return Ok(new { error = 404 });
+                        }
+                        catch (Exception ex)
+                        {
+                            return BadRequest(new { error = 400 });
+                        }
                 }
             }
             catch (CosmosException ex)

+ 1 - 1
TEAMModelOS/Controllers/Research/StandardFileController.cs

@@ -17,7 +17,7 @@ namespace TEAMModelOS.Controllers
     [ProducesResponseType(StatusCodes.Status200OK)]
     [ProducesResponseType(StatusCodes.Status400BadRequest)]
     //[Authorize(Roles = "IES5")]
-    [Route("standard")]
+    [Route("standard-file")]
     [ApiController]
     public class StandardFileController : ControllerBase
     {

+ 2 - 2
TEAMModelOS/Controllers/School/StudentController.cs

@@ -1988,7 +1988,7 @@ namespace TEAMModelOS.Controllers
                         var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(school_code.GetString().ToLower(), BlobContainerSasPermissions.Read);
 
                         //換取AuthToken,提供給前端
-                        var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey, schoolID: school_code.GetString(), roles: new[] { "student" });
+                        var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey,scope: Constant.ScopeStudent, schoolID: school_code.GetString(), roles: new[] { "student" });
 
                         return Ok(new { location = _option.Location, error = 0, auth_token, blob_uri, blob_sas, classinfo, courses });
                     }
@@ -2126,7 +2126,7 @@ namespace TEAMModelOS.Controllers
                             }
                         }
                         //換取AuthToken,提供給前端
-                        var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey, schoolID: school_code.GetString(), roles: new[] { "student" });
+                        var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey, scope: Constant.ScopeStudent, schoolID: school_code.GetString(), roles: new[] { "student" });
                         //其他訊息
                         dynamic school = new ExpandoObject();
                         //回傳

+ 1 - 0
TEAMModelOS/Controllers/School/TeacherCommonController.cs

@@ -9,6 +9,7 @@ using System.Threading.Tasks;
 using TEAMModelOS.Filter;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using TEAMModelOS.Services.Common;
 

+ 1 - 1
TEAMModelOS/Controllers/School/TmdUserController.cs

@@ -125,7 +125,7 @@ namespace TEAMModelOS.Controllers
                     }
                 }
                 //換取AuthToken,提供給前端
-                var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, roles: new[] { "student" });
+                var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey,   scope: Constant.ScopeTmdUser, roles: new[] { "student" });
                 if (!string.IsNullOrEmpty(defaultschool)) { 
 
                 }

+ 2 - 2
TEAMModelOS/Controllers/Teacher/InitController.cs

@@ -315,7 +315,7 @@ namespace TEAMModelOS.Controllers
                     }
                 }
                 //換取AuthToken,提供給前端
-                var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, standard: areaa != null ? areaa.standard : "", roles: roles.ToArray());
+                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);
@@ -422,7 +422,7 @@ namespace TEAMModelOS.Controllers
                     roles.Add("area");
                 }
                 //TODO JJ,更新Token时,在取得学校资讯时,没有传入schoolId
-                var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, schoolID: school_code.ToString(), standard: school_base.standard, roles: roles.ToArray(), permissions: permissions.ToArray());
+                var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, scope: Constant.ScopeTeacher, schoolID: school_code.ToString(), standard: school_base.standard, roles: roles.ToArray(), permissions: permissions.ToArray());
 
                 //取得班级
                 List<object> school_classes = new List<object>();

+ 3 - 1
TEAMModelOS/Filter/AuthTokenAttribute.cs

@@ -38,7 +38,7 @@ namespace TEAMModelOS.Filter
             public void OnResourceExecuting(ResourceExecutingContext context)
             {
                 bool pass = false;
-                string id = string.Empty, name = string.Empty, picture = string.Empty, school = string.Empty, standard = string.Empty;
+                string id = string.Empty, name = string.Empty, picture = string.Empty, school = string.Empty, standard = string.Empty,scope=string.Empty;
                 List<string> _role = new List<string>();
                 var authtoken = context.HttpContext.GetXAuth("AuthToken");
                 if (!string.IsNullOrWhiteSpace(authtoken) && JwtAuthExtension.ValidateAuthToken(authtoken, _option.JwtSecretKey))
@@ -49,6 +49,7 @@ namespace TEAMModelOS.Filter
                     name = jwt.Claims.FirstOrDefault(claim => claim.Type.Equals("name"))?.Value;
                     picture = jwt.Claims.FirstOrDefault(claim => claim.Type.Equals("picture"))?.Value;
                     standard = jwt.Claims.FirstOrDefault(claim => claim.Type.Equals("standard"))?.Value;
+                    scope = jwt.Claims.FirstOrDefault(claim => claim.Type.Equals("scope"))?.Value;
                     if (!string.IsNullOrWhiteSpace(_roles))
                     {
                         var roles = jwt.Claims.Where(c => c.Type.Equals("roles"));
@@ -84,6 +85,7 @@ namespace TEAMModelOS.Filter
                     context.HttpContext.Items.Add("School", school);
                     context.HttpContext.Items.Add("Standard", standard);
                     context.HttpContext.Items.Add("Roles", _role);
+                    context.HttpContext.Items.Add("Scope", scope);
                 }
                 else
                     context.Result = new BadRequestResult();

+ 56 - 0
TEAMModelOS/Filter/SecurityHeadersAttribute.cs

@@ -0,0 +1,56 @@
+// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
+
+
+//using Microsoft.AspNetCore.Mvc;
+//using Microsoft.AspNetCore.Mvc.Filters;
+
+//namespace CoreSDK.Attribute
+//{
+//    public class SecurityHeadersAttribute : ActionFilterAttribute
+//    {
+//        public override void OnResultExecuting(ResultExecutingContext context)
+//        {
+//            var result = context.Result;
+//            if (result is ViewResult)
+//            {
+//                // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
+//                if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options"))
+//                {
+//                    context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff");
+//                }
+
+//                // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+//                if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options"))
+//                {
+//                    context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
+//                }
+
+//                // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
+//                var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';";
+//                // also consider adding upgrade-insecure-requests once you have HTTPS in place for production
+//                //csp += "upgrade-insecure-requests;";
+//                // also an example if you need client images to be displayed from twitter
+//                // csp += "img-src 'self' https://pbs.twimg.com;";
+
+//                // once for standards compliant browsers
+//                if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy"))
+//                {
+//                    context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp);
+//                }
+//                // and once again for IE
+//                if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy"))
+//                {
+//                    context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp);
+//                }
+
+//                // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
+//                var referrer_policy = "no-referrer";
+//                if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy"))
+//                {
+//                    context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy);
+//                }
+//            }
+//        }
+//    }
+//}