Initial commit
This commit is contained in:
356
.gitignore
vendored
Normal file
356
.gitignore
vendored
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Mac
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# docker run data
|
||||||
|
Docker/run/data/
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "UmbraAPI"]
|
||||||
|
path = UmbraAPI
|
||||||
|
url = https://git.umbra-sync.net/SirConstance/UmbraAPI.git
|
||||||
4
MareSynchronosServer/.editorconfig
Normal file
4
MareSynchronosServer/.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[*.cs]
|
||||||
|
|
||||||
|
# MA0048: File name must match type name
|
||||||
|
dotnet_diagnostic.MA0048.severity = suggestion
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace MareSynchronosAuthService.Authentication;
|
||||||
|
|
||||||
|
public record SecretKeyAuthReply(bool Success, string Uid, string Alias, bool TempBan, bool Permaban);
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace MareSynchronosAuthService.Authentication;
|
||||||
|
|
||||||
|
internal record SecretKeyFailedAuthorization
|
||||||
|
{
|
||||||
|
private int failedAttempts = 1;
|
||||||
|
public int FailedAttempts => failedAttempts;
|
||||||
|
public Task ResetTask { get; set; }
|
||||||
|
public void IncreaseFailedAttempts()
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref failedAttempts);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
using MareSynchronos.API.Dto;
|
||||||
|
using MareSynchronos.API.Dto.Account;
|
||||||
|
using MareSynchronos.API.Routes;
|
||||||
|
using MareSynchronosAuthService.Services;
|
||||||
|
using MareSynchronosShared;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Models;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using StackExchange.Redis.Extensions.Core.Abstractions;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MareSynchronosAuthService.Controllers;
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[Route(MareAuth.Auth)]
|
||||||
|
public class JwtController : Controller
|
||||||
|
{
|
||||||
|
private readonly IHttpContextAccessor _accessor;
|
||||||
|
private readonly IRedisDatabase _redis;
|
||||||
|
private readonly IDbContextFactory<MareDbContext> _mareDbContextFactory;
|
||||||
|
private readonly GeoIPService _geoIPProvider;
|
||||||
|
private readonly SecretKeyAuthenticatorService _secretKeyAuthenticatorService;
|
||||||
|
private readonly AccountRegistrationService _accountRegistrationService;
|
||||||
|
private readonly IConfigurationService<AuthServiceConfiguration> _configuration;
|
||||||
|
|
||||||
|
public JwtController(ILogger<JwtController> logger,
|
||||||
|
IHttpContextAccessor accessor, IDbContextFactory<MareDbContext> mareDbContextFactory,
|
||||||
|
SecretKeyAuthenticatorService secretKeyAuthenticatorService,
|
||||||
|
AccountRegistrationService accountRegistrationService,
|
||||||
|
IConfigurationService<AuthServiceConfiguration> configuration,
|
||||||
|
IRedisDatabase redisDb, GeoIPService geoIPProvider)
|
||||||
|
{
|
||||||
|
_accessor = accessor;
|
||||||
|
_redis = redisDb;
|
||||||
|
_geoIPProvider = geoIPProvider;
|
||||||
|
_mareDbContextFactory = mareDbContextFactory;
|
||||||
|
_secretKeyAuthenticatorService = secretKeyAuthenticatorService;
|
||||||
|
_accountRegistrationService = accountRegistrationService;
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost(MareAuth.Auth_CreateIdent)]
|
||||||
|
public async Task<IActionResult> CreateToken(string auth, string charaIdent)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(auth)) return BadRequest("No Authkey");
|
||||||
|
if (string.IsNullOrEmpty(charaIdent)) return BadRequest("No CharaIdent");
|
||||||
|
|
||||||
|
using var dbContext = await _mareDbContextFactory.CreateDbContextAsync();
|
||||||
|
var ip = _accessor.GetIpAddress();
|
||||||
|
|
||||||
|
var authResult = await _secretKeyAuthenticatorService.AuthorizeAsync(ip, auth);
|
||||||
|
|
||||||
|
var isBanned = await dbContext.BannedUsers.AsNoTracking().AnyAsync(u => u.CharacterIdentification == charaIdent).ConfigureAwait(false);
|
||||||
|
if (isBanned)
|
||||||
|
{
|
||||||
|
var authToBan = dbContext.Auth.SingleOrDefault(a => a.UserUID == authResult.Uid);
|
||||||
|
if (authToBan != null)
|
||||||
|
{
|
||||||
|
authToBan.IsBanned = true;
|
||||||
|
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Unauthorized("Your character is banned from using the service.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authResult.Success && !authResult.TempBan) return Unauthorized("The provided secret key is invalid. Verify your accounts existence and/or recover the secret key.");
|
||||||
|
if (!authResult.Success && authResult.TempBan) return Unauthorized("Due to an excessive amount of failed authentication attempts you are temporarily banned. Check your Secret Key configuration and try connecting again in 5 minutes.");
|
||||||
|
if (authResult.Permaban)
|
||||||
|
{
|
||||||
|
if (!dbContext.BannedUsers.Any(c => c.CharacterIdentification == charaIdent))
|
||||||
|
{
|
||||||
|
dbContext.BannedUsers.Add(new Banned()
|
||||||
|
{
|
||||||
|
CharacterIdentification = charaIdent,
|
||||||
|
Reason = "Autobanned CharacterIdent (" + authResult.Uid + ")",
|
||||||
|
});
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
var lodestone = await dbContext.LodeStoneAuth.Include(a => a.User).FirstOrDefaultAsync(c => c.User.UID == authResult.Uid);
|
||||||
|
|
||||||
|
if (lodestone != null)
|
||||||
|
{
|
||||||
|
if (!dbContext.BannedRegistrations.Any(c => c.DiscordIdOrLodestoneAuth == lodestone.HashedLodestoneId))
|
||||||
|
{
|
||||||
|
dbContext.BannedRegistrations.Add(new BannedRegistrations()
|
||||||
|
{
|
||||||
|
DiscordIdOrLodestoneAuth = lodestone.HashedLodestoneId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!dbContext.BannedRegistrations.Any(c => c.DiscordIdOrLodestoneAuth == lodestone.DiscordId.ToString()))
|
||||||
|
{
|
||||||
|
dbContext.BannedRegistrations.Add(new BannedRegistrations()
|
||||||
|
{
|
||||||
|
DiscordIdOrLodestoneAuth = lodestone.DiscordId.ToString(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Unauthorized("You are permanently banned.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var existingIdent = await _redis.GetAsync<string>("UID:" + authResult.Uid);
|
||||||
|
if (!string.IsNullOrEmpty(existingIdent)) return Unauthorized("Already logged in to this account. Reconnect in 60 seconds. If you keep seeing this issue, restart your game.");
|
||||||
|
|
||||||
|
var token = CreateToken(new List<Claim>()
|
||||||
|
{
|
||||||
|
new Claim(MareClaimTypes.Uid, authResult.Uid),
|
||||||
|
new Claim(MareClaimTypes.CharaIdent, charaIdent),
|
||||||
|
new Claim(MareClaimTypes.Alias, authResult.Alias),
|
||||||
|
new Claim(MareClaimTypes.Continent, await _geoIPProvider.GetCountryFromIP(_accessor)),
|
||||||
|
});
|
||||||
|
|
||||||
|
return Content(token.RawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost(MareAuth.Auth_CreateIdentV2)]
|
||||||
|
public async Task<IActionResult> CreateTokenV2(string auth, string charaIdent)
|
||||||
|
{
|
||||||
|
var tokenResponse = await CreateToken(auth, charaIdent);
|
||||||
|
var tokenContent = tokenResponse as ContentResult;
|
||||||
|
if (tokenContent == null)
|
||||||
|
return tokenResponse;
|
||||||
|
return Json(new AuthReplyDto
|
||||||
|
{
|
||||||
|
Token = tokenContent.Content,
|
||||||
|
WellKnown = _configuration.GetValueOrDefault(nameof(AuthServiceConfiguration.WellKnown), string.Empty),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost(MareAuth.Auth_Register)]
|
||||||
|
public async Task<IActionResult> Register()
|
||||||
|
{
|
||||||
|
var ua = HttpContext.Request.Headers["User-Agent"][0] ?? "-";
|
||||||
|
var ip = _accessor.GetIpAddress();
|
||||||
|
|
||||||
|
// Legacy endpoint: generate a secret key for the user
|
||||||
|
var computedHash = StringUtils.Sha256String(StringUtils.GenerateRandomString(64) + DateTime.UtcNow.ToString());
|
||||||
|
var hashedKey = StringUtils.Sha256String(computedHash);
|
||||||
|
|
||||||
|
var dto = await _accountRegistrationService.RegisterAccountAsync(ua, ip, hashedKey);
|
||||||
|
|
||||||
|
return Json(new RegisterReplyDto()
|
||||||
|
{
|
||||||
|
Success = dto.Success,
|
||||||
|
ErrorMessage = dto.ErrorMessage,
|
||||||
|
UID = dto.UID,
|
||||||
|
SecretKey = computedHash
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost(MareAuth.Auth_RegisterV2)]
|
||||||
|
public async Task<IActionResult> RegisterV2(string hashedSecretKey)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(hashedSecretKey)) return BadRequest("No HashedSecretKey");
|
||||||
|
if (hashedSecretKey.Length != 64) return BadRequest("Bad HashedSecretKey");
|
||||||
|
if (!hashedSecretKey.All(char.IsAsciiHexDigitUpper)) return BadRequest("Bad HashedSecretKey");
|
||||||
|
|
||||||
|
var ua = HttpContext.Request.Headers["User-Agent"][0] ?? "-";
|
||||||
|
var ip = _accessor.GetIpAddress();
|
||||||
|
return Json(await _accountRegistrationService.RegisterAccountAsync(ua, ip, hashedSecretKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
private JwtSecurityToken CreateToken(IEnumerable<Claim> authClaims)
|
||||||
|
{
|
||||||
|
var authSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_configuration.GetValue<string>(nameof(MareConfigurationBase.Jwt))));
|
||||||
|
|
||||||
|
var token = new SecurityTokenDescriptor()
|
||||||
|
{
|
||||||
|
Subject = new ClaimsIdentity(authClaims),
|
||||||
|
SigningCredentials = new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256Signature),
|
||||||
|
};
|
||||||
|
|
||||||
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
return handler.CreateJwtSecurityToken(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Remove="appsettings.Development.json" />
|
||||||
|
<Content Remove="appsettings.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="appsettings.Development.json" />
|
||||||
|
<None Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="IDisposableAnalyzers" Version="4.0.7">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.149">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="MaxMind.GeoIP2" Version="5.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MareSynchronosShared\MareSynchronosShared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
40
MareSynchronosServer/MareSynchronosAuthService/Program.cs
Normal file
40
MareSynchronosServer/MareSynchronosAuthService/Program.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
namespace MareSynchronosAuthService;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var hostBuilder = CreateHostBuilder(args);
|
||||||
|
using var host = hostBuilder.Build();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||||
|
{
|
||||||
|
using var loggerFactory = LoggerFactory.Create(builder =>
|
||||||
|
{
|
||||||
|
builder.ClearProviders();
|
||||||
|
builder.AddConsole();
|
||||||
|
});
|
||||||
|
var logger = loggerFactory.CreateLogger<Startup>();
|
||||||
|
return Host.CreateDefaultBuilder(args)
|
||||||
|
.UseSystemd()
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.UseContentRoot(AppContext.BaseDirectory);
|
||||||
|
webBuilder.ConfigureLogging((ctx, builder) =>
|
||||||
|
{
|
||||||
|
builder.AddConfiguration(ctx.Configuration.GetSection("Logging"));
|
||||||
|
builder.AddFile(o => o.RootPath = AppContext.BaseDirectory);
|
||||||
|
});
|
||||||
|
webBuilder.UseStartup(ctx => new Startup(ctx.Configuration, logger));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:37726",
|
||||||
|
"sslPort": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"applicationUrl": "http://localhost:5056",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
using MareSynchronos.API.Dto.Account;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using MareSynchronosShared.Models;
|
||||||
|
|
||||||
|
namespace MareSynchronosAuthService.Services;
|
||||||
|
|
||||||
|
internal record IpRegistrationCount
|
||||||
|
{
|
||||||
|
private int count = 1;
|
||||||
|
public int Count => count;
|
||||||
|
public Task ResetTask { get; set; }
|
||||||
|
public CancellationTokenSource ResetTaskCts { get; set; }
|
||||||
|
public void IncreaseCount()
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AccountRegistrationService
|
||||||
|
{
|
||||||
|
private readonly MareMetrics _metrics;
|
||||||
|
private readonly MareDbContext _mareDbContext;
|
||||||
|
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||||
|
private readonly IConfigurationService<AuthServiceConfiguration> _configurationService;
|
||||||
|
private readonly ILogger<AccountRegistrationService> _logger;
|
||||||
|
private readonly ConcurrentDictionary<string, IpRegistrationCount> _registrationsPerIp = new(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
private Regex _registrationUserAgentRegex = new Regex(@"^MareSynchronos/", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
public AccountRegistrationService(MareMetrics metrics, MareDbContext mareDbContext,
|
||||||
|
IServiceScopeFactory serviceScopeFactory, IConfigurationService<AuthServiceConfiguration> configuration,
|
||||||
|
ILogger<AccountRegistrationService> logger)
|
||||||
|
{
|
||||||
|
_mareDbContext = mareDbContext;
|
||||||
|
_logger = logger;
|
||||||
|
_configurationService = configuration;
|
||||||
|
_metrics = metrics;
|
||||||
|
_serviceScopeFactory = serviceScopeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RegisterReplyV2Dto> RegisterAccountAsync(string ua, string ip, string hashedSecretKey)
|
||||||
|
{
|
||||||
|
var reply = new RegisterReplyV2Dto();
|
||||||
|
|
||||||
|
if (!_registrationUserAgentRegex.Match(ua).Success)
|
||||||
|
{
|
||||||
|
reply.ErrorMessage = "User-Agent not allowed";
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_registrationsPerIp.TryGetValue(ip, out var registrationCount)
|
||||||
|
&& registrationCount.Count >= _configurationService.GetValueOrDefault(nameof(AuthServiceConfiguration.RegisterIpLimit), 3))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Rejecting {ip} for registration spam", ip);
|
||||||
|
|
||||||
|
if (registrationCount.ResetTask == null)
|
||||||
|
{
|
||||||
|
registrationCount.ResetTaskCts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
if (registrationCount.ResetTaskCts != null)
|
||||||
|
registrationCount.ResetTaskCts.Cancel();
|
||||||
|
|
||||||
|
registrationCount.ResetTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(_configurationService.GetValueOrDefault(nameof(AuthServiceConfiguration.RegisterIpDurationInMinutes), 10))).ConfigureAwait(false);
|
||||||
|
|
||||||
|
}).ContinueWith((t) =>
|
||||||
|
{
|
||||||
|
_registrationsPerIp.Remove(ip, out _);
|
||||||
|
}, registrationCount.ResetTaskCts.Token);
|
||||||
|
}
|
||||||
|
reply.ErrorMessage = "Too many registrations from this IP. Please try again later.";
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = new User();
|
||||||
|
|
||||||
|
var hasValidUid = false;
|
||||||
|
while (!hasValidUid)
|
||||||
|
{
|
||||||
|
var uid = StringUtils.GenerateRandomString(7);
|
||||||
|
if (_mareDbContext.Users.Any(u => u.UID == uid || u.Alias == uid)) continue;
|
||||||
|
user.UID = uid;
|
||||||
|
hasValidUid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the first registered user on the service to admin
|
||||||
|
if (!await _mareDbContext.Users.AnyAsync().ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
user.IsAdmin = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.LastLoggedIn = DateTime.UtcNow;
|
||||||
|
|
||||||
|
var auth = new Auth()
|
||||||
|
{
|
||||||
|
HashedKey = hashedSecretKey,
|
||||||
|
User = user,
|
||||||
|
};
|
||||||
|
|
||||||
|
await _mareDbContext.Users.AddAsync(user).ConfigureAwait(false);
|
||||||
|
await _mareDbContext.Auth.AddAsync(auth).ConfigureAwait(false);
|
||||||
|
await _mareDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogInformation("User registered: {userUID} from IP {ip}", user.UID, ip);
|
||||||
|
_metrics.IncCounter(MetricsAPI.CounterAccountsCreated);
|
||||||
|
|
||||||
|
reply.Success = true;
|
||||||
|
reply.UID = user.UID;
|
||||||
|
|
||||||
|
RecordIpRegistration(ip);
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecordIpRegistration(string ip)
|
||||||
|
{
|
||||||
|
var whitelisted = _configurationService.GetValueOrDefault(nameof(AuthServiceConfiguration.WhitelistedIps), new List<string>());
|
||||||
|
if (!whitelisted.Any(w => ip.Contains(w, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
if (_registrationsPerIp.TryGetValue(ip, out var count))
|
||||||
|
{
|
||||||
|
count.IncreaseCount();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = _registrationsPerIp[ip] = new IpRegistrationCount();
|
||||||
|
|
||||||
|
if (count.ResetTaskCts != null)
|
||||||
|
count.ResetTaskCts.Cancel();
|
||||||
|
|
||||||
|
count.ResetTaskCts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
count.ResetTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(_configurationService.GetValueOrDefault(nameof(AuthServiceConfiguration.RegisterIpDurationInMinutes), 10))).ConfigureAwait(false);
|
||||||
|
|
||||||
|
}).ContinueWith((t) =>
|
||||||
|
{
|
||||||
|
_registrationsPerIp.Remove(ip, out _);
|
||||||
|
}, count.ResetTaskCts.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
using MareSynchronosShared;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
using MaxMind.GeoIP2;
|
||||||
|
|
||||||
|
namespace MareSynchronosAuthService.Services;
|
||||||
|
|
||||||
|
public class GeoIPService : IHostedService
|
||||||
|
{
|
||||||
|
private readonly ILogger<GeoIPService> _logger;
|
||||||
|
private readonly IConfigurationService<AuthServiceConfiguration> _mareConfiguration;
|
||||||
|
private bool _useGeoIP = false;
|
||||||
|
private string _cityFile = string.Empty;
|
||||||
|
private DatabaseReader? _dbReader;
|
||||||
|
private DateTime _dbLastWriteTime = DateTime.Now;
|
||||||
|
private CancellationTokenSource _fileWriteTimeCheckCts = new();
|
||||||
|
private bool _processingReload = false;
|
||||||
|
|
||||||
|
public GeoIPService(ILogger<GeoIPService> logger,
|
||||||
|
IConfigurationService<AuthServiceConfiguration> mareConfiguration)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_mareConfiguration = mareConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetCountryFromIP(IHttpContextAccessor httpContextAccessor)
|
||||||
|
{
|
||||||
|
if (!_useGeoIP)
|
||||||
|
{
|
||||||
|
return "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var ip = httpContextAccessor.GetIpAddress();
|
||||||
|
|
||||||
|
using CancellationTokenSource waitCts = new();
|
||||||
|
waitCts.CancelAfter(TimeSpan.FromSeconds(5));
|
||||||
|
while (_processingReload) await Task.Delay(100, waitCts.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (_dbReader!.TryCity(ip, out var response))
|
||||||
|
{
|
||||||
|
string? continent = response?.Continent.Code;
|
||||||
|
if (!string.IsNullOrEmpty(continent) &&
|
||||||
|
string.Equals(continent, "NA", StringComparison.Ordinal)
|
||||||
|
&& response?.Location.Longitude != null)
|
||||||
|
{
|
||||||
|
if (response.Location.Longitude < -102)
|
||||||
|
{
|
||||||
|
continent = "NA-W";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continent = "NA-E";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return continent ?? "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "*";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Error handling Geo IP country in request");
|
||||||
|
return "*";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GeoIP module starting update task");
|
||||||
|
|
||||||
|
var token = _fileWriteTimeCheckCts.Token;
|
||||||
|
_ = PeriodicReloadTask(token);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PeriodicReloadTask(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (!token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_processingReload = true;
|
||||||
|
|
||||||
|
var useGeoIP = _mareConfiguration.GetValueOrDefault(nameof(AuthServiceConfiguration.UseGeoIP), false);
|
||||||
|
var cityFile = _mareConfiguration.GetValueOrDefault(nameof(AuthServiceConfiguration.GeoIPDbCityFile), string.Empty);
|
||||||
|
var lastWriteTime = new FileInfo(cityFile).LastWriteTimeUtc;
|
||||||
|
if (useGeoIP && (!string.Equals(cityFile, _cityFile, StringComparison.OrdinalIgnoreCase) || lastWriteTime != _dbLastWriteTime))
|
||||||
|
{
|
||||||
|
_cityFile = cityFile;
|
||||||
|
if (!File.Exists(_cityFile)) throw new FileNotFoundException($"Could not open GeoIP City Database, path does not exist: {_cityFile}");
|
||||||
|
_dbReader?.Dispose();
|
||||||
|
_dbReader = null;
|
||||||
|
_dbReader = new DatabaseReader(_cityFile);
|
||||||
|
_dbLastWriteTime = lastWriteTime;
|
||||||
|
|
||||||
|
_ = _dbReader.City("8.8.8.8").Continent;
|
||||||
|
|
||||||
|
_logger.LogInformation($"Loaded GeoIP city file from {_cityFile}");
|
||||||
|
|
||||||
|
if (_useGeoIP != useGeoIP)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GeoIP module is now enabled");
|
||||||
|
_useGeoIP = useGeoIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_useGeoIP != useGeoIP && !useGeoIP)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GeoIP module is now disabled");
|
||||||
|
_useGeoIP = useGeoIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(e, "Error during periodic GeoIP module reload task, disabling GeoIP");
|
||||||
|
_useGeoIP = false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_processingReload = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(1)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_fileWriteTimeCheckCts.Cancel();
|
||||||
|
_fileWriteTimeCheckCts.Dispose();
|
||||||
|
_dbReader?.Dispose();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
using MareSynchronosAuthService.Authentication;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace MareSynchronosAuthService.Services;
|
||||||
|
|
||||||
|
public class SecretKeyAuthenticatorService
|
||||||
|
{
|
||||||
|
private readonly MareMetrics _metrics;
|
||||||
|
private readonly MareDbContext _mareDbContext;
|
||||||
|
private readonly IConfigurationService<AuthServiceConfiguration> _configurationService;
|
||||||
|
private readonly ILogger<SecretKeyAuthenticatorService> _logger;
|
||||||
|
private readonly ConcurrentDictionary<string, SecretKeyFailedAuthorization> _failedAuthorizations = new(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
public SecretKeyAuthenticatorService(MareMetrics metrics, MareDbContext mareDbContext,
|
||||||
|
IConfigurationService<AuthServiceConfiguration> configuration, ILogger<SecretKeyAuthenticatorService> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_configurationService = configuration;
|
||||||
|
_metrics = metrics;
|
||||||
|
_mareDbContext = mareDbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SecretKeyAuthReply> AuthorizeAsync(string ip, string hashedSecretKey)
|
||||||
|
{
|
||||||
|
_metrics.IncCounter(MetricsAPI.CounterAuthenticationRequests);
|
||||||
|
|
||||||
|
if (_failedAuthorizations.TryGetValue(ip, out var existingFailedAuthorization)
|
||||||
|
&& existingFailedAuthorization.FailedAttempts > _configurationService.GetValueOrDefault(nameof(AuthServiceConfiguration.FailedAuthForTempBan), 5))
|
||||||
|
{
|
||||||
|
if (existingFailedAuthorization.ResetTask == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("TempBan {ip} for authorization spam", ip);
|
||||||
|
|
||||||
|
existingFailedAuthorization.ResetTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(_configurationService.GetValueOrDefault(nameof(AuthServiceConfiguration.TempBanDurationInMinutes), 5))).ConfigureAwait(false);
|
||||||
|
|
||||||
|
}).ContinueWith((t) =>
|
||||||
|
{
|
||||||
|
_failedAuthorizations.Remove(ip, out _);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new(Success: false, Uid: null, TempBan: true, Alias: null, Permaban: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var authReply = await _mareDbContext.Auth.Include(a => a.User).AsNoTracking()
|
||||||
|
.SingleOrDefaultAsync(u => u.HashedKey == hashedSecretKey).ConfigureAwait(false);
|
||||||
|
|
||||||
|
SecretKeyAuthReply reply = new(authReply != null, authReply?.UserUID, authReply?.User?.Alias ?? string.Empty, TempBan: false, authReply?.IsBanned ?? false);
|
||||||
|
|
||||||
|
if (reply.Success)
|
||||||
|
{
|
||||||
|
_metrics.IncCounter(MetricsAPI.CounterAuthenticationSuccesses);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return AuthenticationFailure(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecretKeyAuthReply AuthenticationFailure(string ip)
|
||||||
|
{
|
||||||
|
_metrics.IncCounter(MetricsAPI.CounterAuthenticationFailures);
|
||||||
|
|
||||||
|
_logger.LogWarning("Failed authorization from {ip}", ip);
|
||||||
|
var whitelisted = _configurationService.GetValueOrDefault(nameof(AuthServiceConfiguration.WhitelistedIps), new List<string>());
|
||||||
|
if (!whitelisted.Any(w => ip.Contains(w, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
if (_failedAuthorizations.TryGetValue(ip, out var auth))
|
||||||
|
{
|
||||||
|
auth.IncreaseFailedAttempts();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_failedAuthorizations[ip] = new SecretKeyFailedAuthorization();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new(Success: false, Uid: null, Alias: null, TempBan: false, Permaban: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
226
MareSynchronosServer/MareSynchronosAuthService/Startup.cs
Normal file
226
MareSynchronosServer/MareSynchronosAuthService/Startup.cs
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
using MareSynchronosAuthService.Controllers;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
|
using StackExchange.Redis.Extensions.Core.Configuration;
|
||||||
|
using StackExchange.Redis.Extensions.System.Text.Json;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using System.Net;
|
||||||
|
using MareSynchronosAuthService.Services;
|
||||||
|
using MareSynchronosShared.RequirementHandlers;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.Text;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Prometheus;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
|
||||||
|
namespace MareSynchronosAuthService;
|
||||||
|
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
private ILogger<Startup> _logger;
|
||||||
|
|
||||||
|
public Startup(IConfiguration configuration, ILogger<Startup> logger)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
|
||||||
|
{
|
||||||
|
var config = app.ApplicationServices.GetRequiredService<IConfigurationService<MareConfigurationBase>>();
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseHttpMetrics();
|
||||||
|
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
KestrelMetricServer metricServer = new KestrelMetricServer(config.GetValueOrDefault<int>(nameof(MareConfigurationBase.MetricsPort), 4985));
|
||||||
|
metricServer.Start();
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapControllers();
|
||||||
|
|
||||||
|
foreach (var source in endpoints.DataSources.SelectMany(e => e.Endpoints).Cast<RouteEndpoint>())
|
||||||
|
{
|
||||||
|
if (source == null) continue;
|
||||||
|
_logger.LogInformation("Endpoint: {url} ", source.RoutePattern.RawText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
var mareConfig = _configuration.GetRequiredSection("MareSynchronos");
|
||||||
|
|
||||||
|
services.AddHttpContextAccessor();
|
||||||
|
|
||||||
|
ConfigureRedis(services, mareConfig);
|
||||||
|
|
||||||
|
services.AddSingleton<SecretKeyAuthenticatorService>();
|
||||||
|
services.AddSingleton<AccountRegistrationService>();
|
||||||
|
services.AddSingleton<GeoIPService>();
|
||||||
|
|
||||||
|
services.AddHostedService(provider => provider.GetRequiredService<GeoIPService>());
|
||||||
|
|
||||||
|
services.Configure<AuthServiceConfiguration>(_configuration.GetRequiredSection("MareSynchronos"));
|
||||||
|
services.Configure<MareConfigurationBase>(_configuration.GetRequiredSection("MareSynchronos"));
|
||||||
|
|
||||||
|
services.AddSingleton<ServerTokenGenerator>();
|
||||||
|
|
||||||
|
ConfigureAuthorization(services);
|
||||||
|
|
||||||
|
ConfigureDatabase(services, mareConfig);
|
||||||
|
|
||||||
|
ConfigureConfigServices(services);
|
||||||
|
|
||||||
|
ConfigureMetrics(services);
|
||||||
|
|
||||||
|
services.AddHealthChecks();
|
||||||
|
services.AddControllers().ConfigureApplicationPartManager(a =>
|
||||||
|
{
|
||||||
|
a.FeatureProviders.Remove(a.FeatureProviders.OfType<ControllerFeatureProvider>().First());
|
||||||
|
a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(JwtController)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureAuthorization(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddTransient<IAuthorizationHandler, UserRequirementHandler>();
|
||||||
|
|
||||||
|
services.AddOptions<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.Configure<IConfigurationService<MareConfigurationBase>>((options, config) =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new()
|
||||||
|
{
|
||||||
|
ValidateIssuer = false,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ValidateAudience = false,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(config.GetValue<string>(nameof(MareConfigurationBase.Jwt)))),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddAuthentication(o =>
|
||||||
|
{
|
||||||
|
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
}).AddJwtBearer();
|
||||||
|
|
||||||
|
services.AddAuthorization(options =>
|
||||||
|
{
|
||||||
|
options.DefaultPolicy = new AuthorizationPolicyBuilder()
|
||||||
|
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.RequireAuthenticatedUser().Build();
|
||||||
|
options.AddPolicy("Authenticated", policy =>
|
||||||
|
{
|
||||||
|
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
|
||||||
|
policy.RequireAuthenticatedUser();
|
||||||
|
});
|
||||||
|
options.AddPolicy("Identified", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified));
|
||||||
|
|
||||||
|
});
|
||||||
|
options.AddPolicy("Admin", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified | UserRequirements.Administrator));
|
||||||
|
|
||||||
|
});
|
||||||
|
options.AddPolicy("Moderator", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified | UserRequirements.Moderator | UserRequirements.Administrator));
|
||||||
|
});
|
||||||
|
options.AddPolicy("Internal", new AuthorizationPolicyBuilder().RequireClaim(MareClaimTypes.Internal, "true").Build());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureMetrics(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<MareMetrics>(m => new MareMetrics(m.GetService<ILogger<MareMetrics>>(), new List<string>
|
||||||
|
{
|
||||||
|
MetricsAPI.CounterAuthenticationCacheHits,
|
||||||
|
MetricsAPI.CounterAuthenticationFailures,
|
||||||
|
MetricsAPI.CounterAuthenticationRequests,
|
||||||
|
MetricsAPI.CounterAuthenticationSuccesses,
|
||||||
|
MetricsAPI.CounterAccountsCreated,
|
||||||
|
}, new List<string>
|
||||||
|
{
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureRedis(IServiceCollection services, IConfigurationSection mareConfig)
|
||||||
|
{
|
||||||
|
// configure redis for SignalR
|
||||||
|
var redisConnection = mareConfig.GetValue(nameof(ServerConfiguration.RedisConnectionString), string.Empty);
|
||||||
|
|
||||||
|
var options = ConfigurationOptions.Parse(redisConnection);
|
||||||
|
|
||||||
|
var endpoint = options.EndPoints[0];
|
||||||
|
string address = "";
|
||||||
|
int port = 0;
|
||||||
|
if (endpoint is DnsEndPoint dnsEndPoint) { address = dnsEndPoint.Host; port = dnsEndPoint.Port; }
|
||||||
|
if (endpoint is IPEndPoint ipEndPoint) { address = ipEndPoint.Address.ToString(); port = ipEndPoint.Port; }
|
||||||
|
var redisConfiguration = new RedisConfiguration()
|
||||||
|
{
|
||||||
|
AbortOnConnectFail = true,
|
||||||
|
KeyPrefix = "",
|
||||||
|
Hosts = new RedisHost[]
|
||||||
|
{
|
||||||
|
new RedisHost(){ Host = address, Port = port },
|
||||||
|
},
|
||||||
|
AllowAdmin = true,
|
||||||
|
ConnectTimeout = options.ConnectTimeout,
|
||||||
|
Database = 0,
|
||||||
|
Ssl = false,
|
||||||
|
Password = options.Password,
|
||||||
|
ServerEnumerationStrategy = new ServerEnumerationStrategy()
|
||||||
|
{
|
||||||
|
Mode = ServerEnumerationStrategy.ModeOptions.All,
|
||||||
|
TargetRole = ServerEnumerationStrategy.TargetRoleOptions.Any,
|
||||||
|
UnreachableServerAction = ServerEnumerationStrategy.UnreachableServerActionOptions.Throw,
|
||||||
|
},
|
||||||
|
MaxValueLength = 1024,
|
||||||
|
PoolSize = mareConfig.GetValue(nameof(ServerConfiguration.RedisPool), 50),
|
||||||
|
SyncTimeout = options.SyncTimeout,
|
||||||
|
};
|
||||||
|
|
||||||
|
services.AddStackExchangeRedisExtensions<SystemTextJsonSerializer>(redisConfiguration);
|
||||||
|
}
|
||||||
|
private void ConfigureConfigServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IConfigurationService<AuthServiceConfiguration>, MareConfigurationServiceServer<AuthServiceConfiguration>>();
|
||||||
|
services.AddSingleton<IConfigurationService<MareConfigurationBase>, MareConfigurationServiceServer<MareConfigurationBase>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureDatabase(IServiceCollection services, IConfigurationSection mareConfig)
|
||||||
|
{
|
||||||
|
services.AddDbContextPool<MareDbContext>(options =>
|
||||||
|
{
|
||||||
|
options.UseNpgsql(_configuration.GetConnectionString("DefaultConnection"), builder =>
|
||||||
|
{
|
||||||
|
builder.MigrationsHistoryTable("_efmigrationshistory", "public");
|
||||||
|
builder.MigrationsAssembly("MareSynchronosShared");
|
||||||
|
}).UseSnakeCaseNamingConvention();
|
||||||
|
options.EnableThreadSafetyChecks(false);
|
||||||
|
}, mareConfig.GetValue(nameof(MareConfigurationBase.DbContextPoolSize), 1024));
|
||||||
|
services.AddDbContextFactory<MareDbContext>(options =>
|
||||||
|
{
|
||||||
|
options.UseNpgsql(_configuration.GetConnectionString("DefaultConnection"), builder =>
|
||||||
|
{
|
||||||
|
builder.MigrationsHistoryTable("_efmigrationshistory", "public");
|
||||||
|
builder.MigrationsAssembly("MareSynchronosShared");
|
||||||
|
}).UseSnakeCaseNamingConvention();
|
||||||
|
options.EnableThreadSafetyChecks(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
60
MareSynchronosServer/MareSynchronosServer.sln
Normal file
60
MareSynchronosServer/MareSynchronosServer.sln
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.2.32602.215
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosServer", "MareSynchronosServer\MareSynchronosServer.csproj", "{029CA97F-E0BA-4172-A191-EA21FB61AD0F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronos.API", "..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj", "{326BFB1B-5571-47A6-8513-1FFDB32D53B0}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosShared", "MareSynchronosShared\MareSynchronosShared.csproj", "{67B1461D-E215-4BA8-A64D-E1836724D5E6}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosStaticFilesServer", "MareSynchronosStaticFilesServer\MareSynchronosStaticFilesServer.csproj", "{3C7F43BB-FE4C-48BC-BF42-D24E70E8FCB7}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosServices", "MareSynchronosServices\MareSynchronosServices.csproj", "{E29C8677-AB44-4950-9EB1-D8E70B710A56}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7D5C2B87-5CC9-4FE7-AD13-4C13F6600683}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.editorconfig = .editorconfig
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MareSynchronosAuthService", "MareSynchronosAuthService\MareSynchronosAuthService.csproj", "{D7D4041C-DCD9-4B7A-B423-0F458DFFF3D6}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{029CA97F-E0BA-4172-A191-EA21FB61AD0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{029CA97F-E0BA-4172-A191-EA21FB61AD0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{029CA97F-E0BA-4172-A191-EA21FB61AD0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{029CA97F-E0BA-4172-A191-EA21FB61AD0F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{326BFB1B-5571-47A6-8513-1FFDB32D53B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{326BFB1B-5571-47A6-8513-1FFDB32D53B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{326BFB1B-5571-47A6-8513-1FFDB32D53B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{326BFB1B-5571-47A6-8513-1FFDB32D53B0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{67B1461D-E215-4BA8-A64D-E1836724D5E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{67B1461D-E215-4BA8-A64D-E1836724D5E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{67B1461D-E215-4BA8-A64D-E1836724D5E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{67B1461D-E215-4BA8-A64D-E1836724D5E6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3C7F43BB-FE4C-48BC-BF42-D24E70E8FCB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3C7F43BB-FE4C-48BC-BF42-D24E70E8FCB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3C7F43BB-FE4C-48BC-BF42-D24E70E8FCB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3C7F43BB-FE4C-48BC-BF42-D24E70E8FCB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E29C8677-AB44-4950-9EB1-D8E70B710A56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E29C8677-AB44-4950-9EB1-D8E70B710A56}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E29C8677-AB44-4950-9EB1-D8E70B710A56}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E29C8677-AB44-4950-9EB1-D8E70B710A56}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D7D4041C-DCD9-4B7A-B423-0F458DFFF3D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D7D4041C-DCD9-4B7A-B423-0F458DFFF3D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D7D4041C-DCD9-4B7A-B423-0F458DFFF3D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D7D4041C-DCD9-4B7A-B423-0F458DFFF3D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {78C476A5-6E88-449B-828D-A2465D9D3295}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-ef": {
|
||||||
|
"version": "6.0.9",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-ef"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using MareSynchronos.API.SignalR;
|
||||||
|
using MareSynchronosServer.Hubs;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Controllers;
|
||||||
|
|
||||||
|
[Route("/msgc")]
|
||||||
|
[Authorize(Policy = "Internal")]
|
||||||
|
public class ClientMessageController : Controller
|
||||||
|
{
|
||||||
|
private ILogger<ClientMessageController> _logger;
|
||||||
|
private IHubContext<MareHub, IMareHub> _hubContext;
|
||||||
|
|
||||||
|
public ClientMessageController(ILogger<ClientMessageController> logger, IHubContext<MareHub, IMareHub> hubContext)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_hubContext = hubContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("sendMessage")]
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> SendMessage([FromBody] ClientMessage msg)
|
||||||
|
{
|
||||||
|
bool hasUid = !string.IsNullOrEmpty(msg.UID);
|
||||||
|
|
||||||
|
if (!hasUid)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Sending Message of severity {severity} to all online users: {message}", msg.Severity, msg.Message);
|
||||||
|
await _hubContext.Clients.All.Client_ReceiveServerMessage(msg.Severity, msg.Message).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Sending Message of severity {severity} to user {uid}: {message}", msg.Severity, msg.UID, msg.Message);
|
||||||
|
await _hubContext.Clients.User(msg.UID).Client_ReceiveServerMessage(msg.Severity, msg.Message).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using MareSynchronos.API.Routes;
|
||||||
|
using MareSynchronos.API.SignalR;
|
||||||
|
using MareSynchronosServer.Hubs;
|
||||||
|
using MareSynchronosServer.Services;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Controllers;
|
||||||
|
|
||||||
|
[Route(MareFiles.Main)]
|
||||||
|
public class MainController : Controller
|
||||||
|
{
|
||||||
|
private IHubContext<MareHub, IMareHub> _hubContext;
|
||||||
|
|
||||||
|
public MainController(ILogger<MainController> logger, IHubContext<MareHub, IMareHub> hubContext)
|
||||||
|
{
|
||||||
|
_hubContext = hubContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet(MareFiles.Main_SendReady)]
|
||||||
|
[Authorize(Policy = "Internal")]
|
||||||
|
public IActionResult SendReadyToClients(string uid, Guid requestId)
|
||||||
|
{
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await _hubContext.Clients.User(uid).Client_DownloadReady(requestId);
|
||||||
|
});
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,638 @@
|
|||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Dto.CharaData;
|
||||||
|
using MareSynchronosServer.Utils;
|
||||||
|
using MareSynchronosShared.Models;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
public partial class MareHub
|
||||||
|
{
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<CharaDataFullDto?> CharaDataCreate()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
|
||||||
|
int uploadCount = DbContext.CharaData.Count(c => c.UploaderUID == UserUID);
|
||||||
|
User user = DbContext.Users.Single(u => u.UID == UserUID);
|
||||||
|
int maximumUploads = _maxCharaDataByUser;
|
||||||
|
if (uploadCount >= maximumUploads)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string charaDataId = null;
|
||||||
|
while (charaDataId == null)
|
||||||
|
{
|
||||||
|
charaDataId = StringUtils.GenerateRandomString(10, "abcdefghijklmnopqrstuvwxyzABCDEFHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
bool idExists = await DbContext.CharaData.AnyAsync(c => c.UploaderUID == UserUID && c.Id == charaDataId).ConfigureAwait(false);
|
||||||
|
if (idExists)
|
||||||
|
{
|
||||||
|
charaDataId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime createdDate = DateTime.UtcNow;
|
||||||
|
CharaData charaData = new()
|
||||||
|
{
|
||||||
|
Id = charaDataId,
|
||||||
|
UploaderUID = UserUID,
|
||||||
|
CreatedDate = createdDate,
|
||||||
|
UpdatedDate = createdDate,
|
||||||
|
AccessType = CharaDataAccess.Individuals,
|
||||||
|
ShareType = CharaDataShare.Private,
|
||||||
|
CustomizeData = string.Empty,
|
||||||
|
GlamourerData = string.Empty,
|
||||||
|
ExpiryDate = DateTime.MaxValue,
|
||||||
|
Description = string.Empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
await DbContext.CharaData.AddAsync(charaData).ConfigureAwait(false);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args("SUCCESS", charaDataId));
|
||||||
|
|
||||||
|
return GetCharaDataFullDto(charaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<bool> CharaDataDelete(string id)
|
||||||
|
{
|
||||||
|
var existingData = await DbContext.CharaData.SingleOrDefaultAsync(u => u.Id == id && u.UploaderUID == UserUID).ConfigureAwait(false);
|
||||||
|
if (existingData == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args("SUCCESS", id));
|
||||||
|
|
||||||
|
DbContext.Remove(existingData);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogCallWarning(MareHubLogger.Args("FAILURE", id, ex.Message));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<CharaDataDownloadDto?> CharaDataDownload(string id)
|
||||||
|
{
|
||||||
|
CharaData charaData = await GetCharaDataById(id, nameof(CharaDataDownload)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!string.Equals(charaData.UploaderUID, UserUID, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
charaData.DownloadCount++;
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args("SUCCESS", id));
|
||||||
|
|
||||||
|
return GetCharaDataDownloadDto(charaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<CharaDataMetaInfoDto?> CharaDataGetMetainfo(string id)
|
||||||
|
{
|
||||||
|
var charaData = await GetCharaDataById(id, nameof(CharaDataGetMetainfo)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args("SUCCESS", id));
|
||||||
|
|
||||||
|
return GetCharaDataMetaInfoDto(charaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<CharaDataFullDto>> CharaDataGetOwn()
|
||||||
|
{
|
||||||
|
var ownCharaData = await DbContext.CharaData
|
||||||
|
.Include(u => u.Files)
|
||||||
|
.Include(u => u.FileSwaps)
|
||||||
|
.Include(u => u.OriginalFiles)
|
||||||
|
.Include(u => u.AllowedIndividiuals)
|
||||||
|
.ThenInclude(u => u.AllowedUser)
|
||||||
|
.Include(u => u.AllowedIndividiuals)
|
||||||
|
.ThenInclude(u => u.AllowedGroup)
|
||||||
|
.Include(u => u.Poses)
|
||||||
|
.AsSplitQuery()
|
||||||
|
.Where(c => c.UploaderUID == UserUID).ToListAsync().ConfigureAwait(false);
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args("SUCCESS"));
|
||||||
|
return [.. ownCharaData.Select(GetCharaDataFullDto)];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<CharaDataFullDto?> CharaDataAttemptRestore(string id)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(id));
|
||||||
|
var charaData = await DbContext.CharaData
|
||||||
|
.Include(u => u.Files)
|
||||||
|
.Include(u => u.FileSwaps)
|
||||||
|
.Include(u => u.OriginalFiles)
|
||||||
|
.Include(u => u.AllowedIndividiuals)
|
||||||
|
.ThenInclude(u => u.AllowedUser)
|
||||||
|
.Include(u => u.AllowedIndividiuals)
|
||||||
|
.ThenInclude(u => u.AllowedGroup)
|
||||||
|
.Include(u => u.Poses)
|
||||||
|
.AsSplitQuery()
|
||||||
|
.SingleOrDefaultAsync(s => s.Id == id && s.UploaderUID == UserUID)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
if (charaData == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var currentHashes = charaData.Files.Select(f => f.FileCacheHash).ToList();
|
||||||
|
var missingFiles = charaData.OriginalFiles.Where(c => !currentHashes.Contains(c.Hash, StringComparer.Ordinal)).ToList();
|
||||||
|
|
||||||
|
// now let's see what's on the db still
|
||||||
|
var existingDbFiles = await DbContext.Files
|
||||||
|
.Where(f => missingFiles.Select(k => k.Hash).Distinct().Contains(f.Hash))
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
// now shove it all back into the db
|
||||||
|
foreach (var dbFile in existingDbFiles)
|
||||||
|
{
|
||||||
|
var missingFileEntry = missingFiles.First(f => string.Equals(f.Hash, dbFile.Hash, StringComparison.Ordinal));
|
||||||
|
charaData.Files.Add(new CharaDataFile()
|
||||||
|
{
|
||||||
|
FileCache = dbFile,
|
||||||
|
GamePath = missingFileEntry.GamePath,
|
||||||
|
Parent = charaData
|
||||||
|
});
|
||||||
|
missingFiles.Remove(missingFileEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingDbFiles.Any())
|
||||||
|
{
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetCharaDataFullDto(charaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<CharaDataMetaInfoDto>> CharaDataGetShared()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
|
||||||
|
List<CharaData> sharedCharaData = [];
|
||||||
|
var groups = await DbContext.GroupPairs
|
||||||
|
.Where(u => u.GroupUserUID == UserUID)
|
||||||
|
.Select(k => k.GroupGID)
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var individualPairs = await GetDirectPairedUnpausedUsers().ConfigureAwait(false);
|
||||||
|
var allPairs = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var allSharedDataByPair = await DbContext.CharaData
|
||||||
|
.Include(u => u.Files)
|
||||||
|
.Include(u => u.OriginalFiles)
|
||||||
|
.Include(u => u.AllowedIndividiuals)
|
||||||
|
.Include(u => u.Poses)
|
||||||
|
.Include(u => u.Uploader)
|
||||||
|
.Where(p => p.UploaderUID != UserUID && p.ShareType == CharaDataShare.Shared)
|
||||||
|
.Where(p =>
|
||||||
|
(individualPairs.Contains(p.UploaderUID) && p.AccessType == CharaDataAccess.ClosePairs)
|
||||||
|
|| (allPairs.Contains(p.UploaderUID) && p.AccessType == CharaDataAccess.AllPairs)
|
||||||
|
|| (p.AllowedIndividiuals.Any(u => u.AllowedUserUID == UserUID || (u.AllowedGroupGID != null && groups.Contains(u.AllowedGroupGID)))))
|
||||||
|
.AsSplitQuery()
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var charaData in allSharedDataByPair)
|
||||||
|
{
|
||||||
|
sharedCharaData.Add(charaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args("SUCCESS", sharedCharaData.Count));
|
||||||
|
|
||||||
|
return [.. sharedCharaData.Select(GetCharaDataMetaInfoDto)];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<CharaDataFullDto?> CharaDataUpdate(CharaDataUpdateDto updateDto)
|
||||||
|
{
|
||||||
|
var charaData = await DbContext.CharaData
|
||||||
|
.Include(u => u.Files)
|
||||||
|
.Include(u => u.OriginalFiles)
|
||||||
|
.Include(u => u.AllowedIndividiuals)
|
||||||
|
.ThenInclude(u => u.AllowedUser)
|
||||||
|
.Include(u => u.AllowedIndividiuals)
|
||||||
|
.ThenInclude(u => u.AllowedGroup)
|
||||||
|
.Include(u => u.FileSwaps)
|
||||||
|
.Include(u => u.Poses)
|
||||||
|
.AsSplitQuery()
|
||||||
|
.SingleOrDefaultAsync(u => u.Id == updateDto.Id && u.UploaderUID == UserUID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (charaData == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
bool anyChanges = false;
|
||||||
|
|
||||||
|
if (updateDto.Description != null)
|
||||||
|
{
|
||||||
|
charaData.Description = updateDto.Description;
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.ExpiryDate != null)
|
||||||
|
{
|
||||||
|
charaData.ExpiryDate = updateDto.ExpiryDate;
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.GlamourerData != null)
|
||||||
|
{
|
||||||
|
charaData.GlamourerData = updateDto.GlamourerData;
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.CustomizeData != null)
|
||||||
|
{
|
||||||
|
charaData.CustomizeData = updateDto.CustomizeData;
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.ManipulationData != null)
|
||||||
|
{
|
||||||
|
charaData.ManipulationData = updateDto.ManipulationData;
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.AccessType != null)
|
||||||
|
{
|
||||||
|
charaData.AccessType = GetAccessType(updateDto.AccessType.Value);
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.ShareType != null)
|
||||||
|
{
|
||||||
|
charaData.ShareType = GetShareType(updateDto.ShareType.Value);
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.AllowedUsers != null)
|
||||||
|
{
|
||||||
|
var individuals = charaData.AllowedIndividiuals.Where(k => k.AllowedGroup == null).ToList();
|
||||||
|
var allowedUserList = updateDto.AllowedUsers.ToList();
|
||||||
|
foreach (var user in updateDto.AllowedUsers)
|
||||||
|
{
|
||||||
|
if (charaData.AllowedIndividiuals.Any(k => k.AllowedUser != null && (string.Equals(k.AllowedUser.UID, user, StringComparison.Ordinal) || string.Equals(k.AllowedUser.Alias, user, StringComparison.Ordinal))))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var dbUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == user || u.Alias == user).ConfigureAwait(false);
|
||||||
|
if (dbUser != null)
|
||||||
|
{
|
||||||
|
charaData.AllowedIndividiuals.Add(new CharaDataAllowance()
|
||||||
|
{
|
||||||
|
AllowedUser = dbUser,
|
||||||
|
Parent = charaData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var dataUser in individuals.Where(k => !updateDto.AllowedUsers.Contains(k.AllowedUser.UID, StringComparer.Ordinal) && !updateDto.AllowedUsers.Contains(k.AllowedUser.Alias, StringComparer.Ordinal)))
|
||||||
|
{
|
||||||
|
DbContext.Remove(dataUser);
|
||||||
|
charaData.AllowedIndividiuals.Remove(dataUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.AllowedGroups != null)
|
||||||
|
{
|
||||||
|
var individualGroups = charaData.AllowedIndividiuals.Where(k => k.AllowedUser == null).ToList();
|
||||||
|
var allowedGroups = updateDto.AllowedGroups.ToList();
|
||||||
|
foreach (var group in updateDto.AllowedGroups)
|
||||||
|
{
|
||||||
|
if (charaData.AllowedIndividiuals.Any(k => k.AllowedGroup != null && (string.Equals(k.AllowedGroup.GID, group, StringComparison.Ordinal) || string.Equals(k.AllowedGroup.Alias, group, StringComparison.Ordinal))))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var groupUser = await DbContext.GroupPairs.Include(u => u.Group).SingleOrDefaultAsync(u => (u.Group.GID == group || u.Group.Alias == group) && u.GroupUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
if (groupUser != null)
|
||||||
|
{
|
||||||
|
charaData.AllowedIndividiuals.Add(new CharaDataAllowance()
|
||||||
|
{
|
||||||
|
AllowedGroup = groupUser.Group,
|
||||||
|
Parent = charaData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var dataGroup in individualGroups.Where(k => !updateDto.AllowedGroups.Contains(k.AllowedGroup.GID, StringComparer.Ordinal) && !updateDto.AllowedGroups.Contains(k.AllowedGroup.Alias, StringComparer.Ordinal)))
|
||||||
|
{
|
||||||
|
DbContext.Remove(dataGroup);
|
||||||
|
charaData.AllowedIndividiuals.Remove(dataGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.FileGamePaths != null)
|
||||||
|
{
|
||||||
|
var originalFiles = charaData.OriginalFiles.ToList();
|
||||||
|
charaData.OriginalFiles.Clear();
|
||||||
|
DbContext.RemoveRange(originalFiles);
|
||||||
|
var files = charaData.Files.ToList();
|
||||||
|
charaData.Files.Clear();
|
||||||
|
DbContext.RemoveRange(files);
|
||||||
|
foreach (var file in updateDto.FileGamePaths)
|
||||||
|
{
|
||||||
|
charaData.Files.Add(new CharaDataFile()
|
||||||
|
{
|
||||||
|
FileCacheHash = file.HashOrFileSwap,
|
||||||
|
GamePath = file.GamePath,
|
||||||
|
Parent = charaData
|
||||||
|
});
|
||||||
|
|
||||||
|
charaData.OriginalFiles.Add(new CharaDataOriginalFile()
|
||||||
|
{
|
||||||
|
Hash = file.HashOrFileSwap,
|
||||||
|
Parent = charaData,
|
||||||
|
GamePath = file.GamePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.FileSwaps != null)
|
||||||
|
{
|
||||||
|
var fileSwaps = charaData.FileSwaps.ToList();
|
||||||
|
charaData.FileSwaps.Clear();
|
||||||
|
DbContext.RemoveRange(fileSwaps);
|
||||||
|
foreach (var file in updateDto.FileSwaps)
|
||||||
|
{
|
||||||
|
charaData.FileSwaps.Add(new CharaDataFileSwap()
|
||||||
|
{
|
||||||
|
FilePath = file.HashOrFileSwap,
|
||||||
|
GamePath = file.GamePath,
|
||||||
|
Parent = charaData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDto.Poses != null)
|
||||||
|
{
|
||||||
|
foreach (var pose in updateDto.Poses)
|
||||||
|
{
|
||||||
|
if (pose.Id == null)
|
||||||
|
{
|
||||||
|
charaData.Poses.Add(new CharaDataPose()
|
||||||
|
{
|
||||||
|
Description = pose.Description,
|
||||||
|
Parent = charaData,
|
||||||
|
ParentUploaderUID = UserUID,
|
||||||
|
PoseData = pose.PoseData,
|
||||||
|
WorldData = pose.WorldData == null ? string.Empty : JsonSerializer.Serialize(pose.WorldData),
|
||||||
|
});
|
||||||
|
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var associatedPose = charaData.Poses.FirstOrDefault(p => p.Id == pose.Id);
|
||||||
|
if (associatedPose == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pose.Description == null && pose.PoseData == null && pose.WorldData == null)
|
||||||
|
{
|
||||||
|
charaData.Poses.Remove(associatedPose);
|
||||||
|
DbContext.Remove(associatedPose);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pose.Description != null)
|
||||||
|
associatedPose.Description = pose.Description;
|
||||||
|
if (pose.WorldData != null)
|
||||||
|
{
|
||||||
|
if (pose.WorldData.Value == default) associatedPose.WorldData = string.Empty;
|
||||||
|
else associatedPose.WorldData = JsonSerializer.Serialize(pose.WorldData.Value);
|
||||||
|
}
|
||||||
|
if (pose.PoseData != null)
|
||||||
|
associatedPose.PoseData = pose.PoseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var overflowingPoses = charaData.Poses.Skip(10).ToList();
|
||||||
|
foreach (var overflowing in overflowingPoses)
|
||||||
|
{
|
||||||
|
charaData.Poses.Remove(overflowing);
|
||||||
|
DbContext.Remove(overflowing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyChanges)
|
||||||
|
{
|
||||||
|
charaData.UpdatedDate = DateTime.UtcNow;
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args("SUCCESS", anyChanges));
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetCharaDataFullDto(charaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CharaDataAccess GetAccessType(AccessTypeDto dataAccess) => dataAccess switch
|
||||||
|
{
|
||||||
|
AccessTypeDto.Public => CharaDataAccess.Public,
|
||||||
|
AccessTypeDto.AllPairs => CharaDataAccess.AllPairs,
|
||||||
|
AccessTypeDto.ClosePairs => CharaDataAccess.ClosePairs,
|
||||||
|
AccessTypeDto.Individuals => CharaDataAccess.Individuals,
|
||||||
|
_ => throw new NotSupportedException(),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static AccessTypeDto GetAccessTypeDto(CharaDataAccess dataAccess) => dataAccess switch
|
||||||
|
{
|
||||||
|
CharaDataAccess.Public => AccessTypeDto.Public,
|
||||||
|
CharaDataAccess.AllPairs => AccessTypeDto.AllPairs,
|
||||||
|
CharaDataAccess.ClosePairs => AccessTypeDto.ClosePairs,
|
||||||
|
CharaDataAccess.Individuals => AccessTypeDto.Individuals,
|
||||||
|
_ => throw new NotSupportedException(),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static CharaDataDownloadDto GetCharaDataDownloadDto(CharaData charaData)
|
||||||
|
{
|
||||||
|
return new CharaDataDownloadDto(charaData.Id, charaData.Uploader.ToUserData())
|
||||||
|
{
|
||||||
|
CustomizeData = charaData.CustomizeData,
|
||||||
|
Description = charaData.Description,
|
||||||
|
FileGamePaths = charaData.Files.Select(k => new GamePathEntry(k.FileCacheHash, k.GamePath)).ToList(),
|
||||||
|
GlamourerData = charaData.GlamourerData,
|
||||||
|
FileSwaps = charaData.FileSwaps.Select(k => new GamePathEntry(k.FilePath, k.GamePath)).ToList(),
|
||||||
|
ManipulationData = charaData.ManipulationData,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private CharaDataFullDto GetCharaDataFullDto(CharaData charaData)
|
||||||
|
{
|
||||||
|
return new CharaDataFullDto(charaData.Id, new(UserUID))
|
||||||
|
{
|
||||||
|
AccessType = GetAccessTypeDto(charaData.AccessType),
|
||||||
|
ShareType = GetShareTypeDto(charaData.ShareType),
|
||||||
|
AllowedUsers = [.. charaData.AllowedIndividiuals.Where(k => !string.IsNullOrEmpty(k.AllowedUserUID)).Select(u => new UserData(u.AllowedUser.UID, u.AllowedUser.Alias))],
|
||||||
|
AllowedGroups = [.. charaData.AllowedIndividiuals.Where(k => !string.IsNullOrEmpty(k.AllowedGroupGID)).Select(k => new GroupData(k.AllowedGroup.GID, k.AllowedGroup.Alias))],
|
||||||
|
CustomizeData = charaData.CustomizeData,
|
||||||
|
Description = charaData.Description,
|
||||||
|
ExpiryDate = charaData.ExpiryDate ?? DateTime.MaxValue,
|
||||||
|
OriginalFiles = charaData.OriginalFiles.Select(k => new GamePathEntry(k.Hash, k.GamePath)).ToList(),
|
||||||
|
FileGamePaths = charaData.Files.Select(k => new GamePathEntry(k.FileCacheHash, k.GamePath)).ToList(),
|
||||||
|
FileSwaps = charaData.FileSwaps.Select(k => new GamePathEntry(k.FilePath, k.GamePath)).ToList(),
|
||||||
|
GlamourerData = charaData.GlamourerData,
|
||||||
|
CreatedDate = charaData.CreatedDate,
|
||||||
|
UpdatedDate = charaData.UpdatedDate,
|
||||||
|
ManipulationData = charaData.ManipulationData,
|
||||||
|
DownloadCount = charaData.DownloadCount,
|
||||||
|
PoseData = [.. charaData.Poses.OrderBy(p => p.Id).Select(k =>
|
||||||
|
{
|
||||||
|
WorldData data = default;
|
||||||
|
|
||||||
|
if(!string.IsNullOrEmpty(k.WorldData)) data = JsonSerializer.Deserialize<WorldData>(k.WorldData);
|
||||||
|
return new PoseEntry(k.Id)
|
||||||
|
{
|
||||||
|
Description = k.Description,
|
||||||
|
PoseData = k.PoseData,
|
||||||
|
WorldData = data
|
||||||
|
};
|
||||||
|
})],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CharaDataMetaInfoDto GetCharaDataMetaInfoDto(CharaData charaData)
|
||||||
|
{
|
||||||
|
var allOrigHashes = charaData.OriginalFiles.Select(k => k.Hash).ToList();
|
||||||
|
var allFileHashes = charaData.Files.Select(f => f.FileCacheHash).ToList();
|
||||||
|
var allHashesPresent = allOrigHashes.TrueForAll(h => allFileHashes.Contains(h, StringComparer.Ordinal));
|
||||||
|
var canBeDownloaded = allHashesPresent &= !string.IsNullOrEmpty(charaData.GlamourerData);
|
||||||
|
return new CharaDataMetaInfoDto(charaData.Id, charaData.Uploader.ToUserData())
|
||||||
|
{
|
||||||
|
CanBeDownloaded = canBeDownloaded,
|
||||||
|
Description = charaData.Description,
|
||||||
|
UpdatedDate = charaData.UpdatedDate,
|
||||||
|
PoseData = [.. charaData.Poses.OrderBy(p => p.Id).Select(k =>
|
||||||
|
{
|
||||||
|
WorldData data = default;
|
||||||
|
if(!string.IsNullOrEmpty(k.WorldData)) data = JsonSerializer.Deserialize<WorldData>(k.WorldData);
|
||||||
|
return new PoseEntry(k.Id)
|
||||||
|
{
|
||||||
|
Description = k.Description,
|
||||||
|
PoseData = k.PoseData,
|
||||||
|
WorldData = data
|
||||||
|
};
|
||||||
|
})],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CharaDataShare GetShareType(ShareTypeDto dataShare) => dataShare switch
|
||||||
|
{
|
||||||
|
ShareTypeDto.Shared => CharaDataShare.Shared,
|
||||||
|
ShareTypeDto.Private => CharaDataShare.Private,
|
||||||
|
_ => throw new NotSupportedException(),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static ShareTypeDto GetShareTypeDto(CharaDataShare dataShare) => dataShare switch
|
||||||
|
{
|
||||||
|
CharaDataShare.Shared => ShareTypeDto.Shared,
|
||||||
|
CharaDataShare.Private => ShareTypeDto.Private,
|
||||||
|
_ => throw new NotSupportedException(),
|
||||||
|
};
|
||||||
|
|
||||||
|
private async Task<bool> CheckCharaDataAllowance(CharaData charaData, List<string> joinedGroups)
|
||||||
|
{
|
||||||
|
// check for self
|
||||||
|
if (string.Equals(charaData.UploaderUID, UserUID, StringComparison.Ordinal))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// check for public access
|
||||||
|
if (charaData.AccessType == CharaDataAccess.Public)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// check for individuals
|
||||||
|
if (charaData.AllowedIndividiuals.Any(u => string.Equals(u.AllowedUserUID, UserUID, StringComparison.Ordinal)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var pairInfoUploader = await GetAllPairedUnpausedUsers(charaData.UploaderUID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// check for all pairs
|
||||||
|
if (charaData.AccessType == CharaDataAccess.AllPairs)
|
||||||
|
{
|
||||||
|
if (pairInfoUploader.Any(pair => string.Equals(pair, UserUID, StringComparison.Ordinal)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for individual pairs
|
||||||
|
if (charaData.AccessType == CharaDataAccess.ClosePairs)
|
||||||
|
{
|
||||||
|
if (pairInfoUploader.Any(pair => string.Equals(pair, UserUID, StringComparison.Ordinal)))
|
||||||
|
{
|
||||||
|
ClientPair callerPair =
|
||||||
|
await DbContext.ClientPairs.AsNoTracking().SingleOrDefaultAsync(w => w.UserUID == UserUID && w.OtherUserUID == charaData.UploaderUID).ConfigureAwait(false);
|
||||||
|
ClientPair uploaderPair =
|
||||||
|
await DbContext.ClientPairs.AsNoTracking().SingleOrDefaultAsync(w => w.UserUID == charaData.UploaderUID && w.OtherUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
return (callerPair != null && uploaderPair != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<CharaData> GetCharaDataById(string id, string methodName)
|
||||||
|
{
|
||||||
|
var splitid = id.Split(":", StringSplitOptions.None);
|
||||||
|
if (splitid.Length != 2)
|
||||||
|
{
|
||||||
|
_logger.LogCallWarning(MareHubLogger.Args("INVALID", id));
|
||||||
|
throw new InvalidOperationException($"Id {id} not in expected format");
|
||||||
|
}
|
||||||
|
|
||||||
|
var charaData = await DbContext.CharaData
|
||||||
|
.Include(u => u.Files)
|
||||||
|
.Include(u => u.FileSwaps)
|
||||||
|
.Include(u => u.AllowedIndividiuals)
|
||||||
|
.Include(u => u.Poses)
|
||||||
|
.Include(u => u.Uploader)
|
||||||
|
.AsSplitQuery()
|
||||||
|
.SingleOrDefaultAsync(c => c.Id == splitid[1] && c.UploaderUID == splitid[0]).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (charaData == null)
|
||||||
|
{
|
||||||
|
_logger.LogCallWarning(MareHubLogger.Args("NOT FOUND", id));
|
||||||
|
throw new InvalidDataException($"No chara data with {id} found");
|
||||||
|
}
|
||||||
|
|
||||||
|
var groups = await DbContext.GroupPairs.Where(u => u.GroupUserUID == UserUID).Select(k => k.GroupGID).ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!await CheckCharaDataAllowance(charaData, groups).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
_logger.LogCallWarning(MareHubLogger.Args("UNAUTHORIZED", id));
|
||||||
|
throw new UnauthorizedAccessException($"User is not allowed to download {id}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return charaData;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Data.Enum;
|
||||||
|
using MareSynchronos.API.Dto.Group;
|
||||||
|
using MareSynchronos.API.Dto.User;
|
||||||
|
using MareSynchronosServer.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
public partial class MareHub
|
||||||
|
{
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public Task UserChatSendMsg(UserDto dto, ChatMessage message)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
// TODO
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupChatSendMsg(GroupDto dto, ChatMessage message)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (userExists, groupPair) = await TryValidateUserInGroup(dto.GID, UserUID).ConfigureAwait(false);
|
||||||
|
if (!userExists) return;
|
||||||
|
|
||||||
|
var group = await DbContext.Groups.AsNoTracking().SingleAsync(g => g.GID == dto.GID).ConfigureAwait(false);
|
||||||
|
var sender = await DbContext.Users.AsNoTracking().SingleAsync(u => u.UID == UserUID).ConfigureAwait(false);
|
||||||
|
var groupPairs = await DbContext.GroupPairs.AsNoTracking().Include(p => p.GroupUser).Where(p => p.GroupGID == dto.Group.GID).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (group == null || sender == null) return;
|
||||||
|
|
||||||
|
// TODO: Add and check chat permissions
|
||||||
|
if (group.Alias?.Equals("Loporrit", StringComparison.Ordinal) ?? false)
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Warning, $"Chat is disabled for syncshell '{dto.GroupAliasOrGID}'.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOOO: Sign the message
|
||||||
|
var signedMessage = new SignedChatMessage(message, sender.ToUserData())
|
||||||
|
{
|
||||||
|
Timestamp = 0,
|
||||||
|
Signature = "",
|
||||||
|
};
|
||||||
|
|
||||||
|
await Clients.Users(groupPairs.Select(p => p.GroupUserUID)).Client_GroupChatMsg(new(new(group.ToGroupData()), signedMessage)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Data.Enum;
|
||||||
|
using MareSynchronos.API.Dto;
|
||||||
|
using MareSynchronos.API.Dto.CharaData;
|
||||||
|
using MareSynchronos.API.Dto.Chat;
|
||||||
|
using MareSynchronos.API.Dto.Group;
|
||||||
|
using MareSynchronos.API.Dto.User;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs
|
||||||
|
{
|
||||||
|
public partial class MareHub
|
||||||
|
{
|
||||||
|
public Task Client_DownloadReady(Guid requestId) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupChangePermissions(GroupPermissionDto groupPermission) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupChatMsg(GroupChatMsgDto groupChatMsgDto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupDelete(GroupDto groupDto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupPairChangePermissions(GroupPairUserPermissionDto permissionDto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupPairChangeUserInfo(GroupPairUserInfoDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupPairJoined(GroupPairFullInfoDto groupPairInfoDto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupPairLeft(GroupPairDto groupPairDto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupSendFullInfo(GroupFullInfoDto groupInfo) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GroupSendInfo(GroupInfoDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_ReceiveServerMessage(MessageSeverity messageSeverity, string message) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UpdateSystemInfo(SystemInfoDto systemInfo) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserAddClientPair(UserPairDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserChatMsg(UserChatMsgDto userChatMsgDto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserReceiveCharacterData(OnlineUserCharaDataDto dataDto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserReceiveUploadStatus(UserDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserRemoveClientPair(UserDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserSendOffline(UserDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserSendOnline(OnlineUserIdentDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserUpdateOtherPairPermissions(UserPermissionsDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserUpdateProfile(UserDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_UserUpdateSelfPairPermissions(UserPermissionsDto dto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
|
||||||
|
public Task Client_GposeLobbyJoin(UserData userData) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
public Task Client_GposeLobbyLeave(UserData userData) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
public Task Client_GposeLobbyPushCharacterData(CharaDataDownloadDto charaDownloadDto) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
public Task Client_GposeLobbyPushPoseData(UserData userData, PoseData poseData) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
public Task Client_GposeLobbyPushWorldData(UserData userData, WorldData worldData) => throw new PlatformNotSupportedException("Calling clientside method on server not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,295 @@
|
|||||||
|
using MareSynchronosShared.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using MareSynchronosServer.Utils;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Dto.Group;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
public partial class MareHub
|
||||||
|
{
|
||||||
|
public string UserCharaIdent => Context.User?.Claims?.SingleOrDefault(c => string.Equals(c.Type, MareClaimTypes.CharaIdent, StringComparison.Ordinal))?.Value ?? throw new Exception("No Chara Ident in Claims");
|
||||||
|
|
||||||
|
public string UserUID => Context.User?.Claims?.SingleOrDefault(c => string.Equals(c.Type, MareClaimTypes.Uid, StringComparison.Ordinal))?.Value ?? throw new Exception("No UID in Claims");
|
||||||
|
|
||||||
|
public string Continent => Context.User?.Claims?.SingleOrDefault(c => string.Equals(c.Type, MareClaimTypes.Continent, StringComparison.Ordinal))?.Value ?? "UNK";
|
||||||
|
|
||||||
|
private async Task DeleteUser(User user)
|
||||||
|
{
|
||||||
|
var ownPairData = await DbContext.ClientPairs.Where(u => u.User.UID == user.UID).ToListAsync().ConfigureAwait(false);
|
||||||
|
var auth = await DbContext.Auth.SingleAsync(u => u.UserUID == user.UID).ConfigureAwait(false);
|
||||||
|
var lodestone = await DbContext.LodeStoneAuth.SingleOrDefaultAsync(a => a.User.UID == user.UID).ConfigureAwait(false);
|
||||||
|
var groupPairs = await DbContext.GroupPairs.Where(g => g.GroupUserUID == user.UID).ToListAsync().ConfigureAwait(false);
|
||||||
|
var userProfileData = await DbContext.UserProfileData.SingleOrDefaultAsync(u => u.UserUID == user.UID).ConfigureAwait(false);
|
||||||
|
var bannedEntries = await DbContext.GroupBans.Where(u => u.BannedUserUID == user.UID).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (lodestone != null)
|
||||||
|
{
|
||||||
|
DbContext.Remove(lodestone);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userProfileData != null)
|
||||||
|
{
|
||||||
|
DbContext.Remove(userProfileData);
|
||||||
|
}
|
||||||
|
|
||||||
|
DbContext.ClientPairs.RemoveRange(ownPairData);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
var otherPairData = await DbContext.ClientPairs.Include(u => u.User)
|
||||||
|
.Where(u => u.OtherUser.UID == user.UID).AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
foreach (var pair in otherPairData)
|
||||||
|
{
|
||||||
|
await Clients.User(pair.UserUID).Client_UserRemoveClientPair(new(user.ToUserData())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var pair in groupPairs)
|
||||||
|
{
|
||||||
|
await UserLeaveGroup(new GroupDto(new GroupData(pair.GroupGID)), user.UID).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mareMetrics.IncCounter(MetricsAPI.CounterUsersRegisteredDeleted, 1);
|
||||||
|
|
||||||
|
DbContext.GroupBans.RemoveRange(bannedEntries);
|
||||||
|
DbContext.ClientPairs.RemoveRange(otherPairData);
|
||||||
|
DbContext.Users.Remove(user);
|
||||||
|
DbContext.Auth.Remove(auth);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<PausedEntry>> GetAllPairedClientsWithPauseState(string? uid = null)
|
||||||
|
{
|
||||||
|
uid ??= UserUID;
|
||||||
|
|
||||||
|
var query = await (from userPair in DbContext.ClientPairs
|
||||||
|
join otherUserPair in DbContext.ClientPairs on userPair.OtherUserUID equals otherUserPair.UserUID
|
||||||
|
where otherUserPair.OtherUserUID == uid && userPair.UserUID == uid
|
||||||
|
select new
|
||||||
|
{
|
||||||
|
UID = Convert.ToString(userPair.OtherUserUID),
|
||||||
|
GID = "DIRECT",
|
||||||
|
PauseStateSelf = userPair.IsPaused,
|
||||||
|
PauseStateOther = otherUserPair.IsPaused,
|
||||||
|
})
|
||||||
|
.Union(
|
||||||
|
(from userGroupPair in DbContext.GroupPairs
|
||||||
|
join otherGroupPair in DbContext.GroupPairs on userGroupPair.GroupGID equals otherGroupPair.GroupGID
|
||||||
|
where
|
||||||
|
userGroupPair.GroupUserUID == uid
|
||||||
|
&& otherGroupPair.GroupUserUID != uid
|
||||||
|
select new
|
||||||
|
{
|
||||||
|
UID = Convert.ToString(otherGroupPair.GroupUserUID),
|
||||||
|
GID = Convert.ToString(otherGroupPair.GroupGID),
|
||||||
|
PauseStateSelf = userGroupPair.IsPaused,
|
||||||
|
PauseStateOther = otherGroupPair.IsPaused,
|
||||||
|
})
|
||||||
|
).AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return query.GroupBy(g => g.UID, g => (g.GID, g.PauseStateSelf, g.PauseStateOther),
|
||||||
|
(key, g) => new PausedEntry
|
||||||
|
{
|
||||||
|
UID = key,
|
||||||
|
PauseStates = g.Select(p => new PauseState() { GID = string.Equals(p.GID, "DIRECT", StringComparison.Ordinal) ? null : p.GID, IsSelfPaused = p.PauseStateSelf, IsOtherPaused = p.PauseStateOther })
|
||||||
|
.ToList(),
|
||||||
|
}, StringComparer.Ordinal).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> GetAllPairedUnpausedUsers(string? uid = null)
|
||||||
|
{
|
||||||
|
uid ??= UserUID;
|
||||||
|
var ret = await GetAllPairedClientsWithPauseState(uid).ConfigureAwait(false);
|
||||||
|
return ret.Where(k => !k.IsPaused).Select(k => k.UID).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> GetDirectPairedUnpausedUsers(string? uid = null)
|
||||||
|
{
|
||||||
|
uid ??= UserUID;
|
||||||
|
|
||||||
|
var query = await (from userPair in DbContext.ClientPairs
|
||||||
|
join otherUserPair in DbContext.ClientPairs on userPair.OtherUserUID equals otherUserPair.UserUID
|
||||||
|
where otherUserPair.OtherUserUID == uid && userPair.UserUID == uid && !userPair.IsPaused && !otherUserPair.IsPaused
|
||||||
|
select Convert.ToString(userPair.OtherUserUID)).AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Dictionary<string, string>> GetOnlineUsers(List<string> uids)
|
||||||
|
{
|
||||||
|
var result = await _redis.GetAllAsync<string>(uids.Select(u => "UID:" + u).ToHashSet(StringComparer.Ordinal)).ConfigureAwait(false);
|
||||||
|
return uids.Where(u => result.TryGetValue("UID:" + u, out var ident) && !string.IsNullOrEmpty(ident)).ToDictionary(u => u, u => result["UID:" + u], StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetUserIdent(string uid)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(uid)) return string.Empty;
|
||||||
|
return await _redis.GetAsync<string>("UID:" + uid).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RemoveUserFromRedis()
|
||||||
|
{
|
||||||
|
await _redis.RemoveAsync("UID:" + UserUID, StackExchange.Redis.CommandFlags.FireAndForget).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SendGroupDeletedToAll(List<GroupPair> groupUsers)
|
||||||
|
{
|
||||||
|
foreach (var pair in groupUsers)
|
||||||
|
{
|
||||||
|
var pairIdent = await GetUserIdent(pair.GroupUserUID).ConfigureAwait(false);
|
||||||
|
if (string.IsNullOrEmpty(pairIdent)) continue;
|
||||||
|
|
||||||
|
var pairs = await GetAllPairedClientsWithPauseState(pair.GroupUserUID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var groupUserPair in groupUsers.Where(g => !string.Equals(g.GroupUserUID, pair.GroupUserUID, StringComparison.Ordinal)))
|
||||||
|
{
|
||||||
|
await UserGroupLeave(groupUserPair, pairs, pairIdent, pair.GroupUserUID).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> SendOfflineToAllPairedUsers()
|
||||||
|
{
|
||||||
|
var usersToSendDataTo = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
|
||||||
|
var self = await DbContext.Users.AsNoTracking().SingleAsync(u => u.UID == UserUID).ConfigureAwait(false);
|
||||||
|
await Clients.Users(usersToSendDataTo).Client_UserSendOffline(new(self.ToUserData())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return usersToSendDataTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> SendOnlineToAllPairedUsers()
|
||||||
|
{
|
||||||
|
var usersToSendDataTo = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
|
||||||
|
var self = await DbContext.Users.AsNoTracking().SingleAsync(u => u.UID == UserUID).ConfigureAwait(false);
|
||||||
|
await Clients.Users(usersToSendDataTo).Client_UserSendOnline(new(self.ToUserData(), UserCharaIdent)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return usersToSendDataTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(bool IsValid, Group ReferredGroup)> TryValidateGroupModeratorOrOwner(string gid)
|
||||||
|
{
|
||||||
|
var isOwnerResult = await TryValidateOwner(gid).ConfigureAwait(false);
|
||||||
|
if (isOwnerResult.isValid) return (true, isOwnerResult.ReferredGroup);
|
||||||
|
|
||||||
|
if (isOwnerResult.ReferredGroup == null) return (false, null);
|
||||||
|
|
||||||
|
var groupPairSelf = await DbContext.GroupPairs.SingleOrDefaultAsync(g => g.GroupGID == gid && g.GroupUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
if (groupPairSelf == null || !groupPairSelf.IsModerator) return (false, null);
|
||||||
|
|
||||||
|
return (true, isOwnerResult.ReferredGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(bool isValid, Group ReferredGroup)> TryValidateOwner(string gid)
|
||||||
|
{
|
||||||
|
var group = await DbContext.Groups.SingleOrDefaultAsync(g => g.GID == gid).ConfigureAwait(false);
|
||||||
|
if (group == null) return (false, null);
|
||||||
|
|
||||||
|
return (string.Equals(group.OwnerUID, UserUID, StringComparison.Ordinal), group);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(bool IsValid, GroupPair ReferredPair)> TryValidateUserInGroup(string gid, string? uid = null)
|
||||||
|
{
|
||||||
|
uid ??= UserUID;
|
||||||
|
|
||||||
|
var groupPair = await DbContext.GroupPairs.Include(c => c.GroupUser)
|
||||||
|
.SingleOrDefaultAsync(g => g.GroupGID == gid && (g.GroupUserUID == uid || g.GroupUser.Alias == uid)).ConfigureAwait(false);
|
||||||
|
if (groupPair == null) return (false, null);
|
||||||
|
|
||||||
|
return (true, groupPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateUserOnRedis()
|
||||||
|
{
|
||||||
|
await _redis.AddAsync("UID:" + UserUID, UserCharaIdent, TimeSpan.FromSeconds(60), StackExchange.Redis.When.Always, StackExchange.Redis.CommandFlags.FireAndForget).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UserGroupLeave(GroupPair groupUserPair, List<PausedEntry> allUserPairs, string userIdent, string? uid = null)
|
||||||
|
{
|
||||||
|
uid ??= UserUID;
|
||||||
|
var userPair = allUserPairs.SingleOrDefault(p => string.Equals(p.UID, groupUserPair.GroupUserUID, StringComparison.Ordinal));
|
||||||
|
if (userPair != null)
|
||||||
|
{
|
||||||
|
if (userPair.IsDirectlyPaused != PauseInfo.NoConnection) return;
|
||||||
|
if (userPair.IsPausedPerGroup is PauseInfo.Unpaused) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var groupUserIdent = await GetUserIdent(groupUserPair.GroupUserUID).ConfigureAwait(false);
|
||||||
|
if (!string.IsNullOrEmpty(groupUserIdent))
|
||||||
|
{
|
||||||
|
await Clients.User(uid).Client_UserSendOffline(new(new(groupUserPair.GroupUserUID))).ConfigureAwait(false);
|
||||||
|
await Clients.User(groupUserPair.GroupUserUID).Client_UserSendOffline(new(new(uid))).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UserLeaveGroup(GroupDto dto, string userUid)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (exists, groupPair) = await TryValidateUserInGroup(dto.Group.GID, userUid).ConfigureAwait(false);
|
||||||
|
if (!exists) return;
|
||||||
|
|
||||||
|
var group = await DbContext.Groups.SingleOrDefaultAsync(g => g.GID == dto.Group.GID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var groupPairs = await DbContext.GroupPairs.Where(p => p.GroupGID == group.GID).ToListAsync().ConfigureAwait(false);
|
||||||
|
var groupPairsWithoutSelf = groupPairs.Where(p => !string.Equals(p.GroupUserUID, userUid, StringComparison.Ordinal)).ToList();
|
||||||
|
|
||||||
|
DbContext.GroupPairs.Remove(groupPair);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.User(userUid).Client_GroupDelete(new GroupDto(group.ToGroupData())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
bool ownerHasLeft = string.Equals(group.OwnerUID, userUid, StringComparison.Ordinal);
|
||||||
|
if (ownerHasLeft)
|
||||||
|
{
|
||||||
|
if (!groupPairsWithoutSelf.Any())
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Deleted"));
|
||||||
|
|
||||||
|
DbContext.Groups.Remove(group);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var groupHasMigrated = await SharedDbFunctions.MigrateOrDeleteGroup(DbContext, group, groupPairsWithoutSelf, _maxExistingGroupsByUser).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (groupHasMigrated.Item1)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Migrated", groupHasMigrated.Item2));
|
||||||
|
|
||||||
|
var user = await DbContext.Users.SingleAsync(u => u.UID == groupHasMigrated.Item2).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.Users(groupPairsWithoutSelf.Select(p => p.GroupUserUID)).Client_GroupSendInfo(new GroupInfoDto(group.ToGroupData(),
|
||||||
|
user.ToUserData(), group.GetGroupPermissions())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Deleted"));
|
||||||
|
|
||||||
|
await Clients.Users(groupPairsWithoutSelf.Select(p => p.GroupUserUID)).Client_GroupDelete(dto).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await SendGroupDeletedToAll(groupPairs).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sharedData = await DbContext.CharaDataAllowances.Where(u => u.AllowedGroup != null && u.AllowedGroupGID == dto.GID && u.ParentUploaderUID == userUid).ToListAsync().ConfigureAwait(false);
|
||||||
|
DbContext.CharaDataAllowances.RemoveRange(sharedData);
|
||||||
|
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
await Clients.Users(groupPairsWithoutSelf.Select(p => p.GroupUserUID)).Client_GroupPairLeft(new GroupPairDto(dto.Group, groupPair.GroupUser.ToUserData())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var allUserPairs = await GetAllPairedClientsWithPauseState().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var ident = await GetUserIdent(userUid).ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var groupUserPair in groupPairsWithoutSelf)
|
||||||
|
{
|
||||||
|
await UserGroupLeave(groupUserPair, allUserPairs, ident, userUid).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Dto.CharaData;
|
||||||
|
using MareSynchronosServer.Utils;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
public partial class MareHub
|
||||||
|
{
|
||||||
|
private async Task<string?> GetUserGposeLobby()
|
||||||
|
{
|
||||||
|
return await _redis.GetAsync<string>(GposeLobbyUser).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> GetUsersInLobby(string lobbyId, bool includeSelf = false)
|
||||||
|
{
|
||||||
|
var users = await _redis.GetAsync<List<string>>($"GposeLobby:{lobbyId}").ConfigureAwait(false);
|
||||||
|
return users?.Where(u => includeSelf || !string.Equals(u, UserUID, StringComparison.Ordinal)).ToList() ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AddUserToLobby(string lobbyId, List<string> priorUsers)
|
||||||
|
{
|
||||||
|
_mareMetrics.IncGauge(MetricsAPI.GaugeGposeLobbyUsers);
|
||||||
|
if (priorUsers.Count == 0)
|
||||||
|
_mareMetrics.IncGauge(MetricsAPI.GaugeGposeLobbies);
|
||||||
|
|
||||||
|
await _redis.AddAsync(GposeLobbyUser, lobbyId).ConfigureAwait(false);
|
||||||
|
await _redis.AddAsync($"GposeLobby:{lobbyId}", priorUsers.Concat([UserUID])).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RemoveUserFromLobby(string lobbyId, List<string> priorUsers)
|
||||||
|
{
|
||||||
|
await _redis.RemoveAsync(GposeLobbyUser).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_mareMetrics.DecGauge(MetricsAPI.GaugeGposeLobbyUsers);
|
||||||
|
|
||||||
|
if (priorUsers.Count == 1)
|
||||||
|
{
|
||||||
|
await _redis.RemoveAsync($"GposeLobby:{lobbyId}").ConfigureAwait(false);
|
||||||
|
_mareMetrics.DecGauge(MetricsAPI.GaugeGposeLobbies);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priorUsers.Remove(UserUID);
|
||||||
|
await _redis.AddAsync($"GposeLobby:{lobbyId}", priorUsers).ConfigureAwait(false);
|
||||||
|
await Clients.Users(priorUsers).Client_GposeLobbyLeave(new(UserUID)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GposeLobbyUser => $"GposeLobbyUser:{UserUID}";
|
||||||
|
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<string> GposeLobbyCreate()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
var alreadyInLobby = await GetUserGposeLobby().ConfigureAwait(false);
|
||||||
|
if (!string.IsNullOrEmpty(alreadyInLobby))
|
||||||
|
{
|
||||||
|
throw new HubException("Already in GPose Lobby, cannot join another");
|
||||||
|
}
|
||||||
|
|
||||||
|
string lobbyId = string.Empty;
|
||||||
|
while (string.IsNullOrEmpty(lobbyId))
|
||||||
|
{
|
||||||
|
lobbyId = StringUtils.GenerateRandomString(30, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
||||||
|
var result = await _redis.GetAsync<List<string>>($"GposeLobby:{lobbyId}").ConfigureAwait(false);
|
||||||
|
if (result != null)
|
||||||
|
lobbyId = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
await AddUserToLobby(lobbyId, []).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return lobbyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<UserData>> GposeLobbyJoin(string lobbyId)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
var existingLobbyId = await GetUserGposeLobby().ConfigureAwait(false);
|
||||||
|
if (!string.IsNullOrEmpty(existingLobbyId))
|
||||||
|
await GposeLobbyLeave().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var lobbyUsers = await GetUsersInLobby(lobbyId).ConfigureAwait(false);
|
||||||
|
if (!lobbyUsers.Any())
|
||||||
|
return [];
|
||||||
|
|
||||||
|
await AddUserToLobby(lobbyId, lobbyUsers).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var user = await DbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false);
|
||||||
|
await Clients.Users(lobbyUsers.Where(u => !string.Equals(u, UserUID, StringComparison.Ordinal)))
|
||||||
|
.Client_GposeLobbyJoin(user.ToUserData()).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var users = await DbContext.Users.Where(u => lobbyUsers.Contains(u.UID))
|
||||||
|
.Select(u => u.ToUserData())
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<bool> GposeLobbyLeave()
|
||||||
|
{
|
||||||
|
var lobbyId = await GetUserGposeLobby().ConfigureAwait(false);
|
||||||
|
if (string.IsNullOrEmpty(lobbyId))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
|
||||||
|
var lobbyUsers = await GetUsersInLobby(lobbyId, true).ConfigureAwait(false);
|
||||||
|
await RemoveUserFromLobby(lobbyId, lobbyUsers).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GposeLobbyPushCharacterData(CharaDataDownloadDto charaDataDownloadDto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
var lobbyId = await GetUserGposeLobby().ConfigureAwait(false);
|
||||||
|
if (string.IsNullOrEmpty(lobbyId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var lobbyUsers = await GetUsersInLobby(lobbyId).ConfigureAwait(false);
|
||||||
|
await Clients.Users(lobbyUsers).Client_GposeLobbyPushCharacterData(charaDataDownloadDto).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GposeLobbyPushPoseData(PoseData poseData)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
var lobbyId = await GetUserGposeLobby().ConfigureAwait(false);
|
||||||
|
if (string.IsNullOrEmpty(lobbyId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await _gPoseLobbyDistributionService.PushPoseData(lobbyId, UserUID, poseData).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GposeLobbyPushWorldData(WorldData worldData)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
var lobbyId = await GetUserGposeLobby().ConfigureAwait(false);
|
||||||
|
if (string.IsNullOrEmpty(lobbyId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await _gPoseLobbyDistributionService.PushWorldData(lobbyId, UserUID, worldData).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
562
MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs
Normal file
562
MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs
Normal file
@@ -0,0 +1,562 @@
|
|||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Data.Enum;
|
||||||
|
using MareSynchronos.API.Data.Extensions;
|
||||||
|
using MareSynchronos.API.Dto.Chat;
|
||||||
|
using MareSynchronos.API.Dto.Group;
|
||||||
|
using MareSynchronosServer.Utils;
|
||||||
|
using MareSynchronosShared.Models;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
public partial class MareHub
|
||||||
|
{
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupBanUser(GroupPairDto dto, string reason)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, reason));
|
||||||
|
|
||||||
|
var (userHasRights, group) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!userHasRights) return;
|
||||||
|
|
||||||
|
var (userExists, groupPair) = await TryValidateUserInGroup(dto.Group.GID, dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (!userExists) return;
|
||||||
|
|
||||||
|
if (groupPair.IsModerator || string.Equals(group.OwnerUID, dto.User.UID, StringComparison.Ordinal)) return;
|
||||||
|
|
||||||
|
var alias = string.IsNullOrEmpty(groupPair.GroupUser.Alias) ? "-" : groupPair.GroupUser.Alias;
|
||||||
|
var ban = new GroupBan()
|
||||||
|
{
|
||||||
|
BannedByUID = UserUID,
|
||||||
|
BannedReason = $"{reason} (Alias at time of ban: {alias})",
|
||||||
|
BannedOn = DateTime.UtcNow,
|
||||||
|
BannedUserUID = dto.User.UID,
|
||||||
|
GroupGID = dto.Group.GID,
|
||||||
|
};
|
||||||
|
|
||||||
|
DbContext.Add(ban);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await GroupRemoveUser(dto).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupChangeGroupPermissionState(GroupPermissionDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (hasRights, group) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!hasRights) return;
|
||||||
|
|
||||||
|
group.InvitesEnabled = !dto.Permissions.HasFlag(GroupPermissions.DisableInvites);
|
||||||
|
group.DisableSounds = dto.Permissions.HasFlag(GroupPermissions.DisableSounds);
|
||||||
|
group.DisableAnimations = dto.Permissions.HasFlag(GroupPermissions.DisableAnimations);
|
||||||
|
group.DisableVFX = dto.Permissions.HasFlag(GroupPermissions.DisableVFX);
|
||||||
|
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var groupPairs = DbContext.GroupPairs.Where(p => p.GroupGID == dto.Group.GID).Select(p => p.GroupUserUID).ToList();
|
||||||
|
await Clients.Users(groupPairs).Client_GroupChangePermissions(new GroupPermissionDto(dto.Group, dto.Permissions)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupChangeIndividualPermissionState(GroupPairUserPermissionDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (inGroup, groupPair) = await TryValidateUserInGroup(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!inGroup) return;
|
||||||
|
|
||||||
|
var wasPaused = groupPair.IsPaused;
|
||||||
|
groupPair.DisableSounds = dto.GroupPairPermissions.IsDisableSounds();
|
||||||
|
groupPair.DisableAnimations = dto.GroupPairPermissions.IsDisableAnimations();
|
||||||
|
groupPair.IsPaused = dto.GroupPairPermissions.IsPaused();
|
||||||
|
groupPair.DisableVFX = dto.GroupPairPermissions.IsDisableVFX();
|
||||||
|
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var groupPairs = DbContext.GroupPairs.Include(p => p.GroupUser).Where(p => p.GroupGID == dto.Group.GID).ToList();
|
||||||
|
await Clients.Users(groupPairs.Select(p => p.GroupUserUID)).Client_GroupPairChangePermissions(dto).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var allUserPairs = await GetAllPairedClientsWithPauseState().ConfigureAwait(false);
|
||||||
|
var self = await DbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (wasPaused == groupPair.IsPaused) return;
|
||||||
|
|
||||||
|
foreach (var groupUserPair in groupPairs.Where(u => !string.Equals(u.GroupUserUID, UserUID, StringComparison.Ordinal)).ToList())
|
||||||
|
{
|
||||||
|
var userPair = allUserPairs.SingleOrDefault(p => string.Equals(p.UID, groupUserPair.GroupUserUID, StringComparison.Ordinal));
|
||||||
|
if (userPair != null)
|
||||||
|
{
|
||||||
|
if (userPair.IsDirectlyPaused != PauseInfo.NoConnection) continue;
|
||||||
|
if (userPair.IsPausedExcludingGroup(dto.Group.GID) is PauseInfo.Unpaused) continue;
|
||||||
|
if (userPair.IsOtherPausedForSpecificGroup(dto.Group.GID) is PauseInfo.Paused) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var groupUserIdent = await GetUserIdent(groupUserPair.GroupUserUID).ConfigureAwait(false);
|
||||||
|
if (!string.IsNullOrEmpty(groupUserIdent))
|
||||||
|
{
|
||||||
|
if (!groupPair.IsPaused)
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_UserSendOnline(new(groupUserPair.ToUserData(), groupUserIdent)).ConfigureAwait(false);
|
||||||
|
await Clients.User(groupUserPair.GroupUserUID)
|
||||||
|
.Client_UserSendOnline(new(self.ToUserData(), UserCharaIdent)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_UserSendOffline(new(groupUserPair.ToUserData())).ConfigureAwait(false);
|
||||||
|
await Clients.User(groupUserPair.GroupUserUID)
|
||||||
|
.Client_UserSendOffline(new(self.ToUserData())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupChangeOwnership(GroupPairDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (isOwner, group) = await TryValidateOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!isOwner) return;
|
||||||
|
|
||||||
|
var (isInGroup, newOwnerPair) = await TryValidateUserInGroup(dto.Group.GID, dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (!isInGroup) return;
|
||||||
|
|
||||||
|
var ownedShells = await DbContext.Groups.CountAsync(g => g.OwnerUID == dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (ownedShells >= _maxExistingGroupsByUser) return;
|
||||||
|
|
||||||
|
var prevOwner = await DbContext.GroupPairs.SingleOrDefaultAsync(g => g.GroupGID == dto.Group.GID && g.GroupUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
prevOwner.IsPinned = false;
|
||||||
|
group.Owner = newOwnerPair.GroupUser;
|
||||||
|
group.Alias = null;
|
||||||
|
newOwnerPair.IsPinned = true;
|
||||||
|
newOwnerPair.IsModerator = false;
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
var groupPairs = await DbContext.GroupPairs.Where(p => p.GroupGID == dto.Group.GID).Select(p => p.GroupUserUID).AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.Users(groupPairs).Client_GroupSendInfo(new GroupInfoDto(group.ToGroupData(), newOwnerPair.GroupUser.ToUserData(), group.GetGroupPermissions())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<bool> GroupChangePassword(GroupPasswordDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (isOwner, group) = await TryValidateOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!isOwner || dto.Password.Length < 10) return false;
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
group.HashedPassword = StringUtils.Sha256String(dto.Password);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupClear(GroupDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (hasRights, group) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!hasRights) return;
|
||||||
|
|
||||||
|
var groupPairs = await DbContext.GroupPairs.Include(p => p.GroupUser).Where(p => p.GroupGID == dto.Group.GID).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.Users(groupPairs.Where(p => !p.IsPinned && !p.IsModerator).Select(g => g.GroupUserUID)).Client_GroupDelete(new GroupDto(group.ToGroupData())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
var notPinned = groupPairs.Where(g => !g.IsPinned && !g.IsModerator).ToList();
|
||||||
|
|
||||||
|
DbContext.GroupPairs.RemoveRange(notPinned);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var pair in notPinned)
|
||||||
|
{
|
||||||
|
await Clients.Users(groupPairs.Where(p => p.IsPinned).Select(g => g.GroupUserUID)).Client_GroupPairLeft(new GroupPairDto(dto.Group, pair.GroupUser.ToUserData())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var pairIdent = await GetUserIdent(pair.GroupUserUID).ConfigureAwait(false);
|
||||||
|
if (string.IsNullOrEmpty(pairIdent)) continue;
|
||||||
|
|
||||||
|
var allUserPairs = await GetAllPairedClientsWithPauseState(pair.GroupUserUID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var sharedData = await DbContext.CharaDataAllowances.Where(u => u.AllowedGroup != null && u.AllowedGroupGID == dto.GID && u.ParentUploaderUID == pair.GroupUserUID).ToListAsync().ConfigureAwait(false);
|
||||||
|
DbContext.CharaDataAllowances.RemoveRange(sharedData);
|
||||||
|
|
||||||
|
foreach (var groupUserPair in groupPairs.Where(p => !string.Equals(p.GroupUserUID, pair.GroupUserUID, StringComparison.Ordinal)))
|
||||||
|
{
|
||||||
|
await UserGroupLeave(groupUserPair, allUserPairs, pairIdent).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<GroupPasswordDto> GroupCreate()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
var existingGroupsByUser = await DbContext.Groups.CountAsync(u => u.OwnerUID == UserUID).ConfigureAwait(false);
|
||||||
|
var existingJoinedGroups = await DbContext.GroupPairs.CountAsync(u => u.GroupUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
if (existingGroupsByUser >= _maxExistingGroupsByUser || existingJoinedGroups >= _maxJoinedGroupsByUser)
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Max groups for user is {_maxExistingGroupsByUser}, max joined groups is {_maxJoinedGroupsByUser}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var gid = StringUtils.GenerateRandomString(9);
|
||||||
|
while (await DbContext.Groups.AnyAsync(g => g.GID == "LSS-" + gid).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
gid = StringUtils.GenerateRandomString(9);
|
||||||
|
}
|
||||||
|
gid = "LSS-" + gid;
|
||||||
|
|
||||||
|
var passwd = StringUtils.GenerateRandomString(16);
|
||||||
|
var sha = SHA256.Create();
|
||||||
|
var hashedPw = StringUtils.Sha256String(passwd);
|
||||||
|
|
||||||
|
Group newGroup = new()
|
||||||
|
{
|
||||||
|
GID = gid,
|
||||||
|
HashedPassword = hashedPw,
|
||||||
|
InvitesEnabled = true,
|
||||||
|
OwnerUID = UserUID,
|
||||||
|
};
|
||||||
|
|
||||||
|
GroupPair initialPair = new()
|
||||||
|
{
|
||||||
|
GroupGID = newGroup.GID,
|
||||||
|
GroupUserUID = UserUID,
|
||||||
|
IsPaused = false,
|
||||||
|
IsPinned = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
await DbContext.Groups.AddAsync(newGroup).ConfigureAwait(false);
|
||||||
|
await DbContext.GroupPairs.AddAsync(initialPair).ConfigureAwait(false);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var self = await DbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.User(UserUID).Client_GroupSendFullInfo(new GroupFullInfoDto(newGroup.ToGroupData(), self.ToUserData(), GroupPermissions.NoneSet, GroupUserPermissions.NoneSet, GroupUserInfo.None))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
||||||
|
|
||||||
|
return new GroupPasswordDto(newGroup.ToGroupData(), passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<string>> GroupCreateTempInvite(GroupDto dto, int amount)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, amount));
|
||||||
|
List<string> inviteCodes = new();
|
||||||
|
List<GroupTempInvite> tempInvites = new();
|
||||||
|
var (hasRights, group) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!hasRights) return new();
|
||||||
|
|
||||||
|
var existingInvites = await DbContext.GroupTempInvites.Where(g => g.GroupGID == group.GID).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
for (int i = 0; i < amount; i++)
|
||||||
|
{
|
||||||
|
bool hasValidInvite = false;
|
||||||
|
string invite = string.Empty;
|
||||||
|
string hashedInvite = string.Empty;
|
||||||
|
while (!hasValidInvite)
|
||||||
|
{
|
||||||
|
invite = StringUtils.GenerateRandomString(10, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
|
||||||
|
hashedInvite = StringUtils.Sha256String(invite);
|
||||||
|
if (existingInvites.Any(i => string.Equals(i.Invite, hashedInvite, StringComparison.Ordinal))) continue;
|
||||||
|
hasValidInvite = true;
|
||||||
|
inviteCodes.Add(invite);
|
||||||
|
}
|
||||||
|
|
||||||
|
tempInvites.Add(new GroupTempInvite()
|
||||||
|
{
|
||||||
|
ExpirationDate = DateTime.UtcNow.AddDays(1),
|
||||||
|
GroupGID = group.GID,
|
||||||
|
Invite = hashedInvite,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DbContext.GroupTempInvites.AddRange(tempInvites);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return inviteCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupDelete(GroupDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (hasRights, group) = await TryValidateOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
var groupPairs = await DbContext.GroupPairs.Where(p => p.GroupGID == dto.Group.GID).ToListAsync().ConfigureAwait(false);
|
||||||
|
DbContext.RemoveRange(groupPairs);
|
||||||
|
DbContext.Remove(group);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.Users(groupPairs.Select(g => g.GroupUserUID)).Client_GroupDelete(new GroupDto(group.ToGroupData())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await SendGroupDeletedToAll(groupPairs).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<BannedGroupUserDto>> GroupGetBannedUsers(GroupDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (userHasRights, group) = await TryValidateGroupModeratorOrOwner(dto.GID).ConfigureAwait(false);
|
||||||
|
if (!userHasRights) return new List<BannedGroupUserDto>();
|
||||||
|
|
||||||
|
var banEntries = await DbContext.GroupBans.Include(b => b.BannedUser).Where(g => g.GroupGID == dto.Group.GID).AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
List<BannedGroupUserDto> bannedGroupUsers = banEntries.Select(b =>
|
||||||
|
new BannedGroupUserDto(group.ToGroupData(), b.BannedUser.ToUserData(), b.BannedReason, b.BannedOn,
|
||||||
|
b.BannedByUID)).ToList();
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, bannedGroupUsers.Count));
|
||||||
|
|
||||||
|
return bannedGroupUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<bool> GroupJoin(GroupPasswordDto dto)
|
||||||
|
{
|
||||||
|
var aliasOrGid = dto.Group.GID.Trim();
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto.Group));
|
||||||
|
|
||||||
|
var group = await DbContext.Groups.Include(g => g.Owner).AsNoTracking().SingleOrDefaultAsync(g => g.GID == aliasOrGid || g.Alias == aliasOrGid).ConfigureAwait(false);
|
||||||
|
var groupGid = group?.GID ?? string.Empty;
|
||||||
|
var existingPair = await DbContext.GroupPairs.AsNoTracking().SingleOrDefaultAsync(g => g.GroupGID == groupGid && g.GroupUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
var hashedPw = StringUtils.Sha256String(dto.Password);
|
||||||
|
var existingUserCount = await DbContext.GroupPairs.AsNoTracking().CountAsync(g => g.GroupGID == groupGid).ConfigureAwait(false);
|
||||||
|
var joinedGroups = await DbContext.GroupPairs.CountAsync(g => g.GroupUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
var isBanned = await DbContext.GroupBans.AnyAsync(g => g.GroupGID == groupGid && g.BannedUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
var oneTimeInvite = await DbContext.GroupTempInvites.SingleOrDefaultAsync(g => g.GroupGID == groupGid && g.Invite == hashedPw).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (group == null
|
||||||
|
|| (!string.Equals(group.HashedPassword, hashedPw, StringComparison.Ordinal) && oneTimeInvite == null)
|
||||||
|
|| existingPair != null
|
||||||
|
|| existingUserCount >= _maxGroupUserCount
|
||||||
|
|| !group.InvitesEnabled
|
||||||
|
|| joinedGroups >= _maxJoinedGroupsByUser
|
||||||
|
|| isBanned)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (oneTimeInvite != null)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(aliasOrGid, "TempInvite", oneTimeInvite.Invite));
|
||||||
|
DbContext.Remove(oneTimeInvite);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupPair newPair = new()
|
||||||
|
{
|
||||||
|
GroupGID = group.GID,
|
||||||
|
GroupUserUID = UserUID,
|
||||||
|
DisableAnimations = false,
|
||||||
|
DisableSounds = false,
|
||||||
|
DisableVFX = false
|
||||||
|
};
|
||||||
|
|
||||||
|
await DbContext.GroupPairs.AddAsync(newPair).ConfigureAwait(false);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(aliasOrGid, "Success"));
|
||||||
|
|
||||||
|
await Clients.User(UserUID).Client_GroupSendFullInfo(new GroupFullInfoDto(group.ToGroupData(), group.Owner.ToUserData(), group.GetGroupPermissions(), newPair.GetGroupPairPermissions(), newPair.GetGroupPairUserInfo())).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var self = DbContext.Users.Single(u => u.UID == UserUID);
|
||||||
|
|
||||||
|
var groupPairs = await DbContext.GroupPairs.Include(p => p.GroupUser).Where(p => p.GroupGID == group.GID && p.GroupUserUID != UserUID).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.Users(groupPairs.Select(p => p.GroupUserUID))
|
||||||
|
.Client_GroupPairJoined(new GroupPairFullInfoDto(group.ToGroupData(), self.ToUserData(), newPair.GetGroupPairUserInfo(), newPair.GetGroupPairPermissions())).ConfigureAwait(false);
|
||||||
|
foreach (var pair in groupPairs)
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_GroupPairJoined(new GroupPairFullInfoDto(group.ToGroupData(), pair.ToUserData(), pair.GetGroupPairUserInfo(), pair.GetGroupPairPermissions())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var allUserPairs = await GetAllPairedClientsWithPauseState().ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var groupUserPair in groupPairs)
|
||||||
|
{
|
||||||
|
var userPair = allUserPairs.Single(p => string.Equals(p.UID, groupUserPair.GroupUserUID, StringComparison.Ordinal));
|
||||||
|
if (userPair.IsDirectlyPaused != PauseInfo.NoConnection) continue;
|
||||||
|
if (userPair.IsPausedExcludingGroup(group.GID) is PauseInfo.Unpaused) continue;
|
||||||
|
if (userPair.IsPausedPerGroup is PauseInfo.Paused) continue;
|
||||||
|
|
||||||
|
var groupUserIdent = await GetUserIdent(groupUserPair.GroupUserUID).ConfigureAwait(false);
|
||||||
|
if (!string.IsNullOrEmpty(groupUserIdent))
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_UserSendOnline(new(groupUserPair.ToUserData(), groupUserIdent)).ConfigureAwait(false);
|
||||||
|
await Clients.User(groupUserPair.GroupUserUID)
|
||||||
|
.Client_UserSendOnline(new(self.ToUserData(), UserCharaIdent)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupLeave(GroupDto dto)
|
||||||
|
{
|
||||||
|
await UserLeaveGroup(dto, UserUID).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<int> GroupPrune(GroupDto dto, int days, bool execute)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, days, execute));
|
||||||
|
|
||||||
|
var (hasRights, group) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!hasRights) return -1;
|
||||||
|
|
||||||
|
var allGroupUsers = await DbContext.GroupPairs.Include(p => p.GroupUser).Include(p => p.Group)
|
||||||
|
.Where(g => g.GroupGID == dto.Group.GID)
|
||||||
|
.ToListAsync().ConfigureAwait(false);
|
||||||
|
var usersToPrune = allGroupUsers.Where(p => !p.IsPinned && !p.IsModerator
|
||||||
|
&& p.GroupUserUID != UserUID
|
||||||
|
&& p.Group.OwnerUID != p.GroupUserUID
|
||||||
|
&& p.GroupUser.LastLoggedIn.AddDays(days) < DateTime.UtcNow);
|
||||||
|
|
||||||
|
if (!execute) return usersToPrune.Count();
|
||||||
|
|
||||||
|
DbContext.GroupPairs.RemoveRange(usersToPrune);
|
||||||
|
|
||||||
|
foreach (var pair in usersToPrune)
|
||||||
|
{
|
||||||
|
await Clients.Users(allGroupUsers.Where(p => !usersToPrune.Contains(p)).Select(g => g.GroupUserUID))
|
||||||
|
.Client_GroupPairLeft(new GroupPairDto(dto.Group, pair.GroupUser.ToUserData())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return usersToPrune.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupRemoveUser(GroupPairDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (hasRights, group) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!hasRights) return;
|
||||||
|
|
||||||
|
var (userExists, groupPair) = await TryValidateUserInGroup(dto.Group.GID, dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (!userExists) return;
|
||||||
|
|
||||||
|
if (groupPair.IsModerator || string.Equals(group.OwnerUID, dto.User.UID, StringComparison.Ordinal)) return;
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
DbContext.GroupPairs.Remove(groupPair);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var groupPairs = DbContext.GroupPairs.Where(p => p.GroupGID == group.GID).AsNoTracking().ToList();
|
||||||
|
await Clients.Users(groupPairs.Select(p => p.GroupUserUID)).Client_GroupPairLeft(dto).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var sharedData = await DbContext.CharaDataAllowances.Where(u => u.AllowedGroup != null && u.AllowedGroupGID == dto.GID && u.ParentUploaderUID == dto.UID).ToListAsync().ConfigureAwait(false);
|
||||||
|
DbContext.CharaDataAllowances.RemoveRange(sharedData);
|
||||||
|
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var userIdent = await GetUserIdent(dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (userIdent == null) return;
|
||||||
|
|
||||||
|
await Clients.User(dto.User.UID).Client_GroupDelete(new GroupDto(dto.Group)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var allUserPairs = await GetAllPairedClientsWithPauseState(dto.User.UID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var groupUserPair in groupPairs)
|
||||||
|
{
|
||||||
|
await UserGroupLeave(groupUserPair, allUserPairs, userIdent, dto.User.UID).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupSetUserInfo(GroupPairUserInfoDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (userExists, userPair) = await TryValidateUserInGroup(dto.Group.GID, dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (!userExists) return;
|
||||||
|
|
||||||
|
var (userIsOwner, _) = await TryValidateOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
var (userIsModerator, _) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (dto.GroupUserInfo.HasFlag(GroupUserInfo.IsPinned) && userIsModerator && !userPair.IsPinned)
|
||||||
|
{
|
||||||
|
userPair.IsPinned = true;
|
||||||
|
}
|
||||||
|
else if (userIsModerator && userPair.IsPinned)
|
||||||
|
{
|
||||||
|
userPair.IsPinned = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.GroupUserInfo.HasFlag(GroupUserInfo.IsModerator) && userIsOwner && !userPair.IsModerator)
|
||||||
|
{
|
||||||
|
userPair.IsModerator = true;
|
||||||
|
}
|
||||||
|
else if (userIsOwner && userPair.IsModerator)
|
||||||
|
{
|
||||||
|
userPair.IsModerator = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var groupPairs = await DbContext.GroupPairs.AsNoTracking().Where(p => p.GroupGID == dto.Group.GID).Select(p => p.GroupUserUID).ToListAsync().ConfigureAwait(false);
|
||||||
|
await Clients.Users(groupPairs).Client_GroupPairChangeUserInfo(new GroupPairUserInfoDto(dto.Group, dto.User, userPair.GetGroupPairUserInfo())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<GroupFullInfoDto>> GroupsGetAll()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
|
||||||
|
var groups = await DbContext.GroupPairs.Include(g => g.Group).Include(g => g.Group.Owner).Where(g => g.GroupUserUID == UserUID).AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return groups.Select(g => new GroupFullInfoDto(g.Group.ToGroupData(), g.Group.Owner.ToUserData(),
|
||||||
|
g.Group.GetGroupPermissions(), g.GetGroupPairPermissions(), g.GetGroupPairUserInfo())).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<GroupPairFullInfoDto>> GroupsGetUsersInGroup(GroupDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (inGroup, _) = await TryValidateUserInGroup(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!inGroup) return new List<GroupPairFullInfoDto>();
|
||||||
|
|
||||||
|
var group = await DbContext.Groups.SingleAsync(g => g.GID == dto.Group.GID).ConfigureAwait(false);
|
||||||
|
var allPairs = await DbContext.GroupPairs.Include(g => g.GroupUser).Where(g => g.GroupGID == dto.Group.GID && g.GroupUserUID != UserUID).AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
return allPairs.Select(p => new GroupPairFullInfoDto(group.ToGroupData(), p.GroupUser.ToUserData(), p.GetGroupPairUserInfo(), p.GetGroupPairPermissions())).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task GroupUnbanUser(GroupPairDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
var (userHasRights, _) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false);
|
||||||
|
if (!userHasRights) return;
|
||||||
|
|
||||||
|
var banEntry = await DbContext.GroupBans.SingleOrDefaultAsync(g => g.GroupGID == dto.Group.GID && g.BannedUserUID == dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (banEntry == null) return;
|
||||||
|
|
||||||
|
DbContext.Remove(banEntry);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
}
|
||||||
|
}
|
||||||
514
MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs
Normal file
514
MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Data.Enum;
|
||||||
|
using MareSynchronos.API.Data.Extensions;
|
||||||
|
using MareSynchronos.API.Dto.User;
|
||||||
|
using MareSynchronosServer.Utils;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Models;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
public partial class MareHub
|
||||||
|
{
|
||||||
|
private static readonly string[] AllowedExtensionsForGamePaths = { ".mdl", ".tex", ".mtrl", ".tmb", ".pap", ".avfx", ".atex", ".sklb", ".eid", ".phyb", ".pbd", ".scd", ".skp", ".shpk" };
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task UserAddPair(UserDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
// don't allow adding nothing
|
||||||
|
var uid = dto.User.UID.Trim();
|
||||||
|
if (string.Equals(dto.User.UID, UserUID, StringComparison.Ordinal) || string.IsNullOrWhiteSpace(dto.User.UID)) return;
|
||||||
|
|
||||||
|
// grab other user, check if it exists and if a pair already exists
|
||||||
|
var otherUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == uid || u.Alias == uid).ConfigureAwait(false);
|
||||||
|
if (otherUser == null)
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Warning, $"Cannot pair with {dto.User.UID}, UID does not exist").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(otherUser.UID, UserUID, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Warning, $"My god you can't pair with yourself why would you do that please stop").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existingEntry =
|
||||||
|
await DbContext.ClientPairs.AsNoTracking()
|
||||||
|
.FirstOrDefaultAsync(p =>
|
||||||
|
p.User.UID == UserUID && p.OtherUserUID == otherUser.UID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (existingEntry != null)
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Warning, $"Cannot pair with {dto.User.UID}, already paired").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// grab self create new client pair and save
|
||||||
|
var user = await DbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
ClientPair wl = new ClientPair()
|
||||||
|
{
|
||||||
|
IsPaused = false,
|
||||||
|
OtherUser = otherUser,
|
||||||
|
User = user,
|
||||||
|
};
|
||||||
|
await DbContext.ClientPairs.AddAsync(wl).ConfigureAwait(false);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
// get the opposite entry of the client pair
|
||||||
|
var otherEntry = OppositeEntry(otherUser.UID);
|
||||||
|
var otherIdent = await GetUserIdent(otherUser.UID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var ownPerm = UserPermissions.Paired;
|
||||||
|
var otherPerm = UserPermissions.NoneSet;
|
||||||
|
otherPerm.SetPaired(otherEntry != null);
|
||||||
|
otherPerm.SetPaused(otherEntry?.IsPaused ?? false);
|
||||||
|
var userPairResponse = new UserPairDto(otherUser.ToUserData(), ownPerm, otherPerm);
|
||||||
|
await Clients.User(user.UID).Client_UserAddClientPair(userPairResponse).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// check if other user is online
|
||||||
|
if (otherIdent == null || otherEntry == null) return;
|
||||||
|
|
||||||
|
// send push with update to other user if other user is online
|
||||||
|
await Clients.User(otherUser.UID).Client_UserAddClientPair(new UserPairDto(user.ToUserData(), otherPerm, ownPerm)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!otherPerm.IsPaused())
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_UserSendOnline(new(otherUser.ToUserData(), otherIdent)).ConfigureAwait(false);
|
||||||
|
await Clients.User(otherUser.UID).Client_UserSendOnline(new(user.ToUserData(), UserCharaIdent)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task UserDelete()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
|
||||||
|
var userEntry = await DbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false);
|
||||||
|
var secondaryUsers = await DbContext.Auth.Include(u => u.User).Where(u => u.PrimaryUserUID == UserUID).Select(c => c.User).ToListAsync().ConfigureAwait(false);
|
||||||
|
foreach (var user in secondaryUsers)
|
||||||
|
{
|
||||||
|
await DeleteUser(user).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
await DeleteUser(userEntry).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<OnlineUserIdentDto>> UserGetOnlinePairs()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
|
||||||
|
var allPairedUsers = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
|
||||||
|
var pairs = await GetOnlineUsers(allPairedUsers).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await SendOnlineToAllPairedUsers().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return pairs.Select(p => new OnlineUserIdentDto(new UserData(p.Key), p.Value)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<List<UserPairDto>> UserGetPairedClients()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
|
||||||
|
var query =
|
||||||
|
from userToOther in DbContext.ClientPairs
|
||||||
|
join otherToUser in DbContext.ClientPairs
|
||||||
|
on new
|
||||||
|
{
|
||||||
|
user = userToOther.UserUID,
|
||||||
|
other = userToOther.OtherUserUID,
|
||||||
|
} equals new
|
||||||
|
{
|
||||||
|
user = otherToUser.OtherUserUID,
|
||||||
|
other = otherToUser.UserUID,
|
||||||
|
} into leftJoin
|
||||||
|
from otherEntry in leftJoin.DefaultIfEmpty()
|
||||||
|
where
|
||||||
|
userToOther.UserUID == UserUID
|
||||||
|
select new
|
||||||
|
{
|
||||||
|
userToOther.OtherUser.Alias,
|
||||||
|
userToOther.IsPaused,
|
||||||
|
OtherIsPaused = otherEntry != null && otherEntry.IsPaused,
|
||||||
|
userToOther.OtherUserUID,
|
||||||
|
IsSynced = otherEntry != null,
|
||||||
|
DisableOwnAnimations = userToOther.DisableAnimations,
|
||||||
|
DisableOwnSounds = userToOther.DisableSounds,
|
||||||
|
DisableOwnVFX = userToOther.DisableVFX,
|
||||||
|
DisableOtherAnimations = otherEntry == null ? false : otherEntry.DisableAnimations,
|
||||||
|
DisableOtherSounds = otherEntry == null ? false : otherEntry.DisableSounds,
|
||||||
|
DisableOtherVFX = otherEntry == null ? false : otherEntry.DisableVFX
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = await query.AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return results.Select(c =>
|
||||||
|
{
|
||||||
|
var ownPerm = UserPermissions.Paired;
|
||||||
|
ownPerm.SetPaused(c.IsPaused);
|
||||||
|
ownPerm.SetDisableAnimations(c.DisableOwnAnimations);
|
||||||
|
ownPerm.SetDisableSounds(c.DisableOwnSounds);
|
||||||
|
ownPerm.SetDisableVFX(c.DisableOwnVFX);
|
||||||
|
var otherPerm = UserPermissions.NoneSet;
|
||||||
|
otherPerm.SetPaired(c.IsSynced);
|
||||||
|
otherPerm.SetPaused(c.OtherIsPaused);
|
||||||
|
otherPerm.SetDisableAnimations(c.DisableOtherAnimations);
|
||||||
|
otherPerm.SetDisableSounds(c.DisableOtherSounds);
|
||||||
|
otherPerm.SetDisableVFX(c.DisableOtherVFX);
|
||||||
|
return new UserPairDto(new(c.OtherUserUID, c.Alias), ownPerm, otherPerm);
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<UserProfileDto> UserGetProfile(UserDto user)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(user));
|
||||||
|
|
||||||
|
var allUserPairs = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!allUserPairs.Contains(user.User.UID, StringComparer.Ordinal) && !string.Equals(user.User.UID, UserUID, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return new UserProfileDto(user.User, false, null, null, "Due to the pause status you cannot access this users profile.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = await DbContext.UserProfileData.SingleOrDefaultAsync(u => u.UserUID == user.User.UID).ConfigureAwait(false);
|
||||||
|
if (data == null) return new UserProfileDto(user.User, false, null, null, null);
|
||||||
|
|
||||||
|
if (data.FlaggedForReport) return new UserProfileDto(user.User, true, null, null, "This profile is flagged for report and pending evaluation");
|
||||||
|
if (data.ProfileDisabled) return new UserProfileDto(user.User, true, null, null, "This profile was permanently disabled");
|
||||||
|
|
||||||
|
return new UserProfileDto(user.User, false, data.IsNSFW, data.Base64ProfileImage, data.UserDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task UserPushData(UserCharaDataMessageDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto.CharaData.FileReplacements.Count));
|
||||||
|
|
||||||
|
// check for honorific containing . and /
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var honorificJson = Encoding.Default.GetString(Convert.FromBase64String(dto.CharaData.HonorificData));
|
||||||
|
var deserialized = JsonSerializer.Deserialize<JsonElement>(honorificJson);
|
||||||
|
if (deserialized.TryGetProperty("Title", out var honorificTitle))
|
||||||
|
{
|
||||||
|
var title = honorificTitle.GetString().Normalize(NormalizationForm.FormKD);
|
||||||
|
if (UrlRegex().IsMatch(title))
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "Your data was not pushed: The usage of URLs the Honorific titles is prohibited. Remove them to be able to continue to push data.").ConfigureAwait(false);
|
||||||
|
throw new HubException("Invalid data provided, Honorific title invalid: " + title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HubException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// swallow
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hadInvalidData = false;
|
||||||
|
List<string> invalidGamePaths = new();
|
||||||
|
List<string> invalidFileSwapPaths = new();
|
||||||
|
foreach (var replacement in dto.CharaData.FileReplacements.SelectMany(p => p.Value))
|
||||||
|
{
|
||||||
|
var invalidPaths = replacement.GamePaths.Where(p => !GamePathRegex().IsMatch(p)).ToList();
|
||||||
|
invalidPaths.AddRange(replacement.GamePaths.Where(p => !AllowedExtensionsForGamePaths.Any(e => p.EndsWith(e, StringComparison.OrdinalIgnoreCase))));
|
||||||
|
replacement.GamePaths = replacement.GamePaths.Where(p => !invalidPaths.Contains(p, StringComparer.OrdinalIgnoreCase)).ToArray();
|
||||||
|
bool validGamePaths = replacement.GamePaths.Any();
|
||||||
|
bool validHash = string.IsNullOrEmpty(replacement.Hash) || HashRegex().IsMatch(replacement.Hash);
|
||||||
|
bool validFileSwapPath = string.IsNullOrEmpty(replacement.FileSwapPath) || GamePathRegex().IsMatch(replacement.FileSwapPath);
|
||||||
|
if (!validGamePaths || !validHash || !validFileSwapPath)
|
||||||
|
{
|
||||||
|
_logger.LogCallWarning(MareHubLogger.Args("Invalid Data", "GamePaths", validGamePaths, string.Join(",", invalidPaths), "Hash", validHash, replacement.Hash, "FileSwap", validFileSwapPath, replacement.FileSwapPath));
|
||||||
|
hadInvalidData = true;
|
||||||
|
if (!validFileSwapPath) invalidFileSwapPaths.Add(replacement.FileSwapPath);
|
||||||
|
if (!validGamePaths) invalidGamePaths.AddRange(replacement.GamePaths);
|
||||||
|
if (!validHash) invalidFileSwapPaths.Add(replacement.Hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hadInvalidData)
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "One or more of your supplied mods were rejected from the server. Consult /xllog for more information.").ConfigureAwait(false);
|
||||||
|
throw new HubException("Invalid data provided, contact the appropriate mod creator to resolve those issues"
|
||||||
|
+ Environment.NewLine
|
||||||
|
+ string.Join(Environment.NewLine, invalidGamePaths.Select(p => "Invalid Game Path: " + p))
|
||||||
|
+ Environment.NewLine
|
||||||
|
+ string.Join(Environment.NewLine, invalidFileSwapPaths.Select(p => "Invalid FileSwap Path: " + p)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var allPairedUsers = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
|
||||||
|
var idents = await GetOnlineUsers(allPairedUsers).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var recipients = allPairedUsers.Where(f => dto.Recipients.Select(r => r.UID).Contains(f, StringComparer.Ordinal)).ToList();
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(idents.Count, recipients.Count()));
|
||||||
|
|
||||||
|
await Clients.Users(recipients).Client_UserReceiveCharacterData(new OnlineUserCharaDataDto(new UserData(UserUID), dto.CharaData)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_mareMetrics.IncCounter(MetricsAPI.CounterUserPushData);
|
||||||
|
_mareMetrics.IncCounter(MetricsAPI.CounterUserPushDataTo, recipients.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task UserRemovePair(UserDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
if (string.Equals(dto.User.UID, UserUID, StringComparison.Ordinal)) return;
|
||||||
|
|
||||||
|
// check if client pair even exists
|
||||||
|
ClientPair callerPair =
|
||||||
|
await DbContext.ClientPairs.SingleOrDefaultAsync(w => w.UserUID == UserUID && w.OtherUserUID == dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (callerPair == null) return;
|
||||||
|
|
||||||
|
bool callerHadPaused = callerPair.IsPaused;
|
||||||
|
|
||||||
|
// delete from database, send update info to users pair list
|
||||||
|
DbContext.ClientPairs.Remove(callerPair);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
await Clients.User(UserUID).Client_UserRemoveClientPair(dto).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// check if opposite entry exists
|
||||||
|
var oppositeClientPair = OppositeEntry(dto.User.UID);
|
||||||
|
if (oppositeClientPair == null) return;
|
||||||
|
|
||||||
|
// check if other user is online, if no then there is no need to do anything further
|
||||||
|
var otherIdent = await GetUserIdent(dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (otherIdent == null) return;
|
||||||
|
|
||||||
|
// get own ident and
|
||||||
|
await Clients.User(dto.User.UID)
|
||||||
|
.Client_UserUpdateOtherPairPermissions(new UserPermissionsDto(new UserData(UserUID),
|
||||||
|
UserPermissions.NoneSet)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// if the other user had paused the user the state will be offline for either, do nothing
|
||||||
|
bool otherHadPaused = oppositeClientPair.IsPaused;
|
||||||
|
if (!callerHadPaused && otherHadPaused) return;
|
||||||
|
|
||||||
|
var allUsers = await GetAllPairedClientsWithPauseState().ConfigureAwait(false);
|
||||||
|
var pauseEntry = allUsers.SingleOrDefault(f => string.Equals(f.UID, dto.User.UID, StringComparison.Ordinal));
|
||||||
|
var isPausedInGroup = pauseEntry == null || pauseEntry.IsPausedPerGroup is PauseInfo.Paused or PauseInfo.NoConnection;
|
||||||
|
|
||||||
|
// if neither user had paused each other and both are in unpaused groups, state will be online for both, do nothing
|
||||||
|
if (!callerHadPaused && !otherHadPaused && !isPausedInGroup) return;
|
||||||
|
|
||||||
|
// if neither user had paused each other and either is not in an unpaused group with each other, change state to offline
|
||||||
|
if (!callerHadPaused && !otherHadPaused && isPausedInGroup)
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_UserSendOffline(dto).ConfigureAwait(false);
|
||||||
|
await Clients.User(dto.User.UID).Client_UserSendOffline(new(new(UserUID))).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the caller had paused other but not the other has paused the caller and they are in an unpaused group together, change state to online
|
||||||
|
if (callerHadPaused && !otherHadPaused && !isPausedInGroup)
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_UserSendOnline(new(dto.User, otherIdent)).ConfigureAwait(false);
|
||||||
|
await Clients.User(dto.User.UID).Client_UserSendOnline(new(new(UserUID), UserCharaIdent)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task UserReportProfile(UserProfileReportDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
UserProfileDataReport report = await DbContext.UserProfileReports.SingleOrDefaultAsync(u => u.ReportedUserUID == dto.User.UID && u.ReportingUserUID == UserUID).ConfigureAwait(false);
|
||||||
|
if (report != null)
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "You already reported this profile and it's pending validation").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserProfileData profile = await DbContext.UserProfileData.SingleOrDefaultAsync(u => u.UserUID == dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (profile == null)
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "This user has no profile").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserProfileDataReport reportToAdd = new()
|
||||||
|
{
|
||||||
|
ReportDate = DateTime.UtcNow,
|
||||||
|
ReportingUserUID = UserUID,
|
||||||
|
ReportReason = dto.ProfileReport,
|
||||||
|
ReportedUserUID = dto.User.UID,
|
||||||
|
};
|
||||||
|
|
||||||
|
profile.FlaggedForReport = true;
|
||||||
|
|
||||||
|
await DbContext.UserProfileReports.AddAsync(reportToAdd).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var allPairedUsers = await GetAllPairedUnpausedUsers(dto.User.UID).ConfigureAwait(false);
|
||||||
|
var pairs = await GetOnlineUsers(allPairedUsers).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.Users(pairs.Select(p => p.Key)).Client_UserUpdateProfile(new(dto.User)).ConfigureAwait(false);
|
||||||
|
await Clients.Users(dto.User.UID).Client_UserUpdateProfile(new(dto.User)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task UserSetPairPermissions(UserPermissionsDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
if (string.Equals(dto.User.UID, UserUID, StringComparison.Ordinal)) return;
|
||||||
|
ClientPair pair = await DbContext.ClientPairs.SingleOrDefaultAsync(w => w.UserUID == UserUID && w.OtherUserUID == dto.User.UID).ConfigureAwait(false);
|
||||||
|
if (pair == null) return;
|
||||||
|
|
||||||
|
var pauseChange = pair.IsPaused != dto.Permissions.IsPaused();
|
||||||
|
|
||||||
|
pair.IsPaused = dto.Permissions.IsPaused();
|
||||||
|
pair.DisableAnimations = dto.Permissions.IsDisableAnimations();
|
||||||
|
pair.DisableSounds = dto.Permissions.IsDisableSounds();
|
||||||
|
pair.DisableVFX = dto.Permissions.IsDisableVFX();
|
||||||
|
DbContext.Update(pair);
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));
|
||||||
|
|
||||||
|
var otherEntry = OppositeEntry(dto.User.UID);
|
||||||
|
|
||||||
|
await Clients.User(UserUID).Client_UserUpdateSelfPairPermissions(dto).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (otherEntry != null)
|
||||||
|
{
|
||||||
|
await Clients.User(dto.User.UID).Client_UserUpdateOtherPairPermissions(new UserPermissionsDto(new UserData(UserUID), dto.Permissions)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (pauseChange)
|
||||||
|
{
|
||||||
|
var otherCharaIdent = await GetUserIdent(pair.OtherUserUID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (UserCharaIdent == null || otherCharaIdent == null || otherEntry.IsPaused) return;
|
||||||
|
|
||||||
|
if (dto.Permissions.IsPaused())
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_UserSendOffline(dto).ConfigureAwait(false);
|
||||||
|
await Clients.User(dto.User.UID).Client_UserSendOffline(new(new(UserUID))).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Clients.User(UserUID).Client_UserSendOnline(new(dto.User, otherCharaIdent)).ConfigureAwait(false);
|
||||||
|
await Clients.User(dto.User.UID).Client_UserSendOnline(new(new(UserUID), UserCharaIdent)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task UserSetProfile(UserProfileDto dto)
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(dto));
|
||||||
|
|
||||||
|
if (!string.Equals(dto.User.UID, UserUID, StringComparison.Ordinal)) throw new HubException("Cannot modify profile data for anyone but yourself");
|
||||||
|
|
||||||
|
var existingData = await DbContext.UserProfileData.SingleOrDefaultAsync(u => u.UserUID == dto.User.UID).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (existingData?.FlaggedForReport ?? false)
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "Your profile is currently flagged for report and cannot be edited").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingData?.ProfileDisabled ?? false)
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "Your profile was permanently disabled and cannot be edited").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(dto.ProfilePictureBase64))
|
||||||
|
{
|
||||||
|
byte[] imageData = Convert.FromBase64String(dto.ProfilePictureBase64);
|
||||||
|
using MemoryStream ms = new(imageData);
|
||||||
|
var format = await Image.DetectFormatAsync(ms).ConfigureAwait(false);
|
||||||
|
if (!format.FileExtensions.Contains("png", StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "Your provided image file is not in PNG format").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using var image = Image.Load<Rgba32>(imageData);
|
||||||
|
|
||||||
|
if (image.Width > 256 || image.Height > 256 || (imageData.Length > 250 * 1024))
|
||||||
|
{
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "Your provided image file is larger than 256x256 or more than 250KiB.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingData != null)
|
||||||
|
{
|
||||||
|
if (string.Equals("", dto.ProfilePictureBase64, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
existingData.Base64ProfileImage = null;
|
||||||
|
}
|
||||||
|
else if (dto.ProfilePictureBase64 != null)
|
||||||
|
{
|
||||||
|
existingData.Base64ProfileImage = dto.ProfilePictureBase64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.IsNSFW != null)
|
||||||
|
{
|
||||||
|
existingData.IsNSFW = dto.IsNSFW.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.Description != null)
|
||||||
|
{
|
||||||
|
existingData.UserDescription = dto.Description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UserProfileData userProfileData = new()
|
||||||
|
{
|
||||||
|
UserUID = dto.User.UID,
|
||||||
|
Base64ProfileImage = dto.ProfilePictureBase64 ?? null,
|
||||||
|
UserDescription = dto.Description ?? null,
|
||||||
|
IsNSFW = dto.IsNSFW ?? false
|
||||||
|
};
|
||||||
|
|
||||||
|
await DbContext.UserProfileData.AddAsync(userProfileData).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var allPairedUsers = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
|
||||||
|
var pairs = await GetOnlineUsers(allPairedUsers).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.Users(pairs.Select(p => p.Key)).Client_UserUpdateProfile(new(dto.User)).ConfigureAwait(false);
|
||||||
|
await Clients.Caller.Client_UserUpdateProfile(new(dto.User)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^([a-z0-9_ '+&,\.\-\{\}]+\/)+([a-z0-9_ '+&,\.\-\{\}]+\.[a-z]{3,4})$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ECMAScript)]
|
||||||
|
private static partial Regex GamePathRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^[A-Z0-9]{40}$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ECMAScript)]
|
||||||
|
private static partial Regex HashRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex("^[-a-zA-Z0-9@:%._\\+~#=]{1,256}[\\.,][a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)$")]
|
||||||
|
private static partial Regex UrlRegex();
|
||||||
|
|
||||||
|
private ClientPair OppositeEntry(string otherUID) =>
|
||||||
|
DbContext.ClientPairs.AsNoTracking().SingleOrDefault(w => w.User.UID == otherUID && w.OtherUser.UID == UserUID);
|
||||||
|
}
|
||||||
147
MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs
Normal file
147
MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Data.Enum;
|
||||||
|
using MareSynchronos.API.Dto;
|
||||||
|
using MareSynchronos.API.SignalR;
|
||||||
|
using MareSynchronosServer.Services;
|
||||||
|
using MareSynchronosServer.Utils;
|
||||||
|
using MareSynchronosShared;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using StackExchange.Redis.Extensions.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
[Authorize(Policy = "Authenticated")]
|
||||||
|
public partial class MareHub : Hub<IMareHub>, IMareHub
|
||||||
|
{
|
||||||
|
private readonly MareMetrics _mareMetrics;
|
||||||
|
private readonly SystemInfoService _systemInfoService;
|
||||||
|
private readonly IHttpContextAccessor _contextAccessor;
|
||||||
|
private readonly MareHubLogger _logger;
|
||||||
|
private readonly string _shardName;
|
||||||
|
private readonly int _maxExistingGroupsByUser;
|
||||||
|
private readonly int _maxJoinedGroupsByUser;
|
||||||
|
private readonly int _maxGroupUserCount;
|
||||||
|
private readonly IRedisDatabase _redis;
|
||||||
|
private readonly GPoseLobbyDistributionService _gPoseLobbyDistributionService;
|
||||||
|
private readonly Uri _fileServerAddress;
|
||||||
|
private readonly Version _expectedClientVersion;
|
||||||
|
private readonly int _maxCharaDataByUser;
|
||||||
|
|
||||||
|
private readonly Lazy<MareDbContext> _dbContextLazy;
|
||||||
|
private MareDbContext DbContext => _dbContextLazy.Value;
|
||||||
|
|
||||||
|
public MareHub(MareMetrics mareMetrics,
|
||||||
|
IDbContextFactory<MareDbContext> mareDbContextFactory, ILogger<MareHub> logger, SystemInfoService systemInfoService,
|
||||||
|
IConfigurationService<ServerConfiguration> configuration, IHttpContextAccessor contextAccessor,
|
||||||
|
IRedisDatabase redisDb, GPoseLobbyDistributionService gPoseLobbyDistributionService)
|
||||||
|
{
|
||||||
|
_mareMetrics = mareMetrics;
|
||||||
|
_systemInfoService = systemInfoService;
|
||||||
|
_shardName = configuration.GetValue<string>(nameof(ServerConfiguration.ShardName));
|
||||||
|
_maxExistingGroupsByUser = configuration.GetValueOrDefault(nameof(ServerConfiguration.MaxExistingGroupsByUser), 3);
|
||||||
|
_maxJoinedGroupsByUser = configuration.GetValueOrDefault(nameof(ServerConfiguration.MaxJoinedGroupsByUser), 6);
|
||||||
|
_maxGroupUserCount = configuration.GetValueOrDefault(nameof(ServerConfiguration.MaxGroupUserCount), 100);
|
||||||
|
_fileServerAddress = configuration.GetValue<Uri>(nameof(ServerConfiguration.CdnFullUrl));
|
||||||
|
_expectedClientVersion = configuration.GetValueOrDefault(nameof(ServerConfiguration.ExpectedClientVersion), new Version(0, 0, 0));
|
||||||
|
_maxCharaDataByUser = configuration.GetValueOrDefault(nameof(ServerConfiguration.MaxCharaDataByUser), 10);
|
||||||
|
_contextAccessor = contextAccessor;
|
||||||
|
_redis = redisDb;
|
||||||
|
_gPoseLobbyDistributionService = gPoseLobbyDistributionService;
|
||||||
|
_logger = new MareHubLogger(this, logger);
|
||||||
|
_dbContextLazy = new Lazy<MareDbContext>(() => mareDbContextFactory.CreateDbContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
DbContext.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Identified")]
|
||||||
|
public async Task<ConnectionDto> GetConnectionDto()
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo();
|
||||||
|
|
||||||
|
_mareMetrics.IncCounter(MetricsAPI.CounterInitializedConnections);
|
||||||
|
|
||||||
|
await Clients.Caller.Client_UpdateSystemInfo(_systemInfoService.SystemInfoDto).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var dbUser = DbContext.Users.SingleOrDefault(f => f.UID == UserUID);
|
||||||
|
dbUser.LastLoggedIn = DateTime.UtcNow;
|
||||||
|
await DbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Information, "Welcome to Loporrit, Current Online Users: " + _systemInfoService.SystemInfoDto.OnlineUsers).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return new ConnectionDto(new UserData(dbUser.UID, string.IsNullOrWhiteSpace(dbUser.Alias) ? null : dbUser.Alias))
|
||||||
|
{
|
||||||
|
CurrentClientVersion = _expectedClientVersion,
|
||||||
|
ServerVersion = IMareHub.ApiVersion,
|
||||||
|
IsAdmin = dbUser.IsAdmin,
|
||||||
|
IsModerator = dbUser.IsModerator,
|
||||||
|
ServerInfo = new ServerInfo()
|
||||||
|
{
|
||||||
|
MaxGroupsCreatedByUser = _maxExistingGroupsByUser,
|
||||||
|
ShardName = _shardName,
|
||||||
|
MaxGroupsJoinedByUser = _maxJoinedGroupsByUser,
|
||||||
|
MaxGroupUserCount = _maxGroupUserCount,
|
||||||
|
FileServerAddress = _fileServerAddress,
|
||||||
|
MaxCharaData = _maxCharaDataByUser
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Authenticated")]
|
||||||
|
public async Task<bool> CheckClientHealth()
|
||||||
|
{
|
||||||
|
await UpdateUserOnRedis().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Authenticated")]
|
||||||
|
public override async Task OnConnectedAsync()
|
||||||
|
{
|
||||||
|
_mareMetrics.IncGaugeWithLabels(MetricsAPI.GaugeConnections, labels: Continent);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(_contextAccessor.GetIpAddress(), UserCharaIdent));
|
||||||
|
|
||||||
|
await UpdateUserOnRedis().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
await base.OnConnectedAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = "Authenticated")]
|
||||||
|
public override async Task OnDisconnectedAsync(Exception exception)
|
||||||
|
{
|
||||||
|
_mareMetrics.DecGaugeWithLabels(MetricsAPI.GaugeConnections, labels: Continent);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogCallInfo(MareHubLogger.Args(_contextAccessor.GetIpAddress(), UserCharaIdent));
|
||||||
|
if (exception != null)
|
||||||
|
_logger.LogCallWarning(MareHubLogger.Args(_contextAccessor.GetIpAddress(), exception.Message, exception.StackTrace));
|
||||||
|
|
||||||
|
await GposeLobbyLeave().ConfigureAwait(false);
|
||||||
|
await RemoveUserFromRedis().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await SendOfflineToAllPairedUsers().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
await base.OnDisconnectedAsync(exception).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
using AspNetCoreRateLimit;
|
||||||
|
using MareSynchronosShared;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
public class SignalRLimitFilter : IHubFilter
|
||||||
|
{
|
||||||
|
private readonly IRateLimitProcessor _processor;
|
||||||
|
private readonly IHttpContextAccessor accessor;
|
||||||
|
private readonly ILogger<SignalRLimitFilter> logger;
|
||||||
|
private static readonly SemaphoreSlim ConnectionLimiterSemaphore = new(20, 20);
|
||||||
|
private static readonly SemaphoreSlim DisconnectLimiterSemaphore = new(20, 20);
|
||||||
|
|
||||||
|
public SignalRLimitFilter(
|
||||||
|
IOptions<IpRateLimitOptions> options, IProcessingStrategy processing, IIpPolicyStore policyStore, IHttpContextAccessor accessor, ILogger<SignalRLimitFilter> logger)
|
||||||
|
{
|
||||||
|
_processor = new IpRateLimitProcessor(options?.Value, policyStore, processing);
|
||||||
|
this.accessor = accessor;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<object> InvokeMethodAsync(
|
||||||
|
HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
|
||||||
|
{
|
||||||
|
var ip = accessor.GetIpAddress();
|
||||||
|
var client = new ClientRequestIdentity
|
||||||
|
{
|
||||||
|
ClientIp = ip,
|
||||||
|
Path = invocationContext.HubMethodName,
|
||||||
|
HttpVerb = "ws",
|
||||||
|
ClientId = invocationContext.Context.UserIdentifier,
|
||||||
|
};
|
||||||
|
foreach (var rule in await _processor.GetMatchingRulesAsync(client).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var counter = await _processor.ProcessRequestAsync(client, rule).ConfigureAwait(false);
|
||||||
|
if (counter.Count > rule.Limit)
|
||||||
|
{
|
||||||
|
var authUserId = invocationContext.Context.User.Claims?.SingleOrDefault(c => string.Equals(c.Type, MareClaimTypes.Uid, StringComparison.Ordinal))?.Value ?? "Unknown";
|
||||||
|
var retry = counter.Timestamp.RetryAfterFrom(rule);
|
||||||
|
logger.LogWarning("Method rate limit triggered from {ip}/{authUserId}: {method}", ip, authUserId, invocationContext.HubMethodName);
|
||||||
|
throw new HubException($"call limit {retry}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return await next(invocationContext).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional method
|
||||||
|
public async Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next)
|
||||||
|
{
|
||||||
|
await ConnectionLimiterSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var ip = accessor.GetIpAddress();
|
||||||
|
var client = new ClientRequestIdentity
|
||||||
|
{
|
||||||
|
ClientIp = ip,
|
||||||
|
Path = "Connect",
|
||||||
|
HttpVerb = "ws",
|
||||||
|
};
|
||||||
|
foreach (var rule in await _processor.GetMatchingRulesAsync(client).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var counter = await _processor.ProcessRequestAsync(client, rule).ConfigureAwait(false);
|
||||||
|
if (counter.Count > rule.Limit)
|
||||||
|
{
|
||||||
|
var retry = counter.Timestamp.RetryAfterFrom(rule);
|
||||||
|
logger.LogWarning("Connection rate limit triggered from {ip}", ip);
|
||||||
|
ConnectionLimiterSemaphore.Release();
|
||||||
|
throw new HubException($"Connection rate limit {retry}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await Task.Delay(25).ConfigureAwait(false);
|
||||||
|
await next(context).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogWarning(ex, "Error on OnConnectedAsync");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ConnectionLimiterSemaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnDisconnectedAsync(
|
||||||
|
HubLifetimeContext context, Exception exception, Func<HubLifetimeContext, Exception, Task> next)
|
||||||
|
{
|
||||||
|
await DisconnectLimiterSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
if (exception != null)
|
||||||
|
{
|
||||||
|
logger.LogWarning(exception, "InitialException on OnDisconnectedAsync");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await next(context, exception).ConfigureAwait(false);
|
||||||
|
await Task.Delay(25).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogWarning(e, "ThrownException on OnDisconnectedAsync");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
DisconnectLimiterSemaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<UserSecretsId>aspnet-MareSynchronosServer-BA82A12A-0B30-463C-801D-B7E81318CD50</UserSecretsId>
|
||||||
|
<AssemblyVersion>1.1.0.0</AssemblyVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Remove="appsettings.Development.json" />
|
||||||
|
<Content Remove="appsettings.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="appsettings.Development.json" />
|
||||||
|
<None Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||||
|
<PackageReference Include="IDisposableAnalyzers" Version="4.0.7">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.149">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.5.1" />
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
||||||
|
<ProjectReference Include="..\MareSynchronosShared\MareSynchronosShared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
77
MareSynchronosServer/MareSynchronosServer/Program.cs
Normal file
77
MareSynchronosServer/MareSynchronosServer/Program.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var hostBuilder = CreateHostBuilder(args);
|
||||||
|
var host = hostBuilder.Build();
|
||||||
|
using (var scope = host.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var services = scope.ServiceProvider;
|
||||||
|
using var context = services.GetRequiredService<MareDbContext>();
|
||||||
|
var options = services.GetRequiredService<IConfigurationService<ServerConfiguration>>();
|
||||||
|
var logger = host.Services.GetRequiredService<ILogger<Program>>();
|
||||||
|
|
||||||
|
if (options.IsMain)
|
||||||
|
{
|
||||||
|
context.Database.Migrate();
|
||||||
|
context.SaveChanges();
|
||||||
|
|
||||||
|
// clean up residuals
|
||||||
|
var unfinishedRegistrations = context.LodeStoneAuth.Where(c => c.StartedAt != null);
|
||||||
|
context.RemoveRange(unfinishedRegistrations);
|
||||||
|
context.SaveChanges();
|
||||||
|
|
||||||
|
logger.LogInformation(options.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
var metrics = services.GetRequiredService<MareMetrics>();
|
||||||
|
|
||||||
|
metrics.SetGaugeTo(MetricsAPI.GaugeUsersRegistered, context.Users.AsNoTracking().Count());
|
||||||
|
metrics.SetGaugeTo(MetricsAPI.GaugePairs, context.ClientPairs.AsNoTracking().Count());
|
||||||
|
metrics.SetGaugeTo(MetricsAPI.GaugePairsPaused, context.ClientPairs.AsNoTracking().Count(p => p.IsPaused));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Length == 0 || !string.Equals(args[0], "dry", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||||
|
{
|
||||||
|
var loggerFactory = LoggerFactory.Create(builder =>
|
||||||
|
{
|
||||||
|
builder.ClearProviders();
|
||||||
|
builder.AddConsole();
|
||||||
|
});
|
||||||
|
var logger = loggerFactory.CreateLogger<Startup>();
|
||||||
|
return Host.CreateDefaultBuilder(args)
|
||||||
|
.UseSystemd()
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.UseContentRoot(AppContext.BaseDirectory);
|
||||||
|
webBuilder.ConfigureLogging((ctx, builder) =>
|
||||||
|
{
|
||||||
|
builder.AddConfiguration(ctx.Configuration.GetSection("Logging"));
|
||||||
|
builder.AddFile(o => o.RootPath = AppContext.BaseDirectory);
|
||||||
|
});
|
||||||
|
webBuilder.UseStartup(ctx => new Startup(ctx.Configuration, logger));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"MareSynchronosServer": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": "true",
|
||||||
|
"launchBrowser": false,
|
||||||
|
//"applicationUrl": "https://localhost:5001;http://localhost:5000;https://192.168.1.124:5001;http://192.168.1.124:5000",
|
||||||
|
"applicationUrl": "http://localhost:5000;https://localhost:5001;https://darkarchon.internet-box.ch:5001",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Services;
|
||||||
|
|
||||||
|
public class CharaDataCleanupService : IHostedService
|
||||||
|
{
|
||||||
|
private readonly ILogger<CharaDataCleanupService> _logger;
|
||||||
|
private readonly IDbContextFactory<MareDbContext> _dbContextFactory;
|
||||||
|
private readonly CancellationTokenSource _cleanupCts = new();
|
||||||
|
|
||||||
|
public CharaDataCleanupService(ILogger<CharaDataCleanupService> logger, IDbContextFactory<MareDbContext> dbContextFactory)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_dbContextFactory = dbContextFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_ = Cleanup(cancellationToken);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Cleanup(CancellationToken ct)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("CharaData Cleanup Service started");
|
||||||
|
while (!ct.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
using (var db = await _dbContextFactory.CreateDbContextAsync(ct).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var dateTime = DateTime.UtcNow;
|
||||||
|
var expiredData = await db.CharaData.Where(c => c.ExpiryDate <= DateTime.UtcNow).ToListAsync(cancellationToken: ct).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_logger.LogInformation("Removing {count} expired Chara Data entries", expiredData.Count);
|
||||||
|
|
||||||
|
db.RemoveRange(expiredData);
|
||||||
|
await db.SaveChangesAsync(ct).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromHours(12), ct).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_cleanupCts?.Cancel();
|
||||||
|
_cleanupCts?.Dispose();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
using MareSynchronos.API.Dto.CharaData;
|
||||||
|
using MareSynchronos.API.SignalR;
|
||||||
|
using MareSynchronosServer.Hubs;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using StackExchange.Redis.Extensions.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Services;
|
||||||
|
|
||||||
|
public sealed class GPoseLobbyDistributionService : IHostedService, IDisposable
|
||||||
|
{
|
||||||
|
private CancellationTokenSource _runtimeCts = new();
|
||||||
|
private readonly Dictionary<string, Dictionary<string, WorldData>> _lobbyWorldData = [];
|
||||||
|
private readonly Dictionary<string, Dictionary<string, PoseData>> _lobbyPoseData = [];
|
||||||
|
private readonly SemaphoreSlim _lobbyPoseDataModificationSemaphore = new(1, 1);
|
||||||
|
private readonly SemaphoreSlim _lobbyWorldDataModificationSemaphore = new(1, 1);
|
||||||
|
|
||||||
|
public GPoseLobbyDistributionService(ILogger<GPoseLobbyDistributionService> logger, IRedisDatabase redisDb,
|
||||||
|
IHubContext<MareHub, IMareHub> hubContext)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_redisDb = redisDb;
|
||||||
|
_hubContext = hubContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
private readonly ILogger<GPoseLobbyDistributionService> _logger;
|
||||||
|
private readonly IRedisDatabase _redisDb;
|
||||||
|
private readonly IHubContext<MareHub, IMareHub> _hubContext;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_runtimeCts.Cancel();
|
||||||
|
_runtimeCts.Dispose();
|
||||||
|
_lobbyPoseDataModificationSemaphore.Dispose();
|
||||||
|
_lobbyWorldDataModificationSemaphore.Dispose();
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PushWorldData(string lobby, string user, WorldData worldData)
|
||||||
|
{
|
||||||
|
await _lobbyWorldDataModificationSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_lobbyWorldData.TryGetValue(lobby, out var worldDataDict))
|
||||||
|
{
|
||||||
|
_lobbyWorldData[lobby] = worldDataDict = new(StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
worldDataDict[user] = worldData;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during Pushing World Data for Lobby {lobby} by User {user}", lobby, user);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lobbyWorldDataModificationSemaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PushPoseData(string lobby, string user, PoseData poseData)
|
||||||
|
{
|
||||||
|
await _lobbyPoseDataModificationSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_lobbyPoseData.TryGetValue(lobby, out var poseDataDict))
|
||||||
|
{
|
||||||
|
_lobbyPoseData[lobby] = poseDataDict = new(StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
poseDataDict[user] = poseData;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during Pushing World Data for Lobby {lobby} by User {user}", lobby, user);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lobbyPoseDataModificationSemaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_ = WorldDataDistribution(_runtimeCts.Token);
|
||||||
|
_ = PoseDataDistribution(_runtimeCts.Token);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task WorldDataDistribution(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (!token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await DistributeWorldData(token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during World Data Distribution");
|
||||||
|
}
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PoseDataDistribution(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (!token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await DistributePoseData(token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during Pose Data Distribution");
|
||||||
|
}
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(2), token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DistributeWorldData(CancellationToken token)
|
||||||
|
{
|
||||||
|
await _lobbyWorldDataModificationSemaphore.WaitAsync(token).ConfigureAwait(false);
|
||||||
|
Dictionary<string, Dictionary<string, WorldData>> clone = [];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clone = _lobbyWorldData.ToDictionary(k => k.Key, k => k.Value, StringComparer.Ordinal);
|
||||||
|
_lobbyWorldData.Clear();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during Distributing World Data Clone generation");
|
||||||
|
_lobbyWorldData.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lobbyWorldDataModificationSemaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var lobbyId in clone)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!lobbyId.Value.Values.Any())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var gposeLobbyUsers = await _redisDb.GetAsync<List<string>>($"GposeLobby:{lobbyId.Key}").ConfigureAwait(false);
|
||||||
|
if (gposeLobbyUsers == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (var data in lobbyId.Value)
|
||||||
|
{
|
||||||
|
await _hubContext.Clients.Users(gposeLobbyUsers.Where(k => !string.Equals(k, data.Key, StringComparison.Ordinal)))
|
||||||
|
.Client_GposeLobbyPushWorldData(new(data.Key), data.Value).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during World Data Distribution for Lobby {lobby}", lobbyId.Key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DistributePoseData(CancellationToken token)
|
||||||
|
{
|
||||||
|
await _lobbyPoseDataModificationSemaphore.WaitAsync(token).ConfigureAwait(false);
|
||||||
|
Dictionary<string, Dictionary<string, PoseData>> clone = [];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clone = _lobbyPoseData.ToDictionary(k => k.Key, k => k.Value, StringComparer.Ordinal);
|
||||||
|
_lobbyPoseData.Clear();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during Distributing Pose Data Clone generation");
|
||||||
|
_lobbyPoseData.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lobbyPoseDataModificationSemaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var lobbyId in clone)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!lobbyId.Value.Values.Any())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var gposeLobbyUsers = await _redisDb.GetAsync<List<string>>($"GposeLobby:{lobbyId.Key}").ConfigureAwait(false);
|
||||||
|
if (gposeLobbyUsers == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (var data in lobbyId.Value)
|
||||||
|
{
|
||||||
|
await _hubContext.Clients.Users(gposeLobbyUsers.Where(k => !string.Equals(k, data.Key, StringComparison.Ordinal)))
|
||||||
|
.Client_GposeLobbyPushPoseData(new(data.Key), data.Value).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during Pose Data Distribution for Lobby {lobby}", lobbyId.Key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_runtimeCts.Cancel();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
using MareSynchronos.API.Dto;
|
||||||
|
using MareSynchronos.API.SignalR;
|
||||||
|
using MareSynchronosServer.Hubs;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using StackExchange.Redis.Extensions.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Services;
|
||||||
|
|
||||||
|
public class SystemInfoService : IHostedService, IDisposable
|
||||||
|
{
|
||||||
|
private readonly MareMetrics _mareMetrics;
|
||||||
|
private readonly IConfigurationService<ServerConfiguration> _config;
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly ILogger<SystemInfoService> _logger;
|
||||||
|
private readonly IHubContext<MareHub, IMareHub> _hubContext;
|
||||||
|
private readonly IRedisDatabase _redis;
|
||||||
|
private Timer _timer;
|
||||||
|
public SystemInfoDto SystemInfoDto { get; private set; } = new();
|
||||||
|
|
||||||
|
public SystemInfoService(MareMetrics mareMetrics, IConfigurationService<ServerConfiguration> configurationService, IServiceProvider services,
|
||||||
|
ILogger<SystemInfoService> logger, IHubContext<MareHub, IMareHub> hubContext, IRedisDatabase redisDb)
|
||||||
|
{
|
||||||
|
_mareMetrics = mareMetrics;
|
||||||
|
_config = configurationService;
|
||||||
|
_services = services;
|
||||||
|
_logger = logger;
|
||||||
|
_hubContext = hubContext;
|
||||||
|
_redis = redisDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("System Info Service started");
|
||||||
|
|
||||||
|
var timeOut = _config.IsMain ? 5 : 15;
|
||||||
|
|
||||||
|
_timer = new Timer(PushSystemInfo, null, TimeSpan.Zero, TimeSpan.FromSeconds(timeOut));
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PushSystemInfo(object state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ThreadPool.GetAvailableThreads(out int workerThreads, out int ioThreads);
|
||||||
|
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugeAvailableWorkerThreads, workerThreads);
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugeAvailableIOWorkerThreads, ioThreads);
|
||||||
|
|
||||||
|
var onlineUsers = (_redis.SearchKeysAsync("UID:*").GetAwaiter().GetResult()).Count();
|
||||||
|
SystemInfoDto = new SystemInfoDto()
|
||||||
|
{
|
||||||
|
OnlineUsers = onlineUsers,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_config.IsMain)
|
||||||
|
{
|
||||||
|
_logger.LogTrace("Sending System Info, Online Users: {onlineUsers}", onlineUsers);
|
||||||
|
|
||||||
|
_hubContext.Clients.All.Client_UpdateSystemInfo(SystemInfoDto);
|
||||||
|
|
||||||
|
using var scope = _services.CreateScope();
|
||||||
|
using var db = scope.ServiceProvider.GetService<MareDbContext>()!;
|
||||||
|
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugeAuthorizedConnections, onlineUsers);
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugePairs, db.ClientPairs.AsNoTracking().Count());
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugePairsPaused, db.ClientPairs.AsNoTracking().Count(p => p.IsPaused));
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugeGroups, db.Groups.AsNoTracking().Count());
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugeGroupPairs, db.GroupPairs.AsNoTracking().Count());
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugeGroupPairsPaused, db.GroupPairs.AsNoTracking().Count(p => p.IsPaused));
|
||||||
|
_mareMetrics.SetGaugeTo(MetricsAPI.GaugeUsersRegistered, db.Users.AsNoTracking().Count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Failed to push system info");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_timer?.Change(Timeout.Infinite, 0);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_timer?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosShared.Models;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Services;
|
||||||
|
|
||||||
|
public class UserCleanupService : IHostedService
|
||||||
|
{
|
||||||
|
private readonly MareMetrics metrics;
|
||||||
|
private readonly ILogger<UserCleanupService> _logger;
|
||||||
|
private readonly IDbContextFactory<MareDbContext> _mareDbContextFactory;
|
||||||
|
private readonly IConfigurationService<ServerConfiguration> _configuration;
|
||||||
|
private CancellationTokenSource _cleanupCts;
|
||||||
|
|
||||||
|
public UserCleanupService(MareMetrics metrics, ILogger<UserCleanupService> logger, IDbContextFactory<MareDbContext> mareDbContextFactory, IConfigurationService<ServerConfiguration> configuration)
|
||||||
|
{
|
||||||
|
this.metrics = metrics;
|
||||||
|
_logger = logger;
|
||||||
|
_mareDbContextFactory = mareDbContextFactory;
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Cleanup Service started");
|
||||||
|
_cleanupCts = new();
|
||||||
|
|
||||||
|
_ = CleanUp(_cleanupCts.Token);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CleanUp(CancellationToken ct)
|
||||||
|
{
|
||||||
|
while (!ct.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
using (var dbContext = await _mareDbContextFactory.CreateDbContextAsync(ct).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
|
||||||
|
CleanUpOutdatedLodestoneAuths(dbContext);
|
||||||
|
|
||||||
|
await PurgeUnusedAccounts(dbContext).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await PurgeTempInvites(dbContext).ConfigureAwait(false);
|
||||||
|
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
var now = DateTime.Now;
|
||||||
|
TimeOnly currentTime = new(now.Hour, now.Minute, now.Second);
|
||||||
|
TimeOnly futureTime = new(now.Hour, now.Minute - now.Minute % 10, 0);
|
||||||
|
var span = futureTime.AddMinutes(10) - currentTime;
|
||||||
|
|
||||||
|
_logger.LogInformation("User Cleanup Complete, next run at {date}", now.Add(span));
|
||||||
|
await Task.Delay(span, ct).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PurgeTempInvites(MareDbContext dbContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tempInvites = await dbContext.GroupTempInvites.ToListAsync().ConfigureAwait(false);
|
||||||
|
dbContext.RemoveRange(tempInvites.Where(i => i.ExpirationDate < DateTime.UtcNow));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Error during Temp Invite purge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PurgeUnusedAccounts(MareDbContext dbContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_configuration.GetValueOrDefault(nameof(ServerConfiguration.PurgeUnusedAccounts), false))
|
||||||
|
{
|
||||||
|
var usersOlderThanDays = _configuration.GetValueOrDefault(nameof(ServerConfiguration.PurgeUnusedAccountsPeriodInDays), 14);
|
||||||
|
var maxGroupsByUser = _configuration.GetValueOrDefault(nameof(ServerConfiguration.MaxGroupUserCount), 3);
|
||||||
|
|
||||||
|
_logger.LogInformation("Cleaning up users older than {usersOlderThanDays} days", usersOlderThanDays);
|
||||||
|
|
||||||
|
var allUsers = dbContext.Users.Where(u => string.IsNullOrEmpty(u.Alias)).ToList();
|
||||||
|
List<User> usersToRemove = new();
|
||||||
|
foreach (var user in allUsers)
|
||||||
|
{
|
||||||
|
if (user.LastLoggedIn < DateTime.UtcNow - TimeSpan.FromDays(usersOlderThanDays))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("User outdated: {userUID}", user.UID);
|
||||||
|
usersToRemove.Add(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var user in usersToRemove)
|
||||||
|
{
|
||||||
|
await SharedDbFunctions.PurgeUser(_logger, user, dbContext, maxGroupsByUser).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Cleaning up unauthorized users");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Error during user purge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CleanUpOutdatedLodestoneAuths(MareDbContext dbContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Cleaning up expired lodestone authentications");
|
||||||
|
var lodestoneAuths = dbContext.LodeStoneAuth.Include(u => u.User).Where(a => a.StartedAt != null).ToList();
|
||||||
|
List<LodeStoneAuth> expiredAuths = new List<LodeStoneAuth>();
|
||||||
|
foreach (var auth in lodestoneAuths)
|
||||||
|
{
|
||||||
|
if (auth.StartedAt < DateTime.UtcNow - TimeSpan.FromMinutes(15))
|
||||||
|
{
|
||||||
|
expiredAuths.Add(auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbContext.Users.RemoveRange(expiredAuths.Where(u => u.User != null).Select(a => a.User));
|
||||||
|
dbContext.RemoveRange(expiredAuths);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Error during expired auths cleanup");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PurgeUser(User user, MareDbContext dbContext)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Purging user: {uid}", user.UID);
|
||||||
|
|
||||||
|
var lodestone = dbContext.LodeStoneAuth.SingleOrDefault(a => a.User.UID == user.UID);
|
||||||
|
|
||||||
|
if (lodestone != null)
|
||||||
|
{
|
||||||
|
dbContext.Remove(lodestone);
|
||||||
|
}
|
||||||
|
|
||||||
|
var auth = dbContext.Auth.Single(a => a.UserUID == user.UID);
|
||||||
|
|
||||||
|
var ownPairData = dbContext.ClientPairs.Where(u => u.User.UID == user.UID).ToList();
|
||||||
|
dbContext.ClientPairs.RemoveRange(ownPairData);
|
||||||
|
var otherPairData = dbContext.ClientPairs.Include(u => u.User)
|
||||||
|
.Where(u => u.OtherUser.UID == user.UID).ToList();
|
||||||
|
dbContext.ClientPairs.RemoveRange(otherPairData);
|
||||||
|
|
||||||
|
var userJoinedGroups = await dbContext.GroupPairs.Include(g => g.Group).Where(u => u.GroupUserUID == user.UID).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var userGroupPair in userJoinedGroups)
|
||||||
|
{
|
||||||
|
bool ownerHasLeft = string.Equals(userGroupPair.Group.OwnerUID, user.UID, StringComparison.Ordinal);
|
||||||
|
|
||||||
|
if (ownerHasLeft)
|
||||||
|
{
|
||||||
|
var groupPairs = await dbContext.GroupPairs.Where(g => g.GroupGID == userGroupPair.GroupGID && g.GroupUserUID != user.UID).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!groupPairs.Any())
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Group {gid} has no new owner, deleting", userGroupPair.GroupGID);
|
||||||
|
dbContext.Groups.Remove(userGroupPair.Group);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ = await SharedDbFunctions.MigrateOrDeleteGroup(dbContext, userGroupPair.Group, groupPairs, _configuration.GetValueOrDefault(nameof(ServerConfiguration.MaxExistingGroupsByUser), 3)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbContext.GroupPairs.Remove(userGroupPair);
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("User purged: {uid}", user.UID);
|
||||||
|
|
||||||
|
dbContext.Auth.Remove(auth);
|
||||||
|
dbContext.Users.Remove(user);
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_cleanupCts.Cancel();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
343
MareSynchronosServer/MareSynchronosServer/Startup.cs
Normal file
343
MareSynchronosServer/MareSynchronosServer/Startup.cs
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using MareSynchronosServer.Hubs;
|
||||||
|
using Microsoft.AspNetCore.Http.Connections;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using AspNetCoreRateLimit;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using MareSynchronosServer.Services;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using Prometheus;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.Text;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using StackExchange.Redis.Extensions.Core.Configuration;
|
||||||
|
using System.Net;
|
||||||
|
using StackExchange.Redis.Extensions.System.Text.Json;
|
||||||
|
using MareSynchronos.API.SignalR;
|
||||||
|
using MessagePack;
|
||||||
|
using MessagePack.Resolvers;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
|
using MareSynchronosServer.Controllers;
|
||||||
|
using MareSynchronosShared.RequirementHandlers;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer;
|
||||||
|
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
private readonly ILogger<Startup> _logger;
|
||||||
|
|
||||||
|
public Startup(IConfiguration configuration, ILogger<Startup> logger)
|
||||||
|
{
|
||||||
|
Configuration = configuration;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddHttpContextAccessor();
|
||||||
|
|
||||||
|
services.AddTransient(_ => Configuration);
|
||||||
|
|
||||||
|
var mareConfig = Configuration.GetRequiredSection("MareSynchronos");
|
||||||
|
|
||||||
|
// configure metrics
|
||||||
|
ConfigureMetrics(services);
|
||||||
|
|
||||||
|
// configure database
|
||||||
|
ConfigureDatabase(services, mareConfig);
|
||||||
|
|
||||||
|
// configure authentication and authorization
|
||||||
|
ConfigureAuthorization(services);
|
||||||
|
|
||||||
|
// configure rate limiting
|
||||||
|
ConfigureIpRateLimiting(services);
|
||||||
|
|
||||||
|
// configure SignalR
|
||||||
|
ConfigureSignalR(services, mareConfig);
|
||||||
|
|
||||||
|
// configure mare specific services
|
||||||
|
ConfigureMareServices(services, mareConfig);
|
||||||
|
|
||||||
|
services.AddHealthChecks();
|
||||||
|
services.AddControllers().ConfigureApplicationPartManager(a =>
|
||||||
|
{
|
||||||
|
a.FeatureProviders.Remove(a.FeatureProviders.OfType<ControllerFeatureProvider>().First());
|
||||||
|
if (mareConfig.GetValue<Uri>(nameof(ServerConfiguration.MainServerAddress), defaultValue: null) == null)
|
||||||
|
{
|
||||||
|
a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(MareServerConfigurationController), typeof(MareBaseConfigurationController), typeof(ClientMessageController), typeof(MainController)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a.FeatureProviders.Add(new AllowedControllersFeatureProvider());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureMareServices(IServiceCollection services, IConfigurationSection mareConfig)
|
||||||
|
{
|
||||||
|
bool isMainServer = mareConfig.GetValue<Uri>(nameof(ServerConfiguration.MainServerAddress), defaultValue: null) == null;
|
||||||
|
|
||||||
|
services.Configure<ServerConfiguration>(Configuration.GetRequiredSection("MareSynchronos"));
|
||||||
|
services.Configure<MareConfigurationBase>(Configuration.GetRequiredSection("MareSynchronos"));
|
||||||
|
|
||||||
|
services.AddSingleton<ServerTokenGenerator>();
|
||||||
|
services.AddSingleton<SystemInfoService>();
|
||||||
|
services.AddHostedService(provider => provider.GetService<SystemInfoService>());
|
||||||
|
// configure services based on main server status
|
||||||
|
ConfigureServicesBasedOnShardType(services, mareConfig, isMainServer);
|
||||||
|
|
||||||
|
if (isMainServer)
|
||||||
|
{
|
||||||
|
services.AddSingleton<UserCleanupService>();
|
||||||
|
services.AddHostedService(provider => provider.GetService<UserCleanupService>());
|
||||||
|
services.AddSingleton<CharaDataCleanupService>();
|
||||||
|
services.AddHostedService(provider => provider.GetService<CharaDataCleanupService>());
|
||||||
|
}
|
||||||
|
|
||||||
|
services.AddSingleton<GPoseLobbyDistributionService>();
|
||||||
|
services.AddHostedService(provider => provider.GetService<GPoseLobbyDistributionService>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureSignalR(IServiceCollection services, IConfigurationSection mareConfig)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IUserIdProvider, IdBasedUserIdProvider>();
|
||||||
|
|
||||||
|
var signalRServiceBuilder = services.AddSignalR(hubOptions =>
|
||||||
|
{
|
||||||
|
hubOptions.MaximumReceiveMessageSize = long.MaxValue;
|
||||||
|
hubOptions.EnableDetailedErrors = true;
|
||||||
|
hubOptions.MaximumParallelInvocationsPerClient = 10;
|
||||||
|
hubOptions.StreamBufferCapacity = 200;
|
||||||
|
|
||||||
|
hubOptions.AddFilter<SignalRLimitFilter>();
|
||||||
|
}).AddMessagePackProtocol(opt =>
|
||||||
|
{
|
||||||
|
var resolver = CompositeResolver.Create(StandardResolverAllowPrivate.Instance,
|
||||||
|
BuiltinResolver.Instance,
|
||||||
|
AttributeFormatterResolver.Instance,
|
||||||
|
// replace enum resolver
|
||||||
|
DynamicEnumAsStringResolver.Instance,
|
||||||
|
DynamicGenericResolver.Instance,
|
||||||
|
DynamicUnionResolver.Instance,
|
||||||
|
DynamicObjectResolver.Instance,
|
||||||
|
PrimitiveObjectResolver.Instance,
|
||||||
|
// final fallback(last priority)
|
||||||
|
StandardResolver.Instance);
|
||||||
|
|
||||||
|
opt.SerializerOptions = MessagePackSerializerOptions.Standard
|
||||||
|
.WithCompression(MessagePackCompression.Lz4Block)
|
||||||
|
.WithResolver(resolver);
|
||||||
|
});
|
||||||
|
|
||||||
|
// configure redis for SignalR
|
||||||
|
var redisConnection = mareConfig.GetValue(nameof(ServerConfiguration.RedisConnectionString), string.Empty);
|
||||||
|
signalRServiceBuilder.AddStackExchangeRedis(redisConnection, options => { });
|
||||||
|
|
||||||
|
var options = ConfigurationOptions.Parse(redisConnection);
|
||||||
|
|
||||||
|
var endpoint = options.EndPoints[0];
|
||||||
|
string address = "";
|
||||||
|
int port = 0;
|
||||||
|
if (endpoint is DnsEndPoint dnsEndPoint) { address = dnsEndPoint.Host; port = dnsEndPoint.Port; }
|
||||||
|
if (endpoint is IPEndPoint ipEndPoint) { address = ipEndPoint.Address.ToString(); port = ipEndPoint.Port; }
|
||||||
|
var redisConfiguration = new RedisConfiguration()
|
||||||
|
{
|
||||||
|
AbortOnConnectFail = true,
|
||||||
|
KeyPrefix = "",
|
||||||
|
Hosts = new RedisHost[]
|
||||||
|
{
|
||||||
|
new RedisHost(){ Host = address, Port = port },
|
||||||
|
},
|
||||||
|
AllowAdmin = true,
|
||||||
|
ConnectTimeout = options.ConnectTimeout,
|
||||||
|
Database = 0,
|
||||||
|
Ssl = false,
|
||||||
|
Password = options.Password,
|
||||||
|
ServerEnumerationStrategy = new ServerEnumerationStrategy()
|
||||||
|
{
|
||||||
|
Mode = ServerEnumerationStrategy.ModeOptions.All,
|
||||||
|
TargetRole = ServerEnumerationStrategy.TargetRoleOptions.Any,
|
||||||
|
UnreachableServerAction = ServerEnumerationStrategy.UnreachableServerActionOptions.Throw,
|
||||||
|
},
|
||||||
|
MaxValueLength = 1024,
|
||||||
|
PoolSize = mareConfig.GetValue(nameof(ServerConfiguration.RedisPool), 50),
|
||||||
|
SyncTimeout = options.SyncTimeout,
|
||||||
|
};
|
||||||
|
|
||||||
|
services.AddStackExchangeRedisExtensions<SystemTextJsonSerializer>(redisConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureIpRateLimiting(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
|
||||||
|
services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));
|
||||||
|
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
|
||||||
|
services.AddMemoryCache();
|
||||||
|
services.AddInMemoryRateLimiting();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureAuthorization(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddTransient<IAuthorizationHandler, UserRequirementHandler>();
|
||||||
|
|
||||||
|
services.AddOptions<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.Configure<IConfigurationService<MareConfigurationBase>>((options, config) =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new()
|
||||||
|
{
|
||||||
|
ValidateIssuer = false,
|
||||||
|
ValidateLifetime = false,
|
||||||
|
ValidateAudience = false,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(config.GetValue<string>(nameof(MareConfigurationBase.Jwt)))),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddAuthentication(o =>
|
||||||
|
{
|
||||||
|
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
}).AddJwtBearer();
|
||||||
|
|
||||||
|
services.AddAuthorization(options =>
|
||||||
|
{
|
||||||
|
options.DefaultPolicy = new AuthorizationPolicyBuilder()
|
||||||
|
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.RequireAuthenticatedUser().Build();
|
||||||
|
options.AddPolicy("Authenticated", policy =>
|
||||||
|
{
|
||||||
|
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
|
||||||
|
policy.RequireAuthenticatedUser();
|
||||||
|
});
|
||||||
|
options.AddPolicy("Identified", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified));
|
||||||
|
});
|
||||||
|
options.AddPolicy("Admin", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified | UserRequirements.Administrator));
|
||||||
|
});
|
||||||
|
options.AddPolicy("Moderator", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified | UserRequirements.Moderator | UserRequirements.Administrator));
|
||||||
|
});
|
||||||
|
options.AddPolicy("Internal", new AuthorizationPolicyBuilder().RequireClaim(MareClaimTypes.Internal, "true").Build());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureDatabase(IServiceCollection services, IConfigurationSection mareConfig)
|
||||||
|
{
|
||||||
|
services.AddDbContextPool<MareDbContext>(options =>
|
||||||
|
{
|
||||||
|
options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"), builder =>
|
||||||
|
{
|
||||||
|
builder.MigrationsHistoryTable("_efmigrationshistory", "public");
|
||||||
|
builder.MigrationsAssembly("MareSynchronosShared");
|
||||||
|
}).UseSnakeCaseNamingConvention();
|
||||||
|
options.EnableThreadSafetyChecks(false);
|
||||||
|
}, mareConfig.GetValue(nameof(MareConfigurationBase.DbContextPoolSize), 1024));
|
||||||
|
services.AddDbContextFactory<MareDbContext>(options =>
|
||||||
|
{
|
||||||
|
options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"), builder =>
|
||||||
|
{
|
||||||
|
builder.MigrationsHistoryTable("_efmigrationshistory", "public");
|
||||||
|
builder.MigrationsAssembly("MareSynchronosShared");
|
||||||
|
}).UseSnakeCaseNamingConvention();
|
||||||
|
options.EnableThreadSafetyChecks(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureMetrics(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<MareMetrics>(m => new MareMetrics(m.GetService<ILogger<MareMetrics>>(), new List<string>
|
||||||
|
{
|
||||||
|
MetricsAPI.CounterInitializedConnections,
|
||||||
|
MetricsAPI.CounterUserPushData,
|
||||||
|
MetricsAPI.CounterUserPushDataTo,
|
||||||
|
MetricsAPI.CounterUsersRegisteredDeleted,
|
||||||
|
MetricsAPI.CounterAuthenticationCacheHits,
|
||||||
|
MetricsAPI.CounterAuthenticationFailures,
|
||||||
|
MetricsAPI.CounterAuthenticationRequests,
|
||||||
|
MetricsAPI.CounterAuthenticationSuccesses,
|
||||||
|
}, new List<string>
|
||||||
|
{
|
||||||
|
MetricsAPI.GaugeAuthorizedConnections,
|
||||||
|
MetricsAPI.GaugeConnections,
|
||||||
|
MetricsAPI.GaugePairs,
|
||||||
|
MetricsAPI.GaugePairsPaused,
|
||||||
|
MetricsAPI.GaugeAvailableIOWorkerThreads,
|
||||||
|
MetricsAPI.GaugeAvailableWorkerThreads,
|
||||||
|
MetricsAPI.GaugeGroups,
|
||||||
|
MetricsAPI.GaugeGroupPairs,
|
||||||
|
MetricsAPI.GaugeGroupPairsPaused,
|
||||||
|
MetricsAPI.GaugeUsersRegistered,
|
||||||
|
MetricsAPI.GaugeGposeLobbies,
|
||||||
|
MetricsAPI.GaugeGposeLobbyUsers
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureServicesBasedOnShardType(IServiceCollection services, IConfigurationSection mareConfig, bool isMainServer)
|
||||||
|
{
|
||||||
|
if (!isMainServer)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IConfigurationService<ServerConfiguration>, MareConfigurationServiceClient<ServerConfiguration>>();
|
||||||
|
services.AddSingleton<IConfigurationService<MareConfigurationBase>, MareConfigurationServiceClient<MareConfigurationBase>>();
|
||||||
|
|
||||||
|
services.AddHostedService(p => (MareConfigurationServiceClient<ServerConfiguration>)p.GetService<IConfigurationService<ServerConfiguration>>());
|
||||||
|
services.AddHostedService(p => (MareConfigurationServiceClient<MareConfigurationBase>)p.GetService<IConfigurationService<MareConfigurationBase>>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
services.AddSingleton<IConfigurationService<ServerConfiguration>, MareConfigurationServiceServer<ServerConfiguration>>();
|
||||||
|
services.AddSingleton<IConfigurationService<MareConfigurationBase>, MareConfigurationServiceServer<MareConfigurationBase>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
|
||||||
|
{
|
||||||
|
logger.LogInformation("Running Configure");
|
||||||
|
|
||||||
|
var config = app.ApplicationServices.GetRequiredService<IConfigurationService<MareConfigurationBase>>();
|
||||||
|
|
||||||
|
app.UseIpRateLimiting();
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseWebSockets();
|
||||||
|
app.UseHttpMetrics();
|
||||||
|
|
||||||
|
var metricServer = new KestrelMetricServer(config.GetValueOrDefault<int>(nameof(MareConfigurationBase.MetricsPort), 4980));
|
||||||
|
metricServer.Start();
|
||||||
|
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapHub<MareHub>(IMareHub.Path, options =>
|
||||||
|
{
|
||||||
|
options.ApplicationMaxBufferSize = 5242880;
|
||||||
|
options.TransportMaxBufferSize = 5242880;
|
||||||
|
options.Transports = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling;
|
||||||
|
});
|
||||||
|
|
||||||
|
endpoints.MapHealthChecks("/health").AllowAnonymous();
|
||||||
|
endpoints.MapControllers();
|
||||||
|
|
||||||
|
foreach (var source in endpoints.DataSources.SelectMany(e => e.Endpoints).Cast<RouteEndpoint>())
|
||||||
|
{
|
||||||
|
if (source == null) continue;
|
||||||
|
_logger.LogInformation("Endpoint: {url} ", source.RoutePattern.RawText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Data.Enum;
|
||||||
|
using MareSynchronos.API.Data.Extensions;
|
||||||
|
using MareSynchronosShared.Models;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Utils
|
||||||
|
{
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static GroupData ToGroupData(this Group group)
|
||||||
|
{
|
||||||
|
return new GroupData(group.GID, group.Alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserData ToUserData(this GroupPair pair)
|
||||||
|
{
|
||||||
|
return new UserData(pair.GroupUser.UID, pair.GroupUser.Alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserData ToUserData(this User user)
|
||||||
|
{
|
||||||
|
return new UserData(user.UID, user.Alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupPermissions GetGroupPermissions(this Group group)
|
||||||
|
{
|
||||||
|
var permissions = GroupPermissions.NoneSet;
|
||||||
|
permissions.SetDisableAnimations(group.DisableAnimations);
|
||||||
|
permissions.SetDisableSounds(group.DisableSounds);
|
||||||
|
permissions.SetDisableInvites(!group.InvitesEnabled);
|
||||||
|
permissions.SetDisableVFX(group.DisableVFX);
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupUserPermissions GetGroupPairPermissions(this GroupPair groupPair)
|
||||||
|
{
|
||||||
|
var permissions = GroupUserPermissions.NoneSet;
|
||||||
|
permissions.SetDisableAnimations(groupPair.DisableAnimations);
|
||||||
|
permissions.SetDisableSounds(groupPair.DisableSounds);
|
||||||
|
permissions.SetPaused(groupPair.IsPaused);
|
||||||
|
permissions.SetDisableVFX(groupPair.DisableVFX);
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupUserInfo GetGroupPairUserInfo(this GroupPair groupPair)
|
||||||
|
{
|
||||||
|
var groupUserInfo = GroupUserInfo.None;
|
||||||
|
groupUserInfo.SetPinned(groupPair.IsPinned);
|
||||||
|
groupUserInfo.SetModerator(groupPair.IsModerator);
|
||||||
|
return groupUserInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using MareSynchronosServer.Hubs;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Utils;
|
||||||
|
|
||||||
|
public class MareHubLogger
|
||||||
|
{
|
||||||
|
private readonly MareHub _hub;
|
||||||
|
private readonly ILogger<MareHub> _logger;
|
||||||
|
|
||||||
|
public MareHubLogger(MareHub hub, ILogger<MareHub> logger)
|
||||||
|
{
|
||||||
|
_hub = hub;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object[] Args(params object[] args)
|
||||||
|
{
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogCallInfo(object[] args = null, [CallerMemberName] string methodName = "")
|
||||||
|
{
|
||||||
|
string formattedArgs = args != null && args.Length != 0 ? "|" + string.Join(":", args) : string.Empty;
|
||||||
|
_logger.LogInformation("{uid}:{method}{args}", _hub.UserUID, methodName, formattedArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogCallWarning(object[] args = null, [CallerMemberName] string methodName = "")
|
||||||
|
{
|
||||||
|
string formattedArgs = args != null && args.Length != 0 ? "|" + string.Join(":", args) : string.Empty;
|
||||||
|
_logger.LogWarning("{uid}:{method}{args}", _hub.UserUID, methodName, formattedArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace MareSynchronosServer.Utils;
|
||||||
|
|
||||||
|
public enum PauseInfo
|
||||||
|
{
|
||||||
|
NoConnection,
|
||||||
|
Paused,
|
||||||
|
Unpaused,
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace MareSynchronosServer.Utils;
|
||||||
|
|
||||||
|
public record PauseState
|
||||||
|
{
|
||||||
|
public string GID { get; set; }
|
||||||
|
public bool IsPaused => IsSelfPaused || IsOtherPaused;
|
||||||
|
public bool IsSelfPaused { get; set; }
|
||||||
|
public bool IsOtherPaused { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
namespace MareSynchronosServer.Utils;
|
||||||
|
|
||||||
|
public record PausedEntry
|
||||||
|
{
|
||||||
|
public string UID { get; set; }
|
||||||
|
public List<PauseState> PauseStates { get; set; } = new();
|
||||||
|
|
||||||
|
public PauseInfo IsDirectlyPaused => PauseStateWithoutGroups == null ? PauseInfo.NoConnection
|
||||||
|
: PauseStates.First(g => g.GID == null).IsPaused ? PauseInfo.Paused : PauseInfo.Unpaused;
|
||||||
|
|
||||||
|
public PauseInfo IsPausedPerGroup => !PauseStatesWithoutDirect.Any() ? PauseInfo.NoConnection
|
||||||
|
: PauseStatesWithoutDirect.All(p => p.IsPaused) ? PauseInfo.Paused : PauseInfo.Unpaused;
|
||||||
|
|
||||||
|
private IEnumerable<PauseState> PauseStatesWithoutDirect => PauseStates.Where(f => f.GID != null);
|
||||||
|
private PauseState PauseStateWithoutGroups => PauseStates.SingleOrDefault(p => p.GID == null);
|
||||||
|
|
||||||
|
public bool IsPaused
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var isDirectlyPaused = IsDirectlyPaused;
|
||||||
|
bool result;
|
||||||
|
if (isDirectlyPaused != PauseInfo.NoConnection)
|
||||||
|
{
|
||||||
|
result = isDirectlyPaused == PauseInfo.Paused;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = IsPausedPerGroup == PauseInfo.Paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PauseInfo IsOtherPausedForSpecificGroup(string gid)
|
||||||
|
{
|
||||||
|
var state = PauseStatesWithoutDirect.SingleOrDefault(g => string.Equals(g.GID, gid, StringComparison.Ordinal));
|
||||||
|
if (state == null) return PauseInfo.NoConnection;
|
||||||
|
return state.IsOtherPaused ? PauseInfo.Paused : PauseInfo.Unpaused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PauseInfo IsPausedForSpecificGroup(string gid)
|
||||||
|
{
|
||||||
|
var state = PauseStatesWithoutDirect.SingleOrDefault(g => string.Equals(g.GID, gid, StringComparison.Ordinal));
|
||||||
|
if (state == null) return PauseInfo.NoConnection;
|
||||||
|
return state.IsPaused ? PauseInfo.Paused : PauseInfo.NoConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PauseInfo IsPausedExcludingGroup(string gid)
|
||||||
|
{
|
||||||
|
var states = PauseStatesWithoutDirect.Where(f => !string.Equals(f.GID, gid, StringComparison.Ordinal)).ToList();
|
||||||
|
if (!states.Any()) return PauseInfo.NoConnection;
|
||||||
|
var result = states.All(p => p.IsPaused);
|
||||||
|
if (result) return PauseInfo.Paused;
|
||||||
|
return PauseInfo.Unpaused;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
MareSynchronosServer/MareSynchronosServer/Utils/UserPair.cs
Normal file
12
MareSynchronosServer/MareSynchronosServer/Utils/UserPair.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
public partial class MareHub
|
||||||
|
{
|
||||||
|
private record UserPair
|
||||||
|
{
|
||||||
|
public string UserUID { get; set; }
|
||||||
|
public string OtherUserUID { get; set; }
|
||||||
|
public bool UserPausedOther { get; set; }
|
||||||
|
public bool OtherPausedUser { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
61
MareSynchronosServer/MareSynchronosServer/appsettings.json
Normal file
61
MareSynchronosServer/MareSynchronosServer/appsettings.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Host=localhost;Port=5432;Database=mare;Username=postgres"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
|
"MareSynchronosServer.Authentication": "Warning",
|
||||||
|
"System.IO.IOException": "Warning"
|
||||||
|
},
|
||||||
|
"File": {
|
||||||
|
"BasePath": "logs",
|
||||||
|
"FileAccessMode": "KeepOpenAndAutoFlush",
|
||||||
|
"FileEncodingName": "utf-8",
|
||||||
|
"DateFormat": "yyyMMdd",
|
||||||
|
"MaxFileSize": 10485760,
|
||||||
|
"Files": [
|
||||||
|
{
|
||||||
|
"Path": "mare-<counter>.log"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MareSynchronos": {
|
||||||
|
"DbContextPoolSize": 2000,
|
||||||
|
"CdnFullUrl": "https://<url or ip to your server>/cache/",
|
||||||
|
"ServiceAddress": "http://localhost:5002",
|
||||||
|
"StaticFileServiceAddress": "http://localhost:5003"
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"Kestrel": {
|
||||||
|
"Endpoints": {
|
||||||
|
"Https": {
|
||||||
|
"Url": "https://+:5000",
|
||||||
|
"Certificate": {
|
||||||
|
"Subject": "darkarchon.internet-box.ch",
|
||||||
|
"Store": "My",
|
||||||
|
"Location": "LocalMachine"
|
||||||
|
//"AllowInvalid": false
|
||||||
|
// "Path": "", //use path, keypath and password to provide a valid certificate if not using windows key store
|
||||||
|
// "KeyPath": ""
|
||||||
|
// "Password": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IpRateLimiting": {
|
||||||
|
"EnableEndpointRateLimiting": false,
|
||||||
|
"StackBlockedRequests": false,
|
||||||
|
"RealIpHeader": "X-Real-IP",
|
||||||
|
"ClientIdHeader": "X-ClientId",
|
||||||
|
"HttpStatusCode": 429,
|
||||||
|
"IpWhitelist": [ ],
|
||||||
|
"GeneralRules": [ ]
|
||||||
|
},
|
||||||
|
"IPRateLimitPolicies": {
|
||||||
|
"IpRules": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-ef": {
|
||||||
|
"version": "6.0.8",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-ef"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,421 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.Interactions;
|
||||||
|
using Discord.Rest;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using MareSynchronos.API.Data.Enum;
|
||||||
|
using MareSynchronos.API.Dto.User;
|
||||||
|
using MareSynchronos.API.SignalR;
|
||||||
|
using MareSynchronosServer.Hubs;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MareSynchronosServices.Discord;
|
||||||
|
|
||||||
|
internal class DiscordBot : IHostedService
|
||||||
|
{
|
||||||
|
private readonly DiscordBotServices _botServices;
|
||||||
|
private readonly IConfigurationService<ServicesConfiguration> _configurationService;
|
||||||
|
private readonly IConnectionMultiplexer _connectionMultiplexer;
|
||||||
|
private readonly DiscordSocketClient _discordClient;
|
||||||
|
private readonly ILogger<DiscordBot> _logger;
|
||||||
|
private readonly IHubContext<MareHub> _mareHubContext;
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private InteractionService _interactionModule;
|
||||||
|
private CancellationTokenSource? _processReportQueueCts;
|
||||||
|
private CancellationTokenSource? _updateStatusCts;
|
||||||
|
private CancellationTokenSource? _vanityUpdateCts;
|
||||||
|
|
||||||
|
public DiscordBot(DiscordBotServices botServices, IServiceProvider services, IConfigurationService<ServicesConfiguration> configuration,
|
||||||
|
IHubContext<MareHub> mareHubContext,
|
||||||
|
ILogger<DiscordBot> logger, IConnectionMultiplexer connectionMultiplexer)
|
||||||
|
{
|
||||||
|
_botServices = botServices;
|
||||||
|
_services = services;
|
||||||
|
_configurationService = configuration;
|
||||||
|
_mareHubContext = mareHubContext;
|
||||||
|
_logger = logger;
|
||||||
|
_connectionMultiplexer = connectionMultiplexer;
|
||||||
|
_discordClient = new(new DiscordSocketConfig()
|
||||||
|
{
|
||||||
|
DefaultRetryMode = RetryMode.AlwaysRetry
|
||||||
|
});
|
||||||
|
|
||||||
|
_discordClient.Log += Log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var token = _configurationService.GetValueOrDefault(nameof(ServicesConfiguration.DiscordBotToken), string.Empty);
|
||||||
|
if (!string.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
|
_interactionModule = new InteractionService(_discordClient);
|
||||||
|
await _interactionModule.AddModuleAsync(typeof(MareModule), _services).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await _discordClient.LoginAsync(TokenType.Bot, token).ConfigureAwait(false);
|
||||||
|
await _discordClient.StartAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_discordClient.Ready += DiscordClient_Ready;
|
||||||
|
_discordClient.ButtonExecuted += ButtonExecutedHandler;
|
||||||
|
_discordClient.InteractionCreated += async (x) =>
|
||||||
|
{
|
||||||
|
var ctx = new SocketInteractionContext(_discordClient, x);
|
||||||
|
await _interactionModule.ExecuteCommandAsync(ctx, _services);
|
||||||
|
};
|
||||||
|
|
||||||
|
await _botServices.Start();
|
||||||
|
_ = UpdateStatusAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(_configurationService.GetValueOrDefault(nameof(ServicesConfiguration.DiscordBotToken), string.Empty)))
|
||||||
|
{
|
||||||
|
_discordClient.ButtonExecuted -= ButtonExecutedHandler;
|
||||||
|
|
||||||
|
await _botServices.Stop();
|
||||||
|
_processReportQueueCts?.Cancel();
|
||||||
|
_updateStatusCts?.Cancel();
|
||||||
|
_vanityUpdateCts?.Cancel();
|
||||||
|
|
||||||
|
await _discordClient.LogoutAsync().ConfigureAwait(false);
|
||||||
|
await _discordClient.StopAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ButtonExecutedHandler(SocketMessageComponent arg)
|
||||||
|
{
|
||||||
|
var id = arg.Data.CustomId;
|
||||||
|
if (!id.StartsWith("mare-report-button", StringComparison.Ordinal)) return;
|
||||||
|
|
||||||
|
var userId = arg.User.Id;
|
||||||
|
using var scope = _services.CreateScope();
|
||||||
|
using var dbContext = scope.ServiceProvider.GetRequiredService<MareDbContext>();
|
||||||
|
var user = await dbContext.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(u => u.DiscordId == userId).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (user == null || (!user.User.IsModerator && !user.User.IsAdmin))
|
||||||
|
{
|
||||||
|
EmbedBuilder eb = new();
|
||||||
|
eb.WithTitle($"Cannot resolve report");
|
||||||
|
eb.WithDescription($"<@{userId}>: You have no rights to resolve this report");
|
||||||
|
await arg.RespondAsync(embed: eb.Build()).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = id.Remove(0, "mare-report-button-".Length);
|
||||||
|
var split = id.Split('-', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
var profile = await dbContext.UserProfileData.SingleAsync(u => u.UserUID == split[1]).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var embed = arg.Message.Embeds.First();
|
||||||
|
|
||||||
|
var builder = embed.ToEmbedBuilder();
|
||||||
|
var otherPairs = await dbContext.ClientPairs.Where(p => p.UserUID == split[1]).Select(p => p.OtherUserUID).ToListAsync().ConfigureAwait(false);
|
||||||
|
switch (split[0])
|
||||||
|
{
|
||||||
|
case "dismiss":
|
||||||
|
builder.AddField("Resolution", $"Dismissed by <@{userId}>");
|
||||||
|
builder.WithColor(Color.Green);
|
||||||
|
profile.FlaggedForReport = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "banreporting":
|
||||||
|
builder.AddField("Resolution", $"Dismissed by <@{userId}>, Reporting user banned");
|
||||||
|
builder.WithColor(Color.DarkGreen);
|
||||||
|
profile.FlaggedForReport = false;
|
||||||
|
var reportingUser = await dbContext.Auth.SingleAsync(u => u.UserUID == split[2]).ConfigureAwait(false);
|
||||||
|
reportingUser.IsBanned = true;
|
||||||
|
var regReporting = await dbContext.LodeStoneAuth.SingleAsync(u => u.User.UID == reportingUser.UserUID).ConfigureAwait(false);
|
||||||
|
dbContext.BannedRegistrations.Add(new MareSynchronosShared.Models.BannedRegistrations()
|
||||||
|
{
|
||||||
|
DiscordIdOrLodestoneAuth = regReporting.HashedLodestoneId
|
||||||
|
});
|
||||||
|
dbContext.BannedRegistrations.Add(new MareSynchronosShared.Models.BannedRegistrations()
|
||||||
|
{
|
||||||
|
DiscordIdOrLodestoneAuth = regReporting.DiscordId.ToString()
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "banprofile":
|
||||||
|
builder.AddField("Resolution", $"Profile has been banned by <@{userId}>");
|
||||||
|
builder.WithColor(Color.Red);
|
||||||
|
profile.Base64ProfileImage = null;
|
||||||
|
profile.UserDescription = null;
|
||||||
|
profile.ProfileDisabled = true;
|
||||||
|
profile.FlaggedForReport = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "banuser":
|
||||||
|
builder.AddField("Resolution", $"User has been banned by <@{userId}>");
|
||||||
|
builder.WithColor(Color.DarkRed);
|
||||||
|
var offendingUser = await dbContext.Auth.SingleAsync(u => u.UserUID == split[1]).ConfigureAwait(false);
|
||||||
|
offendingUser.IsBanned = true;
|
||||||
|
profile.Base64ProfileImage = null;
|
||||||
|
profile.UserDescription = null;
|
||||||
|
profile.ProfileDisabled = true;
|
||||||
|
var reg = await dbContext.LodeStoneAuth.SingleAsync(u => u.User.UID == offendingUser.UserUID).ConfigureAwait(false);
|
||||||
|
dbContext.BannedRegistrations.Add(new MareSynchronosShared.Models.BannedRegistrations()
|
||||||
|
{
|
||||||
|
DiscordIdOrLodestoneAuth = reg.HashedLodestoneId
|
||||||
|
});
|
||||||
|
dbContext.BannedRegistrations.Add(new MareSynchronosShared.Models.BannedRegistrations()
|
||||||
|
{
|
||||||
|
DiscordIdOrLodestoneAuth = reg.DiscordId.ToString()
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
await _mareHubContext.Clients.Users(otherPairs).SendAsync(nameof(IMareHub.Client_UserUpdateProfile), new UserDto(new(split[1]))).ConfigureAwait(false);
|
||||||
|
await _mareHubContext.Clients.User(split[1]).SendAsync(nameof(IMareHub.Client_UserUpdateProfile), new UserDto(new(split[1]))).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await arg.Message.ModifyAsync(msg =>
|
||||||
|
{
|
||||||
|
msg.Content = arg.Message.Content;
|
||||||
|
msg.Components = null;
|
||||||
|
msg.Embed = new Optional<Embed>(builder.Build());
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DiscordClient_Ready()
|
||||||
|
{
|
||||||
|
var guild = (await _discordClient.Rest.GetGuildsAsync()).First();
|
||||||
|
await _interactionModule.RegisterCommandsToGuildAsync(guild.Id, true).ConfigureAwait(false);
|
||||||
|
|
||||||
|
//_ = RemoveUsersNotInVanityRole();
|
||||||
|
_ = ProcessReportsQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task Log(LogMessage msg)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("{msg}", msg);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessReportsQueue()
|
||||||
|
{
|
||||||
|
var guild = (await _discordClient.Rest.GetGuildsAsync()).First();
|
||||||
|
|
||||||
|
_processReportQueueCts?.Cancel();
|
||||||
|
_processReportQueueCts?.Dispose();
|
||||||
|
_processReportQueueCts = new();
|
||||||
|
var token = _processReportQueueCts.Token;
|
||||||
|
while (!token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(30)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (_discordClient.ConnectionState != ConnectionState.Connected) continue;
|
||||||
|
var reportChannelId = _configurationService.GetValue<ulong?>(nameof(ServicesConfiguration.DiscordChannelForReports));
|
||||||
|
if (reportChannelId == null) continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var scope = _services.CreateScope())
|
||||||
|
{
|
||||||
|
_logger.LogTrace("Checking for Profile Reports");
|
||||||
|
var dbContext = scope.ServiceProvider.GetRequiredService<MareDbContext>();
|
||||||
|
if (!dbContext.UserProfileReports.Any())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var reports = await dbContext.UserProfileReports.ToListAsync().ConfigureAwait(false);
|
||||||
|
var restChannel = await guild.GetTextChannelAsync(reportChannelId.Value).ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var report in reports)
|
||||||
|
{
|
||||||
|
var reportedUser = await dbContext.Users.SingleAsync(u => u.UID == report.ReportedUserUID).ConfigureAwait(false);
|
||||||
|
var reportedUserLodestone = await dbContext.LodeStoneAuth.SingleOrDefaultAsync(u => u.User.UID == report.ReportedUserUID).ConfigureAwait(false);
|
||||||
|
var reportingUser = await dbContext.Users.SingleAsync(u => u.UID == report.ReportingUserUID).ConfigureAwait(false);
|
||||||
|
var reportingUserLodestone = await dbContext.LodeStoneAuth.SingleOrDefaultAsync(u => u.User.UID == report.ReportingUserUID).ConfigureAwait(false);
|
||||||
|
var reportedUserProfile = await dbContext.UserProfileData.SingleAsync(u => u.UserUID == report.ReportedUserUID).ConfigureAwait(false);
|
||||||
|
EmbedBuilder eb = new();
|
||||||
|
eb.WithTitle("Mare Synchronos Profile Report");
|
||||||
|
|
||||||
|
StringBuilder reportedUserSb = new();
|
||||||
|
StringBuilder reportingUserSb = new();
|
||||||
|
reportedUserSb.Append(reportedUser.UID);
|
||||||
|
reportingUserSb.Append(reportingUser.UID);
|
||||||
|
if (reportedUserLodestone != null)
|
||||||
|
{
|
||||||
|
reportedUserSb.AppendLine($" (<@{reportedUserLodestone.DiscordId}>)");
|
||||||
|
}
|
||||||
|
if (reportingUserLodestone != null)
|
||||||
|
{
|
||||||
|
reportingUserSb.AppendLine($" (<@{reportingUserLodestone.DiscordId}>)");
|
||||||
|
}
|
||||||
|
eb.AddField("Reported User", reportedUserSb.ToString());
|
||||||
|
eb.AddField("Reporting User", reportingUserSb.ToString());
|
||||||
|
eb.AddField("Report Date (UTC)", report.ReportDate);
|
||||||
|
eb.AddField("Report Reason", string.IsNullOrWhiteSpace(report.ReportReason) ? "-" : report.ReportReason);
|
||||||
|
eb.AddField("Reported User Profile Description", string.IsNullOrWhiteSpace(reportedUserProfile.UserDescription) ? "-" : reportedUserProfile.UserDescription);
|
||||||
|
eb.AddField("Reported User Profile Is NSFW", reportedUserProfile.IsNSFW);
|
||||||
|
|
||||||
|
var cb = new ComponentBuilder();
|
||||||
|
cb.WithButton("Dismiss Report", customId: $"mare-report-button-dismiss-{reportedUser.UID}", style: ButtonStyle.Primary);
|
||||||
|
cb.WithButton("Ban profile", customId: $"mare-report-button-banprofile-{reportedUser.UID}", style: ButtonStyle.Secondary);
|
||||||
|
cb.WithButton("Ban user", customId: $"mare-report-button-banuser-{reportedUser.UID}", style: ButtonStyle.Danger);
|
||||||
|
cb.WithButton("Dismiss and Ban Reporting user", customId: $"mare-report-button-banreporting-{reportedUser.UID}-{reportingUser.UID}", style: ButtonStyle.Danger);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(reportedUserProfile.Base64ProfileImage))
|
||||||
|
{
|
||||||
|
var fileName = reportedUser.UID + "_profile_" + Guid.NewGuid().ToString("N") + ".png";
|
||||||
|
eb.WithImageUrl($"attachment://{fileName}");
|
||||||
|
using MemoryStream ms = new(Convert.FromBase64String(reportedUserProfile.Base64ProfileImage));
|
||||||
|
await restChannel.SendFileAsync(ms, fileName, "User Report", embed: eb.Build(), components: cb.Build(), isSpoiler: true).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var msg = await restChannel.SendMessageAsync(embed: eb.Build(), components: cb.Build()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbContext.Remove(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Failed to process reports");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RemoveUsersNotInVanityRole()
|
||||||
|
{
|
||||||
|
_vanityUpdateCts?.Cancel();
|
||||||
|
_vanityUpdateCts?.Dispose();
|
||||||
|
_vanityUpdateCts = new();
|
||||||
|
var token = _vanityUpdateCts.Token;
|
||||||
|
var guild = (await _discordClient.Rest.GetGuildsAsync()).First();
|
||||||
|
var commands = await guild.GetApplicationCommandsAsync();
|
||||||
|
var appId = await _discordClient.GetApplicationInfoAsync().ConfigureAwait(false);
|
||||||
|
var vanityCommandId = commands.First(c => c.ApplicationId == appId.Id && c.Name == "setvanityuid").Id;
|
||||||
|
|
||||||
|
while (!token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Cleaning up Vanity UIDs");
|
||||||
|
_logger.LogInformation("Getting application commands from guild {guildName}", guild.Name);
|
||||||
|
var restGuild = await _discordClient.Rest.GetGuildAsync(guild.Id);
|
||||||
|
var vanityCommand = await restGuild.GetSlashCommandAsync(vanityCommandId).ConfigureAwait(false);
|
||||||
|
GuildApplicationCommandPermission commandPermissions = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Getting command permissions");
|
||||||
|
commandPermissions = await vanityCommand.GetCommandPermission().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error getting command permissions");
|
||||||
|
throw new Exception("Can't get command permissions");
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation($"Getting allowed role ids from permissions");
|
||||||
|
List<ulong> allowedRoleIds = new();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
allowedRoleIds = (from perm in commandPermissions.Permissions where perm.TargetType == ApplicationCommandPermissionTarget.Role where perm.Permission select perm.TargetId).ToList();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error resolving permissions to roles");
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation($"Found allowed role ids: {string.Join(", ", allowedRoleIds)}");
|
||||||
|
|
||||||
|
if (allowedRoleIds.Any())
|
||||||
|
{
|
||||||
|
await using var scope = _services.CreateAsyncScope();
|
||||||
|
await using (var db = scope.ServiceProvider.GetRequiredService<MareDbContext>())
|
||||||
|
{
|
||||||
|
var aliasedUsers = await db.LodeStoneAuth.Include("User")
|
||||||
|
.Where(c => c.User != null && !string.IsNullOrEmpty(c.User.Alias)).ToListAsync().ConfigureAwait(false);
|
||||||
|
var aliasedGroups = await db.Groups.Include(u => u.Owner)
|
||||||
|
.Where(c => !string.IsNullOrEmpty(c.Alias)).ToListAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var lodestoneAuth in aliasedUsers)
|
||||||
|
{
|
||||||
|
var discordUser = await restGuild.GetUserAsync(lodestoneAuth.DiscordId).ConfigureAwait(false);
|
||||||
|
_logger.LogInformation($"Checking User: {lodestoneAuth.DiscordId}, {lodestoneAuth.User.UID} ({lodestoneAuth.User.Alias}), User in Roles: {string.Join(", ", discordUser?.RoleIds ?? new List<ulong>())}");
|
||||||
|
|
||||||
|
if (discordUser == null || !discordUser.RoleIds.Any(u => allowedRoleIds.Contains(u)))
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"User {lodestoneAuth.User.UID} not in allowed roles, deleting alias");
|
||||||
|
lodestoneAuth.User.Alias = null;
|
||||||
|
var secondaryUsers = await db.Auth.Include(u => u.User).Where(u => u.PrimaryUserUID == lodestoneAuth.User.UID).ToListAsync().ConfigureAwait(false);
|
||||||
|
foreach (var secondaryUser in secondaryUsers)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Secondary User {secondaryUser.User.UID} not in allowed roles, deleting alias");
|
||||||
|
|
||||||
|
secondaryUser.User.Alias = null;
|
||||||
|
db.Update(secondaryUser.User);
|
||||||
|
}
|
||||||
|
db.Update(lodestoneAuth.User);
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var group in aliasedGroups)
|
||||||
|
{
|
||||||
|
var lodestoneUser = await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(f => f.User.UID == group.OwnerUID).ConfigureAwait(false);
|
||||||
|
RestGuildUser discordUser = null;
|
||||||
|
if (lodestoneUser != null)
|
||||||
|
{
|
||||||
|
discordUser = await restGuild.GetUserAsync(lodestoneUser.DiscordId).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation($"Checking Group: {group.GID}, owned by {lodestoneUser?.User?.UID ?? string.Empty} ({lodestoneUser?.User?.Alias ?? string.Empty}), User in Roles: {string.Join(", ", discordUser?.RoleIds ?? new List<ulong>())}");
|
||||||
|
|
||||||
|
if (lodestoneUser == null || discordUser == null || !discordUser.RoleIds.Any(u => allowedRoleIds.Contains(u)))
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"User {lodestoneUser.User.UID} not in allowed roles, deleting group alias");
|
||||||
|
group.Alias = null;
|
||||||
|
db.Update(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation("No roles for command defined, no cleanup performed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Something failed during checking vanity user uids");
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Vanity UID cleanup complete");
|
||||||
|
await Task.Delay(TimeSpan.FromHours(12), _vanityUpdateCts.Token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateStatusAsync()
|
||||||
|
{
|
||||||
|
_updateStatusCts = new();
|
||||||
|
while (!_updateStatusCts.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
var endPoint = _connectionMultiplexer.GetEndPoints().First();
|
||||||
|
var onlineUsers = await _connectionMultiplexer.GetServer(endPoint).KeysAsync(pattern: "UID:*").CountAsync();
|
||||||
|
|
||||||
|
//_logger.LogInformation("Users online: " + onlineUsers);
|
||||||
|
await _discordClient.SetActivityAsync(new Game("with " + onlineUsers + " Users")).ConfigureAwait(false);
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(15)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
|
||||||
|
namespace MareSynchronosServices.Discord;
|
||||||
|
|
||||||
|
public class DiscordBotServices
|
||||||
|
{
|
||||||
|
public readonly string[] LodestoneServers = new[] { "eu", "na", "jp", "fr", "de" };
|
||||||
|
public ConcurrentDictionary<ulong, string> DiscordLodestoneMapping = new();
|
||||||
|
public ConcurrentDictionary<ulong, string> DiscordRelinkLodestoneMapping = new();
|
||||||
|
public ConcurrentDictionary<ulong, DateTime> LastVanityChange = new();
|
||||||
|
public ConcurrentDictionary<string, DateTime> LastVanityGidChange = new();
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private CancellationTokenSource? verificationTaskCts;
|
||||||
|
|
||||||
|
public DiscordBotServices(IServiceProvider serviceProvider, ILogger<DiscordBotServices> logger, MareMetrics metrics)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
Logger = logger;
|
||||||
|
Metrics = metrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILogger<DiscordBotServices> Logger { get; init; }
|
||||||
|
public MareMetrics Metrics { get; init; }
|
||||||
|
public ConcurrentQueue<KeyValuePair<ulong, Action<IServiceProvider>>> VerificationQueue { get; } = new();
|
||||||
|
|
||||||
|
public Task Start()
|
||||||
|
{
|
||||||
|
_ = ProcessVerificationQueue();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Stop()
|
||||||
|
{
|
||||||
|
verificationTaskCts?.Cancel();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessVerificationQueue()
|
||||||
|
{
|
||||||
|
verificationTaskCts = new CancellationTokenSource();
|
||||||
|
while (!verificationTaskCts.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
if (VerificationQueue.TryDequeue(out var queueitem))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
queueitem.Value.Invoke(_serviceProvider);
|
||||||
|
|
||||||
|
Logger.LogInformation("Sent login information to user");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.LogError(e, "Error during queue work");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(2), verificationTaskCts.Token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1260
MareSynchronosServer/MareSynchronosServices/Discord/MareModule.cs
Normal file
1260
MareSynchronosServer/MareSynchronosServices/Discord/MareModule.cs
Normal file
File diff suppressed because it is too large
Load Diff
25
MareSynchronosServer/MareSynchronosServices/DummyHub.cs
Normal file
25
MareSynchronosServer/MareSynchronosServices/DummyHub.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
|
// this is a very hacky way to attach this file server to the main mare hub signalr instance via redis
|
||||||
|
// signalr publishes the namespace and hubname into the redis backend so this needs to be equal to the original
|
||||||
|
// but I don't need to reimplement the hub completely as I only exclusively use it for internal connection calling
|
||||||
|
// from the queue service so I keep the namespace and name of the class the same so it can connect to the same channel
|
||||||
|
// if anyone finds a better way to do this let me know
|
||||||
|
|
||||||
|
#pragma warning disable IDE0130 // Namespace does not match folder structure
|
||||||
|
#pragma warning disable MA0048 // File name must match type name
|
||||||
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
public class MareHub : Hub
|
||||||
|
{
|
||||||
|
public override Task OnConnectedAsync()
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnDisconnectedAsync(Exception exception)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#pragma warning restore IDE0130 // Namespace does not match folder structure
|
||||||
|
#pragma warning restore MA0048 // File name must match type name
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Remove="appsettings.Development.json" />
|
||||||
|
<Content Remove="appsettings.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="appsettings.Development.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Discord.Net" Version="3.14.1" />
|
||||||
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.149">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
||||||
|
<ProjectReference Include="..\MareSynchronosShared\MareSynchronosShared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
43
MareSynchronosServer/MareSynchronosServices/Program.cs
Normal file
43
MareSynchronosServer/MareSynchronosServices/Program.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using MareSynchronosServices;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var hostBuilder = CreateHostBuilder(args);
|
||||||
|
var host = hostBuilder.Build();
|
||||||
|
|
||||||
|
using (var scope = host.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var services = scope.ServiceProvider;
|
||||||
|
using var dbContext = services.GetRequiredService<MareDbContext>();
|
||||||
|
|
||||||
|
var options = host.Services.GetService<IConfigurationService<ServicesConfiguration>>();
|
||||||
|
var optionsServer = host.Services.GetService<IConfigurationService<ServerConfiguration>>();
|
||||||
|
var logger = host.Services.GetService<ILogger<Program>>();
|
||||||
|
logger.LogInformation("Loaded MareSynchronos Services Configuration (IsMain: {isMain})", options.IsMain);
|
||||||
|
logger.LogInformation(options.ToString());
|
||||||
|
logger.LogInformation("Loaded MareSynchronos Server Configuration (IsMain: {isMain})", optionsServer.IsMain);
|
||||||
|
logger.LogInformation(optionsServer.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||||
|
Host.CreateDefaultBuilder(args)
|
||||||
|
.UseSystemd()
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.UseContentRoot(AppContext.BaseDirectory);
|
||||||
|
webBuilder.ConfigureLogging((ctx, builder) =>
|
||||||
|
{
|
||||||
|
builder.AddConfiguration(ctx.Configuration.GetSection("Logging"));
|
||||||
|
builder.AddFile(o => o.RootPath = AppContext.BaseDirectory);
|
||||||
|
});
|
||||||
|
webBuilder.UseStartup<Startup>();
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"MareSynchronosServices": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": false,
|
||||||
|
"applicationUrl": "http://localhost:5294;https://localhost:7294",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
MareSynchronosServer/MareSynchronosServices/Startup.cs
Normal file
104
MareSynchronosServer/MareSynchronosServices/Startup.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using MareSynchronosServices.Discord;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using MareSynchronosShared.Metrics;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Prometheus;
|
||||||
|
using MareSynchronosShared.Utils;
|
||||||
|
using MareSynchronosShared.Services;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using MessagePack.Resolvers;
|
||||||
|
using MessagePack;
|
||||||
|
using MareSynchronosShared.Utils.Configuration;
|
||||||
|
|
||||||
|
namespace MareSynchronosServices;
|
||||||
|
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public Startup(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
Configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
|
{
|
||||||
|
var config = app.ApplicationServices.GetRequiredService<IConfigurationService<MareConfigurationBase>>();
|
||||||
|
|
||||||
|
var metricServer = new KestrelMetricServer(config.GetValueOrDefault<int>(nameof(MareConfigurationBase.MetricsPort), 4982));
|
||||||
|
metricServer.Start();
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
app.UseEndpoints(e =>
|
||||||
|
{
|
||||||
|
e.MapHub<MareSynchronosServer.Hubs.MareHub>("/dummyhub");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
var mareConfig = Configuration.GetSection("MareSynchronos");
|
||||||
|
|
||||||
|
services.AddDbContextPool<MareDbContext>(options =>
|
||||||
|
{
|
||||||
|
options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"), builder =>
|
||||||
|
{
|
||||||
|
builder.MigrationsHistoryTable("_efmigrationshistory", "public");
|
||||||
|
}).UseSnakeCaseNamingConvention();
|
||||||
|
options.EnableThreadSafetyChecks(false);
|
||||||
|
}, Configuration.GetValue(nameof(MareConfigurationBase.DbContextPoolSize), 1024));
|
||||||
|
|
||||||
|
services.AddSingleton(m => new MareMetrics(m.GetService<ILogger<MareMetrics>>(), new List<string> { },
|
||||||
|
new List<string> { }));
|
||||||
|
|
||||||
|
var redis = mareConfig.GetValue(nameof(ServerConfiguration.RedisConnectionString), string.Empty);
|
||||||
|
var options = ConfigurationOptions.Parse(redis);
|
||||||
|
options.ClientName = "Mare";
|
||||||
|
options.ChannelPrefix = "UserData";
|
||||||
|
ConnectionMultiplexer connectionMultiplexer = ConnectionMultiplexer.Connect(options);
|
||||||
|
services.AddSingleton<IConnectionMultiplexer>(connectionMultiplexer);
|
||||||
|
|
||||||
|
var signalRServiceBuilder = services.AddSignalR(hubOptions =>
|
||||||
|
{
|
||||||
|
hubOptions.MaximumReceiveMessageSize = long.MaxValue;
|
||||||
|
hubOptions.EnableDetailedErrors = true;
|
||||||
|
hubOptions.MaximumParallelInvocationsPerClient = 10;
|
||||||
|
hubOptions.StreamBufferCapacity = 200;
|
||||||
|
}).AddMessagePackProtocol(opt =>
|
||||||
|
{
|
||||||
|
var resolver = CompositeResolver.Create(StandardResolverAllowPrivate.Instance,
|
||||||
|
BuiltinResolver.Instance,
|
||||||
|
AttributeFormatterResolver.Instance,
|
||||||
|
// replace enum resolver
|
||||||
|
DynamicEnumAsStringResolver.Instance,
|
||||||
|
DynamicGenericResolver.Instance,
|
||||||
|
DynamicUnionResolver.Instance,
|
||||||
|
DynamicObjectResolver.Instance,
|
||||||
|
PrimitiveObjectResolver.Instance,
|
||||||
|
// final fallback(last priority)
|
||||||
|
StandardResolver.Instance);
|
||||||
|
|
||||||
|
opt.SerializerOptions = MessagePackSerializerOptions.Standard
|
||||||
|
.WithCompression(MessagePackCompression.Lz4Block)
|
||||||
|
.WithResolver(resolver);
|
||||||
|
});
|
||||||
|
|
||||||
|
// configure redis for SignalR
|
||||||
|
var redisConnection = mareConfig.GetValue(nameof(MareConfigurationBase.RedisConnectionString), string.Empty);
|
||||||
|
signalRServiceBuilder.AddStackExchangeRedis(redisConnection, options => { });
|
||||||
|
|
||||||
|
services.Configure<ServicesConfiguration>(Configuration.GetRequiredSection("MareSynchronos"));
|
||||||
|
services.Configure<ServerConfiguration>(Configuration.GetRequiredSection("MareSynchronos"));
|
||||||
|
services.Configure<MareConfigurationBase>(Configuration.GetRequiredSection("MareSynchronos"));
|
||||||
|
services.AddSingleton(Configuration);
|
||||||
|
services.AddSingleton<ServerTokenGenerator>();
|
||||||
|
services.AddSingleton<DiscordBotServices>();
|
||||||
|
services.AddHostedService<DiscordBot>();
|
||||||
|
services.AddSingleton<IConfigurationService<ServicesConfiguration>, MareConfigurationServiceServer<ServicesConfiguration>>();
|
||||||
|
services.AddSingleton<IConfigurationService<ServerConfiguration>, MareConfigurationServiceClient<ServerConfiguration>>();
|
||||||
|
services.AddSingleton<IConfigurationService<MareConfigurationBase>, MareConfigurationServiceClient<MareConfigurationBase>>();
|
||||||
|
|
||||||
|
services.AddHostedService(p => (MareConfigurationServiceClient<MareConfigurationBase>)p.GetService<IConfigurationService<MareConfigurationBase>>());
|
||||||
|
services.AddHostedService(p => (MareConfigurationServiceClient<ServerConfiguration>)p.GetService<IConfigurationService<ServerConfiguration>>());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
MareSynchronosServer/MareSynchronosServices/appsettings.json
Normal file
29
MareSynchronosServer/MareSynchronosServices/appsettings.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Host=localhost;Port=5432;Database=mare;Username=postgres"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Kestrel": {
|
||||||
|
"Endpoints": {
|
||||||
|
"Http": {
|
||||||
|
"Protocols": "Http2",
|
||||||
|
"Url": "http://+:5002"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MareSynchronos": {
|
||||||
|
"DbContextPoolSize": 1024,
|
||||||
|
"DiscordBotToken": "",
|
||||||
|
"DiscordChannelForMessages": "",
|
||||||
|
"PurgeUnusedAccounts": true,
|
||||||
|
"PurgeUnusedAccountsPeriodInDays": 14,
|
||||||
|
"FailedAuthForTempBan": 5,
|
||||||
|
"TempBanDurationInMinutes": 30,
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
131
MareSynchronosServer/MareSynchronosShared/Data/MareDbContext.cs
Normal file
131
MareSynchronosServer/MareSynchronosShared/Data/MareDbContext.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using MareSynchronosShared.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace MareSynchronosShared.Data;
|
||||||
|
|
||||||
|
public class MareDbContext : DbContext
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
public MareDbContext() { }
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
if (optionsBuilder.IsConfigured)
|
||||||
|
{
|
||||||
|
base.OnConfiguring(optionsBuilder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsBuilder.UseNpgsql("Host=localhost;Port=5432;Database=mare;Username=postgres", builder =>
|
||||||
|
{
|
||||||
|
builder.MigrationsHistoryTable("_efmigrationshistory", "public");
|
||||||
|
builder.MigrationsAssembly("MareSynchronosShared");
|
||||||
|
}).UseSnakeCaseNamingConvention();
|
||||||
|
optionsBuilder.EnableThreadSafetyChecks(false);
|
||||||
|
|
||||||
|
base.OnConfiguring(optionsBuilder);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public MareDbContext(DbContextOptions<MareDbContext> options) : base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<Auth> Auth { get; set; }
|
||||||
|
public DbSet<BannedRegistrations> BannedRegistrations { get; set; }
|
||||||
|
public DbSet<Banned> BannedUsers { get; set; }
|
||||||
|
public DbSet<ClientPair> ClientPairs { get; set; }
|
||||||
|
public DbSet<FileCache> Files { get; set; }
|
||||||
|
public DbSet<ForbiddenUploadEntry> ForbiddenUploadEntries { get; set; }
|
||||||
|
public DbSet<GroupBan> GroupBans { get; set; }
|
||||||
|
public DbSet<GroupPair> GroupPairs { get; set; }
|
||||||
|
public DbSet<Group> Groups { get; set; }
|
||||||
|
public DbSet<GroupTempInvite> GroupTempInvites { get; set; }
|
||||||
|
public DbSet<LodeStoneAuth> LodeStoneAuth { get; set; }
|
||||||
|
public DbSet<UserProfileData> UserProfileData { get; set; }
|
||||||
|
public DbSet<UserProfileDataReport> UserProfileReports { get; set; }
|
||||||
|
public DbSet<User> Users { get; set; }
|
||||||
|
public DbSet<CharaData> CharaData { get; set; }
|
||||||
|
public DbSet<CharaDataFile> CharaDataFiles { get; set; }
|
||||||
|
public DbSet<CharaDataFileSwap> CharaDataFileSwaps { get; set; }
|
||||||
|
public DbSet<CharaDataOriginalFile> CharaDataOriginalFiles { get; set; }
|
||||||
|
public DbSet<CharaDataPose> CharaDataPoses { get; set; }
|
||||||
|
public DbSet<CharaDataAllowance> CharaDataAllowances { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder mb)
|
||||||
|
{
|
||||||
|
mb.Entity<Auth>().ToTable("auth");
|
||||||
|
mb.Entity<User>().ToTable("users");
|
||||||
|
mb.Entity<FileCache>().ToTable("file_caches");
|
||||||
|
mb.Entity<FileCache>().HasIndex(c => c.UploaderUID);
|
||||||
|
mb.Entity<ClientPair>().ToTable("client_pairs");
|
||||||
|
mb.Entity<ClientPair>().HasKey(u => new { u.UserUID, u.OtherUserUID });
|
||||||
|
mb.Entity<ClientPair>().HasIndex(c => c.UserUID);
|
||||||
|
mb.Entity<ClientPair>().HasIndex(c => c.OtherUserUID);
|
||||||
|
mb.Entity<ForbiddenUploadEntry>().ToTable("forbidden_upload_entries");
|
||||||
|
mb.Entity<Banned>().ToTable("banned_users");
|
||||||
|
mb.Entity<LodeStoneAuth>().ToTable("lodestone_auth");
|
||||||
|
mb.Entity<BannedRegistrations>().ToTable("banned_registrations");
|
||||||
|
mb.Entity<Group>().ToTable("groups");
|
||||||
|
mb.Entity<Group>().HasIndex(c => c.OwnerUID);
|
||||||
|
mb.Entity<GroupPair>().ToTable("group_pairs");
|
||||||
|
mb.Entity<GroupPair>().HasKey(u => new { u.GroupGID, u.GroupUserUID });
|
||||||
|
mb.Entity<GroupPair>().HasIndex(c => c.GroupUserUID);
|
||||||
|
mb.Entity<GroupPair>().HasIndex(c => c.GroupGID);
|
||||||
|
mb.Entity<GroupBan>().ToTable("group_bans");
|
||||||
|
mb.Entity<GroupBan>().HasKey(u => new { u.GroupGID, u.BannedUserUID });
|
||||||
|
mb.Entity<GroupBan>().HasIndex(c => c.BannedUserUID);
|
||||||
|
mb.Entity<GroupBan>().HasIndex(c => c.GroupGID);
|
||||||
|
mb.Entity<GroupTempInvite>().ToTable("group_temp_invites");
|
||||||
|
mb.Entity<GroupTempInvite>().HasKey(u => new { u.GroupGID, u.Invite });
|
||||||
|
mb.Entity<GroupTempInvite>().HasIndex(c => c.GroupGID);
|
||||||
|
mb.Entity<GroupTempInvite>().HasIndex(c => c.Invite);
|
||||||
|
mb.Entity<UserProfileData>().ToTable("user_profile_data");
|
||||||
|
mb.Entity<UserProfileData>().HasKey(c => c.UserUID);
|
||||||
|
mb.Entity<UserProfileDataReport>().ToTable("user_profile_data_reports");
|
||||||
|
mb.Entity<CharaData>().ToTable("chara_data");
|
||||||
|
mb.Entity<CharaData>()
|
||||||
|
.HasMany(p => p.Poses)
|
||||||
|
.WithOne(c => c.Parent)
|
||||||
|
.HasForeignKey(c => new { c.ParentId, c.ParentUploaderUID });
|
||||||
|
mb.Entity<CharaData>()
|
||||||
|
.HasMany(p => p.Files)
|
||||||
|
.WithOne(c => c.Parent)
|
||||||
|
.HasForeignKey(c => new { c.ParentId, c.ParentUploaderUID });
|
||||||
|
mb.Entity<CharaData>()
|
||||||
|
.HasMany(p => p.OriginalFiles)
|
||||||
|
.WithOne(p => p.Parent)
|
||||||
|
.HasForeignKey(p => new { p.ParentId, p.ParentUploaderUID });
|
||||||
|
mb.Entity<CharaData>()
|
||||||
|
.HasMany(p => p.AllowedIndividiuals)
|
||||||
|
.WithOne(p => p.Parent)
|
||||||
|
.HasForeignKey(p => new { p.ParentId, p.ParentUploaderUID });
|
||||||
|
mb.Entity<CharaData>()
|
||||||
|
.HasMany(p => p.FileSwaps)
|
||||||
|
.WithOne(p => p.Parent)
|
||||||
|
.HasForeignKey(p => new { p.ParentId, p.ParentUploaderUID });
|
||||||
|
mb.Entity<CharaData>().HasKey(p => new { p.Id, p.UploaderUID });
|
||||||
|
mb.Entity<CharaData>().HasIndex(p => p.UploaderUID);
|
||||||
|
mb.Entity<CharaData>().HasIndex(p => p.Id);
|
||||||
|
mb.Entity<CharaDataFile>().ToTable("chara_data_files");
|
||||||
|
mb.Entity<CharaDataFile>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.GamePath });
|
||||||
|
mb.Entity<CharaDataFile>().HasIndex(c => c.ParentId);
|
||||||
|
mb.Entity<CharaDataFile>().HasOne(f => f.FileCache).WithMany().HasForeignKey(f => f.FileCacheHash).OnDelete(DeleteBehavior.Cascade);
|
||||||
|
mb.Entity<CharaDataFileSwap>().ToTable("chara_data_file_swaps");
|
||||||
|
mb.Entity<CharaDataFileSwap>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.GamePath });
|
||||||
|
mb.Entity<CharaDataFileSwap>().HasIndex(c => c.ParentId);
|
||||||
|
mb.Entity<CharaDataPose>().ToTable("chara_data_poses");
|
||||||
|
mb.Entity<CharaDataPose>().Property(p => p.Id).ValueGeneratedOnAdd();
|
||||||
|
mb.Entity<CharaDataPose>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.Id });
|
||||||
|
mb.Entity<CharaDataPose>().HasIndex(c => c.ParentId);
|
||||||
|
mb.Entity<CharaDataOriginalFile>().ToTable("chara_data_orig_files");
|
||||||
|
mb.Entity<CharaDataOriginalFile>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.GamePath });
|
||||||
|
mb.Entity<CharaDataOriginalFile>().HasIndex(c => c.ParentId);
|
||||||
|
mb.Entity<CharaDataAllowance>().ToTable("chara_data_allowance");
|
||||||
|
mb.Entity<CharaDataAllowance>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.Id });
|
||||||
|
mb.Entity<CharaDataAllowance>().Property(p => p.Id).ValueGeneratedOnAdd();
|
||||||
|
mb.Entity<CharaDataAllowance>().HasIndex(c => c.ParentId);
|
||||||
|
mb.Entity<CharaDataAllowance>().HasOne(u => u.AllowedGroup).WithMany().HasForeignKey(u => u.AllowedGroupGID).OnDelete(DeleteBehavior.Cascade);
|
||||||
|
mb.Entity<CharaDataAllowance>().HasOne(u => u.AllowedUser).WithMany().HasForeignKey(u => u.AllowedUserUID).OnDelete(DeleteBehavior.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
MareSynchronosServer/MareSynchronosShared/Extensions.cs
Normal file
39
MareSynchronosServer/MareSynchronosShared/Extensions.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace MareSynchronosShared;
|
||||||
|
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
private static long _noIpCntr = 0;
|
||||||
|
public static string GetIpAddress(this IHttpContextAccessor accessor)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(accessor.HttpContext.Request.Headers["CF-CONNECTING-IP"]))
|
||||||
|
return accessor.HttpContext.Request.Headers["CF-CONNECTING-IP"];
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(accessor.HttpContext.Request.Headers["X-Forwarded-For"]))
|
||||||
|
{
|
||||||
|
return accessor.HttpContext.Request.Headers["X-Forwarded-For"];
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipAddress = accessor.HttpContext.GetServerVariable("HTTP_X_FORWARDED_FOR");
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(ipAddress))
|
||||||
|
{
|
||||||
|
var addresses = ipAddress.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var lastEntry = addresses.LastOrDefault();
|
||||||
|
if (lastEntry != null)
|
||||||
|
{
|
||||||
|
return lastEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessor.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "NoIp";
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return "NoIp" + _noIpCntr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ByteSize" Version="2.1.2" />
|
||||||
|
<PackageReference Include="EFCore.NamingConventions" Version="8.0.3" />
|
||||||
|
<PackageReference Include="IDisposableAnalyzers" Version="4.0.7">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Karambolo.Extensions.Logging.File" Version="3.5.0" />
|
||||||
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.150">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.Core" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="8.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="8.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.5.1" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
|
||||||
|
<PackageReference Include="prometheus-net" Version="8.2.1" />
|
||||||
|
<PackageReference Include="prometheus-net.AspNetCore" Version="8.2.1" />
|
||||||
|
<PackageReference Include="StackExchange.Redis" Version="2.7.33" />
|
||||||
|
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="10.2.0" />
|
||||||
|
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="10.2.0" />
|
||||||
|
<PackageReference Include="StackExchange.Redis.Extensions.System.Text.Json" Version="10.2.0" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.5.1" />
|
||||||
|
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Prometheus;
|
||||||
|
|
||||||
|
namespace MareSynchronosShared.Metrics;
|
||||||
|
|
||||||
|
public class MareMetrics
|
||||||
|
{
|
||||||
|
public MareMetrics(ILogger<MareMetrics> logger, List<string> countersToServe, List<string> gaugesToServe)
|
||||||
|
{
|
||||||
|
logger.LogInformation("Initializing MareMetrics");
|
||||||
|
foreach (var counter in countersToServe)
|
||||||
|
{
|
||||||
|
logger.LogInformation($"Creating Metric for Counter {counter}");
|
||||||
|
counters.Add(counter, Prometheus.Metrics.CreateCounter(counter, counter));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var gauge in gaugesToServe)
|
||||||
|
{
|
||||||
|
logger.LogInformation($"Creating Metric for Counter {gauge}");
|
||||||
|
if (!string.Equals(gauge, MetricsAPI.GaugeConnections, StringComparison.OrdinalIgnoreCase))
|
||||||
|
gauges.Add(gauge, Prometheus.Metrics.CreateGauge(gauge, gauge));
|
||||||
|
else
|
||||||
|
gauges.Add(gauge, Prometheus.Metrics.CreateGauge(gauge, gauge, new[] { "continent" }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<string, Counter> counters = new(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
private readonly Dictionary<string, Gauge> gauges = new(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
public void IncGaugeWithLabels(string gaugeName, double value = 1.0, params string[] labels)
|
||||||
|
{
|
||||||
|
if (gauges.TryGetValue(gaugeName, out Gauge gauge))
|
||||||
|
{
|
||||||
|
lock (gauge)
|
||||||
|
gauge.WithLabels(labels).Inc(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecGaugeWithLabels(string gaugeName, double value = 1.0, params string[] labels)
|
||||||
|
{
|
||||||
|
if (gauges.TryGetValue(gaugeName, out Gauge gauge))
|
||||||
|
{
|
||||||
|
lock (gauge)
|
||||||
|
gauge.WithLabels(labels).Dec(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetGaugeTo(string gaugeName, double value)
|
||||||
|
{
|
||||||
|
if (gauges.TryGetValue(gaugeName, out Gauge gauge))
|
||||||
|
{
|
||||||
|
lock (gauge)
|
||||||
|
gauge.Set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncGauge(string gaugeName, double value = 1.0)
|
||||||
|
{
|
||||||
|
if (gauges.TryGetValue(gaugeName, out Gauge gauge))
|
||||||
|
{
|
||||||
|
lock (gauge)
|
||||||
|
gauge.Inc(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecGauge(string gaugeName, double value = 1.0)
|
||||||
|
{
|
||||||
|
if (gauges.TryGetValue(gaugeName, out Gauge gauge))
|
||||||
|
{
|
||||||
|
lock (gauge)
|
||||||
|
gauge.Dec(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncCounter(string counterName, double value = 1.0)
|
||||||
|
{
|
||||||
|
if (counters.TryGetValue(counterName, out Counter counter))
|
||||||
|
{
|
||||||
|
lock (counter)
|
||||||
|
counter.Inc(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
namespace MareSynchronosShared.Metrics;
|
||||||
|
|
||||||
|
public class MetricsAPI
|
||||||
|
{
|
||||||
|
public const string CounterInitializedConnections = "mare_initialized_connections";
|
||||||
|
public const string GaugeConnections = "mare_connections";
|
||||||
|
public const string GaugeAuthorizedConnections = "mare_authorized_connections";
|
||||||
|
public const string GaugeAvailableWorkerThreads = "mare_available_threadpool";
|
||||||
|
public const string GaugeAvailableIOWorkerThreads = "mare_available_threadpool_io";
|
||||||
|
public const string GaugeUsersRegistered = "mare_users_registered";
|
||||||
|
public const string CounterUsersRegisteredDeleted = "mare_users_registered_deleted";
|
||||||
|
public const string GaugePairs = "mare_pairs";
|
||||||
|
public const string GaugePairsPaused = "mare_pairs_paused";
|
||||||
|
public const string GaugeFilesTotal = "mare_files";
|
||||||
|
public const string GaugeFilesTotalColdStorage = "mare_files_cold";
|
||||||
|
public const string GaugeFilesTotalSize = "mare_files_size";
|
||||||
|
public const string GaugeFilesTotalSizeColdStorage = "mare_files_size_cold";
|
||||||
|
public const string GaugeFilesDownloadingFromCache = "mare_files_downloading_from_cache";
|
||||||
|
public const string GaugeFilesTasksWaitingForDownloadFromCache = "mare_files_waiting_for_dl";
|
||||||
|
public const string CounterUserPushData = "mare_user_push";
|
||||||
|
public const string CounterUserPushDataTo = "mare_user_push_to";
|
||||||
|
public const string CounterAuthenticationRequests = "mare_auth_requests";
|
||||||
|
public const string CounterAuthenticationCacheHits = "mare_auth_requests_cachehit";
|
||||||
|
public const string CounterAuthenticationFailures = "mare_auth_requests_fail";
|
||||||
|
public const string CounterAuthenticationSuccesses = "mare_auth_requests_success";
|
||||||
|
public const string GaugeGroups = "mare_groups";
|
||||||
|
public const string GaugeGroupPairs = "mare_groups_pairs";
|
||||||
|
public const string GaugeGroupPairsPaused = "mare_groups_pairs_paused";
|
||||||
|
public const string GaugeFilesUniquePastHour = "mare_files_unique_past_hour";
|
||||||
|
public const string GaugeFilesUniquePastHourSize = "mare_files_unique_past_hour_size";
|
||||||
|
public const string GaugeFilesUniquePastDay = "mare_files_unique_past_day";
|
||||||
|
public const string GaugeFilesUniquePastDaySize = "mare_files_unique_past_day_size";
|
||||||
|
public const string GaugeCurrentDownloads = "mare_current_downloads";
|
||||||
|
public const string GaugeQueueFree = "mare_download_queue_free";
|
||||||
|
public const string GaugeQueueActive = "mare_download_queue_active";
|
||||||
|
public const string GaugeQueueInactive = "mare_download_queue_inactive";
|
||||||
|
public const string GaugeDownloadQueue = "mare_download_queue";
|
||||||
|
public const string GaugeDownloadQueueCancelled = "mare_download_queue_cancelled";
|
||||||
|
public const string GaugeDownloadPriorityQueue = "mare_download_priority_queue";
|
||||||
|
public const string GaugeDownloadPriorityQueueCancelled = "mare_download_priority_queue_cancelled";
|
||||||
|
public const string CounterFileRequests = "mare_files_requests";
|
||||||
|
public const string CounterFileRequestSize = "mare_files_request_size";
|
||||||
|
public const string CounterAccountsCreated = "mare_accounts_created";
|
||||||
|
public const string GaugeGposeLobbies = "mare_gpose_lobbies";
|
||||||
|
public const string GaugeGposeLobbyUsers = "mare_gpose_lobby_users";
|
||||||
|
}
|
||||||
241
MareSynchronosServer/MareSynchronosShared/Migrations/20220731210149_InitialCreate.Designer.cs
generated
Normal file
241
MareSynchronosServer/MareSynchronosShared/Migrations/20220731210149_InitialCreate.Designer.cs
generated
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220731210149_InitialCreate")]
|
||||||
|
partial class InitialCreate
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.6")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("Auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("BannedUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("ClientPairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("FileCaches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("ForbiddenUploadEntries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.HasIndex("CharacterIdentification")
|
||||||
|
.HasDatabaseName("ix_users_character_identification");
|
||||||
|
|
||||||
|
b.ToTable("Users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_uid");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class InitialCreate : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "BannedUsers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
character_identification = table.Column<string>(type: "text", nullable: false),
|
||||||
|
reason = table.Column<string>(type: "text", nullable: true),
|
||||||
|
timestamp = table.Column<byte[]>(type: "bytea", rowVersion: true, nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_banned_users", x => x.character_identification);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ForbiddenUploadEntries",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
hash = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||||
|
forbidden_by = table.Column<string>(type: "text", nullable: true),
|
||||||
|
timestamp = table.Column<byte[]>(type: "bytea", rowVersion: true, nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_forbidden_upload_entries", x => x.hash);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Users",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
uid = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: false),
|
||||||
|
character_identification = table.Column<string>(type: "text", nullable: true),
|
||||||
|
timestamp = table.Column<byte[]>(type: "bytea", rowVersion: true, nullable: true),
|
||||||
|
is_moderator = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
is_admin = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
last_logged_in = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_users", x => x.uid);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Auth",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
hashed_key = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||||
|
user_uid = table.Column<string>(type: "character varying(10)", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_auth", x => x.hashed_key);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_auth_users_user_uid",
|
||||||
|
column: x => x.user_uid,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ClientPairs",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
user_uid = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: false),
|
||||||
|
other_user_uid = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: false),
|
||||||
|
is_paused = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
allow_receiving_messages = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
timestamp = table.Column<byte[]>(type: "bytea", rowVersion: true, nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_client_pairs", x => new { x.user_uid, x.other_user_uid });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_client_pairs_users_other_user_uid",
|
||||||
|
column: x => x.other_user_uid,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_client_pairs_users_user_uid",
|
||||||
|
column: x => x.user_uid,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "FileCaches",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
hash = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||||
|
uploader_uid = table.Column<string>(type: "character varying(10)", nullable: true),
|
||||||
|
uploaded = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
timestamp = table.Column<byte[]>(type: "bytea", rowVersion: true, nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_file_caches", x => x.hash);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_file_caches_users_uploader_uid",
|
||||||
|
column: x => x.uploader_uid,
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_auth_user_uid",
|
||||||
|
table: "Auth",
|
||||||
|
column: "user_uid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_client_pairs_other_user_uid",
|
||||||
|
table: "ClientPairs",
|
||||||
|
column: "other_user_uid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_client_pairs_user_uid",
|
||||||
|
table: "ClientPairs",
|
||||||
|
column: "user_uid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_file_caches_uploader_uid",
|
||||||
|
table: "FileCaches",
|
||||||
|
column: "uploader_uid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_users_character_identification",
|
||||||
|
table: "Users",
|
||||||
|
column: "character_identification");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Auth");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "BannedUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ClientPairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "FileCaches");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ForbiddenUploadEntries");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Users");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
241
MareSynchronosServer/MareSynchronosShared/Migrations/20220731211419_RenameLowerSnakeCase.Designer.cs
generated
Normal file
241
MareSynchronosServer/MareSynchronosShared/Migrations/20220731211419_RenameLowerSnakeCase.Designer.cs
generated
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220731211419_RenameLowerSnakeCase")]
|
||||||
|
partial class RenameLowerSnakeCase
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.6")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.HasIndex("CharacterIdentification")
|
||||||
|
.HasDatabaseName("ix_users_character_identification");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class RenameLowerSnakeCase : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_auth_users_user_uid",
|
||||||
|
table: "Auth");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_client_pairs_users_other_user_uid",
|
||||||
|
table: "ClientPairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_client_pairs_users_user_uid",
|
||||||
|
table: "ClientPairs");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "Users",
|
||||||
|
newName: "users");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "Auth",
|
||||||
|
newName: "auth");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "ForbiddenUploadEntries",
|
||||||
|
newName: "forbidden_upload_entries");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "FileCaches",
|
||||||
|
newName: "file_caches");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "ClientPairs",
|
||||||
|
newName: "client_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "BannedUsers",
|
||||||
|
newName: "banned_users");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_auth_users_user_temp_id",
|
||||||
|
table: "auth",
|
||||||
|
column: "user_uid",
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_client_pairs_users_other_user_temp_id1",
|
||||||
|
table: "client_pairs",
|
||||||
|
column: "other_user_uid",
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_client_pairs_users_user_temp_id2",
|
||||||
|
table: "client_pairs",
|
||||||
|
column: "user_uid",
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_auth_users_user_temp_id",
|
||||||
|
table: "auth");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_client_pairs_users_other_user_temp_id1",
|
||||||
|
table: "client_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_client_pairs_users_user_temp_id2",
|
||||||
|
table: "client_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "users",
|
||||||
|
newName: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "auth",
|
||||||
|
newName: "Auth");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "forbidden_upload_entries",
|
||||||
|
newName: "ForbiddenUploadEntries");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "file_caches",
|
||||||
|
newName: "FileCaches");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "client_pairs",
|
||||||
|
newName: "ClientPairs");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "banned_users",
|
||||||
|
newName: "BannedUsers");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_auth_users_user_uid",
|
||||||
|
table: "Auth",
|
||||||
|
column: "user_uid",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_client_pairs_users_other_user_uid",
|
||||||
|
table: "ClientPairs",
|
||||||
|
column: "other_user_uid",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_client_pairs_users_user_uid",
|
||||||
|
table: "ClientPairs",
|
||||||
|
column: "user_uid",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
283
MareSynchronosServer/MareSynchronosShared/Migrations/20220801121419_AddLodestoneAuth.Designer.cs
generated
Normal file
283
MareSynchronosServer/MareSynchronosShared/Migrations/20220801121419_AddLodestoneAuth.Designer.cs
generated
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220801121419_AddLodestoneAuth")]
|
||||||
|
partial class AddLodestoneAuth
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.6")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.HasIndex("CharacterIdentification")
|
||||||
|
.HasDatabaseName("ix_users_character_identification");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddLodestoneAuth : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "lodestone_auth",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
discord_id = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
hashed_lodestone_id = table.Column<string>(type: "text", nullable: true),
|
||||||
|
lodestone_auth_string = table.Column<string>(type: "text", nullable: true),
|
||||||
|
user_uid = table.Column<string>(type: "character varying(10)", nullable: true),
|
||||||
|
started_at = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_lodestone_auth", x => x.discord_id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_lodestone_auth_users_user_uid",
|
||||||
|
column: x => x.user_uid,
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_lodestone_auth_user_uid",
|
||||||
|
table: "lodestone_auth",
|
||||||
|
column: "user_uid");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "lodestone_auth");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220801122103_AddNullableLodestoneAuthProperties")]
|
||||||
|
partial class AddNullableLodestoneAuthProperties
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.6")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.HasIndex("CharacterIdentification")
|
||||||
|
.HasDatabaseName("ix_users_character_identification");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddNullableLodestoneAuthProperties : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "started_at",
|
||||||
|
table: "lodestone_auth",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "timestamp with time zone");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "started_at",
|
||||||
|
table: "lodestone_auth",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "timestamp with time zone",
|
||||||
|
oldNullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
295
MareSynchronosServer/MareSynchronosShared/Migrations/20220806103053_AddBannedRegistrations.Designer.cs
generated
Normal file
295
MareSynchronosServer/MareSynchronosShared/Migrations/20220806103053_AddBannedRegistrations.Designer.cs
generated
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220806103053_AddBannedRegistrations")]
|
||||||
|
partial class AddBannedRegistrations
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.6")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.HasIndex("CharacterIdentification")
|
||||||
|
.HasDatabaseName("ix_users_character_identification");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddBannedRegistrations : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "banned_registrations",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
discord_id_or_lodestone_auth = table.Column<string>(type: "text", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_banned_registrations", x => x.discord_id_or_lodestone_auth);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "banned_registrations");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
302
MareSynchronosServer/MareSynchronosShared/Migrations/20220816170426_SetMaxLimitForStrings.Designer.cs
generated
Normal file
302
MareSynchronosServer/MareSynchronosShared/Migrations/20220816170426_SetMaxLimitForStrings.Designer.cs
generated
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220816170426_SetMaxLimitForStrings")]
|
||||||
|
partial class SetMaxLimitForStrings
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.HasIndex("CharacterIdentification")
|
||||||
|
.HasDatabaseName("ix_users_character_identification");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosServer.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosServer.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class SetMaxLimitForStrings : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "character_identification",
|
||||||
|
table: "users",
|
||||||
|
type: "character varying(100)",
|
||||||
|
maxLength: 100,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "lodestone_auth_string",
|
||||||
|
table: "lodestone_auth",
|
||||||
|
type: "character varying(100)",
|
||||||
|
maxLength: 100,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "hashed_lodestone_id",
|
||||||
|
table: "lodestone_auth",
|
||||||
|
type: "character varying(100)",
|
||||||
|
maxLength: 100,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "forbidden_by",
|
||||||
|
table: "forbidden_upload_entries",
|
||||||
|
type: "character varying(100)",
|
||||||
|
maxLength: 100,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "character_identification",
|
||||||
|
table: "banned_users",
|
||||||
|
type: "character varying(100)",
|
||||||
|
maxLength: 100,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "discord_id_or_lodestone_auth",
|
||||||
|
table: "banned_registrations",
|
||||||
|
type: "character varying(100)",
|
||||||
|
maxLength: 100,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "character_identification",
|
||||||
|
table: "users",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(100)",
|
||||||
|
oldMaxLength: 100,
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "lodestone_auth_string",
|
||||||
|
table: "lodestone_auth",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(100)",
|
||||||
|
oldMaxLength: 100,
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "hashed_lodestone_id",
|
||||||
|
table: "lodestone_auth",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(100)",
|
||||||
|
oldMaxLength: 100,
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "forbidden_by",
|
||||||
|
table: "forbidden_upload_entries",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(100)",
|
||||||
|
oldMaxLength: 100,
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "character_identification",
|
||||||
|
table: "banned_users",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(100)",
|
||||||
|
oldMaxLength: 100);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "discord_id_or_lodestone_auth",
|
||||||
|
table: "banned_registrations",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(100)",
|
||||||
|
oldMaxLength: 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
307
MareSynchronosServer/MareSynchronosShared/Migrations/20220824225157_AddAlias.Designer.cs
generated
Normal file
307
MareSynchronosServer/MareSynchronosShared/Migrations/20220824225157_AddAlias.Designer.cs
generated
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220824225157_AddAlias")]
|
||||||
|
partial class AddAlias
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.HasIndex("CharacterIdentification")
|
||||||
|
.HasDatabaseName("ix_users_character_identification");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddAlias : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "alias",
|
||||||
|
table: "users",
|
||||||
|
type: "character varying(10)",
|
||||||
|
maxLength: 10,
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "alias",
|
||||||
|
table: "users");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
389
MareSynchronosServer/MareSynchronosShared/Migrations/20220917115233_Groups.Designer.cs
generated
Normal file
389
MareSynchronosServer/MareSynchronosShared/Migrations/20220917115233_Groups.Designer.cs
generated
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220917115233_Groups")]
|
||||||
|
partial class Groups
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(14)
|
||||||
|
.HasColumnType("character varying(14)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(14)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id5");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id4");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class Groups : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "ix_users_character_identification",
|
||||||
|
table: "users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "character_identification",
|
||||||
|
table: "users");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "alias",
|
||||||
|
table: "users",
|
||||||
|
type: "character varying(10)",
|
||||||
|
maxLength: 10,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(100)",
|
||||||
|
oldMaxLength: 100,
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "groups",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
gid = table.Column<string>(type: "character varying(14)", maxLength: 14, nullable: false),
|
||||||
|
owner_uid = table.Column<string>(type: "character varying(10)", nullable: true),
|
||||||
|
alias = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
|
||||||
|
invites_enabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
hashed_password = table.Column<string>(type: "text", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_groups", x => x.gid);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_groups_users_owner_temp_id5",
|
||||||
|
column: x => x.owner_uid,
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "group_pairs",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
group_gid = table.Column<string>(type: "character varying(14)", nullable: false),
|
||||||
|
group_user_uid = table.Column<string>(type: "character varying(10)", nullable: false),
|
||||||
|
is_paused = table.Column<bool>(type: "boolean", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_group_pairs", x => new { x.group_gid, x.group_user_uid });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_group_pairs_groups_group_temp_id",
|
||||||
|
column: x => x.group_gid,
|
||||||
|
principalTable: "groups",
|
||||||
|
principalColumn: "gid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_group_pairs_users_group_user_temp_id4",
|
||||||
|
column: x => x.group_user_uid,
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_group_pairs_group_gid",
|
||||||
|
table: "group_pairs",
|
||||||
|
column: "group_gid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_group_pairs_group_user_uid",
|
||||||
|
table: "group_pairs",
|
||||||
|
column: "group_user_uid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_groups_owner_uid",
|
||||||
|
table: "groups",
|
||||||
|
column: "owner_uid");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "group_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "groups");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "alias",
|
||||||
|
table: "users",
|
||||||
|
type: "character varying(100)",
|
||||||
|
maxLength: 100,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(10)",
|
||||||
|
oldMaxLength: 10,
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "character_identification",
|
||||||
|
table: "users",
|
||||||
|
type: "character varying(100)",
|
||||||
|
maxLength: 100,
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_users_character_identification",
|
||||||
|
table: "users",
|
||||||
|
column: "character_identification");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
389
MareSynchronosServer/MareSynchronosShared/Migrations/20220929150304_ChangeGidLength.Designer.cs
generated
Normal file
389
MareSynchronosServer/MareSynchronosShared/Migrations/20220929150304_ChangeGidLength.Designer.cs
generated
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20220929150304_ChangeGidLength")]
|
||||||
|
partial class ChangeGidLength
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id5");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id4");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class ChangeGidLength : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "gid",
|
||||||
|
table: "groups",
|
||||||
|
type: "character varying(20)",
|
||||||
|
maxLength: 20,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(14)",
|
||||||
|
oldMaxLength: 14);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "group_gid",
|
||||||
|
table: "group_pairs",
|
||||||
|
type: "character varying(20)",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(14)");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "gid",
|
||||||
|
table: "groups",
|
||||||
|
type: "character varying(14)",
|
||||||
|
maxLength: 14,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(20)",
|
||||||
|
oldMaxLength: 20);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "group_gid",
|
||||||
|
table: "group_pairs",
|
||||||
|
type: "character varying(14)",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(20)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
393
MareSynchronosServer/MareSynchronosShared/Migrations/20221002105428_IsPinned.Designer.cs
generated
Normal file
393
MareSynchronosServer/MareSynchronosShared/Migrations/20221002105428_IsPinned.Designer.cs
generated
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20221002105428_IsPinned")]
|
||||||
|
partial class IsPinned
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id5");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id4");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class IsPinned : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "is_pinned",
|
||||||
|
table: "group_pairs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "is_pinned",
|
||||||
|
table: "group_pairs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
393
MareSynchronosServer/MareSynchronosShared/Migrations/20221004125939_AdjustAliasLength.Designer.cs
generated
Normal file
393
MareSynchronosServer/MareSynchronosShared/Migrations/20221004125939_AdjustAliasLength.Designer.cs
generated
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20221004125939_AdjustAliasLength")]
|
||||||
|
partial class AdjustAliasLength
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id5");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id4");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class AdjustAliasLength : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "alias",
|
||||||
|
table: "users",
|
||||||
|
type: "character varying(15)",
|
||||||
|
maxLength: 15,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(10)",
|
||||||
|
oldMaxLength: 10,
|
||||||
|
oldNullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "alias",
|
||||||
|
table: "users",
|
||||||
|
type: "character varying(10)",
|
||||||
|
maxLength: 10,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(15)",
|
||||||
|
oldMaxLength: 15,
|
||||||
|
oldNullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
397
MareSynchronosServer/MareSynchronosShared/Migrations/20221006115929_GroupModerator.Designer.cs
generated
Normal file
397
MareSynchronosServer/MareSynchronosShared/Migrations/20221006115929_GroupModerator.Designer.cs
generated
Normal file
@@ -0,0 +1,397 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20221006115929_GroupModerator")]
|
||||||
|
partial class GroupModerator
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id5");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id4");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class GroupModerator : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "is_moderator",
|
||||||
|
table: "group_pairs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "is_moderator",
|
||||||
|
table: "group_pairs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
462
MareSynchronosServer/MareSynchronosShared/Migrations/20221006122618_groupbans.Designer.cs
generated
Normal file
462
MareSynchronosServer/MareSynchronosShared/Migrations/20221006122618_groupbans.Designer.cs
generated
Normal file
@@ -0,0 +1,462 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20221006122618_groupbans")]
|
||||||
|
partial class groupbans
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedByUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_by_uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("BannedOn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("banned_on");
|
||||||
|
|
||||||
|
b.Property<string>("BannedReason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("banned_reason");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "BannedUserUID")
|
||||||
|
.HasName("pk_group_bans");
|
||||||
|
|
||||||
|
b.HasIndex("BannedByUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_by_uid");
|
||||||
|
|
||||||
|
b.HasIndex("BannedUserUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_bans_group_gid");
|
||||||
|
|
||||||
|
b.ToTable("group_bans", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id7");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedByUID")
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_by_temp_id4");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_user_temp_id5");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("BannedBy");
|
||||||
|
|
||||||
|
b.Navigation("BannedUser");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id6");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class groupbans : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_group_pairs_groups_group_temp_id",
|
||||||
|
table: "group_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_group_pairs_users_group_user_temp_id4",
|
||||||
|
table: "group_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_groups_users_owner_temp_id5",
|
||||||
|
table: "groups");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "group_bans",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
group_gid = table.Column<string>(type: "character varying(20)", nullable: false),
|
||||||
|
banned_user_uid = table.Column<string>(type: "character varying(10)", nullable: false),
|
||||||
|
banned_by_uid = table.Column<string>(type: "character varying(10)", nullable: true),
|
||||||
|
banned_on = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
banned_reason = table.Column<string>(type: "text", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_group_bans", x => new { x.group_gid, x.banned_user_uid });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_group_bans_groups_group_temp_id",
|
||||||
|
column: x => x.group_gid,
|
||||||
|
principalTable: "groups",
|
||||||
|
principalColumn: "gid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_group_bans_users_banned_by_temp_id4",
|
||||||
|
column: x => x.banned_by_uid,
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_group_bans_users_banned_user_temp_id5",
|
||||||
|
column: x => x.banned_user_uid,
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_group_bans_banned_by_uid",
|
||||||
|
table: "group_bans",
|
||||||
|
column: "banned_by_uid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_group_bans_banned_user_uid",
|
||||||
|
table: "group_bans",
|
||||||
|
column: "banned_user_uid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_group_bans_group_gid",
|
||||||
|
table: "group_bans",
|
||||||
|
column: "group_gid");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_group_pairs_groups_group_temp_id1",
|
||||||
|
table: "group_pairs",
|
||||||
|
column: "group_gid",
|
||||||
|
principalTable: "groups",
|
||||||
|
principalColumn: "gid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_group_pairs_users_group_user_temp_id6",
|
||||||
|
table: "group_pairs",
|
||||||
|
column: "group_user_uid",
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_groups_users_owner_temp_id7",
|
||||||
|
table: "groups",
|
||||||
|
column: "owner_uid",
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_group_pairs_groups_group_temp_id1",
|
||||||
|
table: "group_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_group_pairs_users_group_user_temp_id6",
|
||||||
|
table: "group_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_groups_users_owner_temp_id7",
|
||||||
|
table: "groups");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "group_bans");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_group_pairs_groups_group_temp_id",
|
||||||
|
table: "group_pairs",
|
||||||
|
column: "group_gid",
|
||||||
|
principalTable: "groups",
|
||||||
|
principalColumn: "gid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_group_pairs_users_group_user_temp_id4",
|
||||||
|
table: "group_pairs",
|
||||||
|
column: "group_user_uid",
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_groups_users_owner_temp_id5",
|
||||||
|
table: "groups",
|
||||||
|
column: "owner_uid",
|
||||||
|
principalTable: "users",
|
||||||
|
principalColumn: "uid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
501
MareSynchronosServer/MareSynchronosShared/Migrations/20221024141548_GroupTempInvite.Designer.cs
generated
Normal file
501
MareSynchronosServer/MareSynchronosShared/Migrations/20221024141548_GroupTempInvite.Designer.cs
generated
Normal file
@@ -0,0 +1,501 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20221024141548_GroupTempInvite")]
|
||||||
|
partial class GroupTempInvite
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedByUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_by_uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("BannedOn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("banned_on");
|
||||||
|
|
||||||
|
b.Property<string>("BannedReason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("banned_reason");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "BannedUserUID")
|
||||||
|
.HasName("pk_group_bans");
|
||||||
|
|
||||||
|
b.HasIndex("BannedByUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_by_uid");
|
||||||
|
|
||||||
|
b.HasIndex("BannedUserUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_bans_group_gid");
|
||||||
|
|
||||||
|
b.ToTable("group_bans", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("Invite")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("invite");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpirationDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expiration_date");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "Invite")
|
||||||
|
.HasName("pk_group_temp_invites");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("Invite")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_invite");
|
||||||
|
|
||||||
|
b.ToTable("group_temp_invites", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id7");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedByUID")
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_by_temp_id4");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_user_temp_id5");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("BannedBy");
|
||||||
|
|
||||||
|
b.Navigation("BannedUser");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id6");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_temp_invites_groups_group_gid");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class GroupTempInvite : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "group_temp_invites",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
group_gid = table.Column<string>(type: "character varying(20)", nullable: false),
|
||||||
|
invite = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: false),
|
||||||
|
expiration_date = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_group_temp_invites", x => new { x.group_gid, x.invite });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_group_temp_invites_groups_group_gid",
|
||||||
|
column: x => x.group_gid,
|
||||||
|
principalTable: "groups",
|
||||||
|
principalColumn: "gid",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_group_temp_invites_group_gid",
|
||||||
|
table: "group_temp_invites",
|
||||||
|
column: "group_gid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_group_temp_invites_invite",
|
||||||
|
table: "group_temp_invites",
|
||||||
|
column: "invite");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "group_temp_invites");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
501
MareSynchronosServer/MareSynchronosShared/Migrations/20221024181912_AdjustInviteLength.Designer.cs
generated
Normal file
501
MareSynchronosServer/MareSynchronosShared/Migrations/20221024181912_AdjustInviteLength.Designer.cs
generated
Normal file
@@ -0,0 +1,501 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20221024181912_AdjustInviteLength")]
|
||||||
|
partial class AdjustInviteLength
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "6.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedByUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_by_uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("BannedOn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("banned_on");
|
||||||
|
|
||||||
|
b.Property<string>("BannedReason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("banned_reason");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "BannedUserUID")
|
||||||
|
.HasName("pk_group_bans");
|
||||||
|
|
||||||
|
b.HasIndex("BannedByUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_by_uid");
|
||||||
|
|
||||||
|
b.HasIndex("BannedUserUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_bans_group_gid");
|
||||||
|
|
||||||
|
b.ToTable("group_bans", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("Invite")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("invite");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpirationDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expiration_date");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "Invite")
|
||||||
|
.HasName("pk_group_temp_invites");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("Invite")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_invite");
|
||||||
|
|
||||||
|
b.ToTable("group_temp_invites", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id7");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedByUID")
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_by_temp_id4");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_user_temp_id5");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("BannedBy");
|
||||||
|
|
||||||
|
b.Navigation("BannedUser");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id6");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_temp_invites_groups_group_gid");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
public partial class AdjustInviteLength : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "invite",
|
||||||
|
table: "group_temp_invites",
|
||||||
|
type: "character varying(64)",
|
||||||
|
maxLength: 64,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(10)",
|
||||||
|
oldMaxLength: 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "invite",
|
||||||
|
table: "group_temp_invites",
|
||||||
|
type: "character varying(10)",
|
||||||
|
maxLength: 10,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(64)",
|
||||||
|
oldMaxLength: 64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
506
MareSynchronosServer/MareSynchronosShared/Migrations/20221228033214_FileCacheSize.Designer.cs
generated
Normal file
506
MareSynchronosServer/MareSynchronosShared/Migrations/20221228033214_FileCacheSize.Designer.cs
generated
Normal file
@@ -0,0 +1,506 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20221228033214_FileCacheSize")]
|
||||||
|
partial class FileCacheSize
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.0")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<long>("Size")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("size");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedByUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_by_uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("BannedOn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("banned_on");
|
||||||
|
|
||||||
|
b.Property<string>("BannedReason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("banned_reason");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "BannedUserUID")
|
||||||
|
.HasName("pk_group_bans");
|
||||||
|
|
||||||
|
b.HasIndex("BannedByUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_by_uid");
|
||||||
|
|
||||||
|
b.HasIndex("BannedUserUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_bans_group_gid");
|
||||||
|
|
||||||
|
b.ToTable("group_bans", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("Invite")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("invite");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpirationDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expiration_date");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "Invite")
|
||||||
|
.HasName("pk_group_temp_invites");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("Invite")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_invite");
|
||||||
|
|
||||||
|
b.ToTable("group_temp_invites", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id7");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedByUID")
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_by_temp_id4");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_user_temp_id5");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("BannedBy");
|
||||||
|
|
||||||
|
b.Navigation("BannedUser");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id6");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_temp_invites_groups_group_gid");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class FileCacheSize : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<long>(
|
||||||
|
name: "size",
|
||||||
|
table: "file_caches",
|
||||||
|
type: "bigint",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "size",
|
||||||
|
table: "file_caches");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
510
MareSynchronosServer/MareSynchronosShared/Migrations/20230111092127_IsBannedForAuth.Designer.cs
generated
Normal file
510
MareSynchronosServer/MareSynchronosShared/Migrations/20230111092127_IsBannedForAuth.Designer.cs
generated
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20230111092127_IsBannedForAuth")]
|
||||||
|
partial class IsBannedForAuth
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.0")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBanned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_banned");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<long>("Size")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("size");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedByUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_by_uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("BannedOn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("banned_on");
|
||||||
|
|
||||||
|
b.Property<string>("BannedReason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("banned_reason");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "BannedUserUID")
|
||||||
|
.HasName("pk_group_bans");
|
||||||
|
|
||||||
|
b.HasIndex("BannedByUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_by_uid");
|
||||||
|
|
||||||
|
b.HasIndex("BannedUserUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_bans_group_gid");
|
||||||
|
|
||||||
|
b.ToTable("group_bans", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("Invite")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("invite");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpirationDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expiration_date");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "Invite")
|
||||||
|
.HasName("pk_group_temp_invites");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("Invite")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_invite");
|
||||||
|
|
||||||
|
b.ToTable("group_temp_invites", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id7");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedByUID")
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_by_temp_id4");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_user_temp_id5");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("BannedBy");
|
||||||
|
|
||||||
|
b.Navigation("BannedUser");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id6");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_temp_invites_groups_group_gid");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class IsBannedForAuth : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "is_banned",
|
||||||
|
table: "auth",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "is_banned",
|
||||||
|
table: "auth");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
514
MareSynchronosServer/MareSynchronosShared/Migrations/20230118184347_FilesUploadDate.Designer.cs
generated
Normal file
514
MareSynchronosServer/MareSynchronosShared/Migrations/20230118184347_FilesUploadDate.Designer.cs
generated
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20230118184347_FilesUploadDate")]
|
||||||
|
partial class FilesUploadDate
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.0")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBanned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_banned");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<long>("Size")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("size");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UploadDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("upload_date");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedByUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_by_uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("BannedOn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("banned_on");
|
||||||
|
|
||||||
|
b.Property<string>("BannedReason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("banned_reason");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "BannedUserUID")
|
||||||
|
.HasName("pk_group_bans");
|
||||||
|
|
||||||
|
b.HasIndex("BannedByUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_by_uid");
|
||||||
|
|
||||||
|
b.HasIndex("BannedUserUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_bans_group_gid");
|
||||||
|
|
||||||
|
b.ToTable("group_bans", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("Invite")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("invite");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpirationDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expiration_date");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "Invite")
|
||||||
|
.HasName("pk_group_temp_invites");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("Invite")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_invite");
|
||||||
|
|
||||||
|
b.ToTable("group_temp_invites", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id7");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedByUID")
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_by_temp_id4");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_user_temp_id5");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("BannedBy");
|
||||||
|
|
||||||
|
b.Navigation("BannedUser");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id6");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_temp_invites_groups_group_gid");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class FilesUploadDate : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "upload_date",
|
||||||
|
table: "file_caches",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(2000, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "upload_date",
|
||||||
|
table: "file_caches");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
530
MareSynchronosServer/MareSynchronosShared/Migrations/20230126163758_GroupPerms.Designer.cs
generated
Normal file
530
MareSynchronosServer/MareSynchronosShared/Migrations/20230126163758_GroupPerms.Designer.cs
generated
Normal file
@@ -0,0 +1,530 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20230126163758_GroupPerms")]
|
||||||
|
partial class GroupPerms
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.0")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBanned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_banned");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<long>("Size")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("size");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UploadDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("upload_date");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableAnimations")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disable_animations");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableSounds")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disable_sounds");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedByUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_by_uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("BannedOn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("banned_on");
|
||||||
|
|
||||||
|
b.Property<string>("BannedReason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("banned_reason");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "BannedUserUID")
|
||||||
|
.HasName("pk_group_bans");
|
||||||
|
|
||||||
|
b.HasIndex("BannedByUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_by_uid");
|
||||||
|
|
||||||
|
b.HasIndex("BannedUserUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_bans_group_gid");
|
||||||
|
|
||||||
|
b.ToTable("group_bans", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableAnimations")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disable_animations");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableSounds")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disable_sounds");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("Invite")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("invite");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpirationDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expiration_date");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "Invite")
|
||||||
|
.HasName("pk_group_temp_invites");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("Invite")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_invite");
|
||||||
|
|
||||||
|
b.ToTable("group_temp_invites", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id2");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id7");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedByUID")
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_by_temp_id4");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_user_temp_id5");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("BannedBy");
|
||||||
|
|
||||||
|
b.Navigation("BannedUser");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id6");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_temp_invites_groups_group_gid");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class GroupPerms : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "disable_animations",
|
||||||
|
table: "groups",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "disable_sounds",
|
||||||
|
table: "groups",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "disable_animations",
|
||||||
|
table: "group_pairs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "disable_sounds",
|
||||||
|
table: "group_pairs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "disable_animations",
|
||||||
|
table: "groups");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "disable_sounds",
|
||||||
|
table: "groups");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "disable_animations",
|
||||||
|
table: "group_pairs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "disable_sounds",
|
||||||
|
table: "group_pairs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
544
MareSynchronosServer/MareSynchronosShared/Migrations/20230131193425_AddPrimaryUserToAuth.Designer.cs
generated
Normal file
544
MareSynchronosServer/MareSynchronosShared/Migrations/20230131193425_AddPrimaryUserToAuth.Designer.cs
generated
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MareDbContext))]
|
||||||
|
[Migration("20230131193425_AddPrimaryUserToAuth")]
|
||||||
|
partial class AddPrimaryUserToAuth
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.0")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("HashedKey")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("hashed_key");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBanned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_banned");
|
||||||
|
|
||||||
|
b.Property<string>("PrimaryUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("primary_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("HashedKey")
|
||||||
|
.HasName("pk_auth");
|
||||||
|
|
||||||
|
b.HasIndex("PrimaryUserUID")
|
||||||
|
.HasDatabaseName("ix_auth_primary_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Banned", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("CharacterIdentification")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("character_identification");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("reason");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("CharacterIdentification")
|
||||||
|
.HasName("pk_banned_users");
|
||||||
|
|
||||||
|
b.ToTable("banned_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.BannedRegistrations", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("discord_id_or_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasKey("DiscordIdOrLodestoneAuth")
|
||||||
|
.HasName("pk_banned_registrations");
|
||||||
|
|
||||||
|
b.ToTable("banned_registrations", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("OtherUserUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("other_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowReceivingMessages")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("allow_receiving_messages");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UserUID", "OtherUserUID")
|
||||||
|
.HasName("pk_client_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("OtherUserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_other_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_client_pairs_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("client_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<long>("Size")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("size");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UploadDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("upload_date");
|
||||||
|
|
||||||
|
b.Property<bool>("Uploaded")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("uploaded");
|
||||||
|
|
||||||
|
b.Property<string>("UploaderUID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uploader_uid");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_file_caches");
|
||||||
|
|
||||||
|
b.HasIndex("UploaderUID")
|
||||||
|
.HasDatabaseName("ix_file_caches_uploader_uid");
|
||||||
|
|
||||||
|
b.ToTable("file_caches", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ForbiddenUploadEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Hash")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)")
|
||||||
|
.HasColumnName("hash");
|
||||||
|
|
||||||
|
b.Property<string>("ForbiddenBy")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("forbidden_by");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("Hash")
|
||||||
|
.HasName("pk_forbidden_upload_entries");
|
||||||
|
|
||||||
|
b.ToTable("forbidden_upload_entries", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GID")
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("gid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableAnimations")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disable_animations");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableSounds")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disable_sounds");
|
||||||
|
|
||||||
|
b.Property<string>("HashedPassword")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("hashed_password");
|
||||||
|
|
||||||
|
b.Property<bool>("InvitesEnabled")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("invites_enabled");
|
||||||
|
|
||||||
|
b.Property<string>("OwnerUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("owner_uid");
|
||||||
|
|
||||||
|
b.HasKey("GID")
|
||||||
|
.HasName("pk_groups");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerUID")
|
||||||
|
.HasDatabaseName("ix_groups_owner_uid");
|
||||||
|
|
||||||
|
b.ToTable("groups", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_user_uid");
|
||||||
|
|
||||||
|
b.Property<string>("BannedByUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("banned_by_uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("BannedOn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("banned_on");
|
||||||
|
|
||||||
|
b.Property<string>("BannedReason")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("banned_reason");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "BannedUserUID")
|
||||||
|
.HasName("pk_group_bans");
|
||||||
|
|
||||||
|
b.HasIndex("BannedByUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_by_uid");
|
||||||
|
|
||||||
|
b.HasIndex("BannedUserUID")
|
||||||
|
.HasDatabaseName("ix_group_bans_banned_user_uid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_bans_group_gid");
|
||||||
|
|
||||||
|
b.ToTable("group_bans", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("GroupUserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("group_user_uid");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableAnimations")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disable_animations");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableSounds")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disable_sounds");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPaused")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_paused");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPinned")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_pinned");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "GroupUserUID")
|
||||||
|
.HasName("pk_group_pairs");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("GroupUserUID")
|
||||||
|
.HasDatabaseName("ix_group_pairs_group_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("group_pairs", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("GroupGID")
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasColumnName("group_gid");
|
||||||
|
|
||||||
|
b.Property<string>("Invite")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)")
|
||||||
|
.HasColumnName("invite");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpirationDate")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expiration_date");
|
||||||
|
|
||||||
|
b.HasKey("GroupGID", "Invite")
|
||||||
|
.HasName("pk_group_temp_invites");
|
||||||
|
|
||||||
|
b.HasIndex("GroupGID")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_group_gid");
|
||||||
|
|
||||||
|
b.HasIndex("Invite")
|
||||||
|
.HasDatabaseName("ix_group_temp_invites_invite");
|
||||||
|
|
||||||
|
b.ToTable("group_temp_invites", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("DiscordId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("discord_id");
|
||||||
|
|
||||||
|
b.Property<string>("HashedLodestoneId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("hashed_lodestone_id");
|
||||||
|
|
||||||
|
b.Property<string>("LodestoneAuthString")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("lodestone_auth_string");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("StartedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("started_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserUID")
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("user_uid");
|
||||||
|
|
||||||
|
b.HasKey("DiscordId")
|
||||||
|
.HasName("pk_lodestone_auth");
|
||||||
|
|
||||||
|
b.HasIndex("UserUID")
|
||||||
|
.HasDatabaseName("ix_lodestone_auth_user_uid");
|
||||||
|
|
||||||
|
b.ToTable("lodestone_auth", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UID")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("character varying(10)")
|
||||||
|
.HasColumnName("uid");
|
||||||
|
|
||||||
|
b.Property<string>("Alias")
|
||||||
|
.HasMaxLength(15)
|
||||||
|
.HasColumnType("character varying(15)")
|
||||||
|
.HasColumnName("alias");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAdmin")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_admin");
|
||||||
|
|
||||||
|
b.Property<bool>("IsModerator")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_moderator");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLoggedIn")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_logged_in");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Timestamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea")
|
||||||
|
.HasColumnName("timestamp");
|
||||||
|
|
||||||
|
b.HasKey("UID")
|
||||||
|
.HasName("pk_users");
|
||||||
|
|
||||||
|
b.ToTable("users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Auth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "PrimaryUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PrimaryUserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_primary_user_temp_id");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_auth_users_user_temp_id1");
|
||||||
|
|
||||||
|
b.Navigation("PrimaryUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.ClientPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "OtherUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OtherUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_other_user_temp_id2");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_client_pairs_users_user_temp_id3");
|
||||||
|
|
||||||
|
b.Navigation("OtherUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.FileCache", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Uploader")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UploaderUID")
|
||||||
|
.HasConstraintName("fk_file_caches_users_uploader_uid");
|
||||||
|
|
||||||
|
b.Navigation("Uploader");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.Group", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerUID")
|
||||||
|
.HasConstraintName("fk_groups_users_owner_temp_id8");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupBan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedByUID")
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_by_temp_id5");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "BannedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannedUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_users_banned_user_temp_id6");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_bans_groups_group_temp_id");
|
||||||
|
|
||||||
|
b.Navigation("BannedBy");
|
||||||
|
|
||||||
|
b.Navigation("BannedUser");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupPair", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_groups_group_temp_id1");
|
||||||
|
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "GroupUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupUserUID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_pairs_users_group_user_temp_id7");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
|
||||||
|
b.Navigation("GroupUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.GroupTempInvite", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.Group", "Group")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("GroupGID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_group_temp_invites_groups_group_gid");
|
||||||
|
|
||||||
|
b.Navigation("Group");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MareSynchronosShared.Models.LodeStoneAuth", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MareSynchronosShared.Models.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserUID")
|
||||||
|
.HasConstraintName("fk_lodestone_auth_users_user_uid");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user