Merge pull request #586 from Cyberboss/MoreClientIssues

Cleanup some APIs
This commit is contained in:
Jordan Brown
2018-08-29 11:45:01 -04:00
committed by GitHub
38 changed files with 174 additions and 89 deletions
+6 -2
View File
@@ -212,11 +212,15 @@ Some requests return @ref Tgstation.Server.Api.Models.Job objects. These are lon
To list all jobs in an Instance use the following request
I GET "/Job" => Array of @ref Tgstation.Server.Api.Models.Job
I GET "/Job/List" => Array of @ref Tgstation.Server.Api.Models.Job
Note that the response for this request will only have the @ref Tgstation.Server.Api.Models.Job.Id field populated
To get full details of a job use the following request:
To get full details of _active_ jobs use the following request:
I GET "/Job" => Array of @ref Tgstation.Server.Api.Models.Job
To get full details of a specific job use the following request:
I GET "/Job/{JobId}" => @ref Tgstation.Server.Api.Models.Job
@@ -13,9 +13,9 @@ namespace Tgstation.Server.Api.Rights
/// </summary>
None = 0,
/// <summary>
/// User can edit themself and other <see cref="Models.User"/>s
/// User can edit themself and other <see cref="Models.User"/>s and also create others
/// </summary>
EditUsers = 1,
WriteUsers = 1,
/// <summary>
/// User can gracefully restart the host
/// </summary>
@@ -27,6 +27,10 @@ namespace Tgstation.Server.Api.Rights
/// <summary>
/// User can change their password
/// </summary>
EditPassword = 8,
EditOwnPassword = 8,
/// <summary>
/// User can read info and rights of other users
/// </summary>
ReadUsers = 16
}
}
@@ -35,6 +35,6 @@ namespace Tgstation.Server.Api.Rights
/// <summary>
/// User may list and read all <see cref="Models.CompileJob"/>s
/// </summary>
List = 32
CompileJobs = 32
}
}
@@ -47,10 +47,6 @@ namespace Tgstation.Server.Api.Rights
/// <summary>
/// User can change <see cref="Models.Instance.AutoUpdateInterval"/>
/// </summary>
SetAutoUpdate = 256,
/// <summary>
/// User can cancel move operations
/// </summary>
CancelMove = 512,
SetAutoUpdate = 256
}
}
@@ -17,8 +17,12 @@ namespace Tgstation.Server.Api.Rights
/// </summary>
ReadUsers = 1,
/// <summary>
/// Allow write access to <see cref="Models.InstanceUser"/> for the <see cref="Models.Instance"/>
/// Allow write and delete access to <see cref="Models.InstanceUser"/> for the <see cref="Models.Instance"/>
/// </summary>
WriteUsers = 2
WriteUsers = 2,
/// <summary>
/// Allow adding additional <see cref="Models.InstanceUser"/> to the <see cref="Models.Instance"/>
/// </summary>
CreateUsers = 4
}
}
@@ -13,6 +13,10 @@ namespace Tgstation.Server.Api.Rights
/// </summary>
None = 0,
/// <summary>
/// User may cancel synchronize operations
/// </summary>
CancelPendingChanges = 1,
/// <summary>
/// User may create the <see cref="Models.Repository"/> if it does not exist
/// </summary>
SetOrigin = 2,
@@ -59,10 +63,6 @@ namespace Tgstation.Server.Api.Rights
/// <summary>
/// User may cancel clone operations
/// </summary>
CancelClone = 4096,
/// <summary>
/// User may cancel synchronize operations
/// </summary>
CancelPendingChanges = 8192
CancelClone = 4096
}
}
@@ -17,7 +17,7 @@
<FileVersion>4.0.0.0</FileVersion>
<PackageTags>json web api tgstation-server tgstation ss13 byond</PackageTags>
<PackageReleaseNotes>Prototype release</PackageReleaseNotes>
<Version>4.0.0.0-preview3</Version>
<Version>4.0.0.0-preview4</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -35,7 +35,10 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
</ItemGroup>
@@ -1,4 +1,5 @@
using System.Threading;
using System;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
using Tgstation.Server.Api.Models;
@@ -26,7 +27,7 @@ namespace Tgstation.Server.Client
public Task<Administration> Read(CancellationToken cancellationToken) => apiClient.Read<Administration>(Routes.Administration, cancellationToken);
/// <inheritdoc />
public Task Update(Administration administration, CancellationToken cancellationToken) => apiClient.Update(Routes.Administration, administration, cancellationToken);
public Task Update(Administration administration, CancellationToken cancellationToken) => apiClient.Update(Routes.Administration, administration ?? throw new ArgumentNullException(nameof(administration)), cancellationToken);
/// <inheritdoc />
public Task Restart(CancellationToken cancellationToken) => apiClient.Delete(Routes.Administration, cancellationToken);
@@ -33,6 +33,6 @@ namespace Tgstation.Server.Client.Components
public Task<Byond> Read(CancellationToken cancellationToken) => apiClient.Read<Byond>(Routes.Byond, instance.Id, cancellationToken);
/// <inheritdoc />
public Task<Byond> Update(Byond byond, CancellationToken cancellationToken) => apiClient.Update<Byond, Byond>(Routes.Byond, byond, instance.Id, cancellationToken);
public Task<Byond> Update(Byond byond, CancellationToken cancellationToken) => apiClient.Update<Byond, Byond>(Routes.Byond, byond ?? throw new ArgumentNullException(nameof(byond)), instance.Id, cancellationToken);
}
}
@@ -31,15 +31,15 @@ namespace Tgstation.Server.Client.Components
}
/// <inheritdoc />
public Task<ChatBot> Create(ChatBot settings, CancellationToken cancellationToken) => apiClient.Create<ChatBot, ChatBot>(Routes.Chat, settings, instance.Id, cancellationToken);
public Task<ChatBot> Create(ChatBot settings, CancellationToken cancellationToken) => apiClient.Create<ChatBot, ChatBot>(Routes.Chat, settings ?? throw new ArgumentNullException(nameof(settings)), instance.Id, cancellationToken);
/// <inheritdoc />
public Task Delete(ChatBot settings, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.Chat, settings.Id), instance.Id, cancellationToken);
public Task Delete(ChatBot settings, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.Chat, settings?.Id ?? throw new ArgumentNullException(nameof(settings))), instance.Id, cancellationToken);
/// <inheritdoc />
public Task<IReadOnlyList<ChatBot>> List(CancellationToken cancellationToken) => apiClient.Create<IReadOnlyList<ChatBot>>(Routes.List(Routes.Chat), instance.Id, cancellationToken);
/// <inheritdoc />
public Task<ChatBot> Update(ChatBot settings, CancellationToken cancellationToken) => apiClient.Update<ChatBot, ChatBot>(Routes.Chat, settings, instance.Id, cancellationToken);
public Task<ChatBot> Update(ChatBot settings, CancellationToken cancellationToken) => apiClient.Update<ChatBot, ChatBot>(Routes.Chat, settings ?? throw new ArgumentNullException(nameof(settings)), instance.Id, cancellationToken);
}
}
@@ -47,6 +47,6 @@ namespace Tgstation.Server.Client.Components
}
/// <inheritdoc />
public Task<ConfigurationFile> Write(ConfigurationFile file, CancellationToken cancellationToken) => apiClient.Update<ConfigurationFile, ConfigurationFile>(Routes.Configuration, file, instance.Id, cancellationToken);
public Task<ConfigurationFile> Write(ConfigurationFile file, CancellationToken cancellationToken) => apiClient.Update<ConfigurationFile, ConfigurationFile>(Routes.Configuration, file ?? throw new ArgumentNullException(nameof(file)), instance.Id, cancellationToken);
}
}
@@ -39,6 +39,6 @@ namespace Tgstation.Server.Client.Components
public Task<DreamDaemon> Read(CancellationToken cancellationToken) => apiClient.Read<DreamDaemon>(Routes.DreamDaemon, instance.Id, cancellationToken);
/// <inheritdoc />
public Task<DreamDaemon> Update(DreamDaemon dreamDaemon, CancellationToken cancellationToken) => apiClient.Update<DreamDaemon, DreamDaemon>(Routes.DreamDaemon, dreamDaemon, instance.Id, cancellationToken);
public Task<DreamDaemon> Update(DreamDaemon dreamDaemon, CancellationToken cancellationToken) => apiClient.Update<DreamDaemon, DreamDaemon>(Routes.DreamDaemon, dreamDaemon ?? throw new ArgumentNullException(nameof(dreamDaemon)), instance.Id, cancellationToken);
}
}
@@ -36,6 +36,6 @@ namespace Tgstation.Server.Client.Components
public Task<DreamMaker> Read(CancellationToken cancellationToken) => apiClient.Read<DreamMaker>(Routes.DreamMaker, instance.Id, cancellationToken);
/// <inheritdoc />
public Task<DreamMaker> Update(DreamMaker dreamMaker, CancellationToken cancellationToken) => apiClient.Update<DreamMaker, DreamMaker>(Routes.DreamMaker, dreamMaker, instance.Id, cancellationToken);
public Task<DreamMaker> Update(DreamMaker dreamMaker, CancellationToken cancellationToken) => apiClient.Update<DreamMaker, DreamMaker>(Routes.DreamMaker, dreamMaker ?? throw new ArgumentNullException(nameof(dreamMaker)), instance.Id, cancellationToken);
}
}
@@ -17,6 +17,14 @@ namespace Tgstation.Server.Client.Components
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="InstanceUser"/> associated with the logged on user</returns>
Task<InstanceUser> Read(CancellationToken cancellationToken);
/// <summary>
/// Get a specific <paramref name="instanceUser"/>
/// </summary>
/// <param name="instanceUser">The <see cref="InstanceUser"/> to get</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the requested <paramref name="instanceUser"/></returns>
Task<InstanceUser> GetId(InstanceUser instanceUser, CancellationToken cancellationToken);
/// <summary>
/// Get the <see cref="InstanceUser"/>s in the <see cref="Instance"/>
/// </summary>
@@ -18,13 +18,20 @@ namespace Tgstation.Server.Client.Components
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="IReadOnlyList{T}"/> of the <see cref="Api.Models.Internal.Job.Id"/>s in the <see cref="Instance"/></returns>
Task<IReadOnlyList<Job>> List(CancellationToken cancellationToken);
/// <summary>
/// List the active <see cref="Job"/>s in the <see cref="Instance"/>
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="IReadOnlyList{T}"/> of the active <see cref="Job"/>s in the <see cref="Instance"/></returns>
Task<IReadOnlyList<Job>> ListActive(CancellationToken cancellationToken);
/// <summary>
/// Get a <paramref name="job"/>
/// </summary>
/// <param name="job">The <see cref="Job"/> to get</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="Job"/></returns>
Task<Job> Read(Job job, CancellationToken cancellationToken);
Task<Job> GetId(Job job, CancellationToken cancellationToken);
/// <summary>
/// Cancels a <paramref name="job"/>
@@ -40,7 +47,7 @@ namespace Tgstation.Server.Client.Components
/// <param name="job">The <see cref="Job"/> to create a <see cref="Task"/> for</param>
/// <param name="requeryRate">The rate in to poll the server for results</param>
/// <param name="progressCallback">A <see cref="Action{T}"/> to run with 0-100 progress</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> which will trigger the cancellation of the <paramref name="job"/></param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation. This does not cancel the <paramref name="job"/></param>
/// <returns>A <see cref="Task{TResult}"/> resulting in a complete <see cref="Job"/></returns>
Task<Job> CreateTaskFromJob(Job job, TimeSpan requeryRate, Action<int> progressCallback, CancellationToken cancellationToken);
}
@@ -31,7 +31,7 @@ namespace Tgstation.Server.Client.Components
}
/// <inheritdoc />
public Task<InstanceUser> Create(InstanceUser user, CancellationToken cancellationToken) => apiClient.Create<InstanceUser, InstanceUser>(Routes.InstanceUser, user, instance.Id, cancellationToken);
public Task<InstanceUser> Create(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Create<InstanceUser, InstanceUser>(Routes.InstanceUser, instanceUser ?? throw new ArgumentNullException(nameof(instanceUser)), instance.Id, cancellationToken);
public Task Delete(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.InstanceUser, instanceUser.UserId.Value), instance.Id, cancellationToken);
@@ -39,9 +39,12 @@ namespace Tgstation.Server.Client.Components
public Task<InstanceUser> Read(CancellationToken cancellationToken) => apiClient.Read<InstanceUser>(Routes.InstanceUser, instance.Id, cancellationToken);
/// <inheritdoc />
public Task<InstanceUser> Update(InstanceUser user, CancellationToken cancellationToken) => apiClient.Update<InstanceUser, InstanceUser>(Routes.InstanceUser, user, instance.Id, cancellationToken);
public Task<InstanceUser> Update(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Update<InstanceUser, InstanceUser>(Routes.InstanceUser, instanceUser ?? throw new ArgumentNullException(nameof(instanceUser)), instance.Id, cancellationToken);
/// <inheritdoc />
public Task<IReadOnlyList<InstanceUser>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<InstanceUser>>(Routes.List(Routes.InstanceUser), instance.Id, cancellationToken);
/// <inheritdoc />
public Task<InstanceUser> GetId(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Read<InstanceUser>(Routes.SetID(Routes.InstanceUser, instanceUser?.UserId ?? throw new ArgumentNullException(nameof(instanceUser))), instance.Id, cancellationToken);
}
}
@@ -31,25 +31,30 @@ namespace Tgstation.Server.Client.Components
}
/// <inheritdoc />
public Task Cancel(Job job, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.Jobs, job.Id), instance.Id, cancellationToken);
public Task Cancel(Job job, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.Jobs, job?.Id ?? throw new ArgumentNullException(nameof(job))), instance.Id, cancellationToken);
/// <inheritdoc />
public Task<IReadOnlyList<Job>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Job>>(Routes.List(Routes.Jobs), instance.Id, cancellationToken);
/// <inheritdoc />
public Task<Job> Read(Job job, CancellationToken cancellationToken) => apiClient.Read<Job>(Routes.SetID(Routes.Jobs, job.Id), instance.Id, cancellationToken);
public Task<IReadOnlyList<Job>> ListActive(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Job>>(Routes.Jobs, instance.Id, cancellationToken);
/// <inheritdoc />
public Task<Job> GetId(Job job, CancellationToken cancellationToken) => apiClient.Read<Job>(Routes.SetID(Routes.Jobs, job?.Id ?? throw new ArgumentNullException(nameof(job))), instance.Id, cancellationToken);
/// <inheritdoc />
public async Task<Job> CreateTaskFromJob(Job job, TimeSpan requeryRate, Action<int> progressCallback, CancellationToken cancellationToken)
{
if (job == null)
throw new ArgumentNullException(nameof(job));
if (progressCallback == null)
throw new ArgumentNullException(nameof(progressCallback));
int? lastProgress = null;
while (!job.StoppedAt.HasValue)
{
await Task.Delay(requeryRate, cancellationToken).ConfigureAwait(false);
job = await Read(job, cancellationToken).ConfigureAwait(false);
job = await GetId(job, cancellationToken).ConfigureAwait(false);
if (job.Progress.HasValue && job.Progress != lastProgress)
{
progressCallback(job.Progress.Value);
@@ -1,4 +1,5 @@
using System.Threading;
using System;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
using Tgstation.Server.Api.Models;
@@ -35,6 +36,6 @@ namespace Tgstation.Server.Client.Components
public Task<Repository> Read(CancellationToken cancellationToken) => apiClient.Read<Repository>(Routes.Repository, instance.Id, cancellationToken);
/// <inheritdoc />
public Task<Repository> Update(Repository repository, CancellationToken cancellationToken) => apiClient.Update<Repository, Repository>(Routes.Repository, repository, instance.Id, cancellationToken);
public Task<Repository> Update(Repository repository, CancellationToken cancellationToken) => apiClient.Update<Repository, Repository>(Routes.Repository, repository ?? throw new ArgumentNullException(nameof(repository)), instance.Id, cancellationToken);
}
}
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
@@ -26,30 +27,30 @@ namespace Tgstation.Server.Client
/// <param name="apiClient"></param>
public InstanceManagerClient(IApiClient apiClient)
{
this.apiClient = apiClient;
this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
cachedClients = new Dictionary<long, IInstanceClient>();
}
/// <inheritdoc />
public Task<Instance> Create(Instance instance, CancellationToken cancellationToken) => apiClient.Create<Instance, Instance>(Routes.InstanceManager, instance, cancellationToken);
public Task<Instance> Create(Instance instance, CancellationToken cancellationToken) => apiClient.Create<Instance, Instance>(Routes.InstanceManager, instance ?? throw new ArgumentNullException(nameof(instance)), cancellationToken);
/// <inheritdoc />
public Task Delete(Instance instance, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.InstanceManager, instance.Id), cancellationToken);
public Task Delete(Instance instance, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.InstanceManager, instance?.Id ?? throw new ArgumentNullException(nameof(instance))), cancellationToken);
/// <inheritdoc />
public Task<IReadOnlyList<Instance>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Instance>>(Routes.List(Routes.InstanceManager), cancellationToken);
/// <inheritdoc />
public Task<Instance> Update(Instance instance, CancellationToken cancellationToken) => apiClient.Update<Instance, Instance>(Routes.InstanceManager, instance, cancellationToken);
public Task<Instance> Update(Instance instance, CancellationToken cancellationToken) => apiClient.Update<Instance, Instance>(Routes.InstanceManager, instance ?? throw new ArgumentNullException(nameof(instance)), cancellationToken);
/// <inheritdoc />
public Task<Instance> GetId(Instance instance, CancellationToken cancellationToken) => apiClient.Read<Instance>(Routes.SetID(Routes.InstanceManager, instance.Id), cancellationToken);
public Task<Instance> GetId(Instance instance, CancellationToken cancellationToken) => apiClient.Read<Instance>(Routes.SetID(Routes.InstanceManager, instance?.Id ?? throw new ArgumentNullException(nameof(instance))), cancellationToken);
/// <inheritdoc />
public IInstanceClient CreateClient(Instance instance)
{
if (!cachedClients.TryGetValue(instance.Id, out var client))
if (!cachedClients.TryGetValue(instance?.Id ?? throw new ArgumentNullException(nameof(instance)), out var client))
{
client = new InstanceClient(apiClient, instance);
cachedClients.Add(instance.Id, client);
@@ -38,8 +38,6 @@ namespace Tgstation.Server.Client
throw new ArgumentNullException(nameof(username));
if (password == null)
throw new ArgumentNullException(nameof(password));
if (timeout == null)
throw new ArgumentNullException(nameof(timeout));
Token token;
using (var api = apiClientFactory.CreateApiClient(host, new ApiHeaders(productHeaderValue, username, password)))
@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<DebugType>Full</DebugType>
<Version>4.0.0.0-preview8</Version>
<Version>4.0.0.0-preview9</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Cyberboss</Authors>
<Company>/tg/station 13</Company>
@@ -31,6 +31,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
+3 -3
View File
@@ -25,10 +25,10 @@ namespace Tgstation.Server.Client
}
/// <inheritdoc />
public Task<User> Create(UserUpdate user, CancellationToken cancellationToken) => apiClient.Create<UserUpdate, User>(Routes.User, user, cancellationToken);
public Task<User> Create(UserUpdate user, CancellationToken cancellationToken) => apiClient.Create<UserUpdate, User>(Routes.User, user ?? throw new ArgumentNullException(nameof(user)), cancellationToken);
/// <inheritdoc />
public Task<User> GetId(User user, CancellationToken cancellationToken) => apiClient.Read<User>(Routes.SetID(Routes.User, user.Id), cancellationToken);
public Task<User> GetId(User user, CancellationToken cancellationToken) => apiClient.Read<User>(Routes.SetID(Routes.User, user?.Id ?? throw new ArgumentNullException(nameof(user))), cancellationToken);
/// <inheritdoc />
public Task<IReadOnlyList<User>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<User>>(Routes.List(Routes.User), cancellationToken);
@@ -37,6 +37,6 @@ namespace Tgstation.Server.Client
public Task<User> Read(CancellationToken cancellationToken) => apiClient.Read<User>(Routes.User, cancellationToken);
/// <inheritdoc />
public Task<User> Update(UserUpdate user, CancellationToken cancellationToken) => apiClient.Update<UserUpdate, User>(Routes.User, user, cancellationToken);
public Task<User> Update(UserUpdate user, CancellationToken cancellationToken) => apiClient.Update<UserUpdate, User>(Routes.User, user ?? throw new ArgumentNullException(nameof(user)), cancellationToken);
}
}
@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<DebugType>Full</DebugType>
<FileVersion>4.0.0.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -18,6 +19,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
</ItemGroup>
@@ -9,4 +9,3 @@ using System.Runtime.InteropServices;
[assembly: AssemblyVersion("4.0.0.0")]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyInformationalVersion("4.0.0.0")]
@@ -94,6 +94,10 @@
<PackageReference Include="McMaster.Extensions.CommandLineUtils">
<Version>2.2.5</Version>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging.EventLog">
<Version>2.1.1</Version>
</PackageReference>
@@ -4,6 +4,8 @@
<TargetFramework>netstandard2.0</TargetFramework>
<DebugType>Full</DebugType>
<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<FileVersion>4.0.0.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -18,7 +20,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
</ItemGroup>
@@ -79,8 +79,12 @@ namespace Tgstation.Server.Host.Components
{
Models.WatchdogReattachInformation result = null;
await databaseContextFactory.UseContext(async (db) =>
result = await db.Instances.Where(x => x.Id == metadata.Id).Select(x => x.WatchdogReattachInformation).FirstAsync(cancellationToken).ConfigureAwait(false)
result = await db.Instances.Where(x => x.Id == metadata.Id).Select(x => x.WatchdogReattachInformation).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false)
).ConfigureAwait(false);
if (result == default)
throw new JobException("Unable to load reattach information!");
var bravoDmbTask = dmbFactory.FromCompileJob(result.Bravo.CompileJob, cancellationToken);
return new WatchdogReattachInformation(result, await dmbFactory.FromCompileJob(result.Alpha.CompileJob, cancellationToken).ConfigureAwait(false), await bravoDmbTask.ConfigureAwait(false));
}
@@ -163,7 +163,7 @@ namespace Tgstation.Server.Host.Controllers
var results = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (results == default)
return NotFound();
return StatusCode((int)HttpStatusCode.Gone);
var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
@@ -96,7 +96,12 @@ namespace Tgstation.Server.Host.Controllers
var revision = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadRevision) != 0;
if (settings == null)
settings = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstAsync(cancellationToken).ConfigureAwait(false);
{
settings = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (settings == default)
return StatusCode((int)HttpStatusCode.Gone);
}
var result = new DreamDaemon();
if (metadata)
{
@@ -145,7 +150,10 @@ namespace Tgstation.Server.Host.Controllers
throw new ArgumentNullException(nameof(model));
//alias for changing DD settings
var current = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstAsync(cancellationToken).ConfigureAwait(false);
var current = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (current == default)
return StatusCode((int)HttpStatusCode.Gone);
var userRights = (DreamDaemonRights)AuthenticationContext.GetRight(RightsType.DreamDaemon);
@@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
@@ -58,7 +59,7 @@ namespace Tgstation.Server.Host.Controllers
}
/// <inheritdoc />
[TgsAuthorize(DreamMakerRights.List)]
[TgsAuthorize(DreamMakerRights.CompileJobs)]
public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
{
var compileJob = await DatabaseContext.CompileJobs
@@ -73,11 +74,14 @@ namespace Tgstation.Server.Host.Controllers
}
/// <inheritdoc />
[TgsAuthorize(DreamMakerRights.List)]
[TgsAuthorize(DreamMakerRights.CompileJobs)]
public override async Task<IActionResult> List(CancellationToken cancellationToken)
{
var compileJobs = await DatabaseContext.CompileJobs.Where(x => x.Job.Instance.Id == Instance.Id).ToListAsync(cancellationToken).ConfigureAwait(false);
return Json(compileJobs.Select(x => x.ToApi()));
var compileJobs = await DatabaseContext.CompileJobs.Where(x => x.Job.Instance.Id == Instance.Id).OrderByDescending(x => x.Job.StartedAt).Select(x => new Api.Models.CompileJob
{
Id = x.Id
}).ToListAsync(cancellationToken).ConfigureAwait(false);
return Json(compileJobs);
}
/// <inheritdoc />
@@ -100,12 +104,9 @@ namespace Tgstation.Server.Host.Controllers
[TgsAuthorize(DreamMakerRights.SetDme | DreamMakerRights.SetApiValidationPort)]
public override async Task<IActionResult> Update([FromBody] Api.Models.DreamMaker model, CancellationToken cancellationToken)
{
var hostModel = new DreamMakerSettings
{
InstanceId = Instance.Id
};
DatabaseContext.DreamMakerSettings.Attach(hostModel);
var hostModel = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (hostModel == null)
return StatusCode((int)HttpStatusCode.Gone);
if (model.ProjectName != null)
{
@@ -145,9 +146,15 @@ namespace Tgstation.Server.Host.Controllers
{
StartupTimeout = x.StartupTimeout,
SecurityLevel = x.SecurityLevel
}).FirstAsync(cancellationToken);
}).FirstOrDefaultAsync(cancellationToken);
var dreamMakerSettings = await databaseContext.DreamMakerSettings.Where(x => x.InstanceId == instanceModel.Id).FirstAsync(cancellationToken).ConfigureAwait(false);
if (dreamMakerSettings == default)
throw new JobException("Missing DreamMakerSettings in DB!");
var ddSettings = await ddSettingsTask.ConfigureAwait(false);
if (ddSettings == default)
throw new JobException("Missing DreamDaemonSettings in DB!");
var instance = instanceManager.GetInstance(instanceModel);
@@ -156,10 +163,8 @@ namespace Tgstation.Server.Host.Controllers
using (var repo = await instance.RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
{
if (repo == null)
{
job.ExceptionDetails = "Missing repository!";
return;
}
throw new JobException("Missing Repository!");
var repoSha = repo.Head;
revInfo = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha).Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).FirstOrDefaultAsync().ConfigureAwait(false);
@@ -199,8 +199,8 @@ namespace Tgstation.Server.Host.Controllers
.Include(x => x.WatchdogReattachInformation)
.Include(x => x.WatchdogReattachInformation.Alpha)
.Include(x => x.WatchdogReattachInformation.Bravo)
.FirstAsync(cancellationToken).ConfigureAwait(false);
if (originalModel == default(Models.Instance))
.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (originalModel == default)
return StatusCode((int)HttpStatusCode.Gone);
if (originalModel.WatchdogReattachInformation != null)
@@ -324,7 +324,7 @@ namespace Tgstation.Server.Host.Controllers
Description = String.Format(CultureInfo.InvariantCulture, "Move instance ID {0} from {1} to {2}", Instance.Id, Instance.Path, rawPath),
Instance = Instance,
CancelRightsType = RightsType.InstanceManager,
CancelRight = (ulong)InstanceManagerRights.CancelMove,
CancelRight = (ulong)InstanceManagerRights.Relocate,
StartedBy = AuthenticationContext.User
};
@@ -47,7 +47,7 @@ namespace Tgstation.Server.Host.Controllers
}
/// <inheritdoc />
[TgsAuthorize(InstanceUserRights.WriteUsers)]
[TgsAuthorize(InstanceUserRights.CreateUsers)]
public override async Task<IActionResult> Create([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
{
var test = StandardModelChecks(model);
@@ -114,7 +114,7 @@ namespace Tgstation.Server.Host.Controllers
//this functions as userId
var user = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (user == default)
return NotFound();
return StatusCode((int)HttpStatusCode.Gone);
return Json(user.ToApi());
}
@@ -40,10 +40,8 @@ namespace Tgstation.Server.Host.Controllers
[TgsAuthorize]
public override async Task<IActionResult> Read(CancellationToken cancellationToken)
{
var result = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id).OrderByDescending(x => x.StartedAt).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (result == null)
return StatusCode((int)HttpStatusCode.Gone);
return Json(result);
var result = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id && !x.StoppedAt.HasValue).OrderByDescending(x => x.StartedAt).ToListAsync(cancellationToken).ConfigureAwait(false);
return Json(result.Select(x => x.ToApi()));
}
/// <inheritdoc />
@@ -224,8 +224,11 @@ namespace Tgstation.Server.Host.Controllers
using (var repo = await instanceManager.GetInstance(Instance).RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
{
if (repo != null && await PopulateApi(api, repo, DatabaseContext, Instance, null, null, cancellationToken).ConfigureAwait(false))
{
//user may have fucked with the repo without telling us, do what we can
await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
return StatusCode((int)HttpStatusCode.Created, api);
}
return Json(api);
}
}
@@ -62,7 +62,7 @@ namespace Tgstation.Server.Host.Controllers
}
/// <inheritdoc />
[TgsAuthorize(AdministrationRights.EditUsers)]
[TgsAuthorize(AdministrationRights.WriteUsers)]
public override async Task<IActionResult> Create([FromBody] UserUpdate model, CancellationToken cancellationToken)
{
if (model == null)
@@ -122,17 +122,17 @@ namespace Tgstation.Server.Host.Controllers
}
/// <inheritdoc />
[TgsAuthorize(AdministrationRights.EditUsers | AdministrationRights.EditPassword)]
[TgsAuthorize(AdministrationRights.WriteUsers | AdministrationRights.EditOwnPassword)]
public override async Task<IActionResult> Update([FromBody] UserUpdate model, CancellationToken cancellationToken)
{
if (model == null)
throw new ArgumentNullException(nameof(model));
var passwordEditOnly = !AuthenticationContext.User.AdministrationRights.Value.HasFlag(AdministrationRights.EditUsers);
var passwordEditOnly = !AuthenticationContext.User.AdministrationRights.Value.HasFlag(AdministrationRights.WriteUsers);
var originalUser = passwordEditOnly ? AuthenticationContext.User : await DatabaseContext.Users.Where(x => x.Id == model.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
if (originalUser == default)
return StatusCode((int)HttpStatusCode.Gone);
return NotFound();
if (passwordEditOnly && (model.Id != originalUser.Id || model.InstanceManagerRights.HasValue || model.AdministrationRights.HasValue || model.Enabled.HasValue || model.SystemIdentifier != null || model.Name != null))
return Forbid();
@@ -164,7 +164,7 @@ namespace Tgstation.Server.Host.Controllers
public override Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult<IActionResult>(Json(AuthenticationContext.User.ToApi(true)));
/// <inheritdoc />
[TgsAuthorize(AdministrationRights.EditUsers)]
[TgsAuthorize(AdministrationRights.ReadUsers)]
public override async Task<IActionResult> List(CancellationToken cancellationToken)
{
var users = await DatabaseContext.Users.ToListAsync(cancellationToken).ConfigureAwait(false);
@@ -178,7 +178,7 @@ namespace Tgstation.Server.Host.Controllers
if (id == AuthenticationContext.User.Id)
return await Read(cancellationToken).ConfigureAwait(false);
if (!((AdministrationRights)AuthenticationContext.GetRight(RightsType.Administration)).HasFlag(AdministrationRights.EditUsers))
if (!((AdministrationRights)AuthenticationContext.GetRight(RightsType.Administration)).HasFlag(AdministrationRights.ReadUsers))
return Forbid();
var user = await DatabaseContext.Users.Where(x => x.Id == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
@@ -4,6 +4,8 @@
<TargetFramework>netcoreapp2.0</TargetFramework>
<DebugType>Full</DebugType>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<FileVersion>4.0.0.0</FileVersion>
<Version>1.0.0</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -29,6 +31,10 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" />
@@ -42,7 +42,7 @@ namespace Tgstation.Server.Host.Security.Tests
var instanceUser = new InstanceUser();
var authContext = new AuthenticationContext(null, user, instanceUser);
user.AdministrationRights = AdministrationRights.EditUsers;
user.AdministrationRights = AdministrationRights.WriteUsers;
instanceUser.ByondRights = ByondRights.ChangeVersion | ByondRights.ReadActive;
Assert.AreEqual((ulong)user.AdministrationRights, authContext.GetRight(RightsType.Administration));
Assert.AreEqual((ulong)instanceUser.ByondRights, authContext.GetRight(RightsType.Byond));
+10 -1
View File
@@ -1,3 +1,12 @@
Verify the byond cache folder location on linux
Test watchdog
Test chat channel tagging
UNIT test watchdog
Test chat channel tagging and full stack
Test reattachment
Test auto update
Test auto start