mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-30 08:33:19 +01:00
Slowly coming together
This commit is contained in:
@@ -7,7 +7,6 @@ namespace Tgstation.Server.Api.Models
|
||||
/// <summary>
|
||||
/// Metadata about an installation
|
||||
/// </summary>
|
||||
[Model(RightsType.Administration)]
|
||||
public sealed class Administration : Internal.ServerSettings
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -3,13 +3,8 @@
|
||||
/// <summary>
|
||||
/// Indicates a chat channel
|
||||
/// </summary>
|
||||
public sealed class ChatChannel
|
||||
public class ChatChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// The column ID
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IRC channel name
|
||||
/// </summary>
|
||||
|
||||
@@ -1,63 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
|
||||
namespace Tgstation.Server.Api.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Manage the server chat bots
|
||||
/// </summary>
|
||||
[Model(RightsType.Chat, RequiresInstance = true)]
|
||||
public class ChatSettings
|
||||
/// <inheritdoc />
|
||||
public sealed class ChatSettings : Internal.ChatSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// If the IRC client is enabled
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = ChatSettingsRights.SetIrcEnabled)]
|
||||
public bool IrcEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IRC server name
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ChatSettingsRights.SetIrcSettings, WriteRight = ChatSettingsRights.SetIrcSettings)]
|
||||
[Required]
|
||||
public string IrcHost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IRC server port
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ChatSettingsRights.SetIrcSettings, WriteRight = ChatSettingsRights.SetIrcSettings)]
|
||||
public ushort IrcPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IRC server NickServ password
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ChatSettingsRights.SetIrcSettings, WriteRight = ChatSettingsRights.SetIrcSettings)]
|
||||
public string IrcNickServPassword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the Discord bot is enabled
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = ChatSettingsRights.SetDiscordEnabled)]
|
||||
public bool DiscordEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Discord bot token
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ChatSettingsRights.SetDiscordSettings, WriteRight = ChatSettingsRights.SetDiscordSettings)]
|
||||
public string DiscordBotToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Channels the bot should listen/announce in and allow admin commands
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = ChatSettingsRights.SetDiscordChannels)]
|
||||
public virtual List<ChatChannel> AdminChannels { get; set; }
|
||||
public List<ChatChannel> AdminChannels { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Channels the Discord bot should listen/announce in
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = ChatSettingsRights.SetDiscordChannels)]
|
||||
public virtual List<ChatChannel> GeneralChannels { get; set; }
|
||||
public List<ChatChannel> GeneralChannels { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
|
||||
namespace Tgstation.Server.Api.Models.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Manage the server chat bots
|
||||
/// </summary>
|
||||
[Model(RightsType.Chat, RequiresInstance = true)]
|
||||
public class ChatSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// If the IRC client is enabled
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = ChatSettingsRights.SetIrcEnabled)]
|
||||
public bool IrcEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IRC server name
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ChatSettingsRights.SetIrcSettings, WriteRight = ChatSettingsRights.SetIrcSettings)]
|
||||
[Required]
|
||||
public string IrcHost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IRC server port
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ChatSettingsRights.SetIrcSettings, WriteRight = ChatSettingsRights.SetIrcSettings)]
|
||||
public ushort IrcPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IRC server NickServ password
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ChatSettingsRights.SetIrcSettings, WriteRight = ChatSettingsRights.SetIrcSettings)]
|
||||
public string IrcNickServPassword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the Discord bot is enabled
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = ChatSettingsRights.SetDiscordEnabled)]
|
||||
public bool DiscordEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Discord bot token
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ChatSettingsRights.SetDiscordSettings, WriteRight = ChatSettingsRights.SetDiscordSettings)]
|
||||
public string DiscordBotToken { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Tgstation.Server.Api.Models.Internal
|
||||
{
|
||||
[Model(RightsType.Administration)]
|
||||
public class ServerSettings
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
|
||||
namespace Tgstation.Server.Api.Models.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a server <see cref="User"/>
|
||||
/// </summary>
|
||||
[Model(RightsType.Administration, WriteRight = AdministrationRights.EditUsers)]
|
||||
public class User
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of the <see cref="User"/>
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true)]
|
||||
public long Id { get; set; }
|
||||
|
||||
[Permissions(DenyWrite = true)]
|
||||
[Required]
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The SID/UID of the <see cref="User"/> on Windows/POSIX respectively
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true)]
|
||||
public string SystemIdentifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the <see cref="User"/>
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = AdministrationRights.EditUsers)]
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Rights.AdministrationRights"/> for the <see cref="User"/>
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = AdministrationRights.EditUsers)]
|
||||
public AdministrationRights AdministrationRights { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Rights.InstanceManagerRights"/> for the <see cref="User"/>
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = AdministrationRights.EditUsers)]
|
||||
public InstanceManagerRights InstanceManagerRights { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,11 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
|
||||
namespace Tgstation.Server.Api.Models
|
||||
namespace Tgstation.Server.Api.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a server <see cref="User"/>
|
||||
/// </summary>
|
||||
[Model(RightsType.Administration, WriteRight = AdministrationRights.EditUsers)]
|
||||
public class User
|
||||
public sealed class User : Internal.User
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of the <see cref="User"/>
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true)]
|
||||
public long Id { get; set; }
|
||||
|
||||
[Permissions(DenyWrite = true)]
|
||||
[Required]
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The SID/UID of the <see cref="User"/> on Windows/POSIX respectively
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true)]
|
||||
public string SystemIdentifier { get; set; }
|
||||
|
||||
[Permissions(DenyWrite = true)]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the <see cref="User"/>
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = AdministrationRights.EditUsers)]
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Rights.AdministrationRights"/> for the <see cref="User"/>
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = AdministrationRights.EditUsers)]
|
||||
public AdministrationRights AdministrationRights { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Rights.InstanceManagerRights"/> for the <see cref="User"/>
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = AdministrationRights.EditUsers)]
|
||||
public InstanceManagerRights InstanceManagerRights { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ namespace Tgstation.Server.Api.Rights
|
||||
{
|
||||
{ RightsType.Administration, typeof(AdministrationRights) },
|
||||
{ RightsType.InstanceManager, typeof(InstanceManagerRights) },
|
||||
{ RightsType.Token, typeof(TokenRights) },
|
||||
|
||||
{ RightsType.Repository, typeof(RepositoryRights) },
|
||||
{ RightsType.Byond, typeof(ByondRights) },
|
||||
|
||||
@@ -13,11 +13,6 @@
|
||||
/// <see cref="InstanceManagerRights"/>
|
||||
/// </summary>
|
||||
InstanceManager,
|
||||
/// <summary>
|
||||
/// <see cref="TokenRights"/>
|
||||
/// </summary>
|
||||
Token,
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="RepositoryRights"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Tgstation.Server.Api.Rights
|
||||
{
|
||||
/// <summary>
|
||||
/// Rights for <see cref="Models.Token"/>s
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum TokenRights
|
||||
{
|
||||
/// <summary>
|
||||
/// User has no rights
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// User can create <see cref="Models.Token"/>s
|
||||
/// </summary>
|
||||
Create = 1,
|
||||
/// <summary>
|
||||
/// User can delete <see cref="Models.Token"/>s
|
||||
/// </summary>
|
||||
Delete = 2,
|
||||
/// <summary>
|
||||
/// User can list all their <see cref="Models.Token"/>s
|
||||
/// </summary>
|
||||
List = 4,
|
||||
/// <summary>
|
||||
/// User can perform all the actions they can for themselves on behalf of other users except <see cref="Create"/>
|
||||
/// </summary>
|
||||
Admin = 8,
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Cyberboss.AspNetCore.AsyncInitializer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
@@ -46,6 +47,10 @@ namespace Tgstation.Server.Host.Core
|
||||
|
||||
services.AddDbContext<DatabaseContext>();
|
||||
services.AddScoped<IDatabaseContext>(x => x.GetRequiredService<DatabaseContext>());
|
||||
|
||||
services.AddSingleton<ICryptographySuite, CryptographySuite>();
|
||||
services.AddSingleton<IDatabaseSeeder, DatabaseSeeder>();
|
||||
services.AddSingleton<IPasswordHasher<User>, PasswordHasher<User>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Tgstation.Server.Host.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class CryptographySuite : ICryptographySuite
|
||||
{
|
||||
/// <summary>
|
||||
/// The length of secure strings used in the application
|
||||
/// </summary>
|
||||
public const int SecureStringLength = 40;
|
||||
|
||||
/// <summary>
|
||||
/// Generates a secure ascii <see cref="string"/> of length <see cref="SecureStringLength"/>
|
||||
/// </summary>
|
||||
/// <returns>A secure ascii <see cref="string"/> of length <see cref="SecureStringLength"/></returns>
|
||||
static string GenerateSecureString()
|
||||
{
|
||||
using (var rng = new RNGCryptoServiceProvider())
|
||||
{
|
||||
var byt = new byte[1];
|
||||
var result = new StringBuilder
|
||||
{
|
||||
Capacity = SecureStringLength
|
||||
};
|
||||
while (result.Length < SecureStringLength)
|
||||
{
|
||||
rng.GetBytes(byt);
|
||||
var chr = (char)byt[0];
|
||||
if (Char.IsLetterOrDigit(chr))
|
||||
result.Append(chr);
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IPasswordHasher{TUser}"/> for the <see cref="CryptographySuite"/>
|
||||
/// </summary>
|
||||
readonly IPasswordHasher<User> passwordHasher;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="CryptographySuite"/>
|
||||
/// </summary>
|
||||
/// <param name="passwordHasher">The value of <see cref="passwordHasher"/></param>
|
||||
public CryptographySuite(IPasswordHasher<User> passwordHasher) => this.passwordHasher = passwordHasher ?? throw new ArgumentNullException(nameof(passwordHasher));
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegenerateUserToken(User user)
|
||||
{
|
||||
if (user == null)
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
user.TokenSecret = GenerateSecureString();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetUserPassword(User user, string newPassword)
|
||||
{
|
||||
if (user == null)
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
if (String.IsNullOrEmpty(newPassword))
|
||||
throw new ArgumentNullException(nameof(newPassword));
|
||||
user.PasswordHash = passwordHasher.HashPassword(user, newPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Tgstation.Server.Host.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains various cryptographic functions
|
||||
/// </summary>
|
||||
interface ICryptographySuite
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets a <see cref="User.PasswordHash"/> for a given <paramref name="user"/>
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="User"/> whos <see cref="User.PasswordHash"/> is to be set</param>
|
||||
/// <param name="newPassword">The new password for the <see cref="User"/></param>
|
||||
void SetUserPassword(User user, string newPassword);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a new <see cref="User.TokenSecret"/> for a givent <paramref name="user"/>
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="User"/> whos <see cref="User.TokenSecret"/> is to be set</param>
|
||||
void RegenerateUserToken(User user);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
sealed class ChatChannel : Api.Models.ChatChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// The column ID
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
sealed class ChatSettings : Api.Models.ChatSettings
|
||||
sealed class ChatSettings : Api.Models.Internal.ChatSettings
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
@@ -12,5 +11,9 @@ namespace Tgstation.Server.Host.Models
|
||||
|
||||
[Required]
|
||||
public Instance Instance { get; set; }
|
||||
|
||||
public List<ChatChannel> AdminChannels { get; set; }
|
||||
|
||||
public List<ChatChannel> GeneralChannels { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,14 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using ZNetCS.AspNetCore.Logging.EntityFrameworkCore;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
@@ -49,6 +53,10 @@ namespace Tgstation.Server.Host.Models
|
||||
/// The <see cref="IHostingEnvironment"/> for the <see cref="DatabaseContext"/>
|
||||
/// </summary>
|
||||
readonly IHostingEnvironment hostingEnvironment;
|
||||
/// <summary>
|
||||
/// The <see cref="IDatabaseSeeder"/> for the <see cref="DatabaseContext"/>
|
||||
/// </summary>
|
||||
readonly IDatabaseSeeder databaseSeeder;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="DatabaseContext"/>
|
||||
@@ -57,11 +65,13 @@ namespace Tgstation.Server.Host.Models
|
||||
/// <param name="databaseConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="databaseConfiguration"/></param>
|
||||
/// <param name="loggerFactory">The value of <see cref="loggerFactory"/></param>
|
||||
/// <param name="hostingEnvironment">The value of <see cref="hostingEnvironment"/></param>
|
||||
public DatabaseContext(DbContextOptions<DatabaseContext> dbContextOptions, IOptions<DatabaseConfiguration> databaseConfigurationOptions, ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment) : base(dbContextOptions)
|
||||
/// <param name="databaseSeeder">The value of <see cref="databaseSeeder"/></param>
|
||||
public DatabaseContext(DbContextOptions<DatabaseContext> dbContextOptions, IOptions<DatabaseConfiguration> databaseConfigurationOptions, ILoggerFactory loggerFactory, IHostingEnvironment hostingEnvironment, IDatabaseSeeder databaseSeeder) : base(dbContextOptions)
|
||||
{
|
||||
databaseConfiguration = databaseConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(databaseConfigurationOptions));
|
||||
this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
|
||||
this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
|
||||
this.databaseSeeder = databaseSeeder ?? throw new ArgumentNullException(nameof(databaseSeeder));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -98,13 +108,25 @@ namespace Tgstation.Server.Host.Models
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<ServerSettings> GetServerSettings(CancellationToken cancellationToken) => ServerSettings.FirstOrDefaultAsync(cancellationToken);
|
||||
public async Task<ServerSettings> GetServerSettings(CancellationToken cancellationToken)
|
||||
{
|
||||
var settings = await ServerSettings.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (settings == default(ServerSettings))
|
||||
{
|
||||
settings = new ServerSettings();
|
||||
ServerSettings.Add(settings);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task Initialize(CancellationToken cancellationToken)
|
||||
{
|
||||
await Database.EnsureCreatedAsync(cancellationToken).ConfigureAwait(false);
|
||||
var migrations = await Database.GetAppliedMigrationsAsync().ConfigureAwait(false);
|
||||
var wasEmpty = !migrations.Any();
|
||||
await Database.MigrateAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (wasEmpty)
|
||||
await databaseSeeder.SeedDatabase(this, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class DatabaseSeeder : IDatabaseSeeder
|
||||
{
|
||||
/// <summary>
|
||||
/// The default password mode admin password
|
||||
/// </summary>
|
||||
const string DefaultAdminPassword = "ISolemlySwearToDeleteTheDataDirectory";
|
||||
|
||||
/// <summary>
|
||||
/// The default git repository to pull server updates from
|
||||
/// </summary>
|
||||
const string DefaultUpstreamRepository = "https://github.com/tgstation/tgstation-server";
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ICryptographySuite"/> for the <see cref="DatabaseContext"/>
|
||||
/// </summary>
|
||||
readonly ICryptographySuite cryptographySuite;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="DatabaseSeeder"/>
|
||||
/// </summary>
|
||||
/// <param name="cryptographySuite">The value of <see cref="cryptographySuite"/></param>
|
||||
public DatabaseSeeder(ICryptographySuite cryptographySuite) => this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var admin = new User
|
||||
{
|
||||
AdministrationRights = (AdministrationRights)~0,
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
InstanceManagerRights = (InstanceManagerRights)~0,
|
||||
Name = "Admin"
|
||||
};
|
||||
cryptographySuite.RegenerateUserToken(admin);
|
||||
cryptographySuite.SetUserPassword(admin, DefaultAdminPassword);
|
||||
databaseContext.Users.Add(admin);
|
||||
|
||||
var serverSettings = await databaseContext.GetServerSettings(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
serverSettings.EnableTelemetry = true;
|
||||
serverSettings.UpstreamRepository = DefaultUpstreamRepository;
|
||||
|
||||
await databaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// For initially seeding a database
|
||||
/// </summary>
|
||||
interface IDatabaseSeeder
|
||||
{
|
||||
/// <summary>
|
||||
/// Initially seed a given <paramref name="databaseContext"/>
|
||||
/// </summary>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> to seed</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,5 @@ namespace Tgstation.Server.Host.Models
|
||||
sealed class ServerSettings : Api.Models.Internal.ServerSettings
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The value used for the <see cref="SymmetricSecurityKey"/> to encrypt JWTs
|
||||
/// </summary>
|
||||
[Required]
|
||||
public byte[] TokenSecret { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="Api.Models.User"/> in the database
|
||||
/// </summary>
|
||||
sealed class User : Api.Models.User
|
||||
sealed class User : Api.Models.Internal.User
|
||||
{
|
||||
public string PasswordHash { get; set; }
|
||||
|
||||
public string PasswordSalt { get; set; }
|
||||
/// <summary>
|
||||
/// The value used for the <see cref="SymmetricSecurityKey"/> to encrypt JWTs
|
||||
/// </summary>
|
||||
[StringLength(CryptographySuite.SecureStringLength)]
|
||||
public string TokenSecret { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="InstanceUser"/>s for the <see cref="User"/>
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
<PackageReference Include="Byond.TopicSender" Version="1.1.0.1" />
|
||||
<PackageReference Include="Cyberboss.AspNetCore.AsyncInitializer" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.1.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.0-preview2-final" />
|
||||
|
||||
Reference in New Issue
Block a user