FixAuth
This commit is contained in:
@@ -53,7 +53,7 @@ namespace TechHelper.Context.Configuration
|
||||
builder.HasOne(ct => ct.Teacher) // 当前 ClassTeacher 链接到一个 User (老师)
|
||||
.WithMany(u => u.TaughtClassesLink) // 那个 User (老师) 可以有多个 ClassTeacher 记录 (为所教授的班级)
|
||||
.HasForeignKey(ct => ct.TeacherId) // 外键是 ClassTeacher.TeacherId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (老师) 被删除时,如果还有相关的 ClassTeacher 记录,则会阻止删除。
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 User (老师) 被删除时,如果还有相关的 ClassTeacher 记录,则会阻止删除。
|
||||
// 这通常是防止数据丢失的更安全选择。如果你希望老师被删除时,其所有任教关系也一并删除,可改为 DeleteBehavior.Cascade。
|
||||
}
|
||||
}
|
||||
|
1238
TechHelper.Server/Migrations/20250625032845_up.Designer.cs
generated
Normal file
1238
TechHelper.Server/Migrations/20250625032845_up.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
95
TechHelper.Server/Migrations/20250625032845_up.cs
Normal file
95
TechHelper.Server/Migrations/20250625032845_up.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||
|
||||
namespace TechHelper.Server.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class up : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_class_teachers_AspNetUsers_teacher_id",
|
||||
table: "class_teachers");
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("8b814a50-fd96-4bfa-a666-b247c0f13e22"));
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("ab2c8f8c-1ade-4ff5-9eb4-2925a89567b1"));
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("c6f92bbf-190f-47a5-b4d6-ed6874a378e8"));
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "AspNetRoles",
|
||||
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ new Guid("195b19c5-fd30-455c-9f38-9842b44bf5c3"), null, "Teacher", "TEACHER" },
|
||||
{ new Guid("53cc63db-74bc-47a8-b71a-7e120d4018a9"), null, "Administrator", "ADMINISTRATOR" },
|
||||
{ new Guid("a203eb76-97f0-418f-bc06-9549297d2ac3"), null, "Student", "STUDENT" }
|
||||
});
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_class_teachers_AspNetUsers_teacher_id",
|
||||
table: "class_teachers",
|
||||
column: "teacher_id",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_class_teachers_AspNetUsers_teacher_id",
|
||||
table: "class_teachers");
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("195b19c5-fd30-455c-9f38-9842b44bf5c3"));
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("53cc63db-74bc-47a8-b71a-7e120d4018a9"));
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("a203eb76-97f0-418f-bc06-9549297d2ac3"));
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "AspNetRoles",
|
||||
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ new Guid("8b814a50-fd96-4bfa-a666-b247c0f13e22"), null, "Administrator", "ADMINISTRATOR" },
|
||||
{ new Guid("ab2c8f8c-1ade-4ff5-9eb4-2925a89567b1"), null, "Student", "STUDENT" },
|
||||
{ new Guid("c6f92bbf-190f-47a5-b4d6-ed6874a378e8"), null, "Teacher", "TEACHER" }
|
||||
});
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_class_teachers_AspNetUsers_teacher_id",
|
||||
table: "class_teachers",
|
||||
column: "teacher_id",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
}
|
||||
}
|
@@ -744,19 +744,19 @@ namespace TechHelper.Server.Migrations
|
||||
b.HasData(
|
||||
new
|
||||
{
|
||||
Id = new Guid("ab2c8f8c-1ade-4ff5-9eb4-2925a89567b1"),
|
||||
Id = new Guid("a203eb76-97f0-418f-bc06-9549297d2ac3"),
|
||||
Name = "Student",
|
||||
NormalizedName = "STUDENT"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = new Guid("c6f92bbf-190f-47a5-b4d6-ed6874a378e8"),
|
||||
Id = new Guid("195b19c5-fd30-455c-9f38-9842b44bf5c3"),
|
||||
Name = "Teacher",
|
||||
NormalizedName = "TEACHER"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = new Guid("8b814a50-fd96-4bfa-a666-b247c0f13e22"),
|
||||
Id = new Guid("53cc63db-74bc-47a8-b71a-7e120d4018a9"),
|
||||
Name = "Administrator",
|
||||
NormalizedName = "ADMINISTRATOR"
|
||||
});
|
||||
@@ -982,7 +982,7 @@ namespace TechHelper.Server.Migrations
|
||||
b.HasOne("Entities.Contracts.User", "Teacher")
|
||||
.WithMany("TaughtClassesLink")
|
||||
.HasForeignKey("TeacherId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Class");
|
||||
|
@@ -60,9 +60,14 @@ namespace TechHelper.Services
|
||||
var classInfo = await _classService.GetUserClass(user.Id);
|
||||
if (classInfo.Status)
|
||||
{
|
||||
(byte, byte) info = ((byte, byte))classInfo.Result;
|
||||
claims.Add(new Claim("Grade", info.Item1.ToString()));
|
||||
claims.Add(new Claim("Class", info.Item2.ToString()));
|
||||
var classs = classInfo.Result as List<Class>;
|
||||
|
||||
classs?.ForEach(c =>
|
||||
{
|
||||
|
||||
claims.Add(new Claim("Grade", c.Grade.ToString()));
|
||||
claims.Add(new Claim("Class", c.Number.ToString()));
|
||||
});
|
||||
}
|
||||
|
||||
return claims;
|
||||
@@ -74,7 +79,7 @@ namespace TechHelper.Services
|
||||
issuer: _jwtSettings.ValidIssuer,
|
||||
audience: _jwtSettings.ValidAudience,
|
||||
claims: claims,
|
||||
expires: DateTime.Now.AddMinutes(Convert.ToDouble(
|
||||
expires: DateTime.UtcNow.AddMinutes(Convert.ToDouble(
|
||||
_jwtSettings.ExpiryInMinutes)),
|
||||
signingCredentials: signingCredentials);
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using SharedDATA.Api;
|
||||
|
||||
@@ -105,7 +106,7 @@ namespace TechHelper.Services
|
||||
}
|
||||
|
||||
// 实现 IBaseService<ClassDto, int>.GetAsync
|
||||
public async Task<ApiResponse> GetAsync(Guid id)
|
||||
public async Task<ApiResponse> GetAsync(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -126,13 +127,20 @@ namespace TechHelper.Services
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetUserClass(Guid user)
|
||||
public async Task<ApiResponse> GetUserClass(Guid id)
|
||||
{
|
||||
var existingUserClass = await _work.GetRepository<ClassStudent>().GetFirstOrDefaultAsync(predicate: c=>c.StudentId == user);
|
||||
if(existingUserClass == null) return new ApiResponse("该学生没有班级。");
|
||||
var tch = await _work.GetRepository<ClassTeacher>().GetAllAsync(predicate: user => user.TeacherId == id, include: i => i
|
||||
.Include(t => t.Class));
|
||||
var std = await _work.GetRepository<ClassStudent>().GetAllAsync(predicate: user => user.StudentId == id, include: i => i
|
||||
.Include(t => t.Class));
|
||||
|
||||
var classId = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(predicate: c => c.Id == existingUserClass.ClassId);
|
||||
return new ApiResponse(true, (classId.Grade, classId.Number));
|
||||
if (tch == null && std == null) return new ApiResponse("你没有加入任何班级。");
|
||||
|
||||
|
||||
List<Class> result = new List<Class>();
|
||||
tch?.ToList().ForEach(c => result.Add(c.Class));
|
||||
std?.ToList().ForEach(c => result.Add(c.Class));
|
||||
return ApiResponse.Success(result: result);
|
||||
}
|
||||
|
||||
// 实现 IBaseService<ClassDto, int>.UpdateAsync
|
||||
@@ -142,14 +150,14 @@ namespace TechHelper.Services
|
||||
{
|
||||
// 首先通过 ID 查找现有实体
|
||||
var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
|
||||
predicate: c => c.Number == model.Class);
|
||||
predicate: c => c.Number == model.Class);
|
||||
|
||||
if (existingClass == null)
|
||||
{
|
||||
return new ApiResponse("班级未找到。");
|
||||
}
|
||||
|
||||
_mapper.Map(model, existingClass);
|
||||
_mapper.Map(model, existingClass);
|
||||
_work.GetRepository<Class>().Update(existingClass);
|
||||
|
||||
if (await _work.SaveChangesAsync() > 0)
|
||||
@@ -172,47 +180,87 @@ namespace TechHelper.Services
|
||||
var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
|
||||
predicate: (c => c.Number == user.ClassId && c.Grade == user.GradeId));
|
||||
|
||||
var finduser = await _userManager.FindByEmailAsync(user.User);
|
||||
// finduser and usrinfo are redundant if they are for the same user.
|
||||
// Let's just use usrinfo
|
||||
// var finduser = await _userManager.FindByEmailAsync(user.User);
|
||||
|
||||
if (existingClass == null || finduser == null || usrinfo == null)
|
||||
if (existingClass == null || usrinfo == null) // Simplified check
|
||||
{
|
||||
return new ApiResponse("班级未找到。");
|
||||
return new ApiResponse("班级或用户未找到。"); // More accurate message
|
||||
}
|
||||
|
||||
|
||||
bool registrationExists = false;
|
||||
|
||||
if (user.Roles == UserRoles.Student)
|
||||
{
|
||||
var addresult = await _work.GetRepository<ClassStudent>().InsertAsync(new ClassStudent
|
||||
// Check for existing student registration
|
||||
var existingStudentRegistration = await _work.GetRepository<ClassStudent>().GetFirstOrDefaultAsync(
|
||||
predicate: cs => cs.StudentId == usrinfo.Id && cs.ClassId == existingClass.Id);
|
||||
|
||||
if (existingStudentRegistration != null)
|
||||
{
|
||||
StudentId = finduser.Id,
|
||||
ClassId = existingClass.Id
|
||||
});
|
||||
registrationExists = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var addresult = await _work.GetRepository<ClassStudent>().InsertAsync(new ClassStudent
|
||||
{
|
||||
StudentId = usrinfo.Id, // Use usrinfo.Id
|
||||
ClassId = existingClass.Id
|
||||
});
|
||||
}
|
||||
|
||||
await _userManager.AddToRoleAsync(usrinfo, UserRoles.Student.ToString());
|
||||
}
|
||||
else if (user.Roles == UserRoles.Teacher)
|
||||
{
|
||||
var classTeacher = new ClassTeacher
|
||||
// Check for existing teacher registration
|
||||
var existingTeacherRegistration = await _work.GetRepository<ClassTeacher>().GetFirstOrDefaultAsync(
|
||||
predicate: ct => ct.TeacherId == usrinfo.Id && ct.ClassId == existingClass.Id);
|
||||
|
||||
if (existingTeacherRegistration != null)
|
||||
{
|
||||
ClassId = existingClass.Id,
|
||||
TeacherId = existingClass.Id,
|
||||
SubjectTaught = user.SubjectArea
|
||||
};
|
||||
await _work.GetRepository<ClassTeacher>().InsertAsync(classTeacher);
|
||||
registrationExists = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var classTeacher = new ClassTeacher
|
||||
{
|
||||
ClassId = existingClass.Id,
|
||||
TeacherId = usrinfo.Id, // Use usrinfo.Id
|
||||
SubjectTaught = user.SubjectArea
|
||||
};
|
||||
await _work.GetRepository<ClassTeacher>().InsertAsync(classTeacher);
|
||||
}
|
||||
|
||||
await _userManager.AddToRoleAsync(usrinfo, UserRoles.Teacher.ToString());
|
||||
}
|
||||
|
||||
if (registrationExists)
|
||||
{
|
||||
return new ApiResponse("用户已在此班级注册,请勿重复注册。");
|
||||
}
|
||||
|
||||
if (await _work.SaveChangesAsync() > 0)
|
||||
{
|
||||
// It's possible SaveChangesAsync returns 0 even if a role was added
|
||||
// A more robust check might be needed depending on your exact requirements.
|
||||
return new ApiResponse(true, _mapper.Map<ClassDto>(existingClass));
|
||||
}
|
||||
|
||||
// If SaveChangesAsync returns 0 and registrationExists is false, it means no actual DB change occurred for the ClassStudent/ClassTeacher insert.
|
||||
// This could happen if only the role was added, but the ClassStudent/Teacher was already there (and caught by the check).
|
||||
// Or it means the insert failed for another reason not caught by the duplicate check.
|
||||
// The previous error message "班级注册失败" is still appropriate in such cases.
|
||||
return new ApiResponse("班级注册失败。");
|
||||
|
||||
}
|
||||
catch (Exception ex) { return new ApiResponse($"注册进班级时发生错误: {ex.Message}"); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the exception details for debugging
|
||||
// _logger.LogError(ex, "注册进班级时发生错误");
|
||||
return new ApiResponse($"注册进班级时发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,5 +8,6 @@ namespace TechHelper.Services
|
||||
{
|
||||
public Task<ApiResponse> UserRegister(UserRegistrationToClassDto user);
|
||||
public Task<ApiResponse> GetUserClass(Guid user);
|
||||
public Task<ApiResponse> GetClassStudents(ClassDto classDto);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user