ConGroups are gone. Long live admin flags in content.
This commit is contained in:
82
Content.Client/Administration/ClientAdminManager.cs
Normal file
82
Content.Client/Administration/ClientAdminManager.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Network.NetMessages;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Client.Administration
|
||||
{
|
||||
public class ClientAdminManager : IClientAdminManager, IClientConGroupImplementation, IPostInjectInit
|
||||
{
|
||||
[Dependency] private readonly IClientNetManager _netMgr = default!;
|
||||
[Dependency] private readonly IClientConGroupController _conGroup = default!;
|
||||
|
||||
private AdminData? _adminData;
|
||||
private readonly HashSet<string> _availableCommands = new HashSet<string>();
|
||||
|
||||
public bool HasFlag(AdminFlags flag)
|
||||
{
|
||||
return _adminData?.HasFlag(flag) ?? false;
|
||||
}
|
||||
|
||||
public bool CanCommand(string cmdName)
|
||||
{
|
||||
return _availableCommands.Contains(cmdName);
|
||||
}
|
||||
|
||||
public bool CanViewVar()
|
||||
{
|
||||
return _adminData?.CanViewVar() ?? false;
|
||||
}
|
||||
|
||||
public bool CanAdminPlace()
|
||||
{
|
||||
return _adminData?.CanAdminPlace() ?? false;
|
||||
}
|
||||
|
||||
public bool CanScript()
|
||||
{
|
||||
return _adminData?.CanScript() ?? false;
|
||||
}
|
||||
|
||||
public bool CanAdminMenu()
|
||||
{
|
||||
return _adminData?.CanAdminMenu() ?? false;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netMgr.RegisterNetMessage<MsgUpdateAdminStatus>(MsgUpdateAdminStatus.NAME, UpdateMessageRx);
|
||||
}
|
||||
|
||||
private void UpdateMessageRx(MsgUpdateAdminStatus message)
|
||||
{
|
||||
_availableCommands.Clear();
|
||||
_availableCommands.UnionWith(message.AvailableCommands);
|
||||
Logger.DebugS("admin", $"Have {message.AvailableCommands.Length} commands available");
|
||||
|
||||
_adminData = message.Admin;
|
||||
if (_adminData != null)
|
||||
{
|
||||
var flagsText = string.Join("|", AdminFlagsExt.FlagsToNames(_adminData.Flags));
|
||||
Logger.InfoS("admin", $"Updated admin status: {_adminData.Active}/{_adminData.Title}/{flagsText}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.InfoS("admin", $"Updated admin status: Not admin");
|
||||
}
|
||||
}
|
||||
|
||||
public event Action? ConGroupUpdated;
|
||||
|
||||
void IPostInjectInit.PostInject()
|
||||
{
|
||||
_conGroup.Implementation = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Content.Client/Administration/IClientAdminManager.cs
Normal file
17
Content.Client/Administration/IClientAdminManager.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Content.Shared.Administration;
|
||||
|
||||
namespace Content.Client.Administration
|
||||
{
|
||||
public interface IClientAdminManager
|
||||
{
|
||||
bool HasFlag(AdminFlags flag);
|
||||
|
||||
bool CanCommand(string cmdName);
|
||||
bool CanViewVar();
|
||||
bool CanAdminPlace();
|
||||
bool CanScript();
|
||||
bool CanAdminMenu();
|
||||
|
||||
void Initialize();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Client.Chat;
|
||||
using Content.Client.Administration;
|
||||
using Content.Client.Chat;
|
||||
using Content.Client.GameTicking;
|
||||
using Content.Client.Interfaces;
|
||||
using Content.Client.Interfaces.Chat;
|
||||
@@ -35,6 +36,7 @@ namespace Content.Client
|
||||
IoCManager.Register<IClickMapManager, ClickMapManager>();
|
||||
IoCManager.Register<IStationEventManager, StationEventManager>();
|
||||
IoCManager.Register<IAdminMenuManager, AdminMenuManager>();
|
||||
IoCManager.Register<IClientAdminManager, ClientAdminManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Content.Client.Administration;
|
||||
using Content.Client.GameObjects.Components.Actor;
|
||||
using Content.Client.Input;
|
||||
using Content.Client.Interfaces;
|
||||
@@ -88,6 +89,7 @@ namespace Content.Client
|
||||
|
||||
IoCManager.BuildGraph();
|
||||
|
||||
IoCManager.Resolve<IClientAdminManager>().Initialize();
|
||||
IoCManager.Resolve<IParallaxManager>().LoadParallax();
|
||||
IoCManager.Resolve<IBaseClient>().PlayerJoinedServer += SubscribePlayerAttachmentEvents;
|
||||
IoCManager.Resolve<IStylesheetManager>().Initialize();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Client;
|
||||
using Content.Client.Interfaces.Parallax;
|
||||
@@ -13,7 +12,6 @@ using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.UnitTesting;
|
||||
using EntryPoint = Content.Client.EntryPoint;
|
||||
|
||||
|
||||
509
Content.Server.Database/Migrations/Postgres/20201028210620_Admins.Designer.cs
generated
Normal file
509
Content.Server.Database/Migrations/Postgres/20201028210620_Admins.Designer.cs
generated
Normal file
@@ -0,0 +1,509 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Net;
|
||||
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;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
[DbContext(typeof(PostgresServerDbContext))]
|
||||
[Migration("20201028210620_Admins")]
|
||||
partial class Admins
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
|
||||
.HasAnnotation("ProductVersion", "3.1.4")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int?>("AdminRankId")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnName("title")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.ToTable("admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_flag_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnName("admin_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnName("flag")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("Negative")
|
||||
.HasColumnName("negative")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AdminId");
|
||||
|
||||
b.ToTable("admin_flag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnName("name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("admin_rank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_rank_flag_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnName("flag")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.ToTable("admin_rank_flag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("antag_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<string>("AntagName")
|
||||
.IsRequired()
|
||||
.HasColumnName("antag_name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnName("profile_id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProfileId", "AntagName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("antag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("assigned_user_id_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnName("user_name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("assigned_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("job_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
.HasColumnName("job_name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnName("priority")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnName("profile_id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProfileId");
|
||||
|
||||
b.ToTable("job");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresConnectionLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("connection_log_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<IPAddress>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnName("address")
|
||||
.HasColumnType("inet");
|
||||
|
||||
b.Property<DateTime>("Time")
|
||||
.HasColumnName("time")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnName("user_name")
|
||||
.HasColumnType("text");
|
||||
|
||||
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()
|
||||
.HasColumnName("player_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnName("first_seen_time")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<IPAddress>("LastSeenAddress")
|
||||
.IsRequired()
|
||||
.HasColumnName("last_seen_address")
|
||||
.HasColumnType("inet");
|
||||
|
||||
b.Property<DateTime>("LastSeenTime")
|
||||
.HasColumnName("last_seen_time")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("LastSeenUserName")
|
||||
.IsRequired()
|
||||
.HasColumnName("last_seen_user_name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("player");
|
||||
|
||||
b.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("server_ban_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<ValueTuple<IPAddress, int>?>("Address")
|
||||
.HasColumnName("address")
|
||||
.HasColumnType("inet");
|
||||
|
||||
b.Property<DateTime>("BanTime")
|
||||
.HasColumnName("ban_time")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid?>("BanningAdmin")
|
||||
.HasColumnName("banning_admin")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnName("expiration_time")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.IsRequired()
|
||||
.HasColumnName("reason")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Address");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("server_ban");
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
|
||||
b.HasCheckConstraint("HaveEitherAddressOrUserId", "address IS NOT NULL OR user_id IS NOT NULL");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("unban_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<int>("BanId")
|
||||
.HasColumnName("ban_id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime>("UnbanTime")
|
||||
.HasColumnName("unban_time")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid?>("UnbanningAdmin")
|
||||
.HasColumnName("unbanning_admin")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BanId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("server_unban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("preference_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<int>("SelectedCharacterSlot")
|
||||
.HasColumnName("selected_character_slot")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("preference");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("profile_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnName("age")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("CharacterName")
|
||||
.IsRequired()
|
||||
.HasColumnName("char_name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("EyeColor")
|
||||
.IsRequired()
|
||||
.HasColumnName("eye_color")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("FacialHairColor")
|
||||
.IsRequired()
|
||||
.HasColumnName("facial_hair_color")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnName("facial_hair_name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnName("hair_color")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnName("hair_name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("PreferenceId")
|
||||
.HasColumnName("preference_id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("PreferenceUnavailable")
|
||||
.HasColumnName("pref_unavailable")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.IsRequired()
|
||||
.HasColumnName("sex")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnName("skin_color")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Slot")
|
||||
.HasColumnName("slot")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PreferenceId");
|
||||
|
||||
b.HasIndex("Slot", "PreferenceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Admin", "Admin")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Antags")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Preference", "Preference")
|
||||
.WithMany("Profiles")
|
||||
.HasForeignKey("PreferenceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
public partial class Admins : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_rank",
|
||||
columns: table => new
|
||||
{
|
||||
admin_rank_id = table.Column<int>(nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
name = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_rank", x => x.admin_rank_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin",
|
||||
columns: table => new
|
||||
{
|
||||
user_id = table.Column<Guid>(nullable: false),
|
||||
title = table.Column<string>(nullable: true),
|
||||
admin_rank_id = table.Column<int>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin", x => x.user_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_admin_rank_admin_rank_id",
|
||||
column: x => x.admin_rank_id,
|
||||
principalTable: "admin_rank",
|
||||
principalColumn: "admin_rank_id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_rank_flag",
|
||||
columns: table => new
|
||||
{
|
||||
admin_rank_flag_id = table.Column<int>(nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
flag = table.Column<string>(nullable: false),
|
||||
admin_rank_id = table.Column<int>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_rank_flag", x => x.admin_rank_flag_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_rank_flag_admin_rank_admin_rank_id",
|
||||
column: x => x.admin_rank_id,
|
||||
principalTable: "admin_rank",
|
||||
principalColumn: "admin_rank_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_flag",
|
||||
columns: table => new
|
||||
{
|
||||
admin_flag_id = table.Column<int>(nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
flag = table.Column<string>(nullable: false),
|
||||
negative = table.Column<bool>(nullable: false),
|
||||
admin_id = table.Column<Guid>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_flag", x => x.admin_flag_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_flag_admin_admin_id",
|
||||
column: x => x.admin_id,
|
||||
principalTable: "admin",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_admin_rank_id",
|
||||
table: "admin",
|
||||
column: "admin_rank_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_flag_admin_id",
|
||||
table: "admin_flag",
|
||||
column: "admin_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_rank_flag_admin_rank_id",
|
||||
table: "admin_rank_flag",
|
||||
column: "admin_rank_id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_flag");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_rank_flag");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_rank");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,98 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasAnnotation("ProductVersion", "3.1.4")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int?>("AdminRankId")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnName("title")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.ToTable("admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_flag_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnName("admin_id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnName("flag")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("Negative")
|
||||
.HasColumnName("negative")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AdminId");
|
||||
|
||||
b.ToTable("admin_flag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnName("name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("admin_rank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_rank_flag_id")
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnName("flag")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.ToTable("admin_rank_flag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -348,6 +440,32 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.ToTable("profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Admin", "Admin")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
|
||||
476
Content.Server.Database/Migrations/Sqlite/20201028210616_Admins.Designer.cs
generated
Normal file
476
Content.Server.Database/Migrations/Sqlite/20201028210616_Admins.Designer.cs
generated
Normal file
@@ -0,0 +1,476 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Content.Server.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
[DbContext(typeof(SqliteServerDbContext))]
|
||||
[Migration("20201028210616_Admins")]
|
||||
partial class Admins
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "3.1.4");
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("AdminRankId")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnName("title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.ToTable("admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_flag_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnName("admin_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnName("flag")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Negative")
|
||||
.HasColumnName("negative")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AdminId");
|
||||
|
||||
b.ToTable("admin_flag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnName("name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("admin_rank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_rank_flag_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnName("flag")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.ToTable("admin_rank_flag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("antag_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("AntagName")
|
||||
.IsRequired()
|
||||
.HasColumnName("antag_name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnName("profile_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProfileId", "AntagName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("antag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("assigned_user_id_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnName("user_name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("assigned_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("job_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
.HasColumnName("job_name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnName("priority")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ProfileId")
|
||||
.HasColumnName("profile_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProfileId");
|
||||
|
||||
b.ToTable("job");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("preference_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SelectedCharacterSlot")
|
||||
.HasColumnName("selected_character_slot")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("preference");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("profile_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnName("age")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CharacterName")
|
||||
.IsRequired()
|
||||
.HasColumnName("char_name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("EyeColor")
|
||||
.IsRequired()
|
||||
.HasColumnName("eye_color")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FacialHairColor")
|
||||
.IsRequired()
|
||||
.HasColumnName("facial_hair_color")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnName("facial_hair_name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnName("hair_color")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnName("hair_name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("PreferenceId")
|
||||
.HasColumnName("preference_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("PreferenceUnavailable")
|
||||
.HasColumnName("pref_unavailable")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.IsRequired()
|
||||
.HasColumnName("sex")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnName("skin_color")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Slot")
|
||||
.HasColumnName("slot")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PreferenceId");
|
||||
|
||||
b.HasIndex("Slot", "PreferenceId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteConnectionLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("connection_log_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnName("address")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("Time")
|
||||
.HasColumnName("time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnName("user_name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("connection_log");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqlitePlayer", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("player_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("FirstSeenTime")
|
||||
.HasColumnName("first_seen_time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LastSeenAddress")
|
||||
.IsRequired()
|
||||
.HasColumnName("last_seen_address")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastSeenTime")
|
||||
.HasColumnName("last_seen_time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LastSeenUserName")
|
||||
.IsRequired()
|
||||
.HasColumnName("last_seen_user_name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("ban_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnName("address")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("BanTime")
|
||||
.HasColumnName("ban_time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("BanningAdmin")
|
||||
.HasColumnName("banning_admin")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnName("expiration_time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.IsRequired()
|
||||
.HasColumnName("reason")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("unban_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BanId")
|
||||
.HasColumnName("ban_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UnbanTime")
|
||||
.HasColumnName("unban_time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("UnbanningAdmin")
|
||||
.HasColumnName("unbanning_admin")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BanId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("unban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Admin", "Admin")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Antags")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
.WithMany("Jobs")
|
||||
.HasForeignKey("ProfileId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Profile", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Preference", "Preference")
|
||||
.WithMany("Profiles")
|
||||
.HasForeignKey("PreferenceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
public partial class Admins : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_rank",
|
||||
columns: table => new
|
||||
{
|
||||
admin_rank_id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
name = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_rank", x => x.admin_rank_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin",
|
||||
columns: table => new
|
||||
{
|
||||
user_id = table.Column<Guid>(nullable: false),
|
||||
title = table.Column<string>(nullable: true),
|
||||
admin_rank_id = table.Column<int>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin", x => x.user_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_admin_rank_admin_rank_id",
|
||||
column: x => x.admin_rank_id,
|
||||
principalTable: "admin_rank",
|
||||
principalColumn: "admin_rank_id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_rank_flag",
|
||||
columns: table => new
|
||||
{
|
||||
admin_rank_flag_id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
flag = table.Column<string>(nullable: false),
|
||||
admin_rank_id = table.Column<int>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_rank_flag", x => x.admin_rank_flag_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_rank_flag_admin_rank_admin_rank_id",
|
||||
column: x => x.admin_rank_id,
|
||||
principalTable: "admin_rank",
|
||||
principalColumn: "admin_rank_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "admin_flag",
|
||||
columns: table => new
|
||||
{
|
||||
admin_flag_id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
flag = table.Column<string>(nullable: false),
|
||||
negative = table.Column<bool>(nullable: false),
|
||||
admin_id = table.Column<Guid>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_admin_flag", x => x.admin_flag_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_admin_flag_admin_admin_id",
|
||||
column: x => x.admin_id,
|
||||
principalTable: "admin",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_admin_rank_id",
|
||||
table: "admin",
|
||||
column: "admin_rank_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_flag_admin_id",
|
||||
table: "admin_flag",
|
||||
column: "admin_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_admin_rank_flag_admin_rank_id",
|
||||
table: "admin_rank_flag",
|
||||
column: "admin_rank_id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_flag");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_rank_flag");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "admin_rank");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,95 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "3.1.4");
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("user_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("AdminRankId")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnName("title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.ToTable("admin");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_flag_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("AdminId")
|
||||
.HasColumnName("admin_id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnName("flag")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Negative")
|
||||
.HasColumnName("negative")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AdminId");
|
||||
|
||||
b.ToTable("admin_flag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnName("name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("admin_rank");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("admin_rank_flag_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AdminRankId")
|
||||
.HasColumnName("admin_rank_id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Flag")
|
||||
.IsRequired()
|
||||
.HasColumnName("flag")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.ToTable("admin_rank_flag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -318,6 +407,32 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.ToTable("unban");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
|
||||
.WithMany("Admins")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Admin", "Admin")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.AdminRank", "Rank")
|
||||
.WithMany("Flags")
|
||||
.HasForeignKey("AdminRankId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Antag", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Profile", "Profile")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@@ -26,6 +27,8 @@ namespace Content.Server.Database
|
||||
public DbSet<Preference> Preference { get; set; } = null!;
|
||||
public DbSet<Profile> Profile { get; set; } = null!;
|
||||
public DbSet<AssignedUserId> AssignedUserId { get; set; } = null!;
|
||||
public DbSet<Admin> Admin { get; set; } = null!;
|
||||
public DbSet<AdminRank> AdminRank { get; set; } = null!;
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -49,6 +52,11 @@ namespace Content.Server.Database
|
||||
modelBuilder.Entity<AssignedUserId>()
|
||||
.HasIndex(p => p.UserId)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<Admin>()
|
||||
.HasOne(p => p.AdminRank)
|
||||
.WithMany(p => p!.Admins)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,4 +143,46 @@ namespace Content.Server.Database
|
||||
|
||||
[Column("user_id")] public Guid UserId { get; set; }
|
||||
}
|
||||
|
||||
[Table("admin")]
|
||||
public class Admin
|
||||
{
|
||||
[Column("user_id"), Key] public Guid UserId { get; set; }
|
||||
[Column("title")] public string? Title { get; set; }
|
||||
|
||||
[Column("admin_rank_id")] public int? AdminRankId { get; set; }
|
||||
public AdminRank? AdminRank { get; set; }
|
||||
public List<AdminFlag> Flags { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table("admin_flag")]
|
||||
public class AdminFlag
|
||||
{
|
||||
[Column("admin_flag_id")] public int Id { get; set; }
|
||||
[Column("flag")] public string Flag { get; set; } = default!;
|
||||
[Column("negative")] public bool Negative { get; set; }
|
||||
|
||||
[Column("admin_id")] public Guid AdminId { get; set; }
|
||||
public Admin Admin { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table("admin_rank")]
|
||||
public class AdminRank
|
||||
{
|
||||
[Column("admin_rank_id")] public int Id { get; set; }
|
||||
[Column("name")] public string Name { get; set; } = default!;
|
||||
|
||||
public List<Admin> Admins { get; set; } = default!;
|
||||
public List<AdminRankFlag> Flags { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table("admin_rank_flag")]
|
||||
public class AdminRankFlag
|
||||
{
|
||||
[Column("admin_rank_flag_id")] public int Id { get; set; }
|
||||
[Column("flag")] public string Flag { get; set; } = default!;
|
||||
|
||||
[Column("admin_rank_id")] public int AdminRankId { get; set; }
|
||||
public AdminRank Rank { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
|
||||
27
Content.Server/Administration/AdminCommandAttribute.cs
Normal file
27
Content.Server/Administration/AdminCommandAttribute.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Content.Shared.Administration;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies that a command can only be executed by an admin with the specified flags.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this attribute is used multiple times, either attribute's flag sets can be used to get access.
|
||||
/// </remarks>
|
||||
/// <seealso cref="AnyCommandAttribute"/>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
[BaseTypeRequired(typeof(IClientCommand))]
|
||||
[MeansImplicitUse]
|
||||
public sealed class AdminCommandAttribute : Attribute
|
||||
{
|
||||
public AdminCommandAttribute(AdminFlags flags)
|
||||
{
|
||||
Flags = flags;
|
||||
}
|
||||
|
||||
public AdminFlags Flags { get; }
|
||||
}
|
||||
}
|
||||
377
Content.Server/Administration/AdminManager.cs
Normal file
377
Content.Server/Administration/AdminManager.cs
Normal file
@@ -0,0 +1,377 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.Players;
|
||||
using Content.Shared;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Network.NetMessages;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Resources;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Utility;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Server.Administration
|
||||
{
|
||||
public sealed class AdminManager : IAdminManager, IPostInjectInit, IConGroupControllerImplementation
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IServerDbManager _dbManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IServerNetManager _netMgr = default!;
|
||||
[Dependency] private readonly IConGroupController _conGroup = default!;
|
||||
[Dependency] private readonly IResourceManager _res = default!;
|
||||
[Dependency] private readonly IConsoleShell _consoleShell = default!;
|
||||
|
||||
private readonly Dictionary<IPlayerSession, AdminReg> _admins = new Dictionary<IPlayerSession, AdminReg>();
|
||||
|
||||
public IEnumerable<IPlayerSession> ActiveAdmins => _admins
|
||||
.Where(p => p.Value.Data.Active)
|
||||
.Select(p => p.Key);
|
||||
|
||||
// If a command isn't in this list it's server-console only.
|
||||
// if a command is in but the flags value is null it's available to everybody.
|
||||
private readonly HashSet<string> _anyCommands = new HashSet<string>();
|
||||
private readonly Dictionary<string, AdminFlags[]> _adminCommands = new Dictionary<string, AdminFlags[]>();
|
||||
|
||||
public AdminData? GetAdminData(IPlayerSession session, bool includeDeAdmin = false)
|
||||
{
|
||||
if (_admins.TryGetValue(session, out var reg) && (reg.Data.Active || includeDeAdmin))
|
||||
{
|
||||
return reg.Data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void DeAdmin(IPlayerSession session)
|
||||
{
|
||||
if (!_admins.TryGetValue(session, out var reg))
|
||||
{
|
||||
throw new ArgumentException($"Player {session} is not an admin");
|
||||
}
|
||||
|
||||
if (!reg.Data.Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var plyData = session.ContentData()!;
|
||||
plyData.ExplicitlyDeadminned = true;
|
||||
reg.Data.Active = false;
|
||||
|
||||
// TODO: Send messages to all admins.
|
||||
|
||||
UpdateAdminStatus(session);
|
||||
}
|
||||
|
||||
public void ReAdmin(IPlayerSession session)
|
||||
{
|
||||
if (!_admins.TryGetValue(session, out var reg))
|
||||
{
|
||||
throw new ArgumentException($"Player {session} is not an admin");
|
||||
}
|
||||
|
||||
var plyData = session.ContentData()!;
|
||||
plyData.ExplicitlyDeadminned = true;
|
||||
reg.Data.Active = true;
|
||||
|
||||
// TODO: Send messages to all admins.
|
||||
|
||||
UpdateAdminStatus(session);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netMgr.RegisterNetMessage<MsgUpdateAdminStatus>(MsgUpdateAdminStatus.NAME);
|
||||
|
||||
// Cache permissions for loaded console commands with the requisite attributes.
|
||||
foreach (var (cmdName, cmd) in _consoleShell.AvailableCommands)
|
||||
{
|
||||
var (isAvail, flagsReq) = GetRequiredFlag(cmd);
|
||||
|
||||
if (!isAvail)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flagsReq.Length != 0)
|
||||
{
|
||||
_adminCommands.Add(cmdName, flagsReq);
|
||||
}
|
||||
else
|
||||
{
|
||||
_anyCommands.Add(cmdName);
|
||||
}
|
||||
}
|
||||
|
||||
// Load flags for engine commands, since those don't have the attributes.
|
||||
if (_res.TryContentFileRead(new ResourcePath("/engineCommandPerms.yml"), out var fs))
|
||||
{
|
||||
using var reader = new StreamReader(fs, EncodingHelpers.UTF8);
|
||||
var yStream = new YamlStream();
|
||||
yStream.Load(reader);
|
||||
var root = (YamlSequenceNode) yStream.Documents[0].RootNode;
|
||||
|
||||
foreach (var child in root)
|
||||
{
|
||||
var map = (YamlMappingNode) child;
|
||||
var commands = map.GetNode<YamlSequenceNode>("Commands").Select(p => p.AsString());
|
||||
if (map.TryGetNode("Flags", out var flagsNode))
|
||||
{
|
||||
var flagNames = flagsNode.AsString().Split(",", StringSplitOptions.RemoveEmptyEntries);
|
||||
var flags = AdminFlagsExt.NamesToFlags(flagNames);
|
||||
foreach (var cmd in commands)
|
||||
{
|
||||
if (!_adminCommands.TryGetValue(cmd, out var exFlags))
|
||||
{
|
||||
_adminCommands.Add(cmd, new []{flags});
|
||||
}
|
||||
else
|
||||
{
|
||||
var newArr = new AdminFlags[exFlags.Length + 1];
|
||||
exFlags.CopyTo(newArr, 0);
|
||||
exFlags[^1] = flags;
|
||||
_adminCommands[cmd] = newArr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_anyCommands.UnionWith(commands);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IPostInjectInit.PostInject()
|
||||
{
|
||||
_playerManager.PlayerStatusChanged += PlayerStatusChanged;
|
||||
_conGroup.Implementation = this;
|
||||
}
|
||||
|
||||
// NOTE: Also sends commands list for non admins..
|
||||
private void UpdateAdminStatus(IPlayerSession session)
|
||||
{
|
||||
var msg = _netMgr.CreateNetMessage<MsgUpdateAdminStatus>();
|
||||
|
||||
var commands = new List<string>(_anyCommands);
|
||||
|
||||
if (_admins.TryGetValue(session, out var adminData))
|
||||
{
|
||||
msg.Admin = adminData.Data;
|
||||
|
||||
commands.AddRange(_adminCommands
|
||||
.Where(p => p.Value.Any(f => adminData.Data.HasFlag(f)))
|
||||
.Select(p => p.Key));
|
||||
}
|
||||
|
||||
msg.AvailableCommands = commands.ToArray();
|
||||
|
||||
_netMgr.ServerSendMessage(msg, session.ConnectedClient);
|
||||
}
|
||||
|
||||
private void PlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
{
|
||||
if (e.NewStatus == SessionStatus.Connected)
|
||||
{
|
||||
// Run this so that available commands list gets sent.
|
||||
UpdateAdminStatus(e.Session);
|
||||
}
|
||||
else if (e.NewStatus == SessionStatus.InGame)
|
||||
{
|
||||
LoginAdminMaybe(e.Session);
|
||||
}
|
||||
else if (e.NewStatus == SessionStatus.Disconnected)
|
||||
{
|
||||
_admins.Remove(e.Session);
|
||||
}
|
||||
}
|
||||
|
||||
private async void LoginAdminMaybe(IPlayerSession session)
|
||||
{
|
||||
AdminReg reg;
|
||||
if (IsLocal(session) && _cfg.GetCVar(CCVars.ConsoleLoginLocal))
|
||||
{
|
||||
var data = new AdminData
|
||||
{
|
||||
Title = Loc.GetString("Host"),
|
||||
Flags = AdminFlagsExt.Everything,
|
||||
};
|
||||
|
||||
reg = new AdminReg(session, data)
|
||||
{
|
||||
IsSpecialLogin = true,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
var dbData = await _dbManager.GetAdminDataForAsync(session.UserId);
|
||||
|
||||
if (dbData == null)
|
||||
{
|
||||
// Not an admin!
|
||||
return;
|
||||
}
|
||||
|
||||
var flags = AdminFlags.None;
|
||||
|
||||
if (dbData.AdminRank != null)
|
||||
{
|
||||
flags = AdminFlagsExt.NamesToFlags(dbData.AdminRank.Flags.Select(p => p.Flag));
|
||||
}
|
||||
|
||||
foreach (var dbFlag in dbData.Flags)
|
||||
{
|
||||
var flag = AdminFlagsExt.NameToFlag(dbFlag.Flag);
|
||||
if (dbFlag.Negative)
|
||||
{
|
||||
flags &= ~flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags |= flag;
|
||||
}
|
||||
}
|
||||
|
||||
var data = new AdminData
|
||||
{
|
||||
Flags = flags
|
||||
};
|
||||
|
||||
if (dbData.Title != null)
|
||||
{
|
||||
data.Title = dbData.Title;
|
||||
}
|
||||
else if (dbData.AdminRank != null)
|
||||
{
|
||||
data.Title = dbData.AdminRank.Name;
|
||||
}
|
||||
|
||||
reg = new AdminReg(session, data);
|
||||
}
|
||||
|
||||
_admins.Add(session, reg);
|
||||
|
||||
if (!session.ContentData()!.ExplicitlyDeadminned)
|
||||
{
|
||||
reg.Data.Active = true;
|
||||
}
|
||||
|
||||
UpdateAdminStatus(session);
|
||||
}
|
||||
|
||||
private static bool IsLocal(IPlayerSession player)
|
||||
{
|
||||
var ep = player.ConnectedClient.RemoteEndPoint;
|
||||
var addr = ep.Address;
|
||||
if (addr.IsIPv4MappedToIPv6)
|
||||
{
|
||||
addr = addr.MapToIPv4();
|
||||
}
|
||||
|
||||
return Equals(addr, IPAddress.Loopback) || Equals(addr, IPAddress.IPv6Loopback);
|
||||
}
|
||||
|
||||
public bool CanCommand(IPlayerSession session, string cmdName)
|
||||
{
|
||||
if (_anyCommands.Contains(cmdName))
|
||||
{
|
||||
// Anybody can use this command.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_adminCommands.TryGetValue(cmdName, out var flagsReq))
|
||||
{
|
||||
// Server-console only.
|
||||
return false;
|
||||
}
|
||||
|
||||
var data = GetAdminData(session);
|
||||
if (data == null)
|
||||
{
|
||||
// Player isn't an admin.
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var flagReq in flagsReq)
|
||||
{
|
||||
if (data.HasFlag(flagReq))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static (bool isAvail, AdminFlags[] flagsReq) GetRequiredFlag(IClientCommand cmd)
|
||||
{
|
||||
var type = cmd.GetType();
|
||||
if (Attribute.IsDefined(type, typeof(AnyCommandAttribute)))
|
||||
{
|
||||
// Available to everybody.
|
||||
return (true, Array.Empty<AdminFlags>());
|
||||
}
|
||||
|
||||
var attribs = type.GetCustomAttributes(typeof(AdminCommandAttribute))
|
||||
.Cast<AdminCommandAttribute>()
|
||||
.Select(p => p.Flags)
|
||||
.ToArray();
|
||||
|
||||
// If attribs.length == 0 then no access attribute is specified,
|
||||
// and this is a server-only command.
|
||||
return (attribs.Length != 0, attribs);
|
||||
}
|
||||
|
||||
public bool CanViewVar(IPlayerSession session)
|
||||
{
|
||||
return GetAdminData(session)?.CanViewVar() ?? false;
|
||||
}
|
||||
|
||||
public bool CanAdminPlace(IPlayerSession session)
|
||||
{
|
||||
return GetAdminData(session)?.CanAdminPlace() ?? false;
|
||||
}
|
||||
|
||||
public bool CanScript(IPlayerSession session)
|
||||
{
|
||||
return GetAdminData(session)?.CanScript() ?? false;
|
||||
}
|
||||
|
||||
public bool CanAdminMenu(IPlayerSession session)
|
||||
{
|
||||
return GetAdminData(session)?.CanAdminMenu() ?? false;
|
||||
}
|
||||
|
||||
private sealed class AdminReg
|
||||
{
|
||||
public IPlayerSession Session;
|
||||
|
||||
public AdminData Data;
|
||||
|
||||
// Such as console.loginlocal
|
||||
// Means that stuff like permissions editing is blocked.
|
||||
public bool IsSpecialLogin;
|
||||
|
||||
public AdminReg(IPlayerSession session, AdminData data)
|
||||
{
|
||||
Data = data;
|
||||
Session = session;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Content.Server/Administration/AdminRank.cs
Normal file
18
Content.Server/Administration/AdminRank.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Content.Shared.Administration;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Server.Administration
|
||||
{
|
||||
public sealed class AdminRank
|
||||
{
|
||||
public AdminRank(string name, AdminFlags flags)
|
||||
{
|
||||
Name = name;
|
||||
Flags = flags;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public AdminFlags Flags { get; }
|
||||
}
|
||||
}
|
||||
18
Content.Server/Administration/AnyCommandAttribute.cs
Normal file
18
Content.Server/Administration/AnyCommandAttribute.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies that a command can be executed by any player.
|
||||
/// </summary>
|
||||
/// <seealso cref="AdminCommandAttribute"/>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
[BaseTypeRequired(typeof(IClientCommand))]
|
||||
[MeansImplicitUse]
|
||||
public sealed class AnyCommandAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
using Content.Server.GameObjects.Components.Observer;
|
||||
using Content.Server.Players;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public class AGhost : IClientCommand
|
||||
{
|
||||
public string Command => "aghost";
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using Content.Server.Database;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -8,8 +8,9 @@ using Robust.Shared.Network;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Server.Administration
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Ban)]
|
||||
public sealed class BanCommand : IClientCommand
|
||||
{
|
||||
public string Command => "ban";
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.Components.Observer;
|
||||
using Content.Server.Players;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -8,8 +9,9 @@ using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
class ControlMob : IClientCommand
|
||||
{
|
||||
public string Command => "controlmob";
|
||||
31
Content.Server/Administration/Commands/DeAdminCommand.cs
Normal file
31
Content.Server/Administration/Commands/DeAdminCommand.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Content.Shared.Administration;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Server.Administration
|
||||
{
|
||||
[UsedImplicitly]
|
||||
[AdminCommand(AdminFlags.None)]
|
||||
public class DeAdminCommand : IClientCommand
|
||||
{
|
||||
public string Command => "deadmin";
|
||||
public string Description => "Temporarily de-admins you so you can experience the round as a normal player.";
|
||||
public string Help => "Usage: deadmin\nUse readmin to re-admin after using this.";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
shell.SendText(player, "You cannot use this command from the server console.");
|
||||
return;
|
||||
}
|
||||
|
||||
var mgr = IoCManager.Resolve<IAdminManager>();
|
||||
mgr.DeAdmin(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -7,8 +8,9 @@ using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
class DeleteEntitiesWithComponent : IClientCommand
|
||||
{
|
||||
public string Command => "deleteewc";
|
||||
@@ -1,12 +1,14 @@
|
||||
#nullable enable
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public class DeleteEntitiesWithId : IClientCommand
|
||||
{
|
||||
public string Command => "deleteewi";
|
||||
35
Content.Server/Administration/Commands/ReAdminCommand.cs
Normal file
35
Content.Server/Administration/Commands/ReAdminCommand.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Server.Administration
|
||||
{
|
||||
[AnyCommand]
|
||||
public class ReAdminCommand : IClientCommand
|
||||
{
|
||||
public string Command => "readmin";
|
||||
public string Description => "Re-admins you if you previously de-adminned.";
|
||||
public string Help => "Usage: readmin";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
shell.SendText(player, "You cannot use this command from the server console.");
|
||||
return;
|
||||
}
|
||||
|
||||
var mgr = IoCManager.Resolve<IAdminManager>();
|
||||
|
||||
if (mgr.GetAdminData(player, includeDeAdmin: true) == null)
|
||||
{
|
||||
shell.SendText(player, "You're not an admin.");
|
||||
return;
|
||||
}
|
||||
|
||||
mgr.ReAdmin(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
#nullable enable
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
public class ReadyAll : IClientCommand
|
||||
{
|
||||
public string Command => "readyall";
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GlobalVerbs;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -6,8 +7,9 @@ using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
class Rejuvenate : IClientCommand
|
||||
{
|
||||
public string Command => "rejuvenate";
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Markers;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Enums;
|
||||
@@ -10,8 +11,9 @@ using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server.Administration
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public class WarpCommand : IClientCommand
|
||||
{
|
||||
public string Command => "warp";
|
||||
47
Content.Server/Administration/IAdminManager.cs
Normal file
47
Content.Server/Administration/IAdminManager.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Server.Administration
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages server administrators and their permission flags.
|
||||
/// </summary>
|
||||
public interface IAdminManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all active admins currently on the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This does not include admins that are de-adminned.
|
||||
/// </remarks>
|
||||
IEnumerable<IPlayerSession> ActiveAdmins { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the admin data for a player, if they are an admin.
|
||||
/// </summary>
|
||||
/// <param name="session">The player to get admin data for.</param>
|
||||
/// <param name="includeDeAdmin">
|
||||
/// Whether to return admin data for admins that are current de-adminned.
|
||||
/// </param>
|
||||
/// <returns><see langword="null" /> if the player is not an admin.</returns>
|
||||
AdminData? GetAdminData(IPlayerSession session, bool includeDeAdmin = false);
|
||||
|
||||
/// <summary>
|
||||
/// De-admins an admin temporarily so they are effectively a normal player.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// De-adminned admins are able to re-admin at any time if they so desire.
|
||||
/// </remarks>
|
||||
void DeAdmin(IPlayerSession session);
|
||||
|
||||
/// <summary>
|
||||
/// Re-admins a de-adminned admin.
|
||||
/// </summary>
|
||||
void ReAdmin(IPlayerSession session);
|
||||
|
||||
void Initialize();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.Atmos;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Server.GameObjects.EntitySystems.Atmos;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Atmos;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
@@ -15,6 +17,7 @@ using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Server.Atmos
|
||||
{
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class AddAtmos : IClientCommand
|
||||
{
|
||||
public string Command => "addatmos";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
using Content.Server.GameObjects.Components.Observer;
|
||||
@@ -8,6 +9,7 @@ using Content.Server.Interfaces.GameObjects;
|
||||
using Content.Server.Observer;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Utility;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.Interfaces;
|
||||
@@ -20,6 +22,7 @@ using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.Chat
|
||||
{
|
||||
[AnyCommand]
|
||||
internal class SayCommand : IClientCommand
|
||||
{
|
||||
public string Command => "say";
|
||||
@@ -51,6 +54,7 @@ namespace Content.Server.Chat
|
||||
}
|
||||
}
|
||||
|
||||
[AnyCommand]
|
||||
internal class MeCommand : IClientCommand
|
||||
{
|
||||
public string Command => "me";
|
||||
@@ -76,6 +80,7 @@ namespace Content.Server.Chat
|
||||
}
|
||||
}
|
||||
|
||||
[AnyCommand]
|
||||
internal class OOCCommand : IClientCommand
|
||||
{
|
||||
public string Command => "ooc";
|
||||
@@ -96,6 +101,7 @@ namespace Content.Server.Chat
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
internal class AdminChatCommand : IClientCommand
|
||||
{
|
||||
public string Command => "asay";
|
||||
@@ -116,6 +122,7 @@ namespace Content.Server.Chat
|
||||
}
|
||||
}
|
||||
|
||||
[AnyCommand]
|
||||
internal class SuicideCommand : IClientCommand
|
||||
{
|
||||
public string Command => "suicide";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
using Content.Server.GameObjects.Components.Headset;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
@@ -12,7 +12,6 @@ using Content.Shared.Chat;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
@@ -47,7 +46,7 @@ namespace Content.Server.Chat
|
||||
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IMoMMILink _mommiLink = default!;
|
||||
[Dependency] private readonly IConGroupController _conGroupController = default!;
|
||||
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
@@ -231,12 +230,7 @@ namespace Content.Server.Chat
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_conGroupController.CanCommand(player, "asay"))
|
||||
{
|
||||
SendOOC(player, message);
|
||||
return;
|
||||
}
|
||||
var clients = _playerManager.GetPlayersBy(x => _conGroupController.CanCommand(x, "asay")).Select(p => p.ConnectedClient);;
|
||||
var clients = _adminManager.ActiveAdmins.Select(p => p.ConnectedClient);
|
||||
|
||||
var msg = _netManager.CreateNetMessage<MsgChatMessage>();
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#nullable enable
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.Body.Part;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.GameObjects.Components.Body;
|
||||
using Content.Shared.GameObjects.Components.Body.Part;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
@@ -10,6 +12,7 @@ using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public class AttachBodyPartCommand : IClientCommand
|
||||
{
|
||||
public string Command => "attachbodypart";
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#nullable enable
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Server.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class HideContainedContextCommand : IClientCommand
|
||||
{
|
||||
public string Command => "hidecontainedcontext";
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#nullable enable
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Server.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class ShowContainedContextCommand : IClientCommand
|
||||
{
|
||||
public const string CommandName = "showcontainedcontext";
|
||||
|
||||
@@ -217,6 +217,15 @@ namespace Content.Server.Database
|
||||
*/
|
||||
public abstract Task AddConnectionLogAsync(NetUserId userId, string userName, IPAddress address);
|
||||
|
||||
/*
|
||||
* ADMIN STUFF
|
||||
*/
|
||||
public async Task<Admin?> GetAdminDataForAsync(NetUserId userId)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
return await db.DbContext.Admin.SingleOrDefaultAsync(p => p.UserId == userId.UserId);
|
||||
}
|
||||
|
||||
protected abstract Task<DbGuard> GetDb();
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ namespace Content.Server.Database
|
||||
|
||||
// Connection log
|
||||
Task AddConnectionLogAsync(NetUserId userId, string userName, IPAddress address);
|
||||
|
||||
// Admins
|
||||
Task<Admin?> GetAdminDataForAsync(NetUserId userId);
|
||||
}
|
||||
|
||||
public sealed class ServerDbManager : IServerDbManager
|
||||
@@ -137,6 +140,11 @@ namespace Content.Server.Database
|
||||
return _db.AddConnectionLogAsync(userId, userName, address);
|
||||
}
|
||||
|
||||
public Task<Admin?> GetAdminDataForAsync(NetUserId userId)
|
||||
{
|
||||
return _db.GetAdminDataForAsync(userId);
|
||||
}
|
||||
|
||||
private DbContextOptions<ServerDbContext> CreatePostgresOptions()
|
||||
{
|
||||
var host = _cfg.GetCVar(CCVars.DatabasePgHost);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.AI.Utility.Considerations;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.AI.Utility.Considerations;
|
||||
using Content.Server.AI.WorldState;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.GameObjects.Components.Mobs.Speech;
|
||||
@@ -77,6 +78,7 @@ namespace Content.Server
|
||||
IoCManager.Resolve<BlackboardManager>().Initialize();
|
||||
IoCManager.Resolve<ConsiderationsManager>().Initialize();
|
||||
IoCManager.Resolve<IPDAUplinkManager>().Initialize();
|
||||
IoCManager.Resolve<IAdminManager>().Initialize();
|
||||
}
|
||||
|
||||
public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.GameObjects.Components.Body;
|
||||
using Content.Shared.GameObjects.Components.Body.Part;
|
||||
@@ -16,6 +18,7 @@ using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Body
|
||||
{
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
class AddHandCommand : IClientCommand
|
||||
{
|
||||
public const string DefaultHandPrototype = "LeftHandHuman";
|
||||
@@ -149,6 +152,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
class RemoveHandCommand : IClientCommand
|
||||
{
|
||||
public string Command => "removehand";
|
||||
@@ -190,6 +194,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
class DestroyMechanismCommand : IClientCommand
|
||||
{
|
||||
public string Command => "destroymechanism";
|
||||
@@ -242,6 +247,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
class HurtCommand : IClientCommand
|
||||
{
|
||||
public string Command => "hurt";
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.Atmos;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
@@ -115,6 +117,7 @@ namespace Content.Server.GameObjects.Components.Damage
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public class AddDamageFlagCommand : DamageFlagCommand
|
||||
{
|
||||
public override string Command => "adddamageflag";
|
||||
@@ -133,6 +136,7 @@ namespace Content.Server.GameObjects.Components.Damage
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public class RemoveDamageFlagCommand : DamageFlagCommand
|
||||
{
|
||||
public override string Command => "removedamageflag";
|
||||
@@ -151,6 +155,7 @@ namespace Content.Server.GameObjects.Components.Damage
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public class GodModeCommand : IClientCommand
|
||||
{
|
||||
public string Command => "godmode";
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#nullable enable
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -8,6 +10,7 @@ using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Disposal
|
||||
{
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class TubeConnectionsCommand : IClientCommand
|
||||
{
|
||||
public string Command => "tubeconnections";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#nullable enable
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Maps;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
@@ -14,7 +16,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
||||
/// <summary>
|
||||
/// <see cref="TilePryingComponent.TryPryTile"/>
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
class TilePryCommand : IClientCommand
|
||||
{
|
||||
public string Command => "tilepry";
|
||||
@@ -69,7 +71,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
||||
}
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
class AnchorCommand : IClientCommand
|
||||
{
|
||||
public string Command => "anchor";
|
||||
@@ -114,7 +116,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
||||
}
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
class UnAnchorCommand : IClientCommand
|
||||
{
|
||||
public string Command => "unanchor";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
@@ -17,6 +19,7 @@ namespace Content.Server.GameObjects.Components.Mobs.Speech
|
||||
public string Accentuate(string message);
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public class AddAccent : IClientCommand
|
||||
{
|
||||
public string Command => "addaccent";
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Content.Server.GameObjects.Components.Observer
|
||||
{
|
||||
if (player.AttachedEntity != null && warp.PlayerTarget == player.AttachedEntity.Uid)
|
||||
{
|
||||
session?.AttachedEntity!.Transform.Coordinates =
|
||||
session!.AttachedEntity!.Transform.Coordinates =
|
||||
player.AttachedEntity.Transform.Coordinates;
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ namespace Content.Server.GameObjects.Components.Observer
|
||||
{
|
||||
if (warp.WarpName == warpPoint.Location)
|
||||
{
|
||||
session?.AttachedEntity!.Transform.Coordinates = warpPoint.Owner.Transform.Coordinates ;
|
||||
session!.AttachedEntity!.Transform.Coordinates = warpPoint.Owner.Transform.Coordinates ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.AI;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
@@ -90,6 +92,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public sealed class FactionCommand : IClientCommand
|
||||
{
|
||||
public string Command => "factions";
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.Movement;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.GameObjects.Components.Movement;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.AI;
|
||||
@@ -145,6 +147,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI
|
||||
public bool ProcessorTypeExists(string name) => _processorTypes.ContainsKey(name);
|
||||
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
private class AddAiCommand : IClientCommand
|
||||
{
|
||||
public string Command => "addai";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.MachineLinking;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -96,6 +98,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class SignalLinkerCommand : IClientCommand
|
||||
{
|
||||
public string Command => "signallink";
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.Access;
|
||||
using Content.Server.GameObjects.Components.GUI;
|
||||
using Content.Server.GameObjects.Components.Items.Storage;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Content.Server.Players;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
@@ -18,6 +20,7 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameTicking
|
||||
{
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
class DelayStartCommand : IClientCommand
|
||||
{
|
||||
public string Command => "delaystart";
|
||||
@@ -60,6 +63,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
class StartRoundCommand : IClientCommand
|
||||
{
|
||||
public string Command => "startround";
|
||||
@@ -80,6 +84,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
class EndRoundCommand : IClientCommand
|
||||
{
|
||||
public string Command => "endround";
|
||||
@@ -100,6 +105,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
public class NewRoundCommand : IClientCommand
|
||||
{
|
||||
public string Command => "restartround";
|
||||
@@ -165,6 +171,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AnyCommand]
|
||||
class ObserveCommand : IClientCommand
|
||||
{
|
||||
public string Command => "observe";
|
||||
@@ -183,6 +190,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AnyCommand]
|
||||
class JoinGameCommand : IClientCommand
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
@@ -228,6 +236,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AnyCommand]
|
||||
class ToggleReadyCommand : IClientCommand
|
||||
{
|
||||
public string Command => "toggleready";
|
||||
@@ -246,6 +255,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
class ToggleDisallowLateJoinCommand: IClientCommand
|
||||
{
|
||||
public string Command => "toggledisallowlatejoin";
|
||||
@@ -274,6 +284,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
class SetGamePresetCommand : IClientCommand
|
||||
{
|
||||
public string Command => "setgamepreset";
|
||||
@@ -294,6 +305,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
class ForcePresetCommand : IClientCommand
|
||||
{
|
||||
public string Command => "forcepreset";
|
||||
@@ -327,6 +339,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Server | AdminFlags.Mapping)]
|
||||
class MappingCommand : IClientCommand
|
||||
{
|
||||
public string Command => "mapping";
|
||||
@@ -383,6 +396,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Mapping)]
|
||||
class TileWallsCommand : IClientCommand
|
||||
{
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Text;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.Mobs.Roles;
|
||||
using Content.Server.Players;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
@@ -12,6 +14,7 @@ using Robust.Shared.Prototypes;
|
||||
namespace Content.Server.Mobs
|
||||
{
|
||||
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public class MindInfoCommand : IClientCommand
|
||||
{
|
||||
public string Command => "mindinfo";
|
||||
@@ -49,6 +52,7 @@ namespace Content.Server.Mobs
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public class AddRoleCommand : IClientCommand
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
@@ -81,6 +85,7 @@ namespace Content.Server.Mobs
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public class RemoveRoleCommand : IClientCommand
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
@@ -113,6 +118,7 @@ namespace Content.Server.Mobs
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class AddOverlayCommand : IClientCommand
|
||||
{
|
||||
public string Command => "addoverlay";
|
||||
@@ -137,6 +143,7 @@ namespace Content.Server.Mobs
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class RemoveOverlayCommand : IClientCommand
|
||||
{
|
||||
public string Command => "rmoverlay";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.Components.Observer;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
@@ -12,6 +13,7 @@ using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Observer
|
||||
{
|
||||
[AnyCommand]
|
||||
public class Ghost : IClientCommand
|
||||
{
|
||||
public string Command => "ghost";
|
||||
|
||||
@@ -25,6 +25,12 @@ namespace Content.Server.Players
|
||||
[ViewVariables]
|
||||
public Mind? Mind { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the player is an admin and they explicitly de-adminned mid-game,
|
||||
/// so they should not regain admin if they reconnect.
|
||||
/// </summary>
|
||||
public bool ExplicitlyDeadminned { get; set; }
|
||||
|
||||
public void WipeMind()
|
||||
{
|
||||
Mind?.ChangeOwningPlayer(null);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.AI.Utility.Considerations;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.AI.Utility.Considerations;
|
||||
using Content.Server.AI.WorldState;
|
||||
using Content.Server.Cargo;
|
||||
using Content.Server.Chat;
|
||||
@@ -44,6 +45,7 @@ namespace Content.Server
|
||||
IoCManager.Register<ConsiderationsManager, ConsiderationsManager>();
|
||||
IoCManager.Register<IAccentManager, AccentManager>();
|
||||
IoCManager.Register<IConnectionManager, ConnectionManager>();
|
||||
IoCManager.Register<IAdminManager, AdminManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Shared;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Interfaces;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
@@ -71,6 +73,7 @@ namespace Content.Server
|
||||
_netManager.ServerSendMessage(netMessage, actor.playerSession.ConnectedClient);
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class PopupMsgCommand : IClientCommand
|
||||
{
|
||||
public string Command => "srvpopupmsg";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#nullable enable
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameObjects.EntitySystems.StationEvents;
|
||||
using JetBrains.Annotations;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
@@ -8,7 +9,7 @@ using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.StationEvents
|
||||
{
|
||||
[UsedImplicitly]
|
||||
[AdminCommand(AdminFlags.Server)]
|
||||
public sealed class StationEventCommand : IClientCommand
|
||||
{
|
||||
public string Command => "events";
|
||||
|
||||
39
Content.Shared/Administration/AdminData.cs
Normal file
39
Content.Shared/Administration/AdminData.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Shared.Administration
|
||||
{
|
||||
public sealed class AdminData
|
||||
{
|
||||
public const string DefaultTitle = "Admin";
|
||||
|
||||
// Can be false if they're de-adminned with the ability to re-admin.
|
||||
public bool Active;
|
||||
public string? Title;
|
||||
public AdminFlags Flags;
|
||||
|
||||
public bool HasFlag(AdminFlags flag)
|
||||
{
|
||||
return Active && (Flags & flag) == flag;
|
||||
}
|
||||
|
||||
public bool CanViewVar()
|
||||
{
|
||||
return HasFlag(AdminFlags.VarEdit);
|
||||
}
|
||||
|
||||
public bool CanAdminPlace()
|
||||
{
|
||||
return HasFlag(AdminFlags.Spawn);
|
||||
}
|
||||
|
||||
public bool CanScript()
|
||||
{
|
||||
return HasFlag(AdminFlags.Host);
|
||||
}
|
||||
|
||||
public bool CanAdminMenu()
|
||||
{
|
||||
return HasFlag(AdminFlags.Admin);
|
||||
}
|
||||
}
|
||||
}
|
||||
68
Content.Shared/Administration/AdminFlags.cs
Normal file
68
Content.Shared/Administration/AdminFlags.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
|
||||
namespace Content.Shared.Administration
|
||||
{
|
||||
/// <summary>
|
||||
/// Permissions that admins can have.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum AdminFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Basic admin verbs.
|
||||
/// </summary>
|
||||
Admin = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// Ability to ban people.
|
||||
/// </summary>
|
||||
Ban = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// Debug commands for coders.
|
||||
/// </summary>
|
||||
Debug = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// !!FUN!!
|
||||
/// </summary>
|
||||
Fun = 1 << 3,
|
||||
|
||||
/// <summary>
|
||||
/// Ability to edit permissions for other administrators.
|
||||
/// </summary>
|
||||
Permissions = 1 << 4,
|
||||
|
||||
/// <summary>
|
||||
/// Ability to control teh server like restart it or change the round type.
|
||||
/// </summary>
|
||||
Server = 1 << 5,
|
||||
|
||||
/// <summary>
|
||||
/// Ability to spawn stuff in.
|
||||
/// </summary>
|
||||
Spawn = 1 << 6,
|
||||
|
||||
/// <summary>
|
||||
/// Ability to use VV.
|
||||
/// </summary>
|
||||
VarEdit = 1 << 7,
|
||||
|
||||
/// <summary>
|
||||
/// Large mapping operations.
|
||||
/// </summary>
|
||||
Mapping = 1 << 8,
|
||||
|
||||
/// <summary>
|
||||
/// Makes you british.
|
||||
/// </summary>
|
||||
Piss = 1 << 9,
|
||||
|
||||
/// <summary>
|
||||
/// Dangerous host permissions like scsi.
|
||||
/// </summary>
|
||||
Host = 1u << 31,
|
||||
}
|
||||
}
|
||||
73
Content.Shared/Administration/AdminFlagsExt.cs
Normal file
73
Content.Shared/Administration/AdminFlagsExt.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Shared.Administration
|
||||
{
|
||||
public static class AdminFlagsExt
|
||||
{
|
||||
private static readonly Dictionary<string, AdminFlags> NameFlagsMap = new Dictionary<string, AdminFlags>();
|
||||
private static readonly string[] FlagsNameMap = new string[32];
|
||||
|
||||
public static readonly AdminFlags Everything;
|
||||
|
||||
static AdminFlagsExt()
|
||||
{
|
||||
var t = typeof(AdminFlags);
|
||||
var flags = (AdminFlags[]) Enum.GetValues(t);
|
||||
|
||||
foreach (var value in flags)
|
||||
{
|
||||
var name = value.ToString().ToUpper();
|
||||
|
||||
if (BitOperations.PopCount((uint) value) != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Everything |= value;
|
||||
NameFlagsMap.Add(name, value);
|
||||
FlagsNameMap[BitOperations.Log2((uint) value)] = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static AdminFlags NamesToFlags(IEnumerable<string> names)
|
||||
{
|
||||
var flags = AdminFlags.None;
|
||||
foreach (var name in names)
|
||||
{
|
||||
if (!NameFlagsMap.TryGetValue(name, out var value))
|
||||
{
|
||||
throw new ArgumentException($"Invalid admin flag name: {name}");
|
||||
}
|
||||
|
||||
flags |= value;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public static AdminFlags NameToFlag(string name)
|
||||
{
|
||||
return NameFlagsMap[name];
|
||||
}
|
||||
|
||||
public static string[] FlagsToNames(AdminFlags flags)
|
||||
{
|
||||
var array = new string[BitOperations.PopCount((uint) flags)];
|
||||
var highest = BitOperations.LeadingZeroCount((uint) flags);
|
||||
|
||||
var ai = 0;
|
||||
for (var i = 0; i < 32 - highest; i++)
|
||||
{
|
||||
var flagValue = (AdminFlags) (1u << i);
|
||||
if ((flags & flagValue) != 0)
|
||||
{
|
||||
array[ai++] = FlagsNameMap[i];
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,9 @@ namespace Content.Shared
|
||||
public static readonly CVarDef<bool>
|
||||
GamePersistGuests = CVarDef.Create("game.persistguests", true, CVar.ARCHIVE | CVar.SERVERONLY);
|
||||
|
||||
public static readonly CVarDef<bool>
|
||||
ConsoleLoginLocal = CVarDef.Create("console.loginlocal", true, CVar.ARCHIVE);
|
||||
|
||||
|
||||
/*
|
||||
* Database stuff
|
||||
|
||||
73
Content.Shared/Network/NetMessages/MsgUpdateAdminStatus.cs
Normal file
73
Content.Shared/Network/NetMessages/MsgUpdateAdminStatus.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using Content.Shared.Administration;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared.Network.NetMessages
|
||||
{
|
||||
public sealed class MsgUpdateAdminStatus : NetMessage
|
||||
{
|
||||
#region REQUIRED
|
||||
|
||||
public const MsgGroups GROUP = MsgGroups.Command;
|
||||
public const string NAME = nameof(MsgUpdateAdminStatus);
|
||||
|
||||
public MsgUpdateAdminStatus(INetChannel channel) : base(NAME, GROUP) { }
|
||||
|
||||
#endregion
|
||||
|
||||
public AdminData Admin;
|
||||
public string[] AvailableCommands;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer)
|
||||
{
|
||||
var count = buffer.ReadVariableInt32();
|
||||
|
||||
AvailableCommands = new string[count];
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
AvailableCommands[i] = buffer.ReadString();
|
||||
}
|
||||
|
||||
if (buffer.ReadBoolean())
|
||||
{
|
||||
var active = buffer.ReadBoolean();
|
||||
buffer.ReadPadBits();
|
||||
var flags = (AdminFlags) buffer.ReadUInt32();
|
||||
var title = buffer.ReadString();
|
||||
|
||||
Admin = new AdminData
|
||||
{
|
||||
Active = active,
|
||||
Title = title,
|
||||
Flags = flags,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer)
|
||||
{
|
||||
buffer.WriteVariableInt32(AvailableCommands.Length);
|
||||
|
||||
foreach (var cmd in AvailableCommands)
|
||||
{
|
||||
buffer.Write(cmd);
|
||||
}
|
||||
|
||||
var isAdmin = Admin != null;
|
||||
buffer.Write(isAdmin);
|
||||
|
||||
if (isAdmin)
|
||||
{
|
||||
buffer.Write(Admin.Active);
|
||||
buffer.WritePadBits();
|
||||
buffer.Write((uint) Admin.Flags);
|
||||
buffer.Write(Admin.Title);
|
||||
}
|
||||
}
|
||||
|
||||
public override NetDeliveryMethod DeliveryMethod => NetDeliveryMethod.ReliableOrdered;
|
||||
}
|
||||
}
|
||||
35
Content.Tests/Shared/Administration/AdminFlagsExtTest.cs
Normal file
35
Content.Tests/Shared/Administration/AdminFlagsExtTest.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using Content.Shared.Administration;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Content.Tests.Shared.Administration
|
||||
{
|
||||
[TestFixture]
|
||||
[Parallelizable(ParallelScope.All)]
|
||||
public class AdminFlagsExtTest
|
||||
{
|
||||
[Test]
|
||||
[TestCase("ADMIN", AdminFlags.Admin)]
|
||||
[TestCase("ADMIN,DEBUG", AdminFlags.Admin | AdminFlags.Debug)]
|
||||
[TestCase("ADMIN,DEBUG,HOST", AdminFlags.Admin | AdminFlags.Debug | AdminFlags.Host)]
|
||||
[TestCase("", AdminFlags.None)]
|
||||
public void TestNamesToFlags(string namesConcat, AdminFlags flags)
|
||||
{
|
||||
var names = namesConcat.Split(",", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
Assert.That(AdminFlagsExt.NamesToFlags(names), Is.EqualTo(flags));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("ADMIN", AdminFlags.Admin)]
|
||||
[TestCase("ADMIN,DEBUG", AdminFlags.Admin | AdminFlags.Debug)]
|
||||
[TestCase("ADMIN,DEBUG,HOST", AdminFlags.Admin | AdminFlags.Debug | AdminFlags.Host)]
|
||||
[TestCase("", AdminFlags.None)]
|
||||
public void TestFlagsToNames(string namesConcat, AdminFlags flags)
|
||||
{
|
||||
var names = namesConcat.Split(",", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
Assert.That(AdminFlagsExt.FlagsToNames(flags), Is.EquivalentTo(names));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
- Index: 1
|
||||
Name: Player
|
||||
Commands:
|
||||
- login
|
||||
- joingame
|
||||
- help
|
||||
- list
|
||||
- say
|
||||
- whisper
|
||||
- me
|
||||
- ooc
|
||||
- observe
|
||||
- toggleready
|
||||
- ghost
|
||||
- suicide
|
||||
- hostlogin
|
||||
|
||||
- Index: 50
|
||||
Name: Moderator
|
||||
Commands:
|
||||
- login
|
||||
- logout
|
||||
- joingame
|
||||
- help
|
||||
- list
|
||||
- say
|
||||
- whisper
|
||||
- me
|
||||
- ooc
|
||||
- showtime
|
||||
- observe
|
||||
- toggleready
|
||||
- ghost
|
||||
- suicide
|
||||
- kick
|
||||
- listplayers
|
||||
- loc
|
||||
- hostlogin
|
||||
- events
|
||||
- factions
|
||||
CanAdminMenu: true
|
||||
|
||||
- Index: 100
|
||||
Name: Administrator
|
||||
Commands:
|
||||
- logout
|
||||
- joingame
|
||||
- help
|
||||
- list
|
||||
- say
|
||||
- whisper
|
||||
- me
|
||||
- ooc
|
||||
- showtime
|
||||
- aghost
|
||||
- observe
|
||||
- toggleready
|
||||
- ghost
|
||||
- suicide
|
||||
- spawn
|
||||
- delete
|
||||
- tp
|
||||
- tpgrid
|
||||
- setgamepreset
|
||||
- forcepreset
|
||||
- delaystart
|
||||
- startround
|
||||
- endround
|
||||
- restartround
|
||||
- respawn
|
||||
- rejuvenate
|
||||
- addcomp
|
||||
- rmcomp
|
||||
- controlmob
|
||||
- kick
|
||||
- listplayers
|
||||
- loc
|
||||
- lsmap
|
||||
- lsgrid
|
||||
- mindinfo
|
||||
- addrole
|
||||
- rmrole
|
||||
- addoverlay
|
||||
- rmoverlay
|
||||
- showtime
|
||||
- group
|
||||
- addai
|
||||
- warp
|
||||
- hostlogin
|
||||
- deleteewc
|
||||
- asay
|
||||
- mapping
|
||||
- addhand
|
||||
- removehand
|
||||
- tilepry
|
||||
- anchor
|
||||
- unanchor
|
||||
- tubeconnections
|
||||
- tilewalls
|
||||
- events
|
||||
- destroymechanism
|
||||
- addaccent
|
||||
- readyall
|
||||
- factions
|
||||
- signallink
|
||||
- adddamageflag
|
||||
- removedamageflag
|
||||
- godmode
|
||||
- deleteewi
|
||||
- hurt
|
||||
- toggledisallowlatejoin
|
||||
- showcontainedcontext
|
||||
- hidecontainedcontext
|
||||
- showmechanisms
|
||||
- hidemechanisms
|
||||
- attachbodypart
|
||||
- attachtoself
|
||||
- attachtogrid
|
||||
- attachtograndparent
|
||||
CanViewVar: true
|
||||
CanAdminPlace: true
|
||||
CanAdminMenu: true
|
||||
|
||||
- Index: 200
|
||||
Name: Host
|
||||
Commands:
|
||||
- logout
|
||||
- joingame
|
||||
- help
|
||||
- list
|
||||
- say
|
||||
- whisper
|
||||
- me
|
||||
- ooc
|
||||
- showtime
|
||||
- aghost
|
||||
- observe
|
||||
- toggleready
|
||||
- ghost
|
||||
- suicide
|
||||
- spawn
|
||||
- delete
|
||||
- tp
|
||||
- tpgrid
|
||||
- setgamepreset
|
||||
- forcepreset
|
||||
- delaystart
|
||||
- startround
|
||||
- endround
|
||||
- restartround
|
||||
- respawn
|
||||
- rejuvenate
|
||||
- addcomp
|
||||
- controlmob
|
||||
- kick
|
||||
- listplayers
|
||||
- loc
|
||||
- lsmap
|
||||
- lsgrid
|
||||
- mindinfo
|
||||
- addrole
|
||||
- rmrole
|
||||
- addoverlay
|
||||
- rmoverlay
|
||||
- srvpopupmsg
|
||||
- group
|
||||
- showtime
|
||||
- restart
|
||||
- cvar
|
||||
- netaudit
|
||||
- szr_stats
|
||||
- mem
|
||||
- addai
|
||||
- loglevel
|
||||
- testlog
|
||||
- addmap
|
||||
- rmmap
|
||||
- savebp
|
||||
- loadbp
|
||||
- savemap
|
||||
- loadmap
|
||||
- pausemap
|
||||
- unpausemap
|
||||
- querymappaused
|
||||
- mapinit
|
||||
- saveconfig
|
||||
- gc
|
||||
- gc_mode
|
||||
- warp
|
||||
- deleteewc
|
||||
- sudo
|
||||
- asay
|
||||
- mapping
|
||||
- addhand
|
||||
- removehand
|
||||
- tilepry
|
||||
- anchor
|
||||
- unanchor
|
||||
- tubeconnections
|
||||
- addatmos
|
||||
- addgas
|
||||
- fillgas
|
||||
- listgases
|
||||
- removegas
|
||||
- settemp
|
||||
- setatmostemp
|
||||
- deletegas
|
||||
- showatmos
|
||||
- tilewalls
|
||||
- events
|
||||
- destroymechanism
|
||||
- addaccent
|
||||
- readyall
|
||||
- factions
|
||||
- signallink
|
||||
- adddamageflag
|
||||
- removedamageflag
|
||||
- godmode
|
||||
- deleteewi
|
||||
- hurt
|
||||
- toggledisallowlatejoin
|
||||
- showcontainedcontext
|
||||
- hidecontainedcontext
|
||||
- showmechanisms
|
||||
- hidemechanisms
|
||||
- attachbodypart
|
||||
- attachtoself
|
||||
- attachtogrid
|
||||
- attachtograndparent
|
||||
CanViewVar: true
|
||||
CanAdminPlace: true
|
||||
CanScript: true
|
||||
CanAdminMenu: true
|
||||
63
Resources/engineCommandPerms.yml
Normal file
63
Resources/engineCommandPerms.yml
Normal file
@@ -0,0 +1,63 @@
|
||||
# Available to everybody
|
||||
- Commands:
|
||||
- help
|
||||
- list
|
||||
|
||||
- Flags: FUN
|
||||
Commands:
|
||||
- addcomp
|
||||
- rmcomp
|
||||
|
||||
- Flags: DEBUG
|
||||
Commands:
|
||||
- delete
|
||||
- lsgrid
|
||||
- lsmap
|
||||
- listplayers
|
||||
- loc
|
||||
- mem
|
||||
- netaudit
|
||||
- querymappaused
|
||||
- showtime
|
||||
|
||||
- Flags: MAPPING
|
||||
Commands:
|
||||
- addmap
|
||||
- loadbp
|
||||
- loadmap
|
||||
- pausemap
|
||||
- querymappaused
|
||||
- rmgrid
|
||||
- rmmap
|
||||
- mapinit
|
||||
- savebp
|
||||
- savemap
|
||||
- tpgrid
|
||||
|
||||
- Flags: ADMIN
|
||||
Commands:
|
||||
- delete
|
||||
- kick
|
||||
- listplayers
|
||||
- teleport
|
||||
|
||||
- Flags: SERVER
|
||||
Commands:
|
||||
- delete
|
||||
- pausemap
|
||||
- unpausemap
|
||||
- restart
|
||||
- shutdown
|
||||
|
||||
- Flags: SPAWN
|
||||
Commands:
|
||||
- spawn
|
||||
|
||||
- Flags: HOST
|
||||
Commands:
|
||||
- gc_mode
|
||||
- gc
|
||||
- loglevel
|
||||
- saveconfig
|
||||
- testlog
|
||||
- sudo
|
||||
@@ -63,6 +63,7 @@
|
||||
<s:String x:Key="/Default/FilterSettingsManager/AttributeFilterXml/@EntryValue"><data /></s:String>
|
||||
<s:String x:Key="/Default/FilterSettingsManager/CoverageFilterXml/@EntryValue"><data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="*.UnitTesting" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /></ExcludeFilters></data></s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=adminbus/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=adminned/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Aghost/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=akms/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Anchorable/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
Reference in New Issue
Block a user