添加项目文件。
This commit is contained in:
64
ApplicationDbContext/ApplicationDbContext.cs
Normal file
64
ApplicationDbContext/ApplicationDbContext.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using WebAppServer1.Models;
|
||||||
|
|
||||||
|
namespace WebAppServer1.ApplicationDbContext
|
||||||
|
{
|
||||||
|
public class AppDbContext :DbContext
|
||||||
|
{
|
||||||
|
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
// 好友关系双向约束
|
||||||
|
modelBuilder.Entity<Friend>()
|
||||||
|
.HasOne(f => f.User)
|
||||||
|
.WithMany(u => u.Friends)
|
||||||
|
.HasForeignKey(f => f.UserId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
modelBuilder.Entity<Friend>()
|
||||||
|
.HasOne(f => f.FriendUser)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(f => f.FriendId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
// 群成员约束
|
||||||
|
modelBuilder.Entity<GroupMember>()
|
||||||
|
.HasOne(gm => gm.Group)
|
||||||
|
.WithMany(g => g.Members)
|
||||||
|
.HasForeignKey(gm => gm.GroupId);
|
||||||
|
|
||||||
|
modelBuilder.Entity<GroupMember>()
|
||||||
|
.HasOne(gm => gm.User)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(gm => gm.UserId);
|
||||||
|
|
||||||
|
// 消息约束
|
||||||
|
modelBuilder.Entity<Message>()
|
||||||
|
.HasOne(m => m.Sender)
|
||||||
|
.WithMany(u => u.Messages)
|
||||||
|
.HasForeignKey(m => m.SenderId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
modelBuilder.Entity<Message>()
|
||||||
|
.HasOne(m => m.Receiver)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(m => m.ReceiverId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
modelBuilder.Entity<Message>()
|
||||||
|
.HasOne(m => m.Group)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(m => m.GroupId);
|
||||||
|
}
|
||||||
|
public DbSet<User> Users { get; set; }
|
||||||
|
public DbSet<Friend> Friends { get; set; }
|
||||||
|
public DbSet<Group> Groups { get; set; }
|
||||||
|
public DbSet<GroupMember> GroupMembers { get; set; }
|
||||||
|
public DbSet<Message> Messages { get; set; }
|
||||||
|
public DbSet<Notification> Notifications { get; set; }
|
||||||
|
public DbSet<FileEntity> Files { get; set; }
|
||||||
|
public DbSet<Tokens> Tokens { get; set; }
|
||||||
|
public DbSet<UserProfileHistory> userProfileHistories { get; set; }
|
||||||
|
public DbSet<LoginRecord> LoginRecords { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
6
Authentication/Authentication.cs
Normal file
6
Authentication/Authentication.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace WebAppServer1.Authentication
|
||||||
|
{
|
||||||
|
public class Authentication
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
87
Authentication/JwtService.cs
Normal file
87
Authentication/JwtService.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
using WebAppServer1.ApplicationDbContext;
|
||||||
|
using WebAppServer1.Models;
|
||||||
|
|
||||||
|
namespace WebAppServer1.Authentication
|
||||||
|
{
|
||||||
|
public class TokenService
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
private readonly AppDbContext pgSql;
|
||||||
|
|
||||||
|
public TokenService(IConfiguration config, AppDbContext appDbContext)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
pgSql = appDbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateAccessToken(string username, int userid)
|
||||||
|
{
|
||||||
|
var claims = new List<Claim>()
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.Name, username),
|
||||||
|
//new Claim(ClaimTypes.Email, username),
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, userid.ToString()),
|
||||||
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||||
|
};
|
||||||
|
|
||||||
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
|
||||||
|
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
var token = new JwtSecurityToken(
|
||||||
|
issuer: _config["Jwt:Issuer"],
|
||||||
|
audience: _config["Jwt:Audience"],
|
||||||
|
claims: claims,
|
||||||
|
expires: DateTime.UtcNow.AddMinutes(Convert.ToDouble(_config["Jwt:AccessTokenExpirationMinutes"])),
|
||||||
|
signingCredentials: creds);
|
||||||
|
|
||||||
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GenerateRefreshToken(int userid, string username)
|
||||||
|
{
|
||||||
|
var refreshToken = Guid.NewGuid().ToString("N");
|
||||||
|
var refreshTokenExpiry = DateTime.UtcNow.AddDays(Convert.ToDouble(_config["Jwt:RefreshTokenExpirationDays"]));
|
||||||
|
var tokens = new Tokens
|
||||||
|
{
|
||||||
|
UserId = userid,
|
||||||
|
UserName = username,
|
||||||
|
RefreshToken = refreshToken,
|
||||||
|
IsRevoked = false,
|
||||||
|
IssuedAt = DateTime.UtcNow,
|
||||||
|
ExpiresAt = refreshTokenExpiry,
|
||||||
|
};
|
||||||
|
pgSql.Add(tokens);
|
||||||
|
await pgSql.SaveChangesAsync();
|
||||||
|
return refreshToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ValidateRefreshToken(string refreshToken)
|
||||||
|
{
|
||||||
|
var exists = await pgSql.Tokens.AnyAsync(t => t.RefreshToken == refreshToken);
|
||||||
|
if (!exists) { return false; }
|
||||||
|
var token = await pgSql.Tokens.FirstOrDefaultAsync(t => t.RefreshToken == refreshToken);
|
||||||
|
if (token == null || token.IsRevoked ) { return false; }
|
||||||
|
if (token.ExpiresAt < DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
token.IsRevoked = true;
|
||||||
|
await pgSql.SaveChangesAsync();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RevokeRefreshToken(string refreshToken)
|
||||||
|
{
|
||||||
|
var token = await pgSql.Tokens.FirstOrDefaultAsync(t => t.RefreshToken == refreshToken);
|
||||||
|
pgSql.Tokens.Remove(token!);
|
||||||
|
await pgSql.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
249
Chat/Chat.cs
Normal file
249
Chat/Chat.cs
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Identity.Data;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using WebAppServer1.ApplicationDbContext;
|
||||||
|
using WebAppServer1.Authentication;
|
||||||
|
using WebAppServer1.Models;
|
||||||
|
using WebAppServer1.Tool;
|
||||||
|
|
||||||
|
namespace WebAppServer1.Chat
|
||||||
|
{
|
||||||
|
public class Chat : Hub
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ILogger<Chat> logger;
|
||||||
|
private readonly IConnectionMultiplexer _redis;
|
||||||
|
private readonly AppDbContext pgSql;
|
||||||
|
private readonly TokenService jwtService;
|
||||||
|
|
||||||
|
|
||||||
|
public Chat(ILogger<Chat> _logger, IConnectionMultiplexer redis, AppDbContext _pgsql,TokenService _jwtService)
|
||||||
|
{
|
||||||
|
logger = _logger;
|
||||||
|
_redis = redis;
|
||||||
|
pgSql = _pgsql;
|
||||||
|
jwtService = _jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
//wss子端点API
|
||||||
|
|
||||||
|
public override async Task OnConnectedAsync()
|
||||||
|
{
|
||||||
|
var db = _redis.GetDatabase();
|
||||||
|
await db.SetAddAsync("AllConnections", Context.ConnectionId);
|
||||||
|
await BroadcastOnlineCount();
|
||||||
|
await base.OnConnectedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||||
|
{
|
||||||
|
var db = _redis.GetDatabase();
|
||||||
|
await db.SetRemoveAsync("AllConnections", Context.ConnectionId);
|
||||||
|
// 遍历所有群组,移除该连接
|
||||||
|
var server = _redis.GetServer(_redis.GetEndPoints().First());
|
||||||
|
foreach (var key in server.Keys(pattern: "Group:*"))
|
||||||
|
{
|
||||||
|
await db.SetRemoveAsync(key, Context.ConnectionId);
|
||||||
|
var groupName = key.ToString().Replace("Group:", "");
|
||||||
|
await BroadcastGroupCount(groupName);
|
||||||
|
}
|
||||||
|
await BroadcastOnlineCount();
|
||||||
|
|
||||||
|
await base.OnDisconnectedAsync(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
//简单广播消息
|
||||||
|
[Authorize]
|
||||||
|
public async Task SendMessage(string user, string message)
|
||||||
|
{
|
||||||
|
logger.LogWarning("广播消息");
|
||||||
|
//测试发送
|
||||||
|
var exuser = Context.User?.Identity?.Name ?? "匿名";
|
||||||
|
await Clients.All.SendAsync("ReceiveMessage", exuser, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
//群聊分组消息
|
||||||
|
public async Task JoinGroup(string groupName)
|
||||||
|
{
|
||||||
|
var db = _redis.GetDatabase();
|
||||||
|
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
|
||||||
|
await db.SetAddAsync($"Group:{groupName}", Context.ConnectionId);
|
||||||
|
await BroadcastGroupCount(groupName);
|
||||||
|
|
||||||
|
logger.LogWarning($"用户: {Context.ConnectionId}加入了{groupName}群组!");
|
||||||
|
await Clients.Group(groupName).SendAsync("ReceiveMessage", groupName, "系统", $"{Context.ConnectionId} 加入了群组");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LeaveGroup(string groupName)
|
||||||
|
{
|
||||||
|
var db = _redis.GetDatabase();
|
||||||
|
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
|
||||||
|
await db.SetRemoveAsync($"Group:{groupName}", Context.ConnectionId);
|
||||||
|
await BroadcastGroupCount(groupName);
|
||||||
|
logger.LogInformation($"用户{Context.ConnectionId}---离开了---{groupName}群组");
|
||||||
|
await Clients.Group(groupName).SendAsync("ReceiveMessage",groupName, "系统", $"{Context.ConnectionId} 离开了群聊 {groupName}");
|
||||||
|
}
|
||||||
|
[Authorize]
|
||||||
|
public async Task SendMessageToGroup(string groupName, string user, string message)
|
||||||
|
{
|
||||||
|
logger.LogInformation($"用户{user}发来的的消息:{message}");
|
||||||
|
await Clients.Group(groupName).SendAsync("ReceiveMessage", groupName, user, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送已读回执
|
||||||
|
public async Task SendReadReceipt(int messageId)
|
||||||
|
{
|
||||||
|
var update = await pgSql.Messages.FindAsync(messageId);
|
||||||
|
if (update == null) { return; };
|
||||||
|
update.IsRead = true;
|
||||||
|
pgSql.Messages.Update(update);
|
||||||
|
await pgSql.SaveChangesAsync();
|
||||||
|
await Clients.User(update.SenderId.ToString()).SendAsync("SendReadReceipt",messageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送私聊消息
|
||||||
|
[Authorize]
|
||||||
|
public async Task SendPrivateMessage(string userid, string message)
|
||||||
|
{
|
||||||
|
var receiver = await pgSql.Users.FindAsync(int.Parse(userid));
|
||||||
|
if (receiver == null)
|
||||||
|
{
|
||||||
|
await Clients.Caller.SendAsync("SendPrivateMessage", false, "用户不存在", Context.UserIdentifier);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var newMesssage = new Message
|
||||||
|
{
|
||||||
|
SenderId = int.Parse(Context.UserIdentifier!),
|
||||||
|
ReceiverId = receiver.Id,
|
||||||
|
Content = message,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
MessageType = MessageType.Text,
|
||||||
|
IsDeleted = false,
|
||||||
|
IsRead = false
|
||||||
|
};
|
||||||
|
pgSql.Messages.Add(newMesssage);
|
||||||
|
await pgSql.SaveChangesAsync();
|
||||||
|
await Clients.User(userid).SendAsync("SendPrivateMessage", true, message,Context.UserIdentifier,newMesssage.Id);
|
||||||
|
await Clients.Caller.SendAsync("SendPrivateMessage", false, message, Context.UserIdentifier,newMesssage.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//搜索好友
|
||||||
|
public async Task<SearchFriendsResultResponse> SearchFriends(string username)
|
||||||
|
{
|
||||||
|
User? user = null;
|
||||||
|
|
||||||
|
if (int.TryParse(username, out int userId))
|
||||||
|
{
|
||||||
|
user = await pgSql.Users.FindAsync(userId);
|
||||||
|
Console.WriteLine("按 ID 查询: " + userId);
|
||||||
|
}
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = await pgSql.Users.FirstOrDefaultAsync(a => a.Username == username);
|
||||||
|
}
|
||||||
|
return user == null
|
||||||
|
? new SearchFriendsResultResponse { success = false }
|
||||||
|
: new SearchFriendsResultResponse
|
||||||
|
{
|
||||||
|
success = true,
|
||||||
|
userid = user.Id,
|
||||||
|
username = user.Nickname
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取用户表单测试
|
||||||
|
public async Task<List<object>> GetFormData()
|
||||||
|
{
|
||||||
|
var users = await pgSql.Users
|
||||||
|
.Select(u => new {
|
||||||
|
Id = u.Id,
|
||||||
|
Name = u.Username,
|
||||||
|
Password = u.PasswordHash,
|
||||||
|
CreatedDate = u.CreatedAt,
|
||||||
|
LastModifiedDate = u.LastActive
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return users.Cast<object>().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//刷新Token
|
||||||
|
// 刷新 Token
|
||||||
|
public async Task RefreshAccessToken(string refreshToken)
|
||||||
|
{
|
||||||
|
var token = await pgSql.Tokens.FirstOrDefaultAsync(t => t.RefreshToken == refreshToken);
|
||||||
|
|
||||||
|
if (token == null || token.IsRevoked || token.ExpiresAt < DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
await Clients.Caller.SendAsync("RefreshFailed", "Refresh token invalid or expired");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newAccessToken = jwtService.GenerateAccessToken(token.UserName, token.UserId);
|
||||||
|
var newRefreshToken = await jwtService.GenerateRefreshToken(token.UserId, token.UserName);
|
||||||
|
|
||||||
|
token.IsRevoked = true;
|
||||||
|
await pgSql.SaveChangesAsync();
|
||||||
|
|
||||||
|
await Clients.Caller.SendAsync("ReceiveNewAccessToken", newAccessToken, newRefreshToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
//登录认证
|
||||||
|
public async Task LoginAuthentication(string username, string password)
|
||||||
|
{
|
||||||
|
var exists = await pgSql.Users.AnyAsync(a => a.Username == username && a.PasswordHash == password);
|
||||||
|
if (!exists)
|
||||||
|
{
|
||||||
|
await Clients.Client(Context.ConnectionId).SendAsync("LoginResult",false,"用户名或密码错误!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var user = await pgSql.Users.FirstOrDefaultAsync(a => a.Username == username);
|
||||||
|
if (user == null) { return; }
|
||||||
|
var accessToken = jwtService.GenerateAccessToken(user.Username,user.Id);
|
||||||
|
var refreshToken = await jwtService.GenerateRefreshToken(user.Id, username);
|
||||||
|
await Clients.Client(Context.ConnectionId).SendAsync("LoginResult", true, accessToken, refreshToken);
|
||||||
|
logger.LogInformation($"用户:{username}正在进行登录认证!密码:{password}===accessToken:{accessToken}");
|
||||||
|
}
|
||||||
|
//新用户注册
|
||||||
|
public async Task Register()
|
||||||
|
{
|
||||||
|
|
||||||
|
var newUser = new User
|
||||||
|
{
|
||||||
|
Username = "user_" + Guid.NewGuid().ToString("N").Substring(0, 8),
|
||||||
|
Nickname = GenerateTool.GenerateRandomNickname(),
|
||||||
|
PasswordHash = GenerateTool.GeneratePassword(),
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
LastActive = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
pgSql.Add(newUser);
|
||||||
|
await pgSql.SaveChangesAsync();
|
||||||
|
logger.LogInformation($"新用户:{newUser.Username}正在进行登录注册操作!密码:{newUser.Nickname}");
|
||||||
|
await Clients.Client(Context.ConnectionId).SendAsync("RegisterResult", true,"恭喜注册成功!");
|
||||||
|
await LoginAuthentication(newUser.Username,newUser.PasswordHash);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//统计在线人数
|
||||||
|
private async Task BroadcastOnlineCount()
|
||||||
|
{
|
||||||
|
var db = _redis.GetDatabase();
|
||||||
|
var count = await db.SetLengthAsync("AllConnections");
|
||||||
|
await Clients.All.SendAsync("OnlineCount", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
//统计群组在线人数
|
||||||
|
private async Task BroadcastGroupCount(string groupName)
|
||||||
|
{
|
||||||
|
var db = _redis.GetDatabase();
|
||||||
|
var count = await db.SetLengthAsync($"Group:{groupName}");
|
||||||
|
await Clients.Group(groupName).SendAsync("GroupCount", groupName, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
55
Migrations/20260516024729_InitialCreate.Designer.cs
generated
Normal file
55
Migrations/20260516024729_InitialCreate.Designer.cs
generated
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using WebAppServer1.ApplicationDbContext;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
[Migration("20260516024729_InitialCreate")]
|
||||||
|
partial class InitialCreate
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedDate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastModifiedDate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Migrations/20260516024729_InitialCreate.cs
Normal file
39
Migrations/20260516024729_InitialCreate.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class InitialCreate : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Users",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
Name = table.Column<string>(type: "text", nullable: true),
|
||||||
|
CreatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
LastModifiedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
Password = table.Column<string>(type: "text", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Users", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Users");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
90
Migrations/20260517061910_tokens.Designer.cs
generated
Normal file
90
Migrations/20260517061910_tokens.Designer.cs
generated
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using WebAppServer1.ApplicationDbContext;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
[Migration("20260517061910_tokens")]
|
||||||
|
partial class tokens
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpiresAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRevoked")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("IssuedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("RefreshToken")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedDate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastModifiedDate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
Migrations/20260517061910_tokens.cs
Normal file
41
Migrations/20260517061910_tokens.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class tokens : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Tokens",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
RefreshToken = table.Column<string>(type: "text", nullable: false),
|
||||||
|
UserId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
UserName = table.Column<string>(type: "text", nullable: false),
|
||||||
|
IssuedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
ExpiresAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
IsRevoked = table.Column<bool>(type: "boolean", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Tokens", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Tokens");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
509
Migrations/20260519032425_InitialFriends.Designer.cs
generated
Normal file
509
Migrations/20260519032425_InitialFriends.Designer.cs
generated
Normal file
@@ -0,0 +1,509 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using WebAppServer1.ApplicationDbContext;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
[Migration("20260519032425_InitialFriends")]
|
||||||
|
partial class InitialFriends
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.FileEntity", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("FileType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("FileUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("MessageId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Size")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UploadedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("UploaderId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("MessageId");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderId");
|
||||||
|
|
||||||
|
b.ToTable("Files");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Friend", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("FriendId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FriendId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Friends");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AvatarUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.ToTable("Groups");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.GroupMember", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("GroupId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("JoinedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("Role")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GroupId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("GroupMembers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.LoginRecord", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("DeviceInfo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("IpAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSuccess")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LoginTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("LoginRecords");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Message", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int?>("GroupId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRead")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("MessageType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int?>("ReceiverId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("SenderId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GroupId");
|
||||||
|
|
||||||
|
b.HasIndex("ReceiverId");
|
||||||
|
|
||||||
|
b.HasIndex("SenderId");
|
||||||
|
|
||||||
|
b.ToTable("Messages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Notification", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRead")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Notifications");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpiresAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRevoked")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("IssuedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("RefreshToken")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AvatarUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOnline")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastActive")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Signature")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.UserProfileHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("ChangedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("ChangedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("FieldName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("NewValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("OldValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("userProfileHistories");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.FileEntity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Message", "Message")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("MessageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Message");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Friend", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "FriendUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FriendId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany("Friends")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("FriendUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.GroupMember", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Group", "Group")
|
||||||
|
.WithMany("Members")
|
||||||
|
.HasForeignKey("GroupId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.LoginRecord", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Message", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupId");
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Receiver")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ReceiverId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Sender")
|
||||||
|
.WithMany("Messages")
|
||||||
|
.HasForeignKey("SenderId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("Receiver");
|
||||||
|
|
||||||
|
b.Navigation("Sender");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Notification", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.UserProfileHistory", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Members");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Friends");
|
||||||
|
|
||||||
|
b.Navigation("Messages");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
408
Migrations/20260519032425_InitialFriends.cs
Normal file
408
Migrations/20260519032425_InitialFriends.cs
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class InitialFriends : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "Password",
|
||||||
|
table: "Users",
|
||||||
|
newName: "Username");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "Name",
|
||||||
|
table: "Users",
|
||||||
|
newName: "Signature");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "LastModifiedDate",
|
||||||
|
table: "Users",
|
||||||
|
newName: "LastActive");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "CreatedDate",
|
||||||
|
table: "Users",
|
||||||
|
newName: "CreatedAt");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "AvatarUrl",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Email",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsOnline",
|
||||||
|
table: "Users",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "PasswordHash",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Friends",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
UserId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
FriendId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Status = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Friends", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Friends_Users_FriendId",
|
||||||
|
column: x => x.FriendId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Friends_Users_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Groups",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
Name = table.Column<string>(type: "text", nullable: false),
|
||||||
|
OwnerId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
AvatarUrl = table.Column<string>(type: "text", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Groups", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Groups_Users_OwnerId",
|
||||||
|
column: x => x.OwnerId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "LoginRecords",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
UserId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
LoginTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
IpAddress = table.Column<string>(type: "text", nullable: false),
|
||||||
|
DeviceInfo = table.Column<string>(type: "text", nullable: false),
|
||||||
|
IsSuccess = table.Column<bool>(type: "boolean", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_LoginRecords", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_LoginRecords_Users_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Notifications",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
UserId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Type = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Content = table.Column<string>(type: "text", nullable: false),
|
||||||
|
IsRead = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Notifications", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Notifications_Users_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "userProfileHistories",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
UserId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
FieldName = table.Column<string>(type: "text", nullable: false),
|
||||||
|
OldValue = table.Column<string>(type: "text", nullable: false),
|
||||||
|
NewValue = table.Column<string>(type: "text", nullable: false),
|
||||||
|
ChangedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
ChangedBy = table.Column<string>(type: "text", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_userProfileHistories", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_userProfileHistories_Users_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "GroupMembers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
GroupId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
UserId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Role = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
JoinedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_GroupMembers", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_GroupMembers_Groups_GroupId",
|
||||||
|
column: x => x.GroupId,
|
||||||
|
principalTable: "Groups",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_GroupMembers_Users_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Messages",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
SenderId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
ReceiverId = table.Column<int>(type: "integer", nullable: true),
|
||||||
|
GroupId = table.Column<int>(type: "integer", nullable: true),
|
||||||
|
Content = table.Column<string>(type: "text", nullable: false),
|
||||||
|
MessageType = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
IsRead = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
IsDeleted = table.Column<bool>(type: "boolean", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Messages", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Messages_Groups_GroupId",
|
||||||
|
column: x => x.GroupId,
|
||||||
|
principalTable: "Groups",
|
||||||
|
principalColumn: "Id");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Messages_Users_ReceiverId",
|
||||||
|
column: x => x.ReceiverId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Messages_Users_SenderId",
|
||||||
|
column: x => x.SenderId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Files",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
UploaderId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
MessageId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
FileUrl = table.Column<string>(type: "text", nullable: false),
|
||||||
|
FileType = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Size = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
UploadedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Files", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Files_Messages_MessageId",
|
||||||
|
column: x => x.MessageId,
|
||||||
|
principalTable: "Messages",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Files_Users_UploaderId",
|
||||||
|
column: x => x.UploaderId,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Files_MessageId",
|
||||||
|
table: "Files",
|
||||||
|
column: "MessageId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Files_UploaderId",
|
||||||
|
table: "Files",
|
||||||
|
column: "UploaderId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Friends_FriendId",
|
||||||
|
table: "Friends",
|
||||||
|
column: "FriendId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Friends_UserId",
|
||||||
|
table: "Friends",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_GroupMembers_GroupId",
|
||||||
|
table: "GroupMembers",
|
||||||
|
column: "GroupId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_GroupMembers_UserId",
|
||||||
|
table: "GroupMembers",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Groups_OwnerId",
|
||||||
|
table: "Groups",
|
||||||
|
column: "OwnerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_LoginRecords_UserId",
|
||||||
|
table: "LoginRecords",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Messages_GroupId",
|
||||||
|
table: "Messages",
|
||||||
|
column: "GroupId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Messages_ReceiverId",
|
||||||
|
table: "Messages",
|
||||||
|
column: "ReceiverId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Messages_SenderId",
|
||||||
|
table: "Messages",
|
||||||
|
column: "SenderId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Notifications_UserId",
|
||||||
|
table: "Notifications",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_userProfileHistories_UserId",
|
||||||
|
table: "userProfileHistories",
|
||||||
|
column: "UserId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Files");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Friends");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "GroupMembers");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "LoginRecords");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Notifications");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "userProfileHistories");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Messages");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Groups");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AvatarUrl",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Email",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsOnline",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PasswordHash",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "Username",
|
||||||
|
table: "Users",
|
||||||
|
newName: "Password");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "Signature",
|
||||||
|
table: "Users",
|
||||||
|
newName: "Name");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "LastActive",
|
||||||
|
table: "Users",
|
||||||
|
newName: "LastModifiedDate");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "Users",
|
||||||
|
newName: "CreatedDate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
513
Migrations/20260519043509_addNickName.Designer.cs
generated
Normal file
513
Migrations/20260519043509_addNickName.Designer.cs
generated
Normal file
@@ -0,0 +1,513 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using WebAppServer1.ApplicationDbContext;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
[Migration("20260519043509_addNickName")]
|
||||||
|
partial class addNickName
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.FileEntity", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("FileType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("FileUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("MessageId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Size")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UploadedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("UploaderId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("MessageId");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderId");
|
||||||
|
|
||||||
|
b.ToTable("Files");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Friend", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("FriendId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FriendId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Friends");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AvatarUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.ToTable("Groups");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.GroupMember", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("GroupId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("JoinedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("Role")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GroupId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("GroupMembers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.LoginRecord", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("DeviceInfo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("IpAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSuccess")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LoginTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("LoginRecords");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Message", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int?>("GroupId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRead")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("MessageType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int?>("ReceiverId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("SenderId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GroupId");
|
||||||
|
|
||||||
|
b.HasIndex("ReceiverId");
|
||||||
|
|
||||||
|
b.HasIndex("SenderId");
|
||||||
|
|
||||||
|
b.ToTable("Messages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Notification", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRead")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Notifications");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpiresAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRevoked")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("IssuedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("RefreshToken")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AvatarUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOnline")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastActive")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Nickname")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Signature")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.UserProfileHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("ChangedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("ChangedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("FieldName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("NewValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("OldValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("userProfileHistories");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.FileEntity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Message", "Message")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("MessageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Message");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Friend", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "FriendUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FriendId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany("Friends")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("FriendUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.GroupMember", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Group", "Group")
|
||||||
|
.WithMany("Members")
|
||||||
|
.HasForeignKey("GroupId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.LoginRecord", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Message", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupId");
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Receiver")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ReceiverId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Sender")
|
||||||
|
.WithMany("Messages")
|
||||||
|
.HasForeignKey("SenderId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("Receiver");
|
||||||
|
|
||||||
|
b.Navigation("Sender");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Notification", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.UserProfileHistory", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Members");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Friends");
|
||||||
|
|
||||||
|
b.Navigation("Messages");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Migrations/20260519043509_addNickName.cs
Normal file
29
Migrations/20260519043509_addNickName.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class addNickName : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Nickname",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Nickname",
|
||||||
|
table: "Users");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
510
Migrations/AppDbContextModelSnapshot.cs
Normal file
510
Migrations/AppDbContextModelSnapshot.cs
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using WebAppServer1.ApplicationDbContext;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebAppServer1.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
partial class AppDbContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.FileEntity", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("FileType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("FileUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("MessageId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Size")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UploadedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("UploaderId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("MessageId");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderId");
|
||||||
|
|
||||||
|
b.ToTable("Files");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Friend", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("FriendId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("FriendId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Friends");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AvatarUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.ToTable("Groups");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.GroupMember", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("GroupId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("JoinedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("Role")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GroupId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("GroupMembers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.LoginRecord", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("DeviceInfo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("IpAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSuccess")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LoginTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("LoginRecords");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Message", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int?>("GroupId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRead")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("MessageType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int?>("ReceiverId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("SenderId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GroupId");
|
||||||
|
|
||||||
|
b.HasIndex("ReceiverId");
|
||||||
|
|
||||||
|
b.HasIndex("SenderId");
|
||||||
|
|
||||||
|
b.ToTable("Messages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Notification", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRead")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Notifications");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpiresAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<bool>("IsRevoked")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("IssuedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("RefreshToken")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AvatarUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOnline")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastActive")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Nickname")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Signature")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.UserProfileHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("ChangedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("ChangedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("FieldName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("NewValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("OldValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("userProfileHistories");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.FileEntity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Message", "Message")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("MessageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Message");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Friend", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "FriendUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FriendId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany("Friends")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("FriendUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.GroupMember", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Group", "Group")
|
||||||
|
.WithMany("Members")
|
||||||
|
.HasForeignKey("GroupId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.LoginRecord", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Message", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupId");
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Receiver")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ReceiverId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "Sender")
|
||||||
|
.WithMany("Messages")
|
||||||
|
.HasForeignKey("SenderId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("Receiver");
|
||||||
|
|
||||||
|
b.Navigation("Sender");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Notification", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.UserProfileHistory", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebAppServer1.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Members");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebAppServer1.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Friends");
|
||||||
|
|
||||||
|
b.Navigation("Messages");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Models/ResultResponse.cs
Normal file
15
Models/ResultResponse.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using MessagePack;
|
||||||
|
|
||||||
|
namespace WebAppServer1.Models
|
||||||
|
{
|
||||||
|
[MessagePackObject]
|
||||||
|
public class SearchFriendsResultResponse
|
||||||
|
{
|
||||||
|
[Key("success")]
|
||||||
|
public bool success { get; set; }
|
||||||
|
[Key("username")]
|
||||||
|
public string username { get; set; }
|
||||||
|
[Key("userid")]
|
||||||
|
public int userid { get; set; }
|
||||||
|
};
|
||||||
|
}
|
||||||
13
Models/Tokens.cs
Normal file
13
Models/Tokens.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace WebAppServer1.Models
|
||||||
|
{
|
||||||
|
public class Tokens
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public required string RefreshToken { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public required string UserName { get; set; }
|
||||||
|
public DateTime IssuedAt { get; set; }
|
||||||
|
public DateTime ExpiresAt { get; set; }
|
||||||
|
public bool IsRevoked { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
174
Models/Users.cs
Normal file
174
Models/Users.cs
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
using MessagePack;
|
||||||
|
|
||||||
|
namespace WebAppServer1.Models
|
||||||
|
{
|
||||||
|
// 用户表
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Username { get; set; } = string.Empty;
|
||||||
|
public string Nickname { get; set; } = string.Empty; // 可修改,不唯一
|
||||||
|
public string Email { get; set; } = string.Empty;
|
||||||
|
public string PasswordHash { get; set; } = string.Empty;
|
||||||
|
public string AvatarUrl { get; set; } = string.Empty;
|
||||||
|
public string Signature { get; set; } = string.Empty;
|
||||||
|
public DateTime LastActive { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public bool IsOnline { get; set; }
|
||||||
|
|
||||||
|
public ICollection<Friend> Friends { get; set; } = new List<Friend>();
|
||||||
|
public ICollection<Message> Messages { get; set; } = new List<Message>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 好友关系表
|
||||||
|
public class Friend
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public int FriendId { get; set; }
|
||||||
|
public FriendStatus Status { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public User User { get; set; }
|
||||||
|
public User FriendUser { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FriendStatus
|
||||||
|
{
|
||||||
|
Pending,
|
||||||
|
Accepted,
|
||||||
|
Blocked
|
||||||
|
}
|
||||||
|
|
||||||
|
// 群聊表
|
||||||
|
public class Group
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public int OwnerId { get; set; }
|
||||||
|
public string AvatarUrl { get; set; } = string.Empty;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public User Owner { get; set; }
|
||||||
|
public ICollection<GroupMember> Members { get; set; } = new List<GroupMember>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 群成员表
|
||||||
|
public class GroupMember
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int GroupId { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public GroupRole Role { get; set; }
|
||||||
|
public DateTime JoinedAt { get; set; }
|
||||||
|
|
||||||
|
public Group Group { get; set; }
|
||||||
|
public User User { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum GroupRole
|
||||||
|
{
|
||||||
|
Member,
|
||||||
|
Admin,
|
||||||
|
Owner
|
||||||
|
}
|
||||||
|
|
||||||
|
// 消息表
|
||||||
|
public class Message
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int SenderId { get; set; }
|
||||||
|
public int? ReceiverId { get; set; } // 私聊
|
||||||
|
public int? GroupId { get; set; } // 群聊
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
public MessageType MessageType { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public bool IsRead { get; set; }
|
||||||
|
public bool IsDeleted { get; set; }
|
||||||
|
|
||||||
|
public User Sender { get; set; }
|
||||||
|
public User Receiver { get; set; }
|
||||||
|
public Group Group { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MessageType
|
||||||
|
{
|
||||||
|
Text,
|
||||||
|
Image,
|
||||||
|
File,
|
||||||
|
Video,
|
||||||
|
Voice
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通知表
|
||||||
|
public class Notification
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public NotificationType Type { get; set; }
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
public bool IsRead { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public User User { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum NotificationType
|
||||||
|
{
|
||||||
|
FriendRequest,
|
||||||
|
Message,
|
||||||
|
System
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件表
|
||||||
|
public class FileEntity
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int UploaderId { get; set; }
|
||||||
|
public int MessageId { get; set; }
|
||||||
|
public string FileUrl { get; set; } = string.Empty;
|
||||||
|
public FileType FileType { get; set; }
|
||||||
|
public int Size { get; set; }
|
||||||
|
public DateTime UploadedAt { get; set; }
|
||||||
|
|
||||||
|
public User Uploader { get; set; }
|
||||||
|
public Message Message { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FileType
|
||||||
|
{
|
||||||
|
Image,
|
||||||
|
Video,
|
||||||
|
Document,
|
||||||
|
Audio
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserProfileHistory
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public string FieldName { get; set; } = string.Empty;
|
||||||
|
public string OldValue { get; set; } = string.Empty;
|
||||||
|
public string NewValue { get; set; } = string.Empty;
|
||||||
|
public DateTime ChangedAt { get; set; }
|
||||||
|
public string ChangedBy { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public User User { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LoginRecord
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public DateTime LoginTime { get; set; }
|
||||||
|
public string IpAddress { get; set; } = string.Empty;
|
||||||
|
public string DeviceInfo { get; set; } = string.Empty;
|
||||||
|
public bool IsSuccess { get; set; }
|
||||||
|
|
||||||
|
public User User { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
152
Program.cs
Normal file
152
Program.cs
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using System.Text;
|
||||||
|
using WebAppServer1.ApplicationDbContext;
|
||||||
|
using WebAppServer1.Authentication;
|
||||||
|
using WebAppServer1.Chat;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||||
|
builder.Services.AddOpenApi();
|
||||||
|
|
||||||
|
//注册SignalR服务
|
||||||
|
builder.Services.AddSignalR(options =>
|
||||||
|
{
|
||||||
|
options.MaximumReceiveMessageSize = 1024 * 1024 * 10; // 10MB
|
||||||
|
})
|
||||||
|
.AddMessagePackProtocol(options =>
|
||||||
|
{
|
||||||
|
options.SerializerOptions = MessagePack.MessagePackSerializerOptions.Standard
|
||||||
|
.WithSecurity(MessagePack.MessagePackSecurity.UntrustedData);
|
||||||
|
});
|
||||||
|
|
||||||
|
//连接并注册Redis服务
|
||||||
|
var redis = ConnectionMultiplexer.Connect("83.229.121.44:6378,password=redis_4GG7KG,defaultDatabase=5");
|
||||||
|
builder.Services.AddSingleton<IConnectionMultiplexer>(redis);
|
||||||
|
|
||||||
|
// 服务启动时清理 Redis
|
||||||
|
//var _redis = scope.ServiceProvider.GetRequiredService<IConnectionMultiplexer>();
|
||||||
|
var db = redis.GetDatabase();
|
||||||
|
var server = redis.GetServer(redis.GetEndPoints().First());
|
||||||
|
|
||||||
|
// 清理全局连接
|
||||||
|
await db.KeyDeleteAsync("AllConnections");
|
||||||
|
|
||||||
|
// 清理所有群组
|
||||||
|
foreach (var _key in server.Keys(pattern: "Group:*"))
|
||||||
|
{
|
||||||
|
await db.KeyDeleteAsync(_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
//连接数据库
|
||||||
|
// 添加 DbContext 并使用 PostgreSQL
|
||||||
|
builder.Services.AddDbContext<AppDbContext>(options =>
|
||||||
|
options.UseNpgsql(builder.Configuration.GetConnectionString("PostgresConnection")));
|
||||||
|
|
||||||
|
//配置跨域
|
||||||
|
builder.Services.AddCors(options =>
|
||||||
|
{
|
||||||
|
options.AddPolicy("AllowVueApp",
|
||||||
|
policy =>
|
||||||
|
{
|
||||||
|
policy.WithOrigins("http://192.168.1.254:5173", "http://localhost:5173") // 前端地址
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowCredentials();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//配置jwt
|
||||||
|
// JWT 配置
|
||||||
|
var jwtSettings = builder.Configuration.GetSection("Jwt");
|
||||||
|
var keyString = jwtSettings["Key"] ?? throw new InvalidOperationException("JWT Key 未配置");
|
||||||
|
var key = Encoding.UTF8.GetBytes(keyString);
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
})
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
ValidIssuer = jwtSettings["Issuer"],
|
||||||
|
ValidAudience = jwtSettings["Audience"],
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(key)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 允许 SignalR 使用 JWT
|
||||||
|
options.Events = new JwtBearerEvents
|
||||||
|
{
|
||||||
|
OnMessageReceived = context =>
|
||||||
|
{
|
||||||
|
var accessToken = context.Request.Query["access_token"];
|
||||||
|
var path = context.HttpContext.Request.Path;
|
||||||
|
if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/Chat"))
|
||||||
|
{
|
||||||
|
context.Token = accessToken;
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
builder.Services.AddScoped<TokenService>();
|
||||||
|
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
//启用跨域配置
|
||||||
|
app.UseCors("AllowVueApp");
|
||||||
|
|
||||||
|
//启用jwt
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.MapOpenApi();
|
||||||
|
}
|
||||||
|
|
||||||
|
//app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
var summaries = new[]
|
||||||
|
{
|
||||||
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||||
|
};
|
||||||
|
|
||||||
|
//映射端点
|
||||||
|
app.MapHub<Chat>("/Chat");
|
||||||
|
|
||||||
|
app.MapGet("/weatherforecast", () =>
|
||||||
|
{
|
||||||
|
var forecast = Enumerable.Range(1, 5).Select(index =>
|
||||||
|
new WeatherForecast
|
||||||
|
(
|
||||||
|
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||||
|
Random.Shared.Next(-20, 55),
|
||||||
|
summaries[Random.Shared.Next(summaries.Length)]
|
||||||
|
))
|
||||||
|
.ToArray();
|
||||||
|
return forecast;
|
||||||
|
})
|
||||||
|
.WithName("GetWeatherForecast");
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
|
||||||
|
internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
|
||||||
|
{
|
||||||
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||||
|
}
|
||||||
16
Properties/launchSettings.json
Normal file
16
Properties/launchSettings.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": false,
|
||||||
|
"applicationUrl": "http://0.0.0.0:5162",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
45
Tool/GenerateTool.cs
Normal file
45
Tool/GenerateTool.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace WebAppServer1.Tool
|
||||||
|
{
|
||||||
|
public class GenerateTool
|
||||||
|
{
|
||||||
|
public static string GeneratePassword()
|
||||||
|
{
|
||||||
|
const string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
const string digits = "0123456789";
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
// 生成 2 个字母
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
int index = RandomNumberGenerator.GetInt32(letters.Length);
|
||||||
|
sb.Append(letters[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 4 个数字
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int index = RandomNumberGenerator.GetInt32(digits.Length);
|
||||||
|
sb.Append(digits[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateRandomNickname()
|
||||||
|
{
|
||||||
|
string[] part1 = { "自由的", "快乐的", "孤独的", "勇敢的", "神秘的" };
|
||||||
|
string[] part2 = { "小鸟", "星星", "花朵", "少年", "旅人" };
|
||||||
|
string[] part3 = { "在唱歌", "在飞翔", "在微笑", "在流浪", "在思考" };
|
||||||
|
|
||||||
|
var random = new Random();
|
||||||
|
string nickname = part1[random.Next(part1.Length)]
|
||||||
|
+ part2[random.Next(part2.Length)]
|
||||||
|
+ part3[random.Next(part3.Length)];
|
||||||
|
return nickname;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
21
WebAppServer1.csproj
Normal file
21
WebAppServer1.csproj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="10.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.8">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" />
|
||||||
|
<PackageReference Include="StackExchange.Redis" Version="2.13.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
6
WebAppServer1.http
Normal file
6
WebAppServer1.http
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
@WebAppServer1_HostAddress = http://localhost:5162
|
||||||
|
|
||||||
|
GET {{WebAppServer1_HostAddress}}/weatherforecast/
|
||||||
|
Accept: application/json
|
||||||
|
|
||||||
|
###
|
||||||
3
WebAppServer1.slnx
Normal file
3
WebAppServer1.slnx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="WebAppServer1.csproj" />
|
||||||
|
</Solution>
|
||||||
8
appsettings.Development.json
Normal file
8
appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
appsettings.json
Normal file
21
appsettings.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"PostgresConnection": "Host=localhost;Port=5555;Database=webapp;Username=postgres;Password=123456"
|
||||||
|
},
|
||||||
|
"Jwt": {
|
||||||
|
"Key": "YourSuperSecretKeyForJwtTokenGeneration2024!@#$%^&*()",
|
||||||
|
"Issuer": "SignalRChat",
|
||||||
|
"Audience": "SignalRChatUsers",
|
||||||
|
"AccessTokenExpirationMinutes": 5,
|
||||||
|
"RefreshTokenExpirationDays": 60
|
||||||
|
},
|
||||||
|
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user