Admin logs (#5419)
* Add admin logging, models, migrations * Add logging damage changes * Add Log admin flag, LogFilter, Logs admin menu tab, message Refactor admin logging API * Change admin log get method names * Fix the name again * Minute amount of reorganization * Reset Postgres db snapshot * Reset Sqlite db snapshot * Make AdminLog have a composite primary key of round, id * Minute cleanup * Change admin system to do a type check instead of index check * Make admin logs use C# 10 interpolated string handlers * Implement UI on its own window Custom controls Searching Add admin log converters * Implement limits into the query * Change logs to be put into an OutputPanel instead for text wrapping * Add log <-> player m2m relationship back * UI improvements, make text wrap, add separators * Remove entity prefix from damaged log * Add explicit m2m model, fix any players filter * Add debug command to test bulk adding logs * Admin logs now just kinda go * Add histogram for database update time * Make admin log system update run every 5 seconds * Add a cap to the log queue and a metric for how many times it has been reached * Add metric for logs sent in a round * Make cvars out of admin logs queue send delay and cap * Merge fixes * Reset some changes * Add test for adding and getting a single log * Add tests for bulk adding logs * Add test for querying logs * Add CallerArgumentExpression to LogStringHandler methods and test * Improve UI, fix SQLite, add searching by round * Add entities to admin logs * Move distinct after orderby * Add migrations * ef core eat my ass * Add cvar for client logs batch size * Sort logs from newest to oldest by default * Merge fixes * Reorganize tests and add one for date ordering * Add note to log types to not change their numeric values * Add impacts to logs, better UI filtering * Make log add callable from shared for convenience * Get current round id directly from game ticker * Revert namespace change for DamageableSystem
This commit is contained in:
committed by
GitHub
parent
0f7e81b564
commit
319aec109d
7
Content.Client/Administration/Logs/AdminLogSystem.cs
Normal file
7
Content.Client/Administration/Logs/AdminLogSystem.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using Content.Shared.Administration.Logs;
|
||||
|
||||
namespace Content.Client.Administration.Logs;
|
||||
|
||||
public class AdminLogSystem : SharedAdminLogSystem
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client.Administration.UI.CustomControls;
|
||||
|
||||
public class AdminLogImpactButton : Button
|
||||
{
|
||||
public AdminLogImpactButton(LogImpact impact)
|
||||
{
|
||||
Impact = impact;
|
||||
ToggleMode = true;
|
||||
Pressed = true;
|
||||
}
|
||||
|
||||
public LogImpact Impact { get; }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client.Administration.UI.CustomControls;
|
||||
|
||||
public class AdminLogLabel : RichTextLabel
|
||||
{
|
||||
public AdminLogLabel(ref SharedAdminLog log, HSeparator separator)
|
||||
{
|
||||
Log = log;
|
||||
Separator = separator;
|
||||
|
||||
SetMessage(log.Message);
|
||||
OnVisibilityChanged += VisibilityChanged;
|
||||
}
|
||||
|
||||
public SharedAdminLog Log { get; }
|
||||
|
||||
public HSeparator Separator { get; }
|
||||
|
||||
private void VisibilityChanged(Control control)
|
||||
{
|
||||
Separator.Visible = Visible;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
OnVisibilityChanged -= VisibilityChanged;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client.Administration.UI.CustomControls;
|
||||
|
||||
public class AdminLogPlayerButton : Button
|
||||
{
|
||||
public AdminLogPlayerButton(Guid id)
|
||||
{
|
||||
Id = id;
|
||||
ClipText = true;
|
||||
ToggleMode = true;
|
||||
Pressed = true;
|
||||
}
|
||||
|
||||
public Guid Id { get; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client.Administration.UI.CustomControls;
|
||||
|
||||
public class AdminLogTypeButton : Button
|
||||
{
|
||||
public AdminLogTypeButton(LogType type)
|
||||
{
|
||||
Type = type;
|
||||
ToggleMode = true;
|
||||
Pressed = true;
|
||||
}
|
||||
|
||||
public LogType Type { get; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client.Administration.UI.CustomControls;
|
||||
|
||||
public class HSeparator : Control
|
||||
{
|
||||
private static readonly Color SeparatorColor = Color.FromHex("#3D4059");
|
||||
|
||||
public HSeparator(Color color)
|
||||
{
|
||||
AddChild(new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = color,
|
||||
ContentMarginBottomOverride = 2, ContentMarginLeftOverride = 2
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public HSeparator() : this(SeparatorColor) { }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client.Administration.UI.CustomControls;
|
||||
|
||||
public class VSeparator : PanelContainer
|
||||
{
|
||||
private static readonly Color SeparatorColor = Color.FromHex("#3D4059");
|
||||
|
||||
public VSeparator(Color color)
|
||||
{
|
||||
MinSize = (2, 5);
|
||||
|
||||
AddChild(new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = color
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public VSeparator() : this(SeparatorColor) { }
|
||||
}
|
||||
106
Content.Client/Administration/UI/Logs/AdminLogsEui.cs
Normal file
106
Content.Client/Administration/UI/Logs/AdminLogsEui.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using Content.Client.Eui;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Eui;
|
||||
using JetBrains.Annotations;
|
||||
using static Content.Shared.Administration.AdminLogsEuiMsg;
|
||||
|
||||
namespace Content.Client.Administration.UI.Logs;
|
||||
|
||||
[UsedImplicitly]
|
||||
public class AdminLogsEui : BaseEui
|
||||
{
|
||||
public AdminLogsEui()
|
||||
{
|
||||
Window = new AdminLogsWindow();
|
||||
Window.OnClose += () => SendMessage(new Close());
|
||||
Window.LogSearch.OnTextEntered += _ => RequestLogs();
|
||||
Window.RefreshButton.OnPressed += _ => RequestLogs();
|
||||
Window.NextButton.OnPressed += _ => NextLogs();
|
||||
}
|
||||
|
||||
private AdminLogsWindow Window { get; }
|
||||
|
||||
private bool FirstState { get; set; } = true;
|
||||
|
||||
private void RequestLogs()
|
||||
{
|
||||
var round = Window.GetSelectedRoundId();
|
||||
var types = Window.GetSelectedLogTypes();
|
||||
var players = Window.GetSelectedPlayerIds();
|
||||
|
||||
var request = new LogsRequest(
|
||||
round,
|
||||
types,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
players,
|
||||
null,
|
||||
null,
|
||||
DateOrder.Descending);
|
||||
|
||||
SendMessage(request);
|
||||
}
|
||||
|
||||
private void NextLogs()
|
||||
{
|
||||
var request = new NextLogsRequest();
|
||||
SendMessage(request);
|
||||
}
|
||||
|
||||
private void TrySetFirstState(AdminLogsEuiState state)
|
||||
{
|
||||
if (!FirstState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FirstState = false;
|
||||
Window.SetCurrentRound(state.RoundId);
|
||||
Window.SetRoundSpinBox(state.RoundId);
|
||||
}
|
||||
|
||||
public override void Opened()
|
||||
{
|
||||
Window.OpenCentered();
|
||||
}
|
||||
|
||||
public override void HandleState(EuiStateBase state)
|
||||
{
|
||||
var s = (AdminLogsEuiState) state;
|
||||
|
||||
TrySetFirstState(s);
|
||||
|
||||
if (s.IsLoading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Window.SetCurrentRound(s.RoundId);
|
||||
Window.SetPlayers(s.Players);
|
||||
}
|
||||
|
||||
public override void HandleMessage(EuiMessageBase msg)
|
||||
{
|
||||
base.HandleMessage(msg);
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case NewLogs {Replace: true} newLogs:
|
||||
Window.SetLogs(newLogs.Logs);
|
||||
break;
|
||||
case NewLogs {Replace: false} newLogs:
|
||||
Window.AddLogs(newLogs.Logs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Closed()
|
||||
{
|
||||
base.Closed();
|
||||
|
||||
Window.Close();
|
||||
Window.Dispose();
|
||||
}
|
||||
}
|
||||
55
Content.Client/Administration/UI/Logs/AdminLogsWindow.xaml
Normal file
55
Content.Client/Administration/UI/Logs/AdminLogsWindow.xaml
Normal file
@@ -0,0 +1,55 @@
|
||||
<SS14Window xmlns="https://spacestation14.io"
|
||||
xmlns:aui="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
Title="{Loc admin-logs-title}"
|
||||
MinWidth="1000"
|
||||
MinHeight="400">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal" MinWidth="400">
|
||||
<Label Text="{Loc admin-logs-round}"/>
|
||||
<SpinBox Name="RoundSpinBox" Value="0" MinWidth="150"/>
|
||||
<Control HorizontalExpand="True"/>
|
||||
<Button Name="ResetRoundButton" Text="{Loc admin-logs-reset}" HorizontalAlignment="Right"
|
||||
StyleClasses="OpenRight"/>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" VerticalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" MinWidth="200">
|
||||
<LineEdit Name="TypeSearch" Access="Public" StyleClasses="actionSearchBox"
|
||||
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-types-placeholder}"/>
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Button Name="SelectAllTypesButton" Text="{Loc admin-logs-select-all}"
|
||||
MinWidth="100" StyleClasses="ButtonSquare"/>
|
||||
<Button Name="SelectNoTypesButton" Text="{Loc admin-logs-select-none}"
|
||||
MinWidth="100" StyleClasses="ButtonSquare"/>
|
||||
</BoxContainer>
|
||||
<ScrollContainer VerticalExpand="True">
|
||||
<BoxContainer Name="TypesContainer" Access="Public" Orientation="Vertical"/>
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
<aui:VSeparator/>
|
||||
<BoxContainer Orientation="Vertical" MinWidth="200">
|
||||
<LineEdit Name="PlayerSearch" Access="Public" StyleClasses="actionSearchBox"
|
||||
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-players-placeholder}"/>
|
||||
<Button Name="SelectNoPlayersButton" Text="{Loc admin-logs-select-none}"
|
||||
StyleClasses="ButtonSquare"/>
|
||||
<ScrollContainer VerticalExpand="True">
|
||||
<BoxContainer Name="PlayersContainer" Access="Public" Orientation="Vertical"/>
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
<aui:VSeparator/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<BoxContainer Name="LogImpactContainer" Orientation="Horizontal"/>
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<LineEdit Name="LogSearch" Access="Public" StyleClasses="actionSearchBox"
|
||||
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-logs-placeholder}"/>
|
||||
<Button Name="RefreshButton" Access="Public" Text="{Loc admin-logs-refresh}" StyleClasses="ButtonSquare"/>
|
||||
<Button Name="NextButton" Access="Public" Text="{Loc admin-logs-next}" StyleClasses="OpenLeft"/>
|
||||
</BoxContainer>
|
||||
<ScrollContainer VerticalExpand="True" HorizontalExpand="True" HScrollEnabled="False">
|
||||
<BoxContainer Name="LogsContainer" Access="Public" Orientation="Vertical" VerticalExpand="True"/>
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</SS14Window>
|
||||
439
Content.Client/Administration/UI/Logs/AdminLogsWindow.xaml.cs
Normal file
439
Content.Client/Administration/UI/Logs/AdminLogsWindow.xaml.cs
Normal file
@@ -0,0 +1,439 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Client.Administration.UI.CustomControls;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
using static Robust.Client.UserInterface.Controls.BaseButton;
|
||||
using static Robust.Client.UserInterface.Controls.LineEdit;
|
||||
|
||||
namespace Content.Client.Administration.UI.Logs;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public partial class AdminLogsWindow : SS14Window
|
||||
{
|
||||
private readonly Comparer<AdminLogTypeButton> _adminLogTypeButtonComparer =
|
||||
Comparer<AdminLogTypeButton>.Create((a, b) =>
|
||||
string.Compare(a.Type.ToString(), b.Type.ToString(), StringComparison.Ordinal));
|
||||
|
||||
private readonly Comparer<AdminLogPlayerButton> _adminLogPlayerButtonComparer =
|
||||
Comparer<AdminLogPlayerButton>.Create((a, b) =>
|
||||
string.Compare(a.Text, b.Text, StringComparison.Ordinal));
|
||||
|
||||
public AdminLogsWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
TypeSearch.OnTextChanged += TypeSearchChanged;
|
||||
PlayerSearch.OnTextChanged += PlayerSearchChanged;
|
||||
LogSearch.OnTextChanged += LogSearchChanged;
|
||||
|
||||
SelectAllTypesButton.OnPressed += SelectAllTypes;
|
||||
|
||||
SelectNoTypesButton.OnPressed += SelectNoTypes;
|
||||
SelectNoPlayersButton.OnPressed += SelectNoPlayers;
|
||||
|
||||
RoundSpinBox.IsValid = i => i > 0 && i <= CurrentRound;
|
||||
RoundSpinBox.ValueChanged += RoundSpinBoxChanged;
|
||||
RoundSpinBox.InitDefaultButtons();
|
||||
|
||||
ResetRoundButton.OnPressed += ResetRoundPressed;
|
||||
|
||||
SetImpacts(Enum.GetValues<LogImpact>().OrderBy(impact => impact).ToArray());
|
||||
SetTypes(Enum.GetValues<LogType>());
|
||||
}
|
||||
|
||||
private int CurrentRound { get; set; }
|
||||
|
||||
private HashSet<LogType> SelectedTypes { get; } = new();
|
||||
|
||||
private HashSet<Guid> SelectedPlayers { get; } = new();
|
||||
|
||||
private HashSet<LogImpact> SelectedImpacts { get; } = new();
|
||||
|
||||
public void SetCurrentRound(int round)
|
||||
{
|
||||
CurrentRound = round;
|
||||
ResetRoundButton.Text = Loc.GetString("admin-logs-reset-with-id", ("id", round));
|
||||
UpdateResetButton();
|
||||
}
|
||||
|
||||
public void SetRoundSpinBox(int round)
|
||||
{
|
||||
RoundSpinBox.Value = round;
|
||||
UpdateResetButton();
|
||||
}
|
||||
|
||||
private void RoundSpinBoxChanged(object? sender, ValueChangedEventArgs args)
|
||||
{
|
||||
UpdateResetButton();
|
||||
}
|
||||
|
||||
private void UpdateResetButton()
|
||||
{
|
||||
ResetRoundButton.Disabled = RoundSpinBox.Value == CurrentRound;
|
||||
}
|
||||
|
||||
private void ResetRoundPressed(ButtonEventArgs args)
|
||||
{
|
||||
RoundSpinBox.Value = CurrentRound;
|
||||
}
|
||||
|
||||
private void TypeSearchChanged(LineEditEventArgs args)
|
||||
{
|
||||
UpdateTypes();
|
||||
}
|
||||
|
||||
private void PlayerSearchChanged(LineEditEventArgs obj)
|
||||
{
|
||||
UpdatePlayers();
|
||||
}
|
||||
|
||||
private void LogSearchChanged(LineEditEventArgs args)
|
||||
{
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
private void SelectAllTypes(ButtonEventArgs obj)
|
||||
{
|
||||
foreach (var control in TypesContainer.Children)
|
||||
{
|
||||
if (control is not AdminLogTypeButton type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
type.Pressed = true;
|
||||
}
|
||||
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
private void SelectNoTypes(ButtonEventArgs obj)
|
||||
{
|
||||
foreach (var control in TypesContainer.Children)
|
||||
{
|
||||
if (control is not AdminLogTypeButton type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
type.Pressed = false;
|
||||
type.Visible = ShouldShowType(type);
|
||||
}
|
||||
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
private void SelectNoPlayers(ButtonEventArgs obj)
|
||||
{
|
||||
foreach (var control in PlayersContainer.Children)
|
||||
{
|
||||
if (control is not AdminLogPlayerButton player)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
player.Pressed = false;
|
||||
}
|
||||
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
public void UpdateTypes()
|
||||
{
|
||||
foreach (var control in TypesContainer.Children)
|
||||
{
|
||||
if (control is not AdminLogTypeButton type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
type.Visible = ShouldShowType(type);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePlayers()
|
||||
{
|
||||
foreach (var control in PlayersContainer.Children)
|
||||
{
|
||||
if (control is not AdminLogPlayerButton player)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
player.Visible = ShouldShowPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLogs()
|
||||
{
|
||||
foreach (var child in LogsContainer.Children)
|
||||
{
|
||||
if (child is not AdminLogLabel log)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
child.Visible = ShouldShowLog(log);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldShowType(AdminLogTypeButton button)
|
||||
{
|
||||
return button.Text != null &&
|
||||
button.Text.Contains(TypeSearch.Text, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private bool ShouldShowPlayer(AdminLogPlayerButton button)
|
||||
{
|
||||
return button.Text != null &&
|
||||
button.Text.Contains(PlayerSearch.Text, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private bool ShouldShowLog(AdminLogLabel label)
|
||||
{
|
||||
return SelectedTypes.Contains(label.Log.Type) &&
|
||||
SelectedPlayers.Overlaps(label.Log.Players) &&
|
||||
SelectedImpacts.Contains(label.Log.Impact) &&
|
||||
label.Log.Message.Contains(LogSearch.Text, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private void TypeButtonPressed(ButtonEventArgs args)
|
||||
{
|
||||
var button = (AdminLogTypeButton) args.Button;
|
||||
if (button.Pressed)
|
||||
{
|
||||
SelectedTypes.Add(button.Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedTypes.Remove(button.Type);
|
||||
}
|
||||
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
private void PlayerButtonPressed(ButtonEventArgs args)
|
||||
{
|
||||
var button = (AdminLogPlayerButton) args.Button;
|
||||
if (button.Pressed)
|
||||
{
|
||||
SelectedPlayers.Add(button.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedPlayers.Remove(button.Id);
|
||||
}
|
||||
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
private void ImpactButtonPressed(ButtonEventArgs args)
|
||||
{
|
||||
var button = (AdminLogImpactButton) args.Button;
|
||||
if (button.Pressed)
|
||||
{
|
||||
SelectedImpacts.Add(button.Impact);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedImpacts.Remove(button.Impact);
|
||||
}
|
||||
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
private void SetImpacts(LogImpact[] impacts)
|
||||
{
|
||||
LogImpactContainer.RemoveAllChildren();
|
||||
|
||||
foreach (var impact in impacts)
|
||||
{
|
||||
var button = new AdminLogImpactButton(impact)
|
||||
{
|
||||
Text = impact.ToString()
|
||||
};
|
||||
|
||||
SelectedImpacts.Add(impact);
|
||||
button.OnPressed += ImpactButtonPressed;
|
||||
|
||||
LogImpactContainer.AddChild(button);
|
||||
}
|
||||
|
||||
switch (impacts.Length)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
LogImpactContainer.GetChild(0).StyleClasses.Add("OpenRight");
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < impacts.Length - 1; i++)
|
||||
{
|
||||
LogImpactContainer.GetChild(i).StyleClasses.Add("ButtonSquare");
|
||||
}
|
||||
|
||||
LogImpactContainer.GetChild(LogImpactContainer.ChildCount - 1).StyleClasses.Add("OpenLeft");
|
||||
}
|
||||
|
||||
private void SetTypes(LogType[] types)
|
||||
{
|
||||
var newTypes = types.ToHashSet();
|
||||
var buttons = new SortedSet<AdminLogTypeButton>(_adminLogTypeButtonComparer);
|
||||
|
||||
foreach (var control in TypesContainer.Children.ToArray())
|
||||
{
|
||||
if (control is not AdminLogTypeButton type ||
|
||||
!newTypes.Remove(type.Type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
buttons.Add(type);
|
||||
}
|
||||
|
||||
foreach (var type in newTypes)
|
||||
{
|
||||
var button = new AdminLogTypeButton(type)
|
||||
{
|
||||
Text = type.ToString()
|
||||
};
|
||||
|
||||
SelectedTypes.Add(type);
|
||||
button.OnPressed += TypeButtonPressed;
|
||||
|
||||
buttons.Add(button);
|
||||
}
|
||||
|
||||
TypesContainer.RemoveAllChildren();
|
||||
|
||||
foreach (var type in buttons)
|
||||
{
|
||||
TypesContainer.AddChild(type);
|
||||
}
|
||||
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
public void SetPlayers(Dictionary<Guid, string> players)
|
||||
{
|
||||
var buttons = new SortedSet<AdminLogPlayerButton>(_adminLogPlayerButtonComparer);
|
||||
|
||||
foreach (var control in PlayersContainer.Children.ToArray())
|
||||
{
|
||||
if (control is not AdminLogPlayerButton player ||
|
||||
!players.Remove(player.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
buttons.Add(player);
|
||||
}
|
||||
|
||||
foreach (var (id, name) in players)
|
||||
{
|
||||
var button = new AdminLogPlayerButton(id)
|
||||
{
|
||||
Text = name
|
||||
};
|
||||
|
||||
SelectedPlayers.Add(id);
|
||||
button.OnPressed += PlayerButtonPressed;
|
||||
|
||||
buttons.Add(button);
|
||||
}
|
||||
|
||||
PlayersContainer.RemoveAllChildren();
|
||||
|
||||
foreach (var player in buttons)
|
||||
{
|
||||
PlayersContainer.AddChild(player);
|
||||
}
|
||||
|
||||
UpdateLogs();
|
||||
}
|
||||
|
||||
public void AddLogs(SharedAdminLog[] logs)
|
||||
{
|
||||
for (var i = 0; i < logs.Length; i++)
|
||||
{
|
||||
ref var log = ref logs[i];
|
||||
var separator = new HSeparator();
|
||||
var label = new AdminLogLabel(ref log, separator);
|
||||
label.Visible = ShouldShowLog(label);
|
||||
|
||||
LogsContainer.AddChild(label);
|
||||
LogsContainer.AddChild(separator);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLogs(SharedAdminLog[] logs)
|
||||
{
|
||||
LogsContainer.RemoveAllChildren();
|
||||
AddLogs(logs);
|
||||
}
|
||||
|
||||
public int GetSelectedRoundId()
|
||||
{
|
||||
return RoundSpinBox.Value;
|
||||
}
|
||||
|
||||
public List<LogType> GetSelectedLogTypes()
|
||||
{
|
||||
var types = new List<LogType>();
|
||||
|
||||
foreach (var control in TypesContainer.Children)
|
||||
{
|
||||
if (control is not AdminLogTypeButton {Text: { }, Pressed: true} type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
types.Add(Enum.Parse<LogType>(type.Text));
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
public Guid[] GetSelectedPlayerIds()
|
||||
{
|
||||
var players = new List<Guid>();
|
||||
|
||||
foreach (var control in PlayersContainer.Children)
|
||||
{
|
||||
if (control is not AdminLogPlayerButton {Pressed: true} player)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
players.Add(player.Id);
|
||||
}
|
||||
|
||||
return players.ToArray();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
TypeSearch.OnTextChanged -= TypeSearchChanged;
|
||||
PlayerSearch.OnTextChanged -= PlayerSearchChanged;
|
||||
LogSearch.OnTextChanged -= LogSearchChanged;
|
||||
|
||||
SelectAllTypesButton.OnPressed -= SelectAllTypes;
|
||||
|
||||
SelectNoTypesButton.OnPressed -= SelectNoTypes;
|
||||
SelectNoPlayersButton.OnPressed -= SelectNoPlayers;
|
||||
|
||||
RoundSpinBox.IsValid = null;
|
||||
RoundSpinBox.ValueChanged -= RoundSpinBoxChanged;
|
||||
|
||||
ResetRoundButton.OnPressed -= ResetRoundPressed;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
<cc:CommandButton Command="permissions" Text="{Loc Permissions Panel}" />
|
||||
<cc:CommandButton Command="announceui" Text="{Loc Announce}"/>
|
||||
<cc:UICommandButton Command="callshuttle" Text="{Loc (Re)call Shuttle}" WindowType="{x:Type at:AdminShuttleWindow}"/>
|
||||
<cc:CommandButton Command="adminlogs" Text="{Loc Admin Logs}"/>
|
||||
</GridContainer>
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.Administration.UI.CustomControls;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Events;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
@@ -138,37 +138,5 @@ namespace Content.Client.Administration.UI.Tabs
|
||||
useAltColor ^= true;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Color SeparatorColor = Color.FromHex("#3D4059");
|
||||
|
||||
private class VSeparator : PanelContainer
|
||||
{
|
||||
public VSeparator()
|
||||
{
|
||||
MinSize = (2, 5);
|
||||
AddChild(new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = SeparatorColor
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class HSeparator : Control
|
||||
{
|
||||
public HSeparator()
|
||||
{
|
||||
AddChild(new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = SeparatorColor,
|
||||
ContentMarginBottomOverride = 2, ContentMarginLeftOverride = 2
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,13 +318,19 @@ namespace Content.IntegrationTests
|
||||
|
||||
protected async Task WaitUntil(IntegrationInstance instance, Func<bool> func, int maxTicks = 600,
|
||||
int tickStep = 1)
|
||||
{
|
||||
await WaitUntil(instance, async () => await Task.FromResult(func()), maxTicks);
|
||||
}
|
||||
|
||||
protected async Task WaitUntil(IntegrationInstance instance, Func<Task<bool>> func, int maxTicks = 600,
|
||||
int tickStep = 1)
|
||||
{
|
||||
var ticksAwaited = 0;
|
||||
bool passed;
|
||||
|
||||
await instance.WaitIdleAsync();
|
||||
|
||||
while (!(passed = func()) && ticksAwaited < maxTicks)
|
||||
while (!(passed = await func()) && ticksAwaited < maxTicks)
|
||||
{
|
||||
var ticksToRun = tickStep;
|
||||
|
||||
|
||||
197
Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs
Normal file
197
Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Database;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.CCVar;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Administration.Logs;
|
||||
|
||||
[TestFixture]
|
||||
[TestOf(typeof(AdminLogSystem))]
|
||||
public class AddTests : ContentIntegrationTest
|
||||
{
|
||||
[Test]
|
||||
public async Task AddAndGetSingleLog()
|
||||
{
|
||||
var server = StartServer(new ServerContentIntegrationOption
|
||||
{
|
||||
CVarOverrides =
|
||||
{
|
||||
[CCVars.AdminLogsQueueSendDelay.Name] = "0"
|
||||
},
|
||||
Pool = true
|
||||
});
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var sEntities = server.ResolveDependency<IEntityManager>();
|
||||
var sMaps = server.ResolveDependency<IMapManager>();
|
||||
var sSystems = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
var sAdminLogSystem = sSystems.GetEntitySystem<AdminLogSystem>();
|
||||
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var coordinates = GetMainEntityCoordinates(sMaps);
|
||||
var entity = sEntities.SpawnEntity(null, coordinates);
|
||||
|
||||
sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log: {guid}");
|
||||
});
|
||||
|
||||
await WaitUntil(server, async () =>
|
||||
{
|
||||
var logs = sAdminLogSystem.CurrentRoundJson(new LogFilter
|
||||
{
|
||||
Search = guid.ToString()
|
||||
});
|
||||
|
||||
await foreach (var json in logs)
|
||||
{
|
||||
var root = json.RootElement;
|
||||
|
||||
// camelCased automatically
|
||||
Assert.That(root.TryGetProperty("entity", out _), Is.True);
|
||||
|
||||
json.Dispose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task AddAndGetUnformattedLog()
|
||||
{
|
||||
var server = StartServer(new ServerContentIntegrationOption
|
||||
{
|
||||
CVarOverrides =
|
||||
{
|
||||
[CCVars.AdminLogsQueueSendDelay.Name] = "0"
|
||||
},
|
||||
Pool = true
|
||||
});
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var sDatabase = server.ResolveDependency<IServerDbManager>();
|
||||
var sEntities = server.ResolveDependency<IEntityManager>();
|
||||
var sMaps = server.ResolveDependency<IMapManager>();
|
||||
var sSystems = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
var sAdminLogSystem = sSystems.GetEntitySystem<AdminLogSystem>();
|
||||
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var coordinates = GetMainEntityCoordinates(sMaps);
|
||||
var entity = sEntities.SpawnEntity(null, coordinates);
|
||||
|
||||
sAdminLogSystem.Add(LogType.Unknown, $"{entity} test log: {guid}");
|
||||
});
|
||||
|
||||
LogRecord log = null;
|
||||
|
||||
await WaitUntil(server, async () =>
|
||||
{
|
||||
var logs = sAdminLogSystem.CurrentRoundLogs(new LogFilter
|
||||
{
|
||||
Search = guid.ToString()
|
||||
});
|
||||
|
||||
await foreach (var found in logs)
|
||||
{
|
||||
log = found;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var filter = new LogFilter
|
||||
{
|
||||
Round = log.RoundId,
|
||||
Search = log.Message,
|
||||
Types = new List<LogType> {log.Type},
|
||||
};
|
||||
|
||||
await foreach (var json in sDatabase.GetAdminLogsJson(filter))
|
||||
{
|
||||
var root = json.RootElement;
|
||||
|
||||
Assert.That(root.TryGetProperty("entity", out _), Is.True);
|
||||
Assert.That(root.TryGetProperty("guid", out _), Is.True);
|
||||
|
||||
json.Dispose();
|
||||
}
|
||||
}).Wait();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(500, false)]
|
||||
[TestCase(500, true)]
|
||||
public async Task BulkAddLogs(int amount, bool parallel)
|
||||
{
|
||||
var server = StartServer(new ServerContentIntegrationOption
|
||||
{
|
||||
CVarOverrides =
|
||||
{
|
||||
[CCVars.AdminLogsQueueSendDelay.Name] = "0"
|
||||
},
|
||||
Pool = true
|
||||
});
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var sEntities = server.ResolveDependency<IEntityManager>();
|
||||
var sMaps = server.ResolveDependency<IMapManager>();
|
||||
var sSystems = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
var sAdminLogSystem = sSystems.GetEntitySystem<AdminLogSystem>();
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var coordinates = GetMainEntityCoordinates(sMaps);
|
||||
var entity = sEntities.SpawnEntity(null, coordinates);
|
||||
|
||||
if (parallel)
|
||||
{
|
||||
Parallel.For(0, amount, _ =>
|
||||
{
|
||||
sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log.");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < amount; i++)
|
||||
{
|
||||
sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await WaitUntil(server, async () =>
|
||||
{
|
||||
var messages = sAdminLogSystem.CurrentRoundLogs();
|
||||
var count = 0;
|
||||
|
||||
await foreach (var _ in messages)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count >= amount;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.CCVar;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Administration.Logs;
|
||||
|
||||
[TestFixture]
|
||||
[TestOf(typeof(AdminLogSystem))]
|
||||
public class FilterTests : ContentIntegrationTest
|
||||
{
|
||||
[Test]
|
||||
[TestCase(DateOrder.Ascending)]
|
||||
[TestCase(DateOrder.Descending)]
|
||||
public async Task Date(DateOrder order)
|
||||
{
|
||||
var server = StartServer(new ServerContentIntegrationOption
|
||||
{
|
||||
CVarOverrides =
|
||||
{
|
||||
[CCVars.AdminLogsQueueSendDelay.Name] = "0"
|
||||
},
|
||||
Pool = true
|
||||
});
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var sEntities = server.ResolveDependency<IEntityManager>();
|
||||
var sMaps = server.ResolveDependency<IMapManager>();
|
||||
var sSystems = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
var sAdminLogSystem = sSystems.GetEntitySystem<AdminLogSystem>();
|
||||
|
||||
var commonGuid = Guid.NewGuid();
|
||||
var guids = new[] {Guid.NewGuid(), Guid.NewGuid()};
|
||||
|
||||
for (var i = 0; i < 2; i++)
|
||||
{
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var coordinates = GetMainEntityCoordinates(sMaps);
|
||||
var entity = sEntities.SpawnEntity(null, coordinates);
|
||||
|
||||
sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log: {commonGuid} {guids[i]}");
|
||||
});
|
||||
|
||||
await server.WaitRunTicks(60);
|
||||
}
|
||||
|
||||
await WaitUntil(server, async () =>
|
||||
{
|
||||
var commonGuidStr = commonGuid.ToString();
|
||||
|
||||
string firstGuidStr;
|
||||
string secondGuidStr;
|
||||
|
||||
switch (order)
|
||||
{
|
||||
case DateOrder.Ascending:
|
||||
// Oldest first
|
||||
firstGuidStr = guids[0].ToString();
|
||||
secondGuidStr = guids[1].ToString();
|
||||
break;
|
||||
case DateOrder.Descending:
|
||||
// Newest first
|
||||
firstGuidStr = guids[1].ToString();
|
||||
secondGuidStr = guids[0].ToString();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(order), order, null);
|
||||
}
|
||||
|
||||
var firstFound = false;
|
||||
var secondFound = false;
|
||||
|
||||
var both = sAdminLogSystem.CurrentRoundLogs(new LogFilter
|
||||
{
|
||||
Search = commonGuidStr,
|
||||
DateOrder = order
|
||||
});
|
||||
|
||||
await foreach (var log in both)
|
||||
{
|
||||
if (!log.Message.Contains(commonGuidStr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!firstFound)
|
||||
{
|
||||
Assert.That(log.Message, Does.Contain(firstGuidStr));
|
||||
firstFound = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Assert.That(log.Message, Does.Contain(secondGuidStr));
|
||||
secondFound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return firstFound && secondFound;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.CCVar;
|
||||
using NUnit.Framework;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Administration.Logs;
|
||||
|
||||
[TestFixture]
|
||||
[TestOf(typeof(AdminLogSystem))]
|
||||
public class QueryTests : ContentIntegrationTest
|
||||
{
|
||||
[Test]
|
||||
public async Task QuerySingleLog()
|
||||
{
|
||||
var serverOptions = new ServerContentIntegrationOption
|
||||
{
|
||||
CVarOverrides =
|
||||
{
|
||||
[CCVars.AdminLogsQueueSendDelay.Name] = "0"
|
||||
}
|
||||
};
|
||||
var (client, server) = await StartConnectedServerClientPair(serverOptions: serverOptions);
|
||||
|
||||
await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());
|
||||
|
||||
var sSystems = server.ResolveDependency<IEntitySystemManager>();
|
||||
var sPlayers = server.ResolveDependency<IPlayerManager>();
|
||||
|
||||
var sAdminLogSystem = sSystems.GetEntitySystem<AdminLogSystem>();
|
||||
var sGameTicker = sSystems.GetEntitySystem<GameTicker>();
|
||||
|
||||
var date = DateTime.UtcNow;
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
IPlayerSession player = default;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
player = sPlayers.GetAllPlayers().First();
|
||||
|
||||
sAdminLogSystem.Add(LogType.Unknown, $"{player.AttachedEntity:Entity} test log: {guid}");
|
||||
});
|
||||
|
||||
var filter = new LogFilter
|
||||
{
|
||||
Round = sGameTicker.RoundId,
|
||||
Search = guid.ToString(),
|
||||
Types = new List<LogType> {LogType.Unknown},
|
||||
After = date,
|
||||
AnyPlayers = new[] {player.UserId.UserId}
|
||||
};
|
||||
|
||||
await WaitUntil(server, async () =>
|
||||
{
|
||||
await foreach (var _ in sAdminLogSystem.All(filter))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -20,5 +20,10 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.0-rc.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Content.Shared\Content.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\RobustToolbox\MSBuild\Robust.Analyzers.targets" />
|
||||
</Project>
|
||||
|
||||
848
Content.Server.Database/Migrations/Postgres/20211120202701_AdminLogs.Designer.cs
generated
Normal file
848
Content.Server.Database/Migrations/Postgres/20211120202701_AdminLogs.Designer.cs
generated
Normal file
@@ -0,0 +1,848 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Content.Server.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
[DbContext(typeof(PostgresServerDbContext))]
|
||||
[Migration("20211120202701_AdminLogs")]
|
||||
partial class AdminLogs
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<int?>("AdminRankId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("UserId")
|
||||
.HasName("PK_admin");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_admin_rank_id");
|
||||
|
||||
b.ToTable("admin", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_flag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("admin_id");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.Property<bool>("Negative")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("negative");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_flag");
|
||||
|
||||
b.HasIndex("AdminId")
|
||||
.HasDatabaseName("IX_admin_flag_admin_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<JsonDocument>("Json")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("json");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("message");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("type");
|
||||
|
||||
b.HasKey("Id", "RoundId")
|
||||
.HasName("PK_admin_log");
|
||||
|
||||
b.HasIndex("RoundId")
|
||||
.HasDatabaseName("IX_admin_log_round_id");
|
||||
|
||||
b.HasIndex("Type")
|
||||
.HasDatabaseName("IX_admin_log_type");
|
||||
|
||||
b.ToTable("admin_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.Property<int>("Uid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("uid");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Uid"));
|
||||
|
||||
b.Property<int?>("AdminLogId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int?>("AdminLogRoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_round_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Uid")
|
||||
.HasName("PK_admin_log_entity");
|
||||
|
||||
b.HasIndex("AdminLogId", "AdminLogRoundId")
|
||||
.HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id");
|
||||
|
||||
b.ToTable("admin_log_entity", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerUserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_user_id");
|
||||
|
||||
b.Property<int>("LogId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("PlayerUserId", "LogId", "RoundId")
|
||||
.HasName("PK_admin_log_player");
|
||||
|
||||
b.HasIndex("LogId", "RoundId");
|
||||
|
||||
b.ToTable("admin_log_player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank");
|
||||
|
||||
b.ToTable("admin_rank", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_flag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank_flag");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_rank_flag_admin_rank_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminRankId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_rank_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("antag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("AntagName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("antag_name");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_antag");
|
||||
|
||||
b.HasIndex("ProfileId", "AntagName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("antag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("assigned_user_id_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_assigned_user_id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("assigned_user_id", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("job_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("job_name");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("priority");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_job");
|
||||
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_job_profile_id");
|
||||
|
||||
b.HasIndex("ProfileId", "JobName")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority")
|
||||
.IsUnique()
|
||||
.HasFilter("priority = 3");
|
||||
|
||||
b.ToTable("job", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("first_seen_time");
|
||||
|
||||
b.Property<IPAddress>("LastSeenAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("last_seen_address");
|
||||
|
||||
b.Property<byte[]>("LastSeenHWId")
|
||||
.HasColumnType("bytea")
|
||||
.HasColumnName("last_seen_hwid");
|
||||
|
||||
b.Property<DateTime>("LastSeenTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("last_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenUserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("last_seen_user_name");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_player");
|
||||
|
||||
b.HasAlternateKey("UserId")
|
||||
.HasName("ak_player_user_id");
|
||||
|
||||
b.HasIndex("LastSeenUserName");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("player", (string)null);
|
||||
|
||||
b.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresConnectionLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("connection_log_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<IPAddress>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("bytea")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<DateTime>("Time")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("time");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_connection_log");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("connection_log", (string)null);
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("server_ban_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<ValueTuple<IPAddress, int>?>("Address")
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<DateTime>("BanTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("ban_time");
|
||||
|
||||
b.Property<Guid?>("BanningAdmin")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("banning_admin");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("expiration_time");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("bytea")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("reason");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_server_ban");
|
||||
|
||||
b.HasIndex("Address");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("server_ban", (string)null);
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
|
||||
b.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("unban_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("BanId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("ban_id");
|
||||
|
||||
b.Property<DateTime>("UnbanTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("unban_time");
|
||||
|
||||
b.Property<Guid?>("UnbanningAdmin")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("unbanning_admin");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_server_unban");
|
||||
|
||||
b.HasIndex("BanId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("server_unban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("AdminOOCColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("admin_ooc_color");
|
||||
|
||||
b.Property<int>("SelectedCharacterSlot")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("selected_character_slot");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_preference");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("preference", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("age");
|
||||
|
||||
b.Property<string>("Backpack")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("backpack");
|
||||
|
||||
b.Property<string>("CharacterName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("char_name");
|
||||
|
||||
b.Property<string>("Clothing")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("clothing");
|
||||
|
||||
b.Property<string>("EyeColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("eye_color");
|
||||
|
||||
b.Property<string>("FacialHairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("facial_hair_color");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("facial_hair_name");
|
||||
|
||||
b.Property<string>("Gender")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("gender");
|
||||
|
||||
b.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("hair_color");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("hair_name");
|
||||
|
||||
b.Property<int>("PreferenceId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
b.Property<int>("PreferenceUnavailable")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("pref_unavailable");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("sex");
|
||||
|
||||
b.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("skin_color");
|
||||
|
||||
b.Property<int>("Slot")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("slot");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_profile");
|
||||
|
||||
b.HasIndex("PreferenceId")
|
||||
.HasDatabaseName("IX_profile_preference_id");
|
||||
|
||||
b.HasIndex("Slot", "PreferenceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("profile", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_round");
|
||||
|
||||
b.ToTable("round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.Property<int>("PlayersId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("players_id");
|
||||
|
||||
b.Property<int>("RoundsId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("rounds_id");
|
||||
|
||||
b.HasKey("PlayersId", "RoundsId")
|
||||
.HasName("PK_player_round");
|
||||
|
||||
b.HasIndex("RoundsId")
|
||||
.HasDatabaseName("IX_player_round_rounds_id");
|
||||
|
||||
b.ToTable("player_round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("FK_admin_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("AdminRank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Admin", "Admin")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_flag_admin_admin_id");
|
||||
|
||||
b.Navigation("Admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Round", "Round")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_round_round_id");
|
||||
|
||||
b.Navigation("Round");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminLog", null)
|
||||
.WithMany("Entities")
|
||||
.HasForeignKey("AdminLogId", "AdminLogRoundId")
|
||||
.HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("PlayerUserId")
|
||||
.HasPrincipalKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_player_player_user_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.AdminLog", "Log")
|
||||
.WithMany("Players")
|
||||
.HasForeignKey("LogId", "RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id");
|
||||
|
||||
b.Navigation("Log");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("Rank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Antags")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_antag_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_job_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.PostgresServerBan", "Ban")
|
||||
.WithOne("Unban")
|
||||
.HasForeignKey("Content.Server.Database.PostgresServerUnban", "BanId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_server_unban_server_ban_ban_id");
|
||||
|
||||
b.Navigation("Ban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Preference", "Preference")
|
||||
.WithMany("Profiles")
|
||||
.HasForeignKey("PreferenceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_profile_preference_preference_id");
|
||||
|
||||
b.Navigation("Preference");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PlayersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_player_players_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Round", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoundsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_round_rounds_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Navigation("Entities");
|
||||
|
||||
b.Navigation("Players");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Navigation("Admins");
|
||||
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
|
||||
{
|
||||
b.Navigation("Unban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Navigation("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Navigation("Antags");
|
||||
|
||||
b.Navigation("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
public partial class AdminLogs : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddUniqueConstraint(
|
||||
name: "ak_player_user_id",
|
||||
table: "player",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "round",
|
||||
columns: table => new
|
||||
{
|
||||
round_id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_round", x => x.round_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_log",
|
||||
columns: table => new
|
||||
{
|
||||
admin_log_id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
round_id = table.Column<int>(type: "integer", nullable: false),
|
||||
type = table.Column<int>(type: "integer", nullable: false),
|
||||
date = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
message = table.Column<string>(type: "text", nullable: false),
|
||||
json = table.Column<JsonDocument>(type: "jsonb", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_log", x => new { x.admin_log_id, x.round_id });
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_log_round_round_id",
|
||||
column: x => x.round_id,
|
||||
principalTable: "round",
|
||||
principalColumn: "round_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "player_round",
|
||||
columns: table => new
|
||||
{
|
||||
players_id = table.Column<int>(type: "integer", nullable: false),
|
||||
rounds_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_player_round", x => new { x.players_id, x.rounds_id });
|
||||
table.ForeignKey(
|
||||
name: "FK_player_round_player_players_id",
|
||||
column: x => x.players_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "player_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_player_round_round_rounds_id",
|
||||
column: x => x.rounds_id,
|
||||
principalTable: "round",
|
||||
principalColumn: "round_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_log_entity",
|
||||
columns: table => new
|
||||
{
|
||||
uid = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
name = table.Column<string>(type: "text", nullable: true),
|
||||
admin_log_id = table.Column<int>(type: "integer", nullable: true),
|
||||
admin_log_round_id = table.Column<int>(type: "integer", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_log_entity", x => x.uid);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id",
|
||||
columns: x => new { x.admin_log_id, x.admin_log_round_id },
|
||||
principalTable: "admin_log",
|
||||
principalColumns: new[] { "admin_log_id", "round_id" });
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_log_player",
|
||||
columns: table => new
|
||||
{
|
||||
player_user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
log_id = table.Column<int>(type: "integer", nullable: false),
|
||||
round_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_log_player", x => new { x.player_user_id, x.log_id, x.round_id });
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_log_player_admin_log_log_id_round_id",
|
||||
columns: x => new { x.log_id, x.round_id },
|
||||
principalTable: "admin_log",
|
||||
principalColumns: new[] { "admin_log_id", "round_id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_log_player_player_player_user_id",
|
||||
column: x => x.player_user_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_log_round_id",
|
||||
table: "admin_log",
|
||||
column: "round_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_log_type",
|
||||
table: "admin_log",
|
||||
column: "type");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_log_entity_admin_log_id_admin_log_round_id",
|
||||
table: "admin_log_entity",
|
||||
columns: new[] { "admin_log_id", "admin_log_round_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_log_player_log_id_round_id",
|
||||
table: "admin_log_player",
|
||||
columns: new[] { "log_id", "round_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_player_round_rounds_id",
|
||||
table: "player_round",
|
||||
column: "rounds_id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_log_entity");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_log_player");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "player_round");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_log");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "round");
|
||||
|
||||
migrationBuilder.DropUniqueConstraint(
|
||||
name: "ak_player_user_id",
|
||||
table: "player");
|
||||
}
|
||||
}
|
||||
}
|
||||
852
Content.Server.Database/Migrations/Postgres/20211121123543_AdminLogsImpact.Designer.cs
generated
Normal file
852
Content.Server.Database/Migrations/Postgres/20211121123543_AdminLogsImpact.Designer.cs
generated
Normal file
@@ -0,0 +1,852 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Content.Server.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
[DbContext(typeof(PostgresServerDbContext))]
|
||||
[Migration("20211121123543_AdminLogsImpact")]
|
||||
partial class AdminLogsImpact
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<int?>("AdminRankId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("UserId")
|
||||
.HasName("PK_admin");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_admin_rank_id");
|
||||
|
||||
b.ToTable("admin", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_flag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("admin_id");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.Property<bool>("Negative")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("negative");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_flag");
|
||||
|
||||
b.HasIndex("AdminId")
|
||||
.HasDatabaseName("IX_admin_flag_admin_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<short>("Impact")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("impact");
|
||||
|
||||
b.Property<JsonDocument>("Json")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("json");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("message");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("type");
|
||||
|
||||
b.HasKey("Id", "RoundId")
|
||||
.HasName("PK_admin_log");
|
||||
|
||||
b.HasIndex("RoundId")
|
||||
.HasDatabaseName("IX_admin_log_round_id");
|
||||
|
||||
b.HasIndex("Type")
|
||||
.HasDatabaseName("IX_admin_log_type");
|
||||
|
||||
b.ToTable("admin_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.Property<int>("Uid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("uid");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Uid"));
|
||||
|
||||
b.Property<int?>("AdminLogId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int?>("AdminLogRoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_round_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Uid")
|
||||
.HasName("PK_admin_log_entity");
|
||||
|
||||
b.HasIndex("AdminLogId", "AdminLogRoundId")
|
||||
.HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id");
|
||||
|
||||
b.ToTable("admin_log_entity", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerUserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_user_id");
|
||||
|
||||
b.Property<int>("LogId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("PlayerUserId", "LogId", "RoundId")
|
||||
.HasName("PK_admin_log_player");
|
||||
|
||||
b.HasIndex("LogId", "RoundId");
|
||||
|
||||
b.ToTable("admin_log_player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank");
|
||||
|
||||
b.ToTable("admin_rank", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_flag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank_flag");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_rank_flag_admin_rank_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminRankId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_rank_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("antag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("AntagName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("antag_name");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_antag");
|
||||
|
||||
b.HasIndex("ProfileId", "AntagName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("antag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("assigned_user_id_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_assigned_user_id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("assigned_user_id", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("job_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("job_name");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("priority");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_job");
|
||||
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_job_profile_id");
|
||||
|
||||
b.HasIndex("ProfileId", "JobName")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority")
|
||||
.IsUnique()
|
||||
.HasFilter("priority = 3");
|
||||
|
||||
b.ToTable("job", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("first_seen_time");
|
||||
|
||||
b.Property<IPAddress>("LastSeenAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("last_seen_address");
|
||||
|
||||
b.Property<byte[]>("LastSeenHWId")
|
||||
.HasColumnType("bytea")
|
||||
.HasColumnName("last_seen_hwid");
|
||||
|
||||
b.Property<DateTime>("LastSeenTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("last_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenUserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("last_seen_user_name");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_player");
|
||||
|
||||
b.HasAlternateKey("UserId")
|
||||
.HasName("ak_player_user_id");
|
||||
|
||||
b.HasIndex("LastSeenUserName");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("player", (string)null);
|
||||
|
||||
b.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresConnectionLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("connection_log_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<IPAddress>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("bytea")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<DateTime>("Time")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("time");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_connection_log");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("connection_log", (string)null);
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("server_ban_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<ValueTuple<IPAddress, int>?>("Address")
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<DateTime>("BanTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("ban_time");
|
||||
|
||||
b.Property<Guid?>("BanningAdmin")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("banning_admin");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("expiration_time");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("bytea")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("reason");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_server_ban");
|
||||
|
||||
b.HasIndex("Address");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("server_ban", (string)null);
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
|
||||
b.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("unban_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("BanId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("ban_id");
|
||||
|
||||
b.Property<DateTime>("UnbanTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("unban_time");
|
||||
|
||||
b.Property<Guid?>("UnbanningAdmin")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("unbanning_admin");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_server_unban");
|
||||
|
||||
b.HasIndex("BanId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("server_unban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("AdminOOCColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("admin_ooc_color");
|
||||
|
||||
b.Property<int>("SelectedCharacterSlot")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("selected_character_slot");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_preference");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("preference", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("age");
|
||||
|
||||
b.Property<string>("Backpack")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("backpack");
|
||||
|
||||
b.Property<string>("CharacterName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("char_name");
|
||||
|
||||
b.Property<string>("Clothing")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("clothing");
|
||||
|
||||
b.Property<string>("EyeColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("eye_color");
|
||||
|
||||
b.Property<string>("FacialHairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("facial_hair_color");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("facial_hair_name");
|
||||
|
||||
b.Property<string>("Gender")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("gender");
|
||||
|
||||
b.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("hair_color");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("hair_name");
|
||||
|
||||
b.Property<int>("PreferenceId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
b.Property<int>("PreferenceUnavailable")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("pref_unavailable");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("sex");
|
||||
|
||||
b.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("skin_color");
|
||||
|
||||
b.Property<int>("Slot")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("slot");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_profile");
|
||||
|
||||
b.HasIndex("PreferenceId")
|
||||
.HasDatabaseName("IX_profile_preference_id");
|
||||
|
||||
b.HasIndex("Slot", "PreferenceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("profile", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_round");
|
||||
|
||||
b.ToTable("round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.Property<int>("PlayersId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("players_id");
|
||||
|
||||
b.Property<int>("RoundsId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("rounds_id");
|
||||
|
||||
b.HasKey("PlayersId", "RoundsId")
|
||||
.HasName("PK_player_round");
|
||||
|
||||
b.HasIndex("RoundsId")
|
||||
.HasDatabaseName("IX_player_round_rounds_id");
|
||||
|
||||
b.ToTable("player_round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("FK_admin_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("AdminRank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Admin", "Admin")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_flag_admin_admin_id");
|
||||
|
||||
b.Navigation("Admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Round", "Round")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_round_round_id");
|
||||
|
||||
b.Navigation("Round");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminLog", null)
|
||||
.WithMany("Entities")
|
||||
.HasForeignKey("AdminLogId", "AdminLogRoundId")
|
||||
.HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("PlayerUserId")
|
||||
.HasPrincipalKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_player_player_user_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.AdminLog", "Log")
|
||||
.WithMany("Players")
|
||||
.HasForeignKey("LogId", "RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id");
|
||||
|
||||
b.Navigation("Log");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("Rank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Antags")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_antag_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_job_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.PostgresServerBan", "Ban")
|
||||
.WithOne("Unban")
|
||||
.HasForeignKey("Content.Server.Database.PostgresServerUnban", "BanId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_server_unban_server_ban_ban_id");
|
||||
|
||||
b.Navigation("Ban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Preference", "Preference")
|
||||
.WithMany("Profiles")
|
||||
.HasForeignKey("PreferenceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_profile_preference_preference_id");
|
||||
|
||||
b.Navigation("Preference");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PlayersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_player_players_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Round", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoundsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_round_rounds_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Navigation("Entities");
|
||||
|
||||
b.Navigation("Players");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Navigation("Admins");
|
||||
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
|
||||
{
|
||||
b.Navigation("Unban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Navigation("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Navigation("Antags");
|
||||
|
||||
b.Navigation("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
public partial class AdminLogsImpact : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "impact",
|
||||
table: "admin_log",
|
||||
type: "smallint",
|
||||
nullable: false,
|
||||
defaultValue: (short)0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "impact",
|
||||
table: "admin_log");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Content.Server.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
[DbContext(typeof(PostgresServerDbContext))]
|
||||
@@ -16,9 +19,10 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63)
|
||||
.HasAnnotation("ProductVersion", "5.0.3")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasAnnotation("ProductVersion", "6.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
@@ -35,11 +39,13 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("UserId");
|
||||
b.HasKey("UserId")
|
||||
.HasName("PK_admin");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_admin_rank_id");
|
||||
|
||||
b.ToTable("admin");
|
||||
b.ToTable("admin", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
@@ -47,8 +53,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_flag_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("admin_flag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnType("uuid")
|
||||
@@ -63,14 +70,115 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("negative");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_flag");
|
||||
|
||||
b.HasIndex("AdminId");
|
||||
b.HasIndex("AdminId")
|
||||
.HasDatabaseName("IX_admin_flag_admin_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_flag");
|
||||
b.ToTable("admin_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<short>("Impact")
|
||||
.HasColumnType("smallint")
|
||||
.HasColumnName("impact");
|
||||
|
||||
b.Property<JsonDocument>("Json")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("json");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("message");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("type");
|
||||
|
||||
b.HasKey("Id", "RoundId")
|
||||
.HasName("PK_admin_log");
|
||||
|
||||
b.HasIndex("RoundId")
|
||||
.HasDatabaseName("IX_admin_log_round_id");
|
||||
|
||||
b.HasIndex("Type")
|
||||
.HasDatabaseName("IX_admin_log_type");
|
||||
|
||||
b.ToTable("admin_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.Property<int>("Uid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("uid");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Uid"));
|
||||
|
||||
b.Property<int?>("AdminLogId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int?>("AdminLogRoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_log_round_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Uid")
|
||||
.HasName("PK_admin_log_entity");
|
||||
|
||||
b.HasIndex("AdminLogId", "AdminLogRoundId")
|
||||
.HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id");
|
||||
|
||||
b.ToTable("admin_log_entity", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerUserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_user_id");
|
||||
|
||||
b.Property<int>("LogId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("PlayerUserId", "LogId", "RoundId")
|
||||
.HasName("PK_admin_log_player");
|
||||
|
||||
b.HasIndex("LogId", "RoundId");
|
||||
|
||||
b.ToTable("admin_log_player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
@@ -78,17 +186,19 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank");
|
||||
|
||||
b.ToTable("admin_rank");
|
||||
b.ToTable("admin_rank", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
@@ -96,8 +206,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("admin_rank_flag_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("admin_rank_flag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnType("integer")
|
||||
@@ -108,14 +219,16 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank_flag");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_rank_flag_admin_rank_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminRankId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_rank_flag");
|
||||
b.ToTable("admin_rank_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
@@ -123,8 +236,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("antag_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("antag_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("AntagName")
|
||||
.IsRequired()
|
||||
@@ -135,12 +249,13 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_antag");
|
||||
|
||||
b.HasIndex("ProfileId", "AntagName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("antag");
|
||||
b.ToTable("antag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
|
||||
@@ -148,8 +263,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("assigned_user_id_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("assigned_user_id_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
@@ -160,7 +276,8 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_assigned_user_id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
@@ -168,7 +285,7 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.HasIndex("UserName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("assigned_user_id");
|
||||
b.ToTable("assigned_user_id", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
@@ -176,8 +293,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("job_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("job_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
@@ -192,9 +310,11 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_job");
|
||||
|
||||
b.HasIndex("ProfileId");
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_job_profile_id");
|
||||
|
||||
b.HasIndex("ProfileId", "JobName")
|
||||
.IsUnique();
|
||||
@@ -203,55 +323,17 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.IsUnique()
|
||||
.HasFilter("priority = 3");
|
||||
|
||||
b.ToTable("job");
|
||||
b.ToTable("job", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresConnectionLog", b =>
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("connection_log_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<IPAddress>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("bytea")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<DateTime>("Time")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("time");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("connection_log");
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresPlayer", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("player_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
@@ -279,25 +361,71 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_player");
|
||||
|
||||
b.HasAlternateKey("UserId")
|
||||
.HasName("ak_player_user_id");
|
||||
|
||||
b.HasIndex("LastSeenUserName");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("player");
|
||||
b.ToTable("player", (string)null);
|
||||
|
||||
b.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresConnectionLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("connection_log_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<IPAddress>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("bytea")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<DateTime>("Time")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("time");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_connection_log");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("connection_log", (string)null);
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("server_ban_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("server_ban_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<ValueTuple<IPAddress, int>?>("Address")
|
||||
.HasColumnType("inet")
|
||||
@@ -328,13 +456,14 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_server_ban");
|
||||
|
||||
b.HasIndex("Address");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("server_ban");
|
||||
b.ToTable("server_ban", (string)null);
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
|
||||
@@ -346,8 +475,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("unban_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("unban_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("BanId")
|
||||
.HasColumnType("integer")
|
||||
@@ -361,12 +491,13 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("unbanning_admin");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_server_unban");
|
||||
|
||||
b.HasIndex("BanId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("server_unban");
|
||||
b.ToTable("server_unban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
@@ -374,8 +505,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("preference_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("AdminOOCColor")
|
||||
.IsRequired()
|
||||
@@ -390,12 +522,13 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_preference");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("preference");
|
||||
b.ToTable("preference", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
@@ -403,8 +536,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("profile_id")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnType("integer")
|
||||
@@ -477,14 +611,50 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("slot");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_profile");
|
||||
|
||||
b.HasIndex("PreferenceId");
|
||||
b.HasIndex("PreferenceId")
|
||||
.HasDatabaseName("IX_profile_preference_id");
|
||||
|
||||
b.HasIndex("Slot", "PreferenceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("profile");
|
||||
b.ToTable("profile", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_round");
|
||||
|
||||
b.ToTable("round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.Property<int>("PlayersId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("players_id");
|
||||
|
||||
b.Property<int>("RoundsId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("rounds_id");
|
||||
|
||||
b.HasKey("PlayersId", "RoundsId")
|
||||
.HasName("PK_player_round");
|
||||
|
||||
b.HasIndex("RoundsId")
|
||||
.HasDatabaseName("IX_player_round_rounds_id");
|
||||
|
||||
b.ToTable("player_round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
@@ -492,7 +662,8 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("FK_admin_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("AdminRank");
|
||||
});
|
||||
@@ -503,18 +674,62 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_flag_admin_admin_id");
|
||||
|
||||
b.Navigation("Admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Round", "Round")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_round_round_id");
|
||||
|
||||
b.Navigation("Round");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminLog", null)
|
||||
.WithMany("Entities")
|
||||
.HasForeignKey("AdminLogId", "AdminLogRoundId")
|
||||
.HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("PlayerUserId")
|
||||
.HasPrincipalKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_player_player_user_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.AdminLog", "Log")
|
||||
.WithMany("Players")
|
||||
.HasForeignKey("LogId", "RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id");
|
||||
|
||||
b.Navigation("Log");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("Rank");
|
||||
});
|
||||
@@ -525,7 +740,8 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.WithMany("Antags")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_antag_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
@@ -536,7 +752,8 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_job_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
@@ -547,7 +764,8 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.WithOne("Unban")
|
||||
.HasForeignKey("Content.Server.Database.PostgresServerUnban", "BanId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_server_unban_server_ban_ban_id");
|
||||
|
||||
b.Navigation("Ban");
|
||||
});
|
||||
@@ -558,16 +776,41 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.WithMany("Profiles")
|
||||
.HasForeignKey("PreferenceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_profile_preference_preference_id");
|
||||
|
||||
b.Navigation("Preference");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PlayersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_player_players_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Round", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoundsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_round_rounds_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Navigation("Entities");
|
||||
|
||||
b.Navigation("Players");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Navigation("Admins");
|
||||
@@ -575,6 +818,11 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
|
||||
{
|
||||
b.Navigation("Unban");
|
||||
@@ -591,6 +839,11 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
|
||||
b.Navigation("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
||||
794
Content.Server.Database/Migrations/Sqlite/20211120202654_AdminLogs.Designer.cs
generated
Normal file
794
Content.Server.Database/Migrations/Sqlite/20211120202654_AdminLogs.Designer.cs
generated
Normal file
@@ -0,0 +1,794 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Content.Server.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
[DbContext(typeof(SqliteServerDbContext))]
|
||||
[Migration("20211120202654_AdminLogs")]
|
||||
partial class AdminLogs
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.0");
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<int?>("AdminRankId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("UserId")
|
||||
.HasName("PK_admin");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_admin_rank_id");
|
||||
|
||||
b.ToTable("admin", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_flag_id");
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("admin_id");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.Property<bool>("Negative")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("negative");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_flag");
|
||||
|
||||
b.HasIndex("AdminId")
|
||||
.HasDatabaseName("IX_admin_flag_admin_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<string>("Json")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("json");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("message");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("type");
|
||||
|
||||
b.HasKey("Id", "RoundId")
|
||||
.HasName("PK_admin_log");
|
||||
|
||||
b.HasIndex("RoundId")
|
||||
.HasDatabaseName("IX_admin_log_round_id");
|
||||
|
||||
b.HasIndex("Type")
|
||||
.HasDatabaseName("IX_admin_log_type");
|
||||
|
||||
b.ToTable("admin_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.Property<int>("Uid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("uid");
|
||||
|
||||
b.Property<int?>("AdminLogId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int?>("AdminLogRoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_round_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Uid")
|
||||
.HasName("PK_admin_log_entity");
|
||||
|
||||
b.HasIndex("AdminLogId", "AdminLogRoundId")
|
||||
.HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id");
|
||||
|
||||
b.ToTable("admin_log_entity", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerUserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_user_id");
|
||||
|
||||
b.Property<int>("LogId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("PlayerUserId", "LogId", "RoundId")
|
||||
.HasName("PK_admin_log_player");
|
||||
|
||||
b.HasIndex("LogId", "RoundId");
|
||||
|
||||
b.ToTable("admin_log_player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank");
|
||||
|
||||
b.ToTable("admin_rank", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_rank_flag_id");
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank_flag");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_rank_flag_admin_rank_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminRankId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_rank_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("antag_id");
|
||||
|
||||
b.Property<string>("AntagName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("antag_name");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_antag");
|
||||
|
||||
b.HasIndex("ProfileId", "AntagName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("antag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("assigned_user_id_id");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_assigned_user_id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("assigned_user_id", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("job_id");
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("job_name");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("priority");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_job");
|
||||
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_job_profile_id");
|
||||
|
||||
b.HasIndex("ProfileId", "JobName")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority")
|
||||
.IsUnique()
|
||||
.HasFilter("priority = 3");
|
||||
|
||||
b.ToTable("job", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("first_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_address");
|
||||
|
||||
b.Property<byte[]>("LastSeenHWId")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("last_seen_hwid");
|
||||
|
||||
b.Property<DateTime>("LastSeenTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenUserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_user_name");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_player");
|
||||
|
||||
b.HasAlternateKey("UserId")
|
||||
.HasName("ak_player_user_id");
|
||||
|
||||
b.HasIndex("LastSeenUserName");
|
||||
|
||||
b.ToTable("player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
b.Property<string>("AdminOOCColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("admin_ooc_color");
|
||||
|
||||
b.Property<int>("SelectedCharacterSlot")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("selected_character_slot");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_preference");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("preference", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("age");
|
||||
|
||||
b.Property<string>("Backpack")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("backpack");
|
||||
|
||||
b.Property<string>("CharacterName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("char_name");
|
||||
|
||||
b.Property<string>("Clothing")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("clothing");
|
||||
|
||||
b.Property<string>("EyeColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("eye_color");
|
||||
|
||||
b.Property<string>("FacialHairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("facial_hair_color");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("facial_hair_name");
|
||||
|
||||
b.Property<string>("Gender")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("gender");
|
||||
|
||||
b.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_color");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_name");
|
||||
|
||||
b.Property<int>("PreferenceId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
b.Property<int>("PreferenceUnavailable")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("pref_unavailable");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("sex");
|
||||
|
||||
b.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("skin_color");
|
||||
|
||||
b.Property<int>("Slot")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("slot");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_profile");
|
||||
|
||||
b.HasIndex("PreferenceId")
|
||||
.HasDatabaseName("IX_profile_preference_id");
|
||||
|
||||
b.HasIndex("Slot", "PreferenceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("profile", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_round");
|
||||
|
||||
b.ToTable("round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteConnectionLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("connection_log_id");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<DateTime>("Time")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("time");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_connection_log");
|
||||
|
||||
b.ToTable("connection_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("ban_id");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<DateTime>("BanTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("ban_time");
|
||||
|
||||
b.Property<Guid?>("BanningAdmin")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("banning_admin");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("expiration_time");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("reason");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_ban");
|
||||
|
||||
b.ToTable("ban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("unban_id");
|
||||
|
||||
b.Property<int>("BanId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("ban_id");
|
||||
|
||||
b.Property<DateTime>("UnbanTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("unban_time");
|
||||
|
||||
b.Property<Guid?>("UnbanningAdmin")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("unbanning_admin");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_unban");
|
||||
|
||||
b.HasIndex("BanId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("unban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.Property<int>("PlayersId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("players_id");
|
||||
|
||||
b.Property<int>("RoundsId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rounds_id");
|
||||
|
||||
b.HasKey("PlayersId", "RoundsId")
|
||||
.HasName("PK_player_round");
|
||||
|
||||
b.HasIndex("RoundsId")
|
||||
.HasDatabaseName("IX_player_round_rounds_id");
|
||||
|
||||
b.ToTable("player_round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("FK_admin_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("AdminRank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Admin", "Admin")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_flag_admin_admin_id");
|
||||
|
||||
b.Navigation("Admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Round", "Round")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_round_round_id");
|
||||
|
||||
b.Navigation("Round");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminLog", null)
|
||||
.WithMany("Entities")
|
||||
.HasForeignKey("AdminLogId", "AdminLogRoundId")
|
||||
.HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("PlayerUserId")
|
||||
.HasPrincipalKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_player_player_user_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.AdminLog", "Log")
|
||||
.WithMany("Players")
|
||||
.HasForeignKey("LogId", "RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id");
|
||||
|
||||
b.Navigation("Log");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("Rank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Antags")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_antag_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_job_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Preference", "Preference")
|
||||
.WithMany("Profiles")
|
||||
.HasForeignKey("PreferenceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_profile_preference_preference_id");
|
||||
|
||||
b.Navigation("Preference");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.SqliteServerBan", "Ban")
|
||||
.WithOne("Unban")
|
||||
.HasForeignKey("Content.Server.Database.SqliteServerUnban", "BanId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_unban_ban_ban_id");
|
||||
|
||||
b.Navigation("Ban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PlayersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_player_players_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Round", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoundsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_round_rounds_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Navigation("Entities");
|
||||
|
||||
b.Navigation("Players");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Navigation("Admins");
|
||||
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Navigation("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Navigation("Antags");
|
||||
|
||||
b.Navigation("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
|
||||
{
|
||||
b.Navigation("Unban");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
public partial class AdminLogs : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddUniqueConstraint(
|
||||
name: "ak_player_user_id",
|
||||
table: "player",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "round",
|
||||
columns: table => new
|
||||
{
|
||||
round_id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_round", x => x.round_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_log",
|
||||
columns: table => new
|
||||
{
|
||||
admin_log_id = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
round_id = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
type = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
date = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
message = table.Column<string>(type: "TEXT", nullable: false),
|
||||
json = table.Column<string>(type: "jsonb", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_log", x => new { x.admin_log_id, x.round_id });
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_log_round_round_id",
|
||||
column: x => x.round_id,
|
||||
principalTable: "round",
|
||||
principalColumn: "round_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "player_round",
|
||||
columns: table => new
|
||||
{
|
||||
players_id = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
rounds_id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_player_round", x => new { x.players_id, x.rounds_id });
|
||||
table.ForeignKey(
|
||||
name: "FK_player_round_player_players_id",
|
||||
column: x => x.players_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "player_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_player_round_round_rounds_id",
|
||||
column: x => x.rounds_id,
|
||||
principalTable: "round",
|
||||
principalColumn: "round_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_log_entity",
|
||||
columns: table => new
|
||||
{
|
||||
uid = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
name = table.Column<string>(type: "TEXT", nullable: true),
|
||||
admin_log_id = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
admin_log_round_id = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_log_entity", x => x.uid);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id",
|
||||
columns: x => new { x.admin_log_id, x.admin_log_round_id },
|
||||
principalTable: "admin_log",
|
||||
principalColumns: new[] { "admin_log_id", "round_id" });
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_log_player",
|
||||
columns: table => new
|
||||
{
|
||||
player_user_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
log_id = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
round_id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_log_player", x => new { x.player_user_id, x.log_id, x.round_id });
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_log_player_admin_log_log_id_round_id",
|
||||
columns: x => new { x.log_id, x.round_id },
|
||||
principalTable: "admin_log",
|
||||
principalColumns: new[] { "admin_log_id", "round_id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_log_player_player_player_user_id",
|
||||
column: x => x.player_user_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_log_round_id",
|
||||
table: "admin_log",
|
||||
column: "round_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_log_type",
|
||||
table: "admin_log",
|
||||
column: "type");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_log_entity_admin_log_id_admin_log_round_id",
|
||||
table: "admin_log_entity",
|
||||
columns: new[] { "admin_log_id", "admin_log_round_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_log_player_log_id_round_id",
|
||||
table: "admin_log_player",
|
||||
columns: new[] { "log_id", "round_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_player_round_rounds_id",
|
||||
table: "player_round",
|
||||
column: "rounds_id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_log_entity");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_log_player");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "player_round");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_log");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "round");
|
||||
|
||||
migrationBuilder.DropUniqueConstraint(
|
||||
name: "ak_player_user_id",
|
||||
table: "player");
|
||||
}
|
||||
}
|
||||
}
|
||||
798
Content.Server.Database/Migrations/Sqlite/20211121123536_AdminLogsImpact.Designer.cs
generated
Normal file
798
Content.Server.Database/Migrations/Sqlite/20211121123536_AdminLogsImpact.Designer.cs
generated
Normal file
@@ -0,0 +1,798 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Content.Server.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
[DbContext(typeof(SqliteServerDbContext))]
|
||||
[Migration("20211121123536_AdminLogsImpact")]
|
||||
partial class AdminLogsImpact
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.0");
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<int?>("AdminRankId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("UserId")
|
||||
.HasName("PK_admin");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_admin_rank_id");
|
||||
|
||||
b.ToTable("admin", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_flag_id");
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("admin_id");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.Property<bool>("Negative")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("negative");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_flag");
|
||||
|
||||
b.HasIndex("AdminId")
|
||||
.HasDatabaseName("IX_admin_flag_admin_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<sbyte>("Impact")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("impact");
|
||||
|
||||
b.Property<string>("Json")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("json");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("message");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("type");
|
||||
|
||||
b.HasKey("Id", "RoundId")
|
||||
.HasName("PK_admin_log");
|
||||
|
||||
b.HasIndex("RoundId")
|
||||
.HasDatabaseName("IX_admin_log_round_id");
|
||||
|
||||
b.HasIndex("Type")
|
||||
.HasDatabaseName("IX_admin_log_type");
|
||||
|
||||
b.ToTable("admin_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.Property<int>("Uid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("uid");
|
||||
|
||||
b.Property<int?>("AdminLogId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int?>("AdminLogRoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_round_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Uid")
|
||||
.HasName("PK_admin_log_entity");
|
||||
|
||||
b.HasIndex("AdminLogId", "AdminLogRoundId")
|
||||
.HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id");
|
||||
|
||||
b.ToTable("admin_log_entity", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerUserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_user_id");
|
||||
|
||||
b.Property<int>("LogId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("PlayerUserId", "LogId", "RoundId")
|
||||
.HasName("PK_admin_log_player");
|
||||
|
||||
b.HasIndex("LogId", "RoundId");
|
||||
|
||||
b.ToTable("admin_log_player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank");
|
||||
|
||||
b.ToTable("admin_rank", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_rank_flag_id");
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_rank_id");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank_flag");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_rank_flag_admin_rank_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminRankId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_rank_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("antag_id");
|
||||
|
||||
b.Property<string>("AntagName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("antag_name");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_antag");
|
||||
|
||||
b.HasIndex("ProfileId", "AntagName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("antag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("assigned_user_id_id");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_assigned_user_id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("assigned_user_id", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("job_id");
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("job_name");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("priority");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_job");
|
||||
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_job_profile_id");
|
||||
|
||||
b.HasIndex("ProfileId", "JobName")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority")
|
||||
.IsUnique()
|
||||
.HasFilter("priority = 3");
|
||||
|
||||
b.ToTable("job", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("first_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_address");
|
||||
|
||||
b.Property<byte[]>("LastSeenHWId")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("last_seen_hwid");
|
||||
|
||||
b.Property<DateTime>("LastSeenTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenUserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_user_name");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_player");
|
||||
|
||||
b.HasAlternateKey("UserId")
|
||||
.HasName("ak_player_user_id");
|
||||
|
||||
b.HasIndex("LastSeenUserName");
|
||||
|
||||
b.ToTable("player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
b.Property<string>("AdminOOCColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("admin_ooc_color");
|
||||
|
||||
b.Property<int>("SelectedCharacterSlot")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("selected_character_slot");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_preference");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("preference", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("age");
|
||||
|
||||
b.Property<string>("Backpack")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("backpack");
|
||||
|
||||
b.Property<string>("CharacterName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("char_name");
|
||||
|
||||
b.Property<string>("Clothing")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("clothing");
|
||||
|
||||
b.Property<string>("EyeColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("eye_color");
|
||||
|
||||
b.Property<string>("FacialHairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("facial_hair_color");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("facial_hair_name");
|
||||
|
||||
b.Property<string>("Gender")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("gender");
|
||||
|
||||
b.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_color");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_name");
|
||||
|
||||
b.Property<int>("PreferenceId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("preference_id");
|
||||
|
||||
b.Property<int>("PreferenceUnavailable")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("pref_unavailable");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("sex");
|
||||
|
||||
b.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("skin_color");
|
||||
|
||||
b.Property<int>("Slot")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("slot");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_profile");
|
||||
|
||||
b.HasIndex("PreferenceId")
|
||||
.HasDatabaseName("IX_profile_preference_id");
|
||||
|
||||
b.HasIndex("Slot", "PreferenceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("profile", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_round");
|
||||
|
||||
b.ToTable("round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteConnectionLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("connection_log_id");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<DateTime>("Time")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("time");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_connection_log");
|
||||
|
||||
b.ToTable("connection_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("ban_id");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<DateTime>("BanTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("ban_time");
|
||||
|
||||
b.Property<Guid?>("BanningAdmin")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("banning_admin");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("expiration_time");
|
||||
|
||||
b.Property<byte[]>("HWId")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("hwid");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("reason");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_ban");
|
||||
|
||||
b.ToTable("ban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("unban_id");
|
||||
|
||||
b.Property<int>("BanId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("ban_id");
|
||||
|
||||
b.Property<DateTime>("UnbanTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("unban_time");
|
||||
|
||||
b.Property<Guid?>("UnbanningAdmin")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("unbanning_admin");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_unban");
|
||||
|
||||
b.HasIndex("BanId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("unban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.Property<int>("PlayersId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("players_id");
|
||||
|
||||
b.Property<int>("RoundsId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rounds_id");
|
||||
|
||||
b.HasKey("PlayersId", "RoundsId")
|
||||
.HasName("PK_player_round");
|
||||
|
||||
b.HasIndex("RoundsId")
|
||||
.HasDatabaseName("IX_player_round_rounds_id");
|
||||
|
||||
b.ToTable("player_round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("FK_admin_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("AdminRank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Admin", "Admin")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_flag_admin_admin_id");
|
||||
|
||||
b.Navigation("Admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Round", "Round")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_round_round_id");
|
||||
|
||||
b.Navigation("Round");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminLog", null)
|
||||
.WithMany("Entities")
|
||||
.HasForeignKey("AdminLogId", "AdminLogRoundId")
|
||||
.HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("PlayerUserId")
|
||||
.HasPrincipalKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_player_player_user_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.AdminLog", "Log")
|
||||
.WithMany("Players")
|
||||
.HasForeignKey("LogId", "RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id");
|
||||
|
||||
b.Navigation("Log");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("Rank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Antags")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_antag_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_job_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Preference", "Preference")
|
||||
.WithMany("Profiles")
|
||||
.HasForeignKey("PreferenceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_profile_preference_preference_id");
|
||||
|
||||
b.Navigation("Preference");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.SqliteServerBan", "Ban")
|
||||
.WithOne("Unban")
|
||||
.HasForeignKey("Content.Server.Database.SqliteServerUnban", "BanId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_unban_ban_ban_id");
|
||||
|
||||
b.Navigation("Ban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PlayersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_player_players_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Round", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoundsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_round_rounds_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Navigation("Entities");
|
||||
|
||||
b.Navigation("Players");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Navigation("Admins");
|
||||
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Navigation("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Navigation("Antags");
|
||||
|
||||
b.Navigation("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
|
||||
{
|
||||
b.Navigation("Unban");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
public partial class AdminLogsImpact : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<sbyte>(
|
||||
name: "impact",
|
||||
table: "admin_log",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: (sbyte)0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "impact",
|
||||
table: "admin_log");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
[DbContext(typeof(SqliteServerDbContext))]
|
||||
@@ -13,8 +15,7 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "5.0.3");
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.0");
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
@@ -31,11 +32,13 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("UserId");
|
||||
b.HasKey("UserId")
|
||||
.HasName("PK_admin");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_admin_rank_id");
|
||||
|
||||
b.ToTable("admin");
|
||||
b.ToTable("admin", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
@@ -58,14 +61,111 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("negative");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_flag");
|
||||
|
||||
b.HasIndex("AdminId");
|
||||
b.HasIndex("AdminId")
|
||||
.HasDatabaseName("IX_admin_flag_admin_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_flag");
|
||||
b.ToTable("admin_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("date");
|
||||
|
||||
b.Property<sbyte>("Impact")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("impact");
|
||||
|
||||
b.Property<string>("Json")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("json");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("message");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("type");
|
||||
|
||||
b.HasKey("Id", "RoundId")
|
||||
.HasName("PK_admin_log");
|
||||
|
||||
b.HasIndex("RoundId")
|
||||
.HasDatabaseName("IX_admin_log_round_id");
|
||||
|
||||
b.HasIndex("Type")
|
||||
.HasDatabaseName("IX_admin_log_type");
|
||||
|
||||
b.ToTable("admin_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.Property<int>("Uid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("uid");
|
||||
|
||||
b.Property<int?>("AdminLogId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<int?>("AdminLogRoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_round_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Uid")
|
||||
.HasName("PK_admin_log_entity");
|
||||
|
||||
b.HasIndex("AdminLogId", "AdminLogRoundId")
|
||||
.HasDatabaseName("IX_admin_log_entity_admin_log_id_admin_log_round_id");
|
||||
|
||||
b.ToTable("admin_log_entity", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerUserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_user_id");
|
||||
|
||||
b.Property<int>("LogId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("log_id");
|
||||
|
||||
b.Property<int>("RoundId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("PlayerUserId", "LogId", "RoundId")
|
||||
.HasName("PK_admin_log_player");
|
||||
|
||||
b.HasIndex("LogId", "RoundId");
|
||||
|
||||
b.ToTable("admin_log_player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
@@ -80,9 +180,10 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank");
|
||||
|
||||
b.ToTable("admin_rank");
|
||||
b.ToTable("admin_rank", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
@@ -101,14 +202,16 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("flag");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank_flag");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_rank_flag_admin_rank_id");
|
||||
|
||||
b.HasIndex("Flag", "AdminRankId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("admin_rank_flag");
|
||||
b.ToTable("admin_rank_flag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
@@ -127,12 +230,13 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_antag");
|
||||
|
||||
b.HasIndex("ProfileId", "AntagName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("antag");
|
||||
b.ToTable("antag", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
|
||||
@@ -151,7 +255,8 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_assigned_user_id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
@@ -159,7 +264,7 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.HasIndex("UserName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("assigned_user_id");
|
||||
b.ToTable("assigned_user_id", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
@@ -182,9 +287,11 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("profile_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_job");
|
||||
|
||||
b.HasIndex("ProfileId");
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_job_profile_id");
|
||||
|
||||
b.HasIndex("ProfileId", "JobName")
|
||||
.IsUnique();
|
||||
@@ -193,7 +300,51 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.IsUnique()
|
||||
.HasFilter("priority = 3");
|
||||
|
||||
b.ToTable("job");
|
||||
b.ToTable("job", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("first_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_address");
|
||||
|
||||
b.Property<byte[]>("LastSeenHWId")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("last_seen_hwid");
|
||||
|
||||
b.Property<DateTime>("LastSeenTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenUserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_user_name");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_player");
|
||||
|
||||
b.HasAlternateKey("UserId")
|
||||
.HasName("ak_player_user_id");
|
||||
|
||||
b.HasIndex("LastSeenUserName");
|
||||
|
||||
b.ToTable("player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
@@ -216,12 +367,13 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_preference");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("preference");
|
||||
b.ToTable("preference", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
@@ -302,14 +454,29 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("slot");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_profile");
|
||||
|
||||
b.HasIndex("PreferenceId");
|
||||
b.HasIndex("PreferenceId")
|
||||
.HasDatabaseName("IX_profile_preference_id");
|
||||
|
||||
b.HasIndex("Slot", "PreferenceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("profile");
|
||||
b.ToTable("profile", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_round");
|
||||
|
||||
b.ToTable("round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteConnectionLog", b =>
|
||||
@@ -341,49 +508,10 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_connection_log");
|
||||
|
||||
b.ToTable("connection_log");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqlitePlayer", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("first_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_address");
|
||||
|
||||
b.Property<byte[]>("LastSeenHWId")
|
||||
.HasColumnType("BLOB")
|
||||
.HasColumnName("last_seen_hwid");
|
||||
|
||||
b.Property<DateTime>("LastSeenTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_time");
|
||||
|
||||
b.Property<string>("LastSeenUserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("last_seen_user_name");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LastSeenUserName");
|
||||
|
||||
b.ToTable("player");
|
||||
b.ToTable("connection_log", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
|
||||
@@ -422,9 +550,10 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_ban");
|
||||
|
||||
b.ToTable("ban");
|
||||
b.ToTable("ban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b =>
|
||||
@@ -446,12 +575,32 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("unbanning_admin");
|
||||
|
||||
b.HasKey("Id");
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_unban");
|
||||
|
||||
b.HasIndex("BanId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("unban");
|
||||
b.ToTable("unban", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.Property<int>("PlayersId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("players_id");
|
||||
|
||||
b.Property<int>("RoundsId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rounds_id");
|
||||
|
||||
b.HasKey("PlayersId", "RoundsId")
|
||||
.HasName("PK_player_round");
|
||||
|
||||
b.HasIndex("RoundsId")
|
||||
.HasDatabaseName("IX_player_round_rounds_id");
|
||||
|
||||
b.ToTable("player_round", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
@@ -459,7 +608,8 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("FK_admin_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("AdminRank");
|
||||
});
|
||||
@@ -470,18 +620,62 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_flag_admin_admin_id");
|
||||
|
||||
b.Navigation("Admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Round", "Round")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_round_round_id");
|
||||
|
||||
b.Navigation("Round");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogEntity", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminLog", null)
|
||||
.WithMany("Entities")
|
||||
.HasForeignKey("AdminLogId", "AdminLogRoundId")
|
||||
.HasConstraintName("FK_admin_log_entity_admin_log_admin_log_id_admin_log_round_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithMany("AdminLogs")
|
||||
.HasForeignKey("PlayerUserId")
|
||||
.HasPrincipalKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_player_player_user_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.AdminLog", "Log")
|
||||
.WithMany("Players")
|
||||
.HasForeignKey("LogId", "RoundId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_log_player_admin_log_log_id_round_id");
|
||||
|
||||
b.Navigation("Log");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id");
|
||||
|
||||
b.Navigation("Rank");
|
||||
});
|
||||
@@ -492,7 +686,8 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.WithMany("Antags")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_antag_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
@@ -503,7 +698,8 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_job_profile_profile_id");
|
||||
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
@@ -514,7 +710,8 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.WithMany("Profiles")
|
||||
.HasForeignKey("PreferenceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_profile_preference_preference_id");
|
||||
|
||||
b.Navigation("Preference");
|
||||
});
|
||||
@@ -525,16 +722,41 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.WithOne("Unban")
|
||||
.HasForeignKey("Content.Server.Database.SqliteServerUnban", "BanId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_unban_ban_ban_id");
|
||||
|
||||
b.Navigation("Ban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlayerRound", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PlayersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_player_players_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Round", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoundsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_player_round_round_rounds_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminLog", b =>
|
||||
{
|
||||
b.Navigation("Entities");
|
||||
|
||||
b.Navigation("Players");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Navigation("Admins");
|
||||
@@ -542,6 +764,11 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.Navigation("Flags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Navigation("Profiles");
|
||||
@@ -554,6 +781,11 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.Navigation("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
|
||||
{
|
||||
b.Navigation("Unban");
|
||||
|
||||
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Content.Server.Database
|
||||
@@ -31,6 +33,9 @@ namespace Content.Server.Database
|
||||
public DbSet<Player> Player { get; set; } = default!;
|
||||
public DbSet<Admin> Admin { get; set; } = null!;
|
||||
public DbSet<AdminRank> AdminRank { get; set; } = null!;
|
||||
public DbSet<Round> Round { get; set; } = null!;
|
||||
public DbSet<AdminLog> AdminLog { get; set; } = null!;
|
||||
public DbSet<AdminLogPlayer> AdminLogPlayer { get; set; } = null!;
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -79,6 +84,22 @@ namespace Content.Server.Database
|
||||
modelBuilder.Entity<AdminRankFlag>()
|
||||
.HasIndex(f => new {f.Flag, f.AdminRankId})
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<AdminLog>()
|
||||
.HasKey(log => new {log.Id, log.RoundId});
|
||||
|
||||
modelBuilder.Entity<AdminLog>()
|
||||
.Property(log => log.Id)
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
modelBuilder.Entity<AdminLogPlayer>()
|
||||
.HasOne(player => player.Player)
|
||||
.WithMany(player => player.AdminLogs)
|
||||
.HasForeignKey(player => player.PlayerUserId)
|
||||
.HasPrincipalKey(player => player.UserId);
|
||||
|
||||
modelBuilder.Entity<AdminLogPlayer>()
|
||||
.HasKey(logPlayer => new {logPlayer.PlayerUserId, logPlayer.LogId, logPlayer.RoundId});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +199,10 @@ namespace Content.Server.Database
|
||||
public DateTime LastSeenTime { get; set; }
|
||||
public IPAddress LastSeenAddress { get; set; } = null!;
|
||||
public byte[]? LastSeenHWId { get; set; }
|
||||
|
||||
// Data that changes with each round
|
||||
public List<Round> Rounds { get; set; } = null!;
|
||||
public List<AdminLogPlayer> AdminLogs { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class Admin
|
||||
@@ -217,4 +242,54 @@ namespace Content.Server.Database
|
||||
public int AdminRankId { get; set; }
|
||||
public AdminRank Rank { get; set; } = default!;
|
||||
}
|
||||
|
||||
public class Round
|
||||
{
|
||||
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
|
||||
public List<Player> Players { get; set; } = default!;
|
||||
|
||||
public List<AdminLog> AdminLogs { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Index(nameof(Type))]
|
||||
public class AdminLog
|
||||
{
|
||||
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Key, ForeignKey("Round")] public int RoundId { get; set; }
|
||||
public Round Round { get; set; } = default!;
|
||||
|
||||
[Required] public LogType Type { get; set; }
|
||||
|
||||
[Required] public LogImpact Impact { get; set; }
|
||||
|
||||
[Required] public DateTime Date { get; set; }
|
||||
|
||||
[Required] public string Message { get; set; } = default!;
|
||||
|
||||
[Required, Column(TypeName = "jsonb")] public JsonDocument Json { get; set; } = default!;
|
||||
|
||||
public List<AdminLogPlayer> Players { get; set; } = default!;
|
||||
|
||||
public List<AdminLogEntity> Entities { get; set; } = default!;
|
||||
}
|
||||
|
||||
public class AdminLogPlayer
|
||||
{
|
||||
[Required, Key, ForeignKey("Player")] public Guid PlayerUserId { get; set; }
|
||||
public Player Player { get; set; } = default!;
|
||||
|
||||
[Required, Key] public int LogId { get; set; }
|
||||
[Required, Key] public int RoundId { get; set; }
|
||||
[ForeignKey("LogId,RoundId")] public AdminLog Log { get; set; } = default!;
|
||||
}
|
||||
|
||||
public class AdminLogEntity
|
||||
{
|
||||
[Required, Key] public int Uid { get; set; }
|
||||
public string? Name { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
@@ -57,6 +60,14 @@ namespace Content.Server.Database
|
||||
.Property(e => e.Address)
|
||||
.HasColumnType("TEXT")
|
||||
.HasConversion(ipMaskConverter);
|
||||
|
||||
var jsonConverter = new ValueConverter<JsonDocument, string>(
|
||||
v => JsonDocumentToString(v),
|
||||
v => StringToJsonDocument(v));
|
||||
|
||||
modelBuilder.Entity<AdminLog>()
|
||||
.Property(log => log.Json)
|
||||
.HasConversion(jsonConverter);
|
||||
}
|
||||
|
||||
public SqliteServerDbContext(DbContextOptions<ServerDbContext> options) : base(options)
|
||||
@@ -81,6 +92,22 @@ namespace Content.Server.Database
|
||||
int.Parse(inet.AsSpan(idx + 1), provider: CultureInfo.InvariantCulture)
|
||||
);
|
||||
}
|
||||
|
||||
private static string JsonDocumentToString(JsonDocument document)
|
||||
{
|
||||
using var stream = new MemoryStream();
|
||||
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions {Indented = false});
|
||||
|
||||
document.WriteTo(writer);
|
||||
writer.Flush();
|
||||
|
||||
return Encoding.UTF8.GetString(stream.ToArray());
|
||||
}
|
||||
|
||||
private static JsonDocument StringToJsonDocument(string str)
|
||||
{
|
||||
return JsonDocument.Parse(str);
|
||||
}
|
||||
}
|
||||
|
||||
[Table("ban")]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Players;
|
||||
|
||||
64
Content.Server/Administration/Commands/AdminLogBulk.cs
Normal file
64
Content.Server/Administration/Commands/AdminLogBulk.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Administration.Commands;
|
||||
|
||||
#if DEBUG
|
||||
[AdminCommand(AdminFlags.Host)]
|
||||
public class AdminLogBulk : IConsoleCommand
|
||||
{
|
||||
public string Command => "adminlogbulk";
|
||||
public string Description => "Adds debug logs to the database.";
|
||||
public string Help => $"Usage: {Command} <amount> <parallel>";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (shell.Player?.AttachedEntity is not { } entity)
|
||||
{
|
||||
shell.WriteError("This command can only be ran by a player with an attached entity.");
|
||||
return;
|
||||
}
|
||||
|
||||
int amount;
|
||||
var parallel = false;
|
||||
|
||||
switch (args)
|
||||
{
|
||||
case {Length: 1} when int.TryParse(args[0], out amount):
|
||||
case {Length: 2} when int.TryParse(args[0], out amount) &&
|
||||
bool.TryParse(args[1], out parallel):
|
||||
break;
|
||||
default:
|
||||
shell.WriteError(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
var logs = EntitySystem.Get<AdminLogSystem>();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
if (parallel)
|
||||
{
|
||||
Parallel.For(0, amount, _ =>
|
||||
{
|
||||
logs.Add(LogType.Unknown, $"Debug log added by {entity:Player}");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < amount; i++)
|
||||
{
|
||||
logs.Add(LogType.Unknown, $"Debug log added by {entity:Player}");
|
||||
}
|
||||
}
|
||||
|
||||
shell.WriteLine($"Added {amount} logs in {stopwatch.Elapsed.TotalMilliseconds} ms");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.UI;
|
||||
using Content.Server.EUI;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Administration.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.Logs)]
|
||||
public class OpenAdminLogsCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "adminlogs";
|
||||
public string Description => "Opens the admin logs panel.";
|
||||
public string Help => $"Usage: {Command}";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (shell.Player is not IPlayerSession player)
|
||||
{
|
||||
shell.WriteLine("This does not work from the server console.");
|
||||
return;
|
||||
}
|
||||
|
||||
var eui = IoCManager.Resolve<EuiManager>();
|
||||
var ui = new AdminLogsEui();
|
||||
eui.OpenEui(ui, player);
|
||||
}
|
||||
}
|
||||
302
Content.Server/Administration/Logs/AdminLogSystem.cs
Normal file
302
Content.Server/Administration/Logs/AdminLogSystem.cs
Normal file
@@ -0,0 +1,302 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs.Converters;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Events;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.CCVar;
|
||||
using Prometheus;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Reflection;
|
||||
|
||||
namespace Content.Server.Administration.Logs;
|
||||
|
||||
public class AdminLogSystem : SharedAdminLogSystem
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
[Dependency] private readonly IServerDbManager _db = default!;
|
||||
[Dependency] private readonly IDynamicTypeFactory _typeFactory = default!;
|
||||
[Dependency] private readonly IReflectionManager _reflection = default!;
|
||||
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
|
||||
public const string SawmillId = "admin.logs";
|
||||
|
||||
private static readonly Histogram DatabaseUpdateTime = Metrics.CreateHistogram(
|
||||
"admin_logs_database_time",
|
||||
"Time used to send logs to the database in ms",
|
||||
new HistogramConfiguration
|
||||
{
|
||||
Buckets = Histogram.LinearBuckets(0, 0.5, 20)
|
||||
});
|
||||
|
||||
private static readonly Gauge QueueCapReached = Metrics.CreateGauge(
|
||||
"admin_logs_queue_cap_reached",
|
||||
"Number of times the log queue cap has been reached in a round.");
|
||||
|
||||
private static readonly Gauge LogsSent = Metrics.CreateGauge(
|
||||
"admin_logs_sent",
|
||||
"Amount of logs sent to the database in a round.");
|
||||
|
||||
private static readonly JsonNamingPolicy NamingPolicy = JsonNamingPolicy.CamelCase;
|
||||
|
||||
// Init only
|
||||
private ISawmill _sawmill = default!;
|
||||
private JsonSerializerOptions _jsonOptions = default!;
|
||||
|
||||
// CVars
|
||||
private bool _metricsEnabled;
|
||||
private TimeSpan _queueSendDelay;
|
||||
private int _queueMax;
|
||||
|
||||
// Per update
|
||||
private float _accumulatedFrameTime;
|
||||
private readonly ConcurrentQueue<QueuedLog> _logsToAdd = new();
|
||||
|
||||
private int CurrentRoundId => _gameTicker.RoundId;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_sawmill = _logManager.GetSawmill(SawmillId);
|
||||
_jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = NamingPolicy
|
||||
};
|
||||
|
||||
foreach (var converter in _reflection.FindTypesWithAttribute<AdminLogConverterAttribute>())
|
||||
{
|
||||
var instance = _typeFactory.CreateInstance<JsonConverter>(converter);
|
||||
_jsonOptions.Converters.Add(instance);
|
||||
}
|
||||
|
||||
var converterNames = _jsonOptions.Converters.Select(converter => converter.GetType().Name);
|
||||
_sawmill.Info($"Admin log converters found: {string.Join(" ", converterNames)}");
|
||||
|
||||
_configuration.OnValueChanged(CVars.MetricsEnabled,
|
||||
value => _metricsEnabled = value, true);
|
||||
_configuration.OnValueChanged(CCVars.AdminLogsQueueSendDelay,
|
||||
value => _queueSendDelay = TimeSpan.FromSeconds(value), true);
|
||||
_configuration.OnValueChanged(CCVars.AdminLogsQueueMax,
|
||||
value => _queueMax = value, true);
|
||||
|
||||
if (_metricsEnabled)
|
||||
{
|
||||
QueueCapReached.Set(0);
|
||||
LogsSent.Set(0);
|
||||
}
|
||||
|
||||
SubscribeLocalEvent<RoundStartingEvent>(RoundStarting);
|
||||
}
|
||||
|
||||
public override async void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
if (!_logsToAdd.IsEmpty)
|
||||
{
|
||||
await SendLogs();
|
||||
}
|
||||
}
|
||||
|
||||
public override async void Update(float frameTime)
|
||||
{
|
||||
var count = _logsToAdd.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (count < _queueMax && _accumulatedFrameTime < _queueSendDelay.TotalSeconds)
|
||||
{
|
||||
_accumulatedFrameTime += frameTime;
|
||||
return;
|
||||
}
|
||||
|
||||
await SendLogs();
|
||||
}
|
||||
|
||||
private async Task SendLogs()
|
||||
{
|
||||
var copy = new List<QueuedLog>(_logsToAdd);
|
||||
_logsToAdd.Clear();
|
||||
_accumulatedFrameTime = 0;
|
||||
|
||||
// ship the logs to Azkaban
|
||||
var task = Task.Run(() =>
|
||||
{
|
||||
_db.AddAdminLogs(copy);
|
||||
});
|
||||
|
||||
if (_metricsEnabled)
|
||||
{
|
||||
if (copy.Count >= _queueMax)
|
||||
{
|
||||
QueueCapReached.Inc();
|
||||
}
|
||||
|
||||
LogsSent.Inc(copy.Count);
|
||||
|
||||
using (DatabaseUpdateTime.NewTimer())
|
||||
{
|
||||
await task;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await task;
|
||||
}
|
||||
|
||||
private void RoundStarting(RoundStartingEvent ev)
|
||||
{
|
||||
if (_metricsEnabled)
|
||||
{
|
||||
QueueCapReached.Set(0);
|
||||
LogsSent.Set(0);
|
||||
}
|
||||
}
|
||||
|
||||
public (JsonDocument json, List<Guid> players, List<(int id, string? name)> entities) ToJson(
|
||||
Dictionary<string, object?> properties)
|
||||
{
|
||||
var entities = new List<(int id, string? name)>();
|
||||
var players = new List<Guid>();
|
||||
var parsed = new Dictionary<string, object?>();
|
||||
|
||||
foreach (var key in properties.Keys)
|
||||
{
|
||||
var value = properties[key];
|
||||
var parsedKey = NamingPolicy.ConvertName(key);
|
||||
parsed.Add(parsedKey, value);
|
||||
|
||||
EntityUid? entityId = properties[key] switch
|
||||
{
|
||||
EntityUid id => id,
|
||||
IEntity entity => entity.Uid,
|
||||
IPlayerSession {AttachedEntityUid: { }} session => session.AttachedEntityUid.Value,
|
||||
IComponent component => component.OwnerUid,
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (entityId is not { } uid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var entityName = _entityManager.TryGetEntity(uid, out var resolvedEntity)
|
||||
? resolvedEntity.Name
|
||||
: null;
|
||||
|
||||
entities.Add(((int) uid, entityName));
|
||||
|
||||
if (_entityManager.TryGetComponent(uid, out ActorComponent? actor))
|
||||
{
|
||||
players.Add(actor.PlayerSession.UserId.UserId);
|
||||
}
|
||||
}
|
||||
|
||||
return (JsonSerializer.SerializeToDocument(parsed, _jsonOptions), players, entities);
|
||||
}
|
||||
|
||||
private async void Add(LogType type, LogImpact impact, string message, JsonDocument json, List<Guid> players, List<(int id, string? name)> entities)
|
||||
{
|
||||
var log = new AdminLog
|
||||
{
|
||||
RoundId = CurrentRoundId,
|
||||
Type = type,
|
||||
Impact = impact,
|
||||
Date = DateTime.UtcNow,
|
||||
Message = message,
|
||||
Json = json,
|
||||
Players = new List<AdminLogPlayer>(players.Count)
|
||||
};
|
||||
|
||||
var queued = new QueuedLog(log, entities);
|
||||
_logsToAdd.Enqueue(queued);
|
||||
|
||||
foreach (var id in players)
|
||||
{
|
||||
var player = new AdminLogPlayer
|
||||
{
|
||||
PlayerUserId = id,
|
||||
RoundId = CurrentRoundId
|
||||
};
|
||||
|
||||
log.Players.Add(player);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Add(LogType type, LogImpact impact, ref LogStringHandler handler)
|
||||
{
|
||||
var (json, players, entities) = ToJson(handler.Values);
|
||||
var message = handler.ToStringAndClear();
|
||||
|
||||
Add(type, impact, message, json, players, entities);
|
||||
}
|
||||
|
||||
public override void Add(LogType type, ref LogStringHandler handler)
|
||||
{
|
||||
Add(type, LogImpact.Medium, ref handler);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<LogRecord> All(LogFilter? filter = null)
|
||||
{
|
||||
return _db.GetAdminLogs(filter);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<string> AllMessages(LogFilter? filter = null)
|
||||
{
|
||||
return _db.GetAdminLogMessages(filter);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<JsonDocument> AllJson(LogFilter? filter = null)
|
||||
{
|
||||
return _db.GetAdminLogsJson(filter);
|
||||
}
|
||||
|
||||
public Task<Round> Round(int roundId)
|
||||
{
|
||||
return _db.GetRound(roundId);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<LogRecord> CurrentRoundLogs(LogFilter? filter = null)
|
||||
{
|
||||
filter ??= new LogFilter();
|
||||
filter.Round = CurrentRoundId;
|
||||
return All(filter);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<string> CurrentRoundMessages(LogFilter? filter = null)
|
||||
{
|
||||
filter ??= new LogFilter();
|
||||
filter.Round = CurrentRoundId;
|
||||
return AllMessages(filter);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<JsonDocument> CurrentRoundJson(LogFilter? filter = null)
|
||||
{
|
||||
filter ??= new LogFilter();
|
||||
filter.Round = CurrentRoundId;
|
||||
return AllJson(filter);
|
||||
}
|
||||
|
||||
public Task<Round> CurrentRound()
|
||||
{
|
||||
return Round(CurrentRoundId);
|
||||
}
|
||||
}
|
||||
204
Content.Server/Administration/Logs/AdminLogsEui.cs
Normal file
204
Content.Server/Administration/Logs/AdminLogsEui.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Eui;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using static Content.Shared.Administration.AdminLogsEuiMsg;
|
||||
|
||||
namespace Content.Server.Administration.Logs;
|
||||
|
||||
public sealed class AdminLogsEui : BaseEui
|
||||
{
|
||||
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
|
||||
private readonly ISawmill _sawmill;
|
||||
private readonly AdminLogSystem _logSystem;
|
||||
|
||||
private int _clientBatchSize;
|
||||
private bool _isLoading = true;
|
||||
private readonly Dictionary<Guid, string> _players = new();
|
||||
private CancellationTokenSource _logSendCancellation = new();
|
||||
private LogFilter _filter;
|
||||
|
||||
public AdminLogsEui()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_sawmill = _logManager.GetSawmill(AdminLogSystem.SawmillId);
|
||||
|
||||
_configuration.OnValueChanged(CCVars.AdminLogsClientBatchSize, ClientBatchSizeChanged, true);
|
||||
|
||||
_logSystem = EntitySystem.Get<AdminLogSystem>();
|
||||
_filter = new LogFilter
|
||||
{
|
||||
CancellationToken = _logSendCancellation.Token,
|
||||
Limit = _clientBatchSize
|
||||
};
|
||||
}
|
||||
|
||||
public int CurrentRoundId => EntitySystem.Get<GameTicker>().RoundId;
|
||||
|
||||
public override async void Opened()
|
||||
{
|
||||
base.Opened();
|
||||
|
||||
_adminManager.OnPermsChanged += OnPermsChanged;
|
||||
|
||||
var roundId = _filter.Round ?? EntitySystem.Get<GameTicker>().RoundId;
|
||||
LoadFromDb(roundId);
|
||||
}
|
||||
|
||||
private void ClientBatchSizeChanged(int value)
|
||||
{
|
||||
_clientBatchSize = value;
|
||||
}
|
||||
|
||||
private void OnPermsChanged(AdminPermsChangedEventArgs args)
|
||||
{
|
||||
if (args.Player == Player && !_adminManager.HasAdminFlag(Player, AdminFlags.Logs))
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
public override EuiStateBase GetNewState()
|
||||
{
|
||||
if (_isLoading)
|
||||
{
|
||||
return new AdminLogsEuiState(CurrentRoundId, new Dictionary<Guid, string>())
|
||||
{
|
||||
IsLoading = true
|
||||
};
|
||||
}
|
||||
|
||||
var state = new AdminLogsEuiState(CurrentRoundId, _players);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public override async void HandleMessage(EuiMessageBase msg)
|
||||
{
|
||||
if (!_adminManager.HasAdminFlag(Player, AdminFlags.Logs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case Close _:
|
||||
{
|
||||
Close();
|
||||
break;
|
||||
}
|
||||
case LogsRequest request:
|
||||
{
|
||||
_sawmill.Info($"Admin log request from admin with id {Player.UserId.UserId} and name {Player.Name}");
|
||||
|
||||
_logSendCancellation.Cancel();
|
||||
_logSendCancellation = new CancellationTokenSource();
|
||||
_filter = new LogFilter
|
||||
{
|
||||
CancellationToken = _logSendCancellation.Token,
|
||||
Round = request.RoundId,
|
||||
Types = request.Types,
|
||||
Impacts = request.Impacts,
|
||||
Before = request.Before,
|
||||
After = request.After,
|
||||
AnyPlayers = request.AnyPlayers,
|
||||
AllPlayers = request.AllPlayers,
|
||||
LastLogId = 0,
|
||||
Limit = _clientBatchSize
|
||||
};
|
||||
|
||||
var roundId = _filter.Round ??= EntitySystem.Get<GameTicker>().RoundId;
|
||||
LoadFromDb(roundId);
|
||||
|
||||
SendLogs(true);
|
||||
break;
|
||||
}
|
||||
case NextLogsRequest:
|
||||
{
|
||||
_sawmill.Info($"Admin log next batch request from admin with id {Player.UserId.UserId} and name {Player.Name}");
|
||||
|
||||
SendLogs(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void SendLogs(bool replace)
|
||||
{
|
||||
var logs = new List<SharedAdminLog>(_clientBatchSize);
|
||||
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
var results = await Task.Run(() => _logSystem.All(_filter));
|
||||
|
||||
await foreach (var record in results.WithCancellation(_logSendCancellation.Token))
|
||||
{
|
||||
var log = new SharedAdminLog(record.Id, record.Type, record.Impact, record.Date, record.Message, record.Players);
|
||||
logs.Add(log);
|
||||
}
|
||||
}, _filter.CancellationToken);
|
||||
|
||||
if (logs.Count > 0)
|
||||
{
|
||||
var largestId = _filter.DateOrder switch
|
||||
{
|
||||
DateOrder.Ascending => ^1,
|
||||
DateOrder.Descending => 0,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(_filter.DateOrder), _filter.DateOrder, null)
|
||||
};
|
||||
|
||||
_filter.LastLogId = logs[largestId].Id;
|
||||
}
|
||||
|
||||
var message = new NewLogs(logs.ToArray(), replace);
|
||||
|
||||
SendMessage(message);
|
||||
}
|
||||
|
||||
public override void Closed()
|
||||
{
|
||||
base.Closed();
|
||||
|
||||
_configuration.UnsubValueChanged(CCVars.AdminLogsClientBatchSize, ClientBatchSizeChanged);
|
||||
_adminManager.OnPermsChanged -= OnPermsChanged;
|
||||
|
||||
_logSendCancellation.Cancel();
|
||||
_logSendCancellation.Dispose();
|
||||
}
|
||||
|
||||
private async void LoadFromDb(int roundId)
|
||||
{
|
||||
_isLoading = true;
|
||||
StateDirty();
|
||||
|
||||
var round = await Task.Run(() => _logSystem.Round(roundId));
|
||||
var players = round.Players
|
||||
.ToDictionary(player => player.UserId, player => player.LastSeenUserName);
|
||||
|
||||
_players.Clear();
|
||||
|
||||
foreach (var (id, name) in players)
|
||||
{
|
||||
_players.Add(id, name);
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
StateDirty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Content.Server.Administration.Logs.Converters;
|
||||
|
||||
public abstract class AdminLogConverter<T> : JsonConverter<T>
|
||||
{
|
||||
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public abstract override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Server.Administration.Logs.Converters;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
[BaseTypeRequired(typeof(AdminLogConverter<>))]
|
||||
public class AdminLogConverterAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Administration.Logs.Converters;
|
||||
|
||||
[AdminLogConverter]
|
||||
public class EntityJsonConverter : AdminLogConverter<Entity>
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entities = default!;
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Entity value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
|
||||
writer.WriteNumber("id", (int) value.Uid);
|
||||
writer.WriteString("name", value.Name);
|
||||
|
||||
if (_entities.TryGetComponent(value.Uid, out ActorComponent? actor))
|
||||
{
|
||||
writer.WriteString("player", actor.PlayerSession.UserId.UserId);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Text.Json;
|
||||
using Content.Shared.FixedPoint;
|
||||
|
||||
namespace Content.Server.Administration.Logs.Converters;
|
||||
|
||||
[AdminLogConverter]
|
||||
public class FixedPoint2Converter : AdminLogConverter<FixedPoint2>
|
||||
{
|
||||
public override void Write(Utf8JsonWriter writer, FixedPoint2 value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteNumberValue(value.Int());
|
||||
}
|
||||
}
|
||||
33
Content.Server/Administration/Logs/LogFilter.cs
Normal file
33
Content.Server/Administration/Logs/LogFilter.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Content.Shared.Administration.Logs;
|
||||
|
||||
namespace Content.Server.Administration.Logs;
|
||||
|
||||
public sealed class LogFilter
|
||||
{
|
||||
public CancellationToken CancellationToken { get; set; }
|
||||
|
||||
public int? Round { get; set; }
|
||||
|
||||
public string? Search { get; set; }
|
||||
|
||||
public List<LogType>? Types { get; set; }
|
||||
|
||||
public List<LogImpact>? Impacts { get; set; }
|
||||
|
||||
public DateTime? Before { get; set; }
|
||||
|
||||
public DateTime? After { get; set; }
|
||||
|
||||
public Guid[]? AnyPlayers { get; set; }
|
||||
|
||||
public Guid[]? AllPlayers { get; set; }
|
||||
|
||||
public int? LastLogId { get; set; }
|
||||
|
||||
public int? Limit { get; set; }
|
||||
|
||||
public DateOrder DateOrder { get; set; } = DateOrder.Descending;
|
||||
}
|
||||
35
Content.Server/Administration/Logs/LogRecord.cs
Normal file
35
Content.Server/Administration/Logs/LogRecord.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Database;
|
||||
using Content.Shared.Administration.Logs;
|
||||
|
||||
namespace Content.Server.Administration.Logs;
|
||||
|
||||
public class LogRecord
|
||||
{
|
||||
public LogRecord(
|
||||
int id,
|
||||
int roundId,
|
||||
LogType type,
|
||||
LogImpact impact,
|
||||
DateTime date,
|
||||
string message,
|
||||
Guid[] players)
|
||||
{
|
||||
Id = id;
|
||||
RoundId = roundId;
|
||||
Type = type;
|
||||
Impact = impact;
|
||||
Date = date;
|
||||
Message = message;
|
||||
Players = players;
|
||||
}
|
||||
|
||||
public int Id { get; }
|
||||
public int RoundId { get; }
|
||||
public LogType Type { get; }
|
||||
public LogImpact Impact { get; }
|
||||
public DateTime Date { get; }
|
||||
public string Message { get; }
|
||||
public Guid[] Players { get; }
|
||||
}
|
||||
24
Content.Server/Administration/Logs/QueuedLog.cs
Normal file
24
Content.Server/Administration/Logs/QueuedLog.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Database;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Server.Administration.Logs;
|
||||
|
||||
public readonly struct QueuedLog
|
||||
{
|
||||
public QueuedLog(AdminLog log, List<(int id, string? name)> entities)
|
||||
{
|
||||
Log = log;
|
||||
Entities = entities;
|
||||
}
|
||||
|
||||
public AdminLog Log { get; }
|
||||
|
||||
public List<(int id, string? name)> Entities { get; }
|
||||
|
||||
public void Deconstruct(out AdminLog log, out List<(int id, string? name)> entities)
|
||||
{
|
||||
log = Log;
|
||||
entities = Entities;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
@@ -3,14 +3,18 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.CharacterAppearance;
|
||||
using Content.Shared.Preferences;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Database
|
||||
{
|
||||
@@ -440,6 +444,54 @@ namespace Content.Server.Database
|
||||
await db.DbContext.SaveChangesAsync(cancel);
|
||||
}
|
||||
|
||||
public virtual async Task<int> AddNewRound(params Guid[] playerIds)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var players = await db.DbContext.Player
|
||||
.Where(player => playerIds.Contains(player.UserId))
|
||||
.ToListAsync();
|
||||
|
||||
var round = new Round
|
||||
{
|
||||
Players = players
|
||||
};
|
||||
|
||||
db.DbContext.Round.Add(round);
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
|
||||
return round.Id;
|
||||
}
|
||||
|
||||
public async Task<Round> GetRound(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var round = await db.DbContext.Round
|
||||
.Include(round => round.Players)
|
||||
.SingleAsync(round => round.Id == id);
|
||||
|
||||
return round;
|
||||
}
|
||||
|
||||
public async Task AddRoundPlayers(int id, Guid[] playerIds)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var round = await db.DbContext.Round
|
||||
.Include(round => round.Players)
|
||||
.SingleAsync(round => round.Id == id);
|
||||
|
||||
var players = await db.DbContext.Player
|
||||
.Where(player => playerIds.Contains(player.UserId))
|
||||
.ToListAsync();
|
||||
|
||||
round.Players.AddRange(players);
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task UpdateAdminRankAsync(AdminRank rank, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
@@ -455,6 +507,160 @@ namespace Content.Server.Database
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Admin Logs
|
||||
|
||||
public virtual async Task AddAdminLogs(List<QueuedLog> logs)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var entities = new Dictionary<int, AdminLogEntity>();
|
||||
|
||||
foreach (var (log, entityData) in logs)
|
||||
{
|
||||
var logEntities = new List<AdminLogEntity>(entityData.Count);
|
||||
foreach (var (id, name) in entityData)
|
||||
{
|
||||
var entity = entities.GetOrNew(id);
|
||||
entity.Name = name;
|
||||
logEntities.Add(entity);
|
||||
}
|
||||
|
||||
log.Entities = logEntities;
|
||||
db.DbContext.AdminLog.Add(log);
|
||||
}
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private async Task<IQueryable<AdminLog>> GetAdminLogsQuery(ServerDbContext db, LogFilter? filter = null)
|
||||
{
|
||||
IQueryable<AdminLog> query = db.AdminLog;
|
||||
|
||||
if (filter == null)
|
||||
{
|
||||
return query.OrderBy(log => log.Date);
|
||||
}
|
||||
|
||||
if (filter.Round != null)
|
||||
{
|
||||
query = query.Where(log => log.RoundId == filter.Round);
|
||||
}
|
||||
|
||||
if (filter.Search != null)
|
||||
{
|
||||
query = query.Where(log => log.Message.Contains(filter.Search));
|
||||
}
|
||||
|
||||
if (filter.Types != null)
|
||||
{
|
||||
query = query.Where(log => filter.Types.Contains(log.Type));
|
||||
}
|
||||
|
||||
if (filter.Impacts != null)
|
||||
{
|
||||
query = query.Where(log => filter.Impacts.Contains(log.Impact));
|
||||
}
|
||||
|
||||
if (filter.Before != null)
|
||||
{
|
||||
query = query.Where(log => log.Date < filter.Before);
|
||||
}
|
||||
|
||||
if (filter.After != null)
|
||||
{
|
||||
query = query.Where(log => log.Date > filter.After);
|
||||
}
|
||||
|
||||
if (filter.AnyPlayers != null)
|
||||
{
|
||||
var players = await db.AdminLogPlayer
|
||||
.Where(player => filter.AnyPlayers.Contains(player.PlayerUserId))
|
||||
.ToListAsync();
|
||||
|
||||
if (players.Count > 0)
|
||||
{
|
||||
query = from log in query
|
||||
join player in db.AdminLogPlayer on log.Id equals player.LogId
|
||||
where filter.AnyPlayers.Contains(player.Player.UserId)
|
||||
select log;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.AllPlayers != null)
|
||||
{
|
||||
// TODO ADMIN LOGGING
|
||||
}
|
||||
|
||||
query = query.Distinct();
|
||||
|
||||
if (filter.LastLogId != null)
|
||||
{
|
||||
query = filter.DateOrder switch
|
||||
{
|
||||
DateOrder.Ascending => query.Where(log => log.Id < filter.LastLogId),
|
||||
DateOrder.Descending => query.Where(log => log.Id > filter.LastLogId),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(filter),
|
||||
$"Unknown {nameof(DateOrder)} value {filter.DateOrder}")
|
||||
};
|
||||
}
|
||||
|
||||
query = filter.DateOrder switch
|
||||
{
|
||||
DateOrder.Ascending => query.OrderBy(log => log.Date),
|
||||
DateOrder.Descending => query.OrderByDescending(log => log.Date),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(filter),
|
||||
$"Unknown {nameof(DateOrder)} value {filter.DateOrder}")
|
||||
};
|
||||
|
||||
if (filter.Limit != null)
|
||||
{
|
||||
query = query.Take(filter.Limit.Value);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<string> GetAdminLogMessages(LogFilter? filter = null)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var query = await GetAdminLogsQuery(db.DbContext, filter);
|
||||
|
||||
await foreach (var log in query.Select(log => log.Message).AsAsyncEnumerable())
|
||||
{
|
||||
yield return log;
|
||||
}
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<LogRecord> GetAdminLogs(LogFilter? filter = null)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var query = await GetAdminLogsQuery(db.DbContext, filter);
|
||||
|
||||
await foreach (var log in query.AsAsyncEnumerable())
|
||||
{
|
||||
var players = new Guid[log.Players.Count];
|
||||
for (var i = 0; i < log.Players.Count; i++)
|
||||
{
|
||||
players[i] = log.Players[i].PlayerUserId;
|
||||
}
|
||||
|
||||
yield return new LogRecord(log.Id, log.RoundId, log.Type, log.Impact, log.Date, log.Message, players);
|
||||
}
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<JsonDocument> GetAdminLogsJson(LogFilter? filter = null)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var query = await GetAdminLogsQuery(db.DbContext, filter);
|
||||
|
||||
await foreach (var json in query.Select(log => log.Json).AsAsyncEnumerable())
|
||||
{
|
||||
yield return json;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected abstract Task<DbGuard> GetDb();
|
||||
|
||||
protected abstract class DbGuard : IAsyncDisposable
|
||||
|
||||
@@ -3,8 +3,10 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Preferences;
|
||||
using Microsoft.Data.Sqlite;
|
||||
@@ -17,17 +19,17 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using Logger = Robust.Shared.Log.Logger;
|
||||
using LogLevel = Robust.Shared.Log.LogLevel;
|
||||
using MSLogLevel = Microsoft.Extensions.Logging.LogLevel;
|
||||
|
||||
|
||||
namespace Content.Server.Database
|
||||
{
|
||||
public interface IServerDbManager
|
||||
{
|
||||
void Init();
|
||||
|
||||
// Preferences
|
||||
#region Preferences
|
||||
Task<PlayerPreferences> InitPrefsAsync(NetUserId userId, ICharacterProfile defaultProfile);
|
||||
Task SaveSelectedCharacterIndexAsync(NetUserId userId, int index);
|
||||
|
||||
@@ -38,12 +40,15 @@ namespace Content.Server.Database
|
||||
// Single method for two operations for transaction.
|
||||
Task DeleteSlotAndSetSelectedIndex(NetUserId userId, int deleteSlot, int newSlot);
|
||||
Task<PlayerPreferences?> GetPlayerPreferencesAsync(NetUserId userId);
|
||||
#endregion
|
||||
|
||||
#region User Ids
|
||||
// Username assignment (for guest accounts, so they persist GUID)
|
||||
Task AssignUserIdAsync(string name, NetUserId userId);
|
||||
Task<NetUserId?> GetAssignedUserIdAsync(string name);
|
||||
#endregion
|
||||
|
||||
// Ban stuff
|
||||
#region Bans
|
||||
/// <summary>
|
||||
/// Looks up a ban by id.
|
||||
/// This will return a pardoned ban as well.
|
||||
@@ -82,8 +87,9 @@ namespace Content.Server.Database
|
||||
|
||||
Task AddServerBanAsync(ServerBanDef serverBan);
|
||||
Task AddServerUnbanAsync(ServerUnbanDef serverBan);
|
||||
#endregion
|
||||
|
||||
// Player records
|
||||
#region Player Records
|
||||
Task UpdatePlayerRecordAsync(
|
||||
NetUserId userId,
|
||||
string userName,
|
||||
@@ -91,15 +97,17 @@ namespace Content.Server.Database
|
||||
ImmutableArray<byte> hwId);
|
||||
Task<PlayerRecord?> GetPlayerRecordByUserName(string userName, CancellationToken cancel = default);
|
||||
Task<PlayerRecord?> GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel = default);
|
||||
#endregion
|
||||
|
||||
// Connection log
|
||||
#region Connection Logs
|
||||
Task AddConnectionLogAsync(
|
||||
NetUserId userId,
|
||||
string userName,
|
||||
IPAddress address,
|
||||
ImmutableArray<byte> hwId);
|
||||
#endregion
|
||||
|
||||
// Admins
|
||||
#region Admin Ranks
|
||||
Task<Admin?> GetAdminDataForAsync(NetUserId userId, CancellationToken cancel = default);
|
||||
Task<AdminRank?> GetAdminRankAsync(int id, CancellationToken cancel = default);
|
||||
|
||||
@@ -113,6 +121,24 @@ namespace Content.Server.Database
|
||||
Task RemoveAdminRankAsync(int rankId, CancellationToken cancel = default);
|
||||
Task AddAdminRankAsync(AdminRank rank, CancellationToken cancel = default);
|
||||
Task UpdateAdminRankAsync(AdminRank rank, CancellationToken cancel = default);
|
||||
#endregion
|
||||
|
||||
#region Rounds
|
||||
|
||||
Task<int> AddNewRound(params Guid[] playerIds);
|
||||
Task<Round> GetRound(int id);
|
||||
Task AddRoundPlayers(int id, params Guid[] playerIds);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Admin Logs
|
||||
|
||||
Task AddAdminLogs(List<QueuedLog> logs);
|
||||
IAsyncEnumerable<string> GetAdminLogMessages(LogFilter? filter = null);
|
||||
IAsyncEnumerable<LogRecord> GetAdminLogs(LogFilter? filter = null);
|
||||
IAsyncEnumerable<JsonDocument> GetAdminLogsJson(LogFilter? filter = null);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public sealed class ServerDbManager : IServerDbManager
|
||||
@@ -290,11 +316,46 @@ namespace Content.Server.Database
|
||||
return _db.AddAdminRankAsync(rank, cancel);
|
||||
}
|
||||
|
||||
public Task<int> AddNewRound(params Guid[] playerIds)
|
||||
{
|
||||
return _db.AddNewRound(playerIds);
|
||||
}
|
||||
|
||||
public Task<Round> GetRound(int id)
|
||||
{
|
||||
return _db.GetRound(id);
|
||||
}
|
||||
|
||||
public Task AddRoundPlayers(int id, params Guid[] playerIds)
|
||||
{
|
||||
return _db.AddRoundPlayers(id, playerIds);
|
||||
}
|
||||
|
||||
public Task UpdateAdminRankAsync(AdminRank rank, CancellationToken cancel = default)
|
||||
{
|
||||
return _db.UpdateAdminRankAsync(rank, cancel);
|
||||
}
|
||||
|
||||
public Task AddAdminLogs(List<QueuedLog> logs)
|
||||
{
|
||||
return _db.AddAdminLogs(logs);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<string> GetAdminLogMessages(LogFilter? filter = null)
|
||||
{
|
||||
return _db.GetAdminLogMessages(filter);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<LogRecord> GetAdminLogs(LogFilter? filter = null)
|
||||
{
|
||||
return _db.GetAdminLogs(filter);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<JsonDocument> GetAdminLogsJson(LogFilter? filter = null)
|
||||
{
|
||||
return _db.GetAdminLogsJson(filter);
|
||||
}
|
||||
|
||||
private DbContextOptions<ServerDbContext> CreatePostgresOptions()
|
||||
{
|
||||
var host = _cfg.GetCVar(CCVars.DatabasePgHost);
|
||||
|
||||
@@ -3,15 +3,19 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.IP;
|
||||
using Content.Server.Preferences.Managers;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.CCVar;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Database
|
||||
{
|
||||
@@ -246,6 +250,65 @@ namespace Content.Server.Database
|
||||
return (admins.Select(p => (p.a, p.LastSeenUserName)).ToArray(), adminRanks)!;
|
||||
}
|
||||
|
||||
private async Task<int> NextId<TModel>(DbSet<TModel> set, Func<TModel, int> selector) where TModel : class
|
||||
{
|
||||
var id = 1;
|
||||
|
||||
if (await set.AnyAsync())
|
||||
{
|
||||
id = set.Max(selector) + 1;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public override async Task<int> AddNewRound(params Guid[] playerIds)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var players = await db.DbContext.Player
|
||||
.Where(player => playerIds.Contains(player.UserId))
|
||||
.ToListAsync();
|
||||
|
||||
var round = new Round
|
||||
{
|
||||
Id = await NextId(db.DbContext.Round, round => round.Id),
|
||||
Players = players
|
||||
};
|
||||
|
||||
db.DbContext.Round.Add(round);
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
|
||||
return round.Id;
|
||||
}
|
||||
|
||||
public override async Task AddAdminLogs(List<QueuedLog> logs)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var nextId = await NextId(db.DbContext.AdminLog, log => log.Id);
|
||||
var entities = new Dictionary<int, AdminLogEntity>();
|
||||
|
||||
foreach (var (log, entityData) in logs)
|
||||
{
|
||||
log.Id = nextId++;
|
||||
|
||||
var logEntities = new List<AdminLogEntity>(entityData.Count);
|
||||
foreach (var (id, name) in entityData)
|
||||
{
|
||||
var entity = entities.GetOrNew(id);
|
||||
entity.Name = name;
|
||||
logEntities.Add(entity);
|
||||
}
|
||||
|
||||
log.Entities = logEntities;
|
||||
db.DbContext.AdminLog.Add(log);
|
||||
}
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private async Task<DbGuardImpl> GetDbImpl()
|
||||
{
|
||||
await _dbReadyTask;
|
||||
|
||||
10
Content.Server/GameTicking/Events/RoundStartingEvent.cs
Normal file
10
Content.Server/GameTicking/Events/RoundStartingEvent.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.GameTicking.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Raised at the start of <see cref="GameTicker.StartRound"/>
|
||||
/// </summary>
|
||||
public class RoundStartingEvent : EntityEventArgs
|
||||
{
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Content.Server.Players;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.GameWindow;
|
||||
@@ -35,6 +36,8 @@ namespace Content.Server.GameTicking
|
||||
|
||||
case SessionStatus.Connected:
|
||||
{
|
||||
AddPlayerToDb(args.Session.UserId.UserId);
|
||||
|
||||
// Always make sure the client has player data. Mind gets assigned on spawn.
|
||||
if (session.Data.ContentDataUncast == null)
|
||||
session.Data.ContentDataUncast = new PlayerData(session.UserId, args.Session.Name);
|
||||
@@ -106,6 +109,14 @@ namespace Content.Server.GameTicking
|
||||
await _prefsManager.WaitPreferencesLoaded(session);
|
||||
SpawnPlayer(session);
|
||||
}
|
||||
|
||||
async void AddPlayerToDb(Guid id)
|
||||
{
|
||||
if (RoundId != 0 && _runLevel != GameRunLevel.PreRoundLobby)
|
||||
{
|
||||
await _db.AddRoundPlayers(RoundId, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private HumanoidCharacterProfile GetPlayerProfile(IPlayerSession p)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.GameTicking.Events;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Ghost;
|
||||
@@ -33,6 +36,8 @@ namespace Content.Server.GameTicking
|
||||
"ss14_round_length",
|
||||
"Round length in seconds.");
|
||||
|
||||
[Dependency] private readonly IServerDbManager _db = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private TimeSpan _roundStartTimeSpan;
|
||||
|
||||
@@ -54,6 +59,9 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public int RoundId { get; private set; }
|
||||
|
||||
private void PreRoundSetup()
|
||||
{
|
||||
DefaultMap = _mapManager.CreateMap();
|
||||
@@ -88,7 +96,7 @@ namespace Content.Server.GameTicking
|
||||
Logger.InfoS("ticker", $"Loaded map in {timeSpan.TotalMilliseconds:N2}ms.");
|
||||
}
|
||||
|
||||
public void StartRound(bool force = false)
|
||||
public async void StartRound(bool force = false)
|
||||
{
|
||||
// If this game ticker is a dummy, do nothing!
|
||||
if (DummyTicker)
|
||||
@@ -97,6 +105,12 @@ namespace Content.Server.GameTicking
|
||||
DebugTools.Assert(RunLevel == GameRunLevel.PreRoundLobby);
|
||||
Logger.InfoS("ticker", "Starting round!");
|
||||
|
||||
var playerIds = _playersInLobby.Keys.Select(player => player.UserId.UserId).ToArray();
|
||||
RoundId = await _db.AddNewRound(playerIds);
|
||||
|
||||
var startingEvent = new RoundStartingEvent();
|
||||
RaiseLocalEvent(startingEvent);
|
||||
|
||||
SendServerMessage(Loc.GetString("game-ticker-start-round"));
|
||||
|
||||
List<IPlayerSession> readyPlayers;
|
||||
|
||||
@@ -2,14 +2,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Audio;
|
||||
using Content.Server.Damage.Systems;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Physics;
|
||||
@@ -21,7 +18,6 @@ using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Shuttles.EntitySystems
|
||||
|
||||
@@ -60,6 +60,11 @@ namespace Content.Shared.Administration
|
||||
/// </summary>
|
||||
//Piss = 1 << 9,
|
||||
|
||||
/// <summary>
|
||||
/// Lets you view admin logs.
|
||||
/// </summary>
|
||||
Logs = 1 << 9,
|
||||
|
||||
/// <summary>
|
||||
/// Dangerous host permissions like scsi.
|
||||
/// </summary>
|
||||
|
||||
85
Content.Shared/Administration/AdminLogsEuiState.cs
Normal file
85
Content.Shared/Administration/AdminLogsEuiState.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Eui;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Administration;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class AdminLogsEuiState : EuiStateBase
|
||||
{
|
||||
public AdminLogsEuiState(int roundId, Dictionary<Guid, string> players)
|
||||
{
|
||||
RoundId = roundId;
|
||||
Players = players;
|
||||
}
|
||||
|
||||
public bool IsLoading { get; set; }
|
||||
|
||||
public int RoundId { get; }
|
||||
|
||||
public Dictionary<Guid, string> Players { get; }
|
||||
}
|
||||
|
||||
public static class AdminLogsEuiMsg
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class Close : EuiMessageBase
|
||||
{
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class NewLogs : EuiMessageBase
|
||||
{
|
||||
public NewLogs(SharedAdminLog[] logs, bool replace)
|
||||
{
|
||||
Logs = logs;
|
||||
Replace = replace;
|
||||
}
|
||||
|
||||
public SharedAdminLog[] Logs { get; set; }
|
||||
public bool Replace { get; set; }
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class LogsRequest : EuiMessageBase
|
||||
{
|
||||
public LogsRequest(
|
||||
int? roundId,
|
||||
List<LogType>? types,
|
||||
List<LogImpact>? impacts,
|
||||
DateTime? before,
|
||||
DateTime? after,
|
||||
Guid[]? anyPlayers,
|
||||
Guid[]? allPlayers,
|
||||
int? lastLogId,
|
||||
DateOrder dateOrder)
|
||||
{
|
||||
RoundId = roundId;
|
||||
Types = types;
|
||||
Impacts = impacts;
|
||||
Before = before;
|
||||
After = after;
|
||||
AnyPlayers = anyPlayers is { Length: > 0 } ? anyPlayers : null;
|
||||
AllPlayers = allPlayers is { Length: > 0 } ? allPlayers : null;
|
||||
LastLogId = lastLogId;
|
||||
DateOrder = dateOrder;
|
||||
}
|
||||
|
||||
public int? RoundId { get; set; }
|
||||
public List<LogType>? Types { get; set; }
|
||||
public List<LogImpact>? Impacts { get; set; }
|
||||
public DateTime? Before { get; set; }
|
||||
public DateTime? After { get; set; }
|
||||
public Guid[]? AnyPlayers { get; set; }
|
||||
public Guid[]? AllPlayers { get; set; }
|
||||
public int? LastLogId { get; set; }
|
||||
public DateOrder DateOrder { get; set; }
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class NextLogsRequest : EuiMessageBase
|
||||
{
|
||||
}
|
||||
}
|
||||
7
Content.Shared/Administration/Logs/DateOrder.cs
Normal file
7
Content.Shared/Administration/Logs/DateOrder.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Content.Shared.Administration.Logs;
|
||||
|
||||
public enum DateOrder
|
||||
{
|
||||
Ascending = 0,
|
||||
Descending
|
||||
}
|
||||
10
Content.Shared/Administration/Logs/LogImpact.cs
Normal file
10
Content.Shared/Administration/Logs/LogImpact.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Content.Shared.Administration.Logs;
|
||||
|
||||
// DO NOT CHANGE THE NUMERIC VALUES OF THESE
|
||||
public enum LogImpact : sbyte
|
||||
{
|
||||
Low = -1,
|
||||
Medium = 0,
|
||||
High = 1,
|
||||
Extreme = 2 // Nar'Sie just dropped
|
||||
}
|
||||
110
Content.Shared/Administration/Logs/LogStringHandler.cs
Normal file
110
Content.Shared/Administration/Logs/LogStringHandler.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Content.Shared.Administration.Logs;
|
||||
|
||||
[InterpolatedStringHandler]
|
||||
public ref struct LogStringHandler
|
||||
{
|
||||
private DefaultInterpolatedStringHandler _handler;
|
||||
public readonly Dictionary<string, object?> Values;
|
||||
|
||||
public LogStringHandler(int literalLength, int formattedCount)
|
||||
{
|
||||
_handler = new DefaultInterpolatedStringHandler(literalLength, formattedCount);
|
||||
Values = new Dictionary<string, object?>();
|
||||
}
|
||||
|
||||
public LogStringHandler(int literalLength, int formattedCount, IFormatProvider? provider)
|
||||
{
|
||||
_handler = new DefaultInterpolatedStringHandler(literalLength, formattedCount, provider);
|
||||
Values = new Dictionary<string, object?>();
|
||||
}
|
||||
|
||||
public LogStringHandler(int literalLength, int formattedCount, IFormatProvider? provider, Span<char> initialBuffer)
|
||||
{
|
||||
_handler = new DefaultInterpolatedStringHandler(literalLength, formattedCount, provider, initialBuffer);
|
||||
Values = new Dictionary<string, object?>();
|
||||
}
|
||||
|
||||
private void AddFormat<T>(string? format, T value, string? argument = null)
|
||||
{
|
||||
if (format == null)
|
||||
{
|
||||
if (argument == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
format = argument[0] == '@' ? argument[1..] : argument;
|
||||
}
|
||||
|
||||
Values.Add(format, value);
|
||||
}
|
||||
|
||||
public void AppendLiteral(string value)
|
||||
{
|
||||
_handler.AppendLiteral(value);
|
||||
}
|
||||
|
||||
public void AppendFormatted<T>(T value, [CallerArgumentExpression("value")] string? argument = null)
|
||||
{
|
||||
AddFormat(null, value, argument);
|
||||
_handler.AppendFormatted(value);
|
||||
}
|
||||
|
||||
public void AppendFormatted<T>(T value, string? format, [CallerArgumentExpression("value")] string? argument = null)
|
||||
{
|
||||
AddFormat(format, value, argument);
|
||||
_handler.AppendFormatted(value, format);
|
||||
}
|
||||
|
||||
public void AppendFormatted<T>(T value, int alignment, [CallerArgumentExpression("value")] string? argument = null)
|
||||
{
|
||||
AddFormat(null, value, argument);
|
||||
_handler.AppendFormatted(value, alignment);
|
||||
}
|
||||
|
||||
public void AppendFormatted<T>(T value, int alignment, string? format, [CallerArgumentExpression("value")] string? argument = null)
|
||||
{
|
||||
AddFormat(format, value, argument);
|
||||
_handler.AppendFormatted(value, alignment, format);
|
||||
}
|
||||
|
||||
public void AppendFormatted(ReadOnlySpan<char> value)
|
||||
{
|
||||
_handler.AppendFormatted(value);
|
||||
}
|
||||
|
||||
// ReSharper disable once MethodOverloadWithOptionalParameter
|
||||
public void AppendFormatted(ReadOnlySpan<char> value, int alignment = 0, string? format = null)
|
||||
{
|
||||
AddFormat(format, value.ToString());
|
||||
_handler.AppendFormatted(value, alignment, format);
|
||||
}
|
||||
|
||||
public void AppendFormatted(string? value)
|
||||
{
|
||||
_handler.AppendFormatted(value);
|
||||
}
|
||||
|
||||
// ReSharper disable once MethodOverloadWithOptionalParameter
|
||||
public void AppendFormatted(string? value, int alignment = 0, string? format = null)
|
||||
{
|
||||
AddFormat(format, value);
|
||||
_handler.AppendFormatted(value, alignment, format);
|
||||
}
|
||||
|
||||
public void AppendFormatted(object? value, int alignment = 0, string? format = null)
|
||||
{
|
||||
AddFormat(null, value, format);
|
||||
_handler.AppendFormatted(value, alignment, format);
|
||||
}
|
||||
|
||||
public string ToStringAndClear()
|
||||
{
|
||||
Values.Clear();
|
||||
return _handler.ToStringAndClear();
|
||||
}
|
||||
}
|
||||
8
Content.Shared/Administration/Logs/LogType.cs
Normal file
8
Content.Shared/Administration/Logs/LogType.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Content.Shared.Administration.Logs;
|
||||
|
||||
// DO NOT CHANGE THE NUMERIC VALUES OF THESE
|
||||
public enum LogType
|
||||
{
|
||||
Unknown = 0, // do not use
|
||||
DamageChange = 1
|
||||
}
|
||||
13
Content.Shared/Administration/Logs/SharedAdminLog.cs
Normal file
13
Content.Shared/Administration/Logs/SharedAdminLog.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Administration.Logs;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public readonly record struct SharedAdminLog(
|
||||
int Id,
|
||||
LogType Type,
|
||||
LogImpact Impact,
|
||||
DateTime Date,
|
||||
string Message,
|
||||
Guid[] Players);
|
||||
17
Content.Shared/Administration/Logs/SharedAdminLogSystem.cs
Normal file
17
Content.Shared/Administration/Logs/SharedAdminLogSystem.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Globalization;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.Administration.Logs;
|
||||
|
||||
public abstract class SharedAdminLogSystem : EntitySystem
|
||||
{
|
||||
public virtual void Add(LogType type, LogImpact impact, ref LogStringHandler handler)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
public virtual void Add(LogType type, ref LogStringHandler handler)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
}
|
||||
@@ -294,6 +294,20 @@ namespace Content.Shared.CCVar
|
||||
public static readonly CVarDef<bool> AdminAnnounceLogout =
|
||||
CVarDef.Create("admin.announce_logout", true, CVar.SERVERONLY);
|
||||
|
||||
/*
|
||||
* Admin logs
|
||||
*/
|
||||
|
||||
public static readonly CVarDef<float> AdminLogsQueueSendDelay =
|
||||
CVarDef.Create("adminlogs.queue_send_delay_seconds", 5f, CVar.SERVERONLY);
|
||||
|
||||
public static readonly CVarDef<int> AdminLogsQueueMax =
|
||||
CVarDef.Create("adminlogs.queue_max", 5000, CVar.SERVERONLY);
|
||||
|
||||
// How many logs to send to the client at once
|
||||
public static readonly CVarDef<int> AdminLogsClientBatchSize =
|
||||
CVarDef.Create("adminlogs.client_batch_size", 1000, CVar.SERVERONLY);
|
||||
|
||||
/*
|
||||
* Atmos
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Acts;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Radiation;
|
||||
using Robust.Shared.Analyzers;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Movement.EntitySystems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -15,6 +14,8 @@ namespace Content.Shared.Damage
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
[Dependency] private readonly SharedAdminLogSystem _logs = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<DamageableComponent, ComponentInit>(DamageableInit);
|
||||
@@ -22,6 +23,17 @@ namespace Content.Shared.Damage
|
||||
SubscribeLocalEvent<DamageableComponent, ComponentGetState>(DamageableGetState);
|
||||
}
|
||||
|
||||
protected virtual void SetTotalDamage(DamageableComponent damageable, FixedPoint2 @new)
|
||||
{
|
||||
var owner = damageable.Owner;
|
||||
var old = damageable.TotalDamage;
|
||||
var change = @new - old;
|
||||
|
||||
_logs.Add(LogType.DamageChange, $"{owner} received {change} damage. Old: {old} | New: {@new}");
|
||||
|
||||
damageable.TotalDamage = @new;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a damageable component
|
||||
/// </summary>
|
||||
@@ -83,7 +95,7 @@ namespace Content.Shared.Damage
|
||||
public void DamageChanged(DamageableComponent component, DamageSpecifier? damageDelta = null)
|
||||
{
|
||||
component.DamagePerGroup = component.Damage.GetDamagePerGroup();
|
||||
component.TotalDamage = component.Damage.Total;
|
||||
SetTotalDamage(component, component.Damage.Total);
|
||||
component.Dirty();
|
||||
|
||||
if (EntityManager.TryGetComponent<SharedAppearanceComponent>(component.OwnerUid, out var appearance) && damageDelta != null)
|
||||
|
||||
@@ -5,7 +5,7 @@ using Content.Shared.Movement.EntitySystems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Shared.Damage.Systems
|
||||
namespace Content.Shared.Damage
|
||||
{
|
||||
public class SlowOnDamageSystem : EntitySystem
|
||||
{
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.FixedPoint
|
||||
@@ -13,10 +10,10 @@ namespace Content.Shared.FixedPoint
|
||||
/// To enforce this level of precision, floats are shifted by 2 decimal points, rounded, and converted to an int.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct FixedPoint2 : ISelfSerialize, IComparable<FixedPoint2>, IEquatable<FixedPoint2>
|
||||
public struct FixedPoint2 : ISelfSerialize, IComparable<FixedPoint2>, IEquatable<FixedPoint2>, IFormattable
|
||||
{
|
||||
private int _value;
|
||||
private static readonly int Shift = 2;
|
||||
private const int Shift = 2;
|
||||
|
||||
public static FixedPoint2 MaxValue { get; } = new(int.MaxValue);
|
||||
public static FixedPoint2 Epsilon { get; } = new(1);
|
||||
@@ -250,6 +247,11 @@ namespace Content.Shared.FixedPoint
|
||||
|
||||
public override readonly string ToString() => $"{ShiftDown().ToString(CultureInfo.InvariantCulture)}";
|
||||
|
||||
public string ToString(string? format, IFormatProvider? formatProvider)
|
||||
{
|
||||
return ToString();
|
||||
}
|
||||
|
||||
public readonly string Serialize()
|
||||
{
|
||||
return ToString();
|
||||
|
||||
20
Resources/Locale/en-US/administration/ui/admin-logs.ftl
Normal file
20
Resources/Locale/en-US/administration/ui/admin-logs.ftl
Normal file
@@ -0,0 +1,20 @@
|
||||
admin-logs-title = Admin Logs Panel
|
||||
|
||||
# Round
|
||||
admin-logs-round = Round{" "}
|
||||
admin-logs-reset = Reset
|
||||
admin-logs-reset-with-id = Reset Round (#{$id})
|
||||
|
||||
# Types
|
||||
admin-logs-search-types-placeholder = Search Types (OR)
|
||||
admin-logs-select-all = All
|
||||
admin-logs-select-none = None
|
||||
|
||||
# Players
|
||||
admin-logs-search-players-placeholder = Search Players (OR)
|
||||
admin-logs-select-none = None
|
||||
|
||||
# Logs
|
||||
admin-logs-search-logs-placeholder = Search Logs
|
||||
admin-logs-refresh = Refresh
|
||||
admin-logs-next = Next
|
||||
@@ -6,4 +6,4 @@ admin-menu-adminbus-tab = Adminbus
|
||||
admin-menu-atmos-tab = Atmos
|
||||
admin-menu-round-tab = Round
|
||||
admin-menu-server-tab = Server
|
||||
admin-menu-players-tab = Players
|
||||
admin-menu-players-tab = Players
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=metabolizable/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mommi/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Monstermos/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nar_0027/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Noto/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=occluder/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Occluders/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
Reference in New Issue
Block a user