123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- using Azure.Cosmos;
- using HTEXLib.COMM.Helpers;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.Options;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Text.Json;
- using System.Threading.Tasks;
- using TEAMModelOS.Filter;
- using TEAMModelOS.Models;
- using TEAMModelOS.SDK.DI;
- using TEAMModelOS.SDK.Extension;
- using TEAMModelOS.SDK.Models;
- using TEAMModelOS.SDK.Models.Cosmos;
- using TEAMModelOS.SDK.Models.Cosmos.Common;
- using TEAMModelOS.SDK.Models.Service;
- using TEAMModelOS.Services.Common;
- namespace TEAMModelOS.Controllers
- {
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
- //[Authorize(Roles = "IES5")]
- [Route("teacher/share")]
- [ApiController]
- public class ShareController : ControllerBase
- {
- private readonly AzureCosmosFactory _azureCosmos;
- private readonly SnowflakeId _snowflakeId;
- private readonly DingDing _dingDing;
- private readonly Option _option;
- private readonly IConfiguration _configuration;
- private readonly NotificationService _notificationService;
- public ShareController(AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
- {
- _azureCosmos = azureCosmos;
- _snowflakeId = snowflakeId;
- _dingDing = dingDing;
- _option = option?.Value;
- _configuration = configuration;
- _notificationService = notificationService;
- }
- /*
- {
- "school": "学校编码",
- "scope":"school|private",
- "tmdInfo":["tmdid":"id1","tmdname":"name1"],
- "type":"coedit共编,share分享",
- "agree":0,1,
- "issuer":"权限颁发者tmdid",
- "opt":"add/del/edit"
- "syllabusId":"分享的课纲章节id",
- "syllabusName":"章节名称",
- "volumeId":"册别id",
- "volumeName":"册别name"
- }
- */
- /// <summary>
- /// 分享及邀请共编,并设置TTL过期时间
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- [ProducesDefaultResponseType]
- [HttpPost("to")]
- // [AuthToken(Roles = "Teacher")]
- public async Task<IActionResult> To(ShareData request) {
- // var (id, _, _, _) = HttpContext.GetAuthTokenInfo();
- try {
- var client = _azureCosmos.GetCosmosClient();
- //需要判断id== req.issuer 才能进行授权操作
- if (request.scope.Equals("school"))
- {
- Syllabus syllabusD = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
- if (request.opt == "del")
- {
- if (syllabusD.auth.IsNotEmpty())
- {
- List<SyllabusAuth> syllabusAuths = new List<SyllabusAuth>();
- syllabusD.auth.ForEach(x => {
- if (request.tmdInfo.Select(tmd => tmd.tmdid).Contains(x.tmdid)) {
- syllabusAuths.Add(x);
- }
- });
- syllabusAuths.ForEach(x => {
- syllabusD.auth.Remove(x);
- });
- await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
- request.tmdInfo.ForEach(async x => {
- await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{x.tmdid}"));
- });
- }
- }
- else if (request.opt.Equals("add") || request.opt.Equals("edit"))
- {
- (Syllabus syllabus, List<Share> shares) = DoAuth(request, syllabusD);
- shares.ForEach(async x => {
- await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Share>(x, new PartitionKey($"{x.code}"));
- //发送共编或分享通知
- Notification notification = new Notification
- {
- hubName = "hita",
- type = "msg",
- from = $"ies5:{request.school}",
- to = new List<string>() { x.code.Replace("Share-", "") },
- label = $"{x.type}_syllabus",
- body = new { biz = x.type, tmdid = x.issuer, schoolcode = $"{request.school}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
- expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
- };
- var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
- var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
- var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
- var location = _option.Location;
- var code = await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
- });
- await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<Syllabus>(syllabus, new PartitionKey($"Syllabus-{request.volumeId}"));
- }
- }
- else if (request.scope.Equals("private"))
- {
- Syllabus syllabusD = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
- if (request.opt == "del")
- {
- if (syllabusD.auth.IsNotEmpty())
- {
- List<SyllabusAuth> syllabusAuths = new List<SyllabusAuth>();
- syllabusD.auth.ForEach(x => {
- if (request.tmdInfo.Select(tmd => x.tmdid).Contains(x.tmdid))
- {
- syllabusAuths.Add(x);
- }
- });
- syllabusAuths.ForEach(x => {
- syllabusD.auth.Remove(x);
- });
- await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
- request.tmdInfo.ForEach(async x => {
- await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{x.tmdid}"));
- });
- }
- }
- else if (request.opt.Equals("add") || request.opt.Equals("edit"))
- {
- (Syllabus vlm, List<Share> shares) = DoAuth(request, syllabusD);
- shares.ForEach(async x => {
- await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Share>(x, new PartitionKey($"{x.code}"));
- });
- await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Syllabus>(syllabusD, new PartitionKey($"Syllabus-{request.volumeId}"));
- }
- }
- return Ok(new { code = 200 });
- }
- catch (Exception ex) {
- await _dingDing.SendBotMsg($"OS,{_option.Location},teacher/share/to\n{ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
- }
- return Ok(new { code = 500 });
- }
- private (Syllabus, List<Share>) DoAuth(ShareData request, Syllabus syllabus)
- {
- long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- List<Share> shares = new List<Share>();
- request.tmdInfo.ForEach(xmd => {
- var share = new Share
- {
- id = request.syllabusId,
- volumeId = request.volumeId,
- volumeName = request.volumeName,
- syllabusName = request.syllabusName,
- code = $"Share-{request.type}-{xmd.tmdid}",
- pk = "Share",
- ttl = -1,
- issuer = request.issuer,
- createTime = now,
- school = request.school,
- scope = request.scope,
- type = request.type,
- agree = request.agree
- };
- shares.Add(share);
- });
- if (syllabus.auth.IsNotEmpty())
- {
- request.tmdInfo.ForEach(xmd => {
- bool flag = false;
- int indx = 0;
- for (int index = 0; index < syllabus.auth.Count; index++)
- {
- if (syllabus.auth[index].tmdid == xmd.tmdid && request.type == syllabus.auth[index].type)
- {
- flag = true;
- indx = index;
- break;
- }
- }
- ///更新位置上的授权信息
- if (flag)
- {
- syllabus.auth[indx] = new SyllabusAuth
- {
- tmdid = xmd.tmdid,
- tmdname = xmd.tmdname,
- type = request.type,
- agree = request.agree,
- };
- }
- //新增
- else
- {
- syllabus.auth.Add(new SyllabusAuth
- {
- tmdid = xmd.tmdid,
- tmdname = xmd.tmdname,
- type = request.type,
- agree = request.agree,
- });
- }
- });
- }
- else
- {
- request.tmdInfo.ForEach(xmd => {
- syllabus.auth = new List<SyllabusAuth>() {
- new SyllabusAuth {
- tmdid = xmd.tmdid,
- tmdname = xmd.tmdname,
- type = request.type,
- agree = request.agree,
- }
- };
- });
- }
- return (syllabus, shares);
- }
- /// <summary>
- /// {"code":"教师编码","id":"章节id","type":"coedit/share","opt":"ignore/agree"}
- ///
- /// 教师操作收到的分享及课纲共编, ignore 忽略,需要删除Share 数据 并更新syllabus.auth
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- [ProducesDefaultResponseType]
- [HttpPost("agree-share")]
- // [AuthToken(Roles = "Teacher")]
- public async Task<IActionResult> AgreeShare(JsonElement request) {
- try {
- if (!request.TryGetProperty("type", out JsonElement type)) { return BadRequest(); }
- if (!request.TryGetProperty("code", out JsonElement code)) { return BadRequest(); }
- if (!request.TryGetProperty("id", out JsonElement id)) { return BadRequest(); }
- if (!request.TryGetProperty("opt", out JsonElement opt)) { return BadRequest(); }
- var client = _azureCosmos.GetCosmosClient();
- Share share = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
- Syllabus syllabus = null;
- if (share.scope == "school")
- {
- syllabus = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>($"{id}", new PartitionKey($"Syllabus-{share.volumeId}"));
- }
- else if (share.scope == "private")
- {
- syllabus = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>($"{id}", new PartitionKey($"Syllabus-{share.volumeId}"));
- }
- if (syllabus.auth.IsNotEmpty())
- {
- syllabus.auth.ForEach(x =>
- {
- if (x.tmdid == $"{code}" && x.type == $"{type}")
- {
- if ($"{opt}".Equals("ignore"))
- {
- x.agree = 0;
- }
- else if ($"{opt}".Equals("ignore")) {
- x.agree = 1;
- }
- }
- });
- }
- if ($"{opt}".Equals("ignore"))
- {
- share.agree = 1;
- await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Share>(share, $"{id}", new PartitionKey($"Share-{type}-{code}"));
- }
- else if ($"{opt}".Equals("ignore"))
- {
- await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
- }
- if (share.scope == "school")
- {
- syllabus = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabus, $"{id}", new PartitionKey($"Syllabus-{share.volumeId}"));
- }
- else if (share.scope == "private")
- {
- syllabus = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Syllabus>(syllabus, $"{id}", new PartitionKey($"Syllabus-{share.volumeId}"));
- }
- return Ok(new { status = 200 });
- } catch (Exception ex) {
- await _dingDing.SendBotMsg($"OS,{_option.Location},teacher/share/agree-share()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
- return Ok(new { status = 500 });
- }
- }
- [ProducesDefaultResponseType]
- [HttpPost("del-share")]
- public async Task<IActionResult> DelShare(JsonElement request) {
- try
- {
- var client = _azureCosmos.GetCosmosClient();
- if (!request.TryGetProperty("type", out JsonElement type)) { return BadRequest(); }
- if (!request.TryGetProperty("code", out JsonElement code)) { return BadRequest(); }
- if (!request.TryGetProperty("id", out JsonElement id)) { return BadRequest(); }
- await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
- return Ok(new { status = 200 });
- } catch (Exception ex)
- {
- await _dingDing.SendBotMsg($"OS,{_option.Location},teacher/share/del-share()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
- return Ok(new { status = 500 });
- }
- }
- /// <summary>
- /// {"code":"教师编码","type":"coedit/share","id":"册别id"}
- /// 教师拉取自己收到的分享及共编
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- [ProducesDefaultResponseType]
- [HttpPost("find")]
- // [AuthToken(Roles = "Teacher")]
- public async Task<IActionResult> Find(JsonElement request)
- {
- try
- {
- List<Share> shares = new List<Share>();
- if (!request.TryGetProperty("code", out JsonElement code)) { return BadRequest(); }
- if (!request.TryGetProperty("type", out JsonElement type)) { return BadRequest(); }
- request.TryGetProperty("id", out JsonElement id);
- var client = _azureCosmos.GetCosmosClient();
- StringBuilder queryText = new StringBuilder("select value(c) from c");
- queryText.Append($" where c.type='{type}' ");
- if (id.ValueKind.Equals(JsonValueKind.String) && !string.IsNullOrEmpty(id.GetString())) {
- queryText.Append($" and c.id='{id}'");
- }
- await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Share>(queryText: queryText.ToString(),
- requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Share-{type}-{code}") }))
- {
- shares.Add(item);
- }
- var sharesGp = shares.GroupBy(x => new {id= x.volumeId ,code=x.scope=="school"?x.school:x.issuer}).Select(y=>new { id=y.Key.id,code=y.Key.code,list=y.ToList()});
- return Ok(new { shares = sharesGp ,status=200});
- }
- catch (Exception ex)
- {
- await _dingDing.SendBotMsg($"OS,{_option.Location},teacher/share/find()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
- return Ok(new { status = 404 });
- }
- }
- public record ShareView
- {
- public string scope { get; set; }
- // public string code { get; set; }
- public string school { get; set; }
- public string issuer { get; set; }
- public string volumeId { get; set; }
- public List<string> syllabusId { get; set; }
- }
- /*
- {
- "scope": "school/private",
- "school": "学校编码",
- "issuer": "权限颁发者",
- "volumeId": "册别id",
- "syllabusId": ["id1课纲章节节点id","id2课纲章节节点id"],
- }
- */
- /// <summary>
- /// 查看分享
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- [ProducesDefaultResponseType]
- [HttpPost("view-share")]
- [AuthToken(Roles = "teacher")]
- public async Task<IActionResult> View(ShareView request)
- {
- try
- {
- List<SyllabusTreeNode> treeNodes = new List<SyllabusTreeNode>();
- Volume volume;
- var client = _azureCosmos.GetCosmosClient();
- string code = null;
- List<string> sid = new List<string>();
- request.syllabusId.ForEach(x => { sid.Add($"'{x}'"); });
- var sidSql= string.Join(",", sid);
- if (request.scope == "school")
- {
- code = request.school;
- var queryslt = $"SELECT value(c) FROM c where c.id in ({sidSql})";
- await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.volumeId}") }))
- {
- List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
- SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth };
- treeNodes.Add(tree);
- }
- volume = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Volume>(request.volumeId, new PartitionKey($"Volume-{code}"));
-
- }
- else if (request.scope == "private")
- {
- code = request.issuer;
- var queryslt = $"SELECT value(c) FROM c where c.id in ({sidSql})";
- await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.volumeId}") }))
- {
- List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
- SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth };
- treeNodes.Add(tree);
- }
- volume = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Volume>(request.volumeId, new PartitionKey($"Volume-{code}"));
- }
- else
- {
- return BadRequest();
- }
-
- return Ok(new { volume,tree= treeNodes });
- }
- catch (Exception ex) {
- await _dingDing.SendBotMsg($"OS,{_option.Location},teacher/share/view()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
- return BadRequest();
- }
- }
- /// <summary>
- ///二维码扫码方式
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- [ProducesDefaultResponseType]
- [HttpPost("qrcode")]
- //[AuthToken(Roles = "Teacher")]
- public async Task<IActionResult> Qrcode(Favorite request)
- {
- return Ok();
- }
- }
-
- }
|