|
@@ -1,323 +0,0 @@
|
|
|
-using Azure.Cosmos;
|
|
|
-using Microsoft.AspNetCore.Mvc;
|
|
|
-using System;
|
|
|
-using System.Collections.Generic;
|
|
|
-using System.Linq;
|
|
|
-using System.Threading.Tasks;
|
|
|
-using TEAMModelOS.SDK;
|
|
|
-using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
|
|
|
-using TEAMModelOS.SDK.Helper.Security.TmdCrypt;
|
|
|
-using TEAMModelOS.SDK.DI;
|
|
|
-using TEAMModelOS.SDK.Helper.Common.ValidateHelper;
|
|
|
-using TEAMModelOS.Models;
|
|
|
-using System.Text.Json;
|
|
|
-using TEAMModelOS.Models.StudentInfo;
|
|
|
-using Microsoft.AspNetCore.Http;
|
|
|
-using TEAMModelOS.SDK.Extension;
|
|
|
-using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
|
|
-using System.Text;
|
|
|
-using Microsoft.Extensions.Options;
|
|
|
-
|
|
|
-namespace TEAMModelOS.Controllers
|
|
|
-{
|
|
|
- [ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
- //[Authorize(Roles = "IES5")]
|
|
|
- [Route("student/init")]
|
|
|
- [ApiController]
|
|
|
- // [Authorize]
|
|
|
- public class StudentController : ControllerBase
|
|
|
- {
|
|
|
- private readonly AzureCosmosFactory _azureCosmos;
|
|
|
- private readonly Option _option;
|
|
|
-
|
|
|
- public StudentController(AzureCosmosFactory azureCosmos, IOptionsSnapshot<Option> option)
|
|
|
- {
|
|
|
- _azureCosmos = azureCosmos;
|
|
|
- _option = option?.Value;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 保存或更新学生,并维护学生关系表
|
|
|
- /// </summary>
|
|
|
- /// <param name="request"></param>
|
|
|
- /// <returns></returns>
|
|
|
- [ProducesDefaultResponseType]
|
|
|
- //[AuthToken(Roles = "teacher")]
|
|
|
- [HttpPost("upsert")]
|
|
|
- public async Task<BaseResponse> Upsert(Student request)
|
|
|
- {
|
|
|
- ResponseBuilder builder = ResponseBuilder.custom();
|
|
|
- //设置密码 isSet 是否加密 如果加密则不会再次加密
|
|
|
- if (!request.password.isSet)
|
|
|
- {
|
|
|
- request.password.value = TmdCrypt.Encrypt(request.password.value);
|
|
|
- request.password.isSet = true;
|
|
|
- }
|
|
|
- request.id = request.studentId.Replace("#", "-");
|
|
|
- ///假如更新了班级则先获取更新之前的班级
|
|
|
- var olStudent= await _azureCosmos.FindByIdPk<Student>(request.id,request.code);
|
|
|
- if (olStudent!=null && !string.IsNullOrEmpty(olStudent.classroomCode) && ! olStudent.classroomCode.Equals(request.classroomCode) ) {
|
|
|
- //移除之前的原生班级
|
|
|
- IdPk idPk=await _azureCosmos.DeleteAsync<ClassStudent>( olStudent.classroomCode ,olStudent.studentId);
|
|
|
-
|
|
|
- }
|
|
|
- ///新建最新的班级关系表
|
|
|
- ClassStudent classroomStudent = new ClassStudent { id = request.classroomCode, code = request.studentId };
|
|
|
- await _azureCosmos.SaveOrUpdate(classroomStudent);
|
|
|
- Student data = await _azureCosmos.SaveOrUpdate<Student>(request);
|
|
|
- return builder.Data(data).build();
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 查找学生
|
|
|
- /// </summary>
|
|
|
- /// <param name="request"></param>
|
|
|
- /// <returns></returns>
|
|
|
- [ProducesDefaultResponseType]
|
|
|
- //[AuthToken(Roles = "teacher")]
|
|
|
- [HttpPost("find")]
|
|
|
- public async Task<IActionResult> Find(JsonElement requert)
|
|
|
- {
|
|
|
-
|
|
|
- var client = _azureCosmos.GetCosmosClient();
|
|
|
- if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
|
|
|
- List<object> students = new List<object>();
|
|
|
- await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id, c.name,c.mail,c.mobile,c.year,c.schoolId from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Student-{school_code}") }))
|
|
|
- {
|
|
|
- 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())
|
|
|
- {
|
|
|
- students.Add(obj.ToObject<object>());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return Ok(new { students });
|
|
|
- /* ResponseBuilder builder = ResponseBuilder.custom();
|
|
|
- if (request.TryGetProperty("code", out _))
|
|
|
- {
|
|
|
- List<Student> data = await _azureCosmos.FindByDict<Student>(request);
|
|
|
- return builder.Data(data).build();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return builder.Error(ResponseCode.PARAMS_ERROR, "code is null !").build();
|
|
|
-
|
|
|
- }*/
|
|
|
- }
|
|
|
- [ProducesDefaultResponseType]
|
|
|
- //[AuthToken(Roles = "teacher")]
|
|
|
- [HttpPost("upsert-all")]
|
|
|
- public async Task<IActionResult> UpsertAll(List<Student> request)
|
|
|
- {
|
|
|
- ResponseBuilder builder = ResponseBuilder.custom();
|
|
|
-
|
|
|
- if (ValidateHelper.IsValid(request) && request.IsNotEmpty()) {
|
|
|
-
|
|
|
- ///假如更新了班级则先获取更新之前的班级
|
|
|
- string[] ids = request.Select(x=>x.studentId).ToArray();
|
|
|
- List<Student> oldStudent = await _azureCosmos.FindByDict<Student>(new Dictionary<string, object>() { { "studentId", ids } });
|
|
|
- List<IdPk> idPks = new List<IdPk>();
|
|
|
- ///处理未变动的班级关系
|
|
|
- List<IdPk> unpk = new List<IdPk>();
|
|
|
- oldStudent.ForEach(x=> {
|
|
|
- request.ForEach(m => {
|
|
|
- if (x.studentId.Equals(m.studentId)) {
|
|
|
- if (!x.classroomCode.Equals(m.classroomCode))
|
|
|
- {
|
|
|
- idPks.Add(new IdPk { id = x.classroomCode, pk = x.studentId });
|
|
|
- }
|
|
|
- else {
|
|
|
- unpk.Add(new IdPk { id = x.classroomCode, pk = x.studentId });
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
- if (idPks.IsNotEmpty()) {
|
|
|
- await _azureCosmos.DeleteAll<ClassStudent>(idPks);
|
|
|
- }
|
|
|
- long createDate = DateTimeOffset.UtcNow.Ticks;
|
|
|
- request.ForEach(
|
|
|
- x => {
|
|
|
- x.createDate = createDate;
|
|
|
- x.id = x.studentId.Replace("#", "-");
|
|
|
- //设置密码 isSet 是否加密 如果加密则不会再次加密
|
|
|
- if (!x.password.isSet)
|
|
|
- {
|
|
|
- x.password.value = TmdCrypt.Encrypt(x.password.value);
|
|
|
- x.password.isSet = true;
|
|
|
- }
|
|
|
- });
|
|
|
- List<Student> students = await _azureCosmos.SaveOrUpdateAll(request);
|
|
|
- ///更新学生关系表
|
|
|
- List<ClassStudent> classroomStudents = new List<ClassStudent>();
|
|
|
- foreach (var student in students)
|
|
|
- {
|
|
|
- // 处理未变更原生班级的学生
|
|
|
- bool has = false;
|
|
|
- foreach (IdPk idPk in unpk) {
|
|
|
- if (idPk.id.Equals(student.classroomCode) && idPk.pk.Equals(student.studentId)) {
|
|
|
- has = true;
|
|
|
- }
|
|
|
- }
|
|
|
- if (has)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
- else {
|
|
|
- classroomStudents.Add(new ClassStudent { id = student.classroomCode, code = student.studentId });
|
|
|
- }
|
|
|
- }
|
|
|
- await _azureCosmos.SaveOrUpdateAll(classroomStudents);
|
|
|
- builder.Data(students);
|
|
|
- }
|
|
|
- return Ok();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 删除单个学生
|
|
|
- /// </summary>
|
|
|
- /// <param name="request"></param>
|
|
|
- /// <returns></returns>
|
|
|
- [ProducesDefaultResponseType]
|
|
|
- //[AuthToken(Roles = "teacher")]
|
|
|
- [HttpPost("delete")]
|
|
|
- public async Task<IActionResult> Delete(JsonElement requert)
|
|
|
- {
|
|
|
- if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
|
|
|
- if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
|
|
|
- var client = _azureCosmos.GetCosmosClient();
|
|
|
- var response = await client.GetContainer("TEAMModelOS", "Student").DeleteItemStreamAsync(id.ToJsonString(), new PartitionKey($"Base-{school_code}"));
|
|
|
- if (response.Status == 200)
|
|
|
- {
|
|
|
- await _azureCosmos.DeleteAll<ClassStudent>(new Dictionary<string, object> { { "code", id.ToJsonString() } });
|
|
|
- }
|
|
|
- else {
|
|
|
- return BadRequest();
|
|
|
- }
|
|
|
- return Ok();
|
|
|
- /*ResponseBuilder builder = ResponseBuilder.custom();
|
|
|
- IdPk data = await _azureCosmos.DeleteAsync<Student>(request.id, request.code);
|
|
|
- ///更新学生关系表
|
|
|
- await _azureCosmos.DeleteAll<ClassStudent>(new Dictionary<string, object> { { "code", request.studentId } });
|
|
|
- return builder.Data(data).build();*/
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 批量删除并维护关联关系
|
|
|
- /// </summary>
|
|
|
- /// <param name="request"></param>
|
|
|
- /// <returns></returns>
|
|
|
- [ProducesDefaultResponseType]
|
|
|
- //[AuthToken(Roles = "teacher")]
|
|
|
- [HttpPost("bulkDelete")]
|
|
|
- public async Task<IActionResult> BulkDelete(JsonElement request)
|
|
|
- {
|
|
|
- ResponseBuilder builder = ResponseBuilder.custom();
|
|
|
- //Dictionary<string, object> dict = new Dictionary<string, object>();
|
|
|
- var emobj = request.EnumerateObject();
|
|
|
- int keys = 0;
|
|
|
- while (emobj.MoveNext())
|
|
|
- {
|
|
|
- keys++;
|
|
|
- //dict[emobj.Current.Name] = emobj.Current.Value;
|
|
|
- }
|
|
|
- if (keys > 0&& request.TryGetProperty("code",out JsonElement code)) {
|
|
|
- List<Student> students = await _azureCosmos.FindByDict<Student>(request);
|
|
|
- await _azureCosmos.DeleteAll<Student>(students);
|
|
|
- ///更新学生关系表
|
|
|
- await _azureCosmos.DeleteAll<ClassStudent>(new Dictionary<string, object> { {"code",students.Select(x=>x.studentId).ToArray() } });
|
|
|
- builder.Data(students);
|
|
|
- }
|
|
|
- return Ok();
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 學生登入
|
|
|
- /// </summary>
|
|
|
- /// <param name = "request" ></ param >
|
|
|
- [HttpPost("Login")]
|
|
|
-
|
|
|
- public async Task<IActionResult> Login(JsonElement request)
|
|
|
- {
|
|
|
- var client = _azureCosmos.GetCosmosClient();
|
|
|
- //參數取得
|
|
|
- if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
|
|
|
- if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
|
|
|
- if (!request.TryGetProperty("pw", out JsonElement pw)) return BadRequest();
|
|
|
-
|
|
|
- var response = await client.GetContainer("TEAMModelOS", "Student").ReadItemStreamAsync(id.GetString(), new PartitionKey($"Base-{school_code.ToString().ToLower()}"));
|
|
|
-
|
|
|
-
|
|
|
- int error = 0;
|
|
|
- string message = "帳號或密碼錯誤";
|
|
|
- string auth_token = "";
|
|
|
-
|
|
|
- if (response.Status == 200)
|
|
|
- {
|
|
|
- using var json = await JsonDocument.ParseAsync(response.ContentStream);
|
|
|
-
|
|
|
- // 取得資料庫salt
|
|
|
- json.RootElement.TryGetProperty("salt", out JsonElement salt);
|
|
|
- // 取得資料庫pw
|
|
|
- json.RootElement.TryGetProperty("pw", out JsonElement dbpw);
|
|
|
- // 取得資料庫name
|
|
|
- json.RootElement.TryGetProperty("name", out JsonElement name);
|
|
|
-
|
|
|
- var HashedPW = HashedPassword(pw.ToString(), salt.ToString());
|
|
|
-
|
|
|
- if (dbpw.ToString().Equals(HashedPW.ToString()))
|
|
|
- {
|
|
|
- //換取AuthToken,提供給前端
|
|
|
- auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), "", _option.JwtSecretKey, roles: new[] { "student" });
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- error = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- error = 1;
|
|
|
- }
|
|
|
-
|
|
|
- if (error > 0)
|
|
|
- {
|
|
|
- return Ok(
|
|
|
- new
|
|
|
- {
|
|
|
- error,
|
|
|
- message
|
|
|
- }
|
|
|
- );
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return Ok(
|
|
|
- new
|
|
|
- {
|
|
|
- auth_token
|
|
|
- }
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static string HashedPassword(string password, string salt)
|
|
|
- {
|
|
|
- byte[] hashBytes = KeyDerivation.Pbkdf2(
|
|
|
- password: password,
|
|
|
- salt: Encoding.UTF8.GetBytes(salt), // SHA1鹽(8-20字節), SHA256(32字節)
|
|
|
- prf: KeyDerivationPrf.HMACSHA1,
|
|
|
- iterationCount: 10000, // hash次數,越多次代表破解難度變高,但效能差點
|
|
|
- numBytesRequested: 256 / 8 // 指定得出結果長度
|
|
|
- );
|
|
|
-
|
|
|
- String hashText = BitConverter.ToString(hashBytes).Replace("-", string.Empty);
|
|
|
- return hashText;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|