Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ name: ci-build

env:
REGISTRY: ghcr.io
DOTNET_VERSION: 10.0.x
DOTNET_VERSION: 11.0.x
COVERAGE_MIN_PERCENT: '85'

jobs:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
name: ci-tag

env:
DOTNET_VERSION: 10.0.x
DOTNET_VERSION: 11.0.x
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/api

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
- cron: '0 6 * * 1'

env:
DOTNET_VERSION: 10.x.x
DOTNET_VERSION: 11.x.x

jobs:
analyze:
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/update-cloudflare-proxies.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
name: Update Cloudflare Proxies

on:
schedule:
- cron: '0 0 1 * *' # runs at 00:00 UTC on the 1st day of every month
Expand All @@ -9,6 +7,11 @@ on:
- '.github/workflows/update-cloudflare-proxies.yml'
- 'Common/CloudflareIPs.targets'

name: Update Cloudflare Proxies

env:
DOTNET_VERSION: 11.0.x

jobs:
update-proxies:
runs-on: ubuntu-latest
Expand Down
22 changes: 14 additions & 8 deletions API/Controller/Account/Authenticated/ChangeEmail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
using System.Net.Mime;
using Microsoft.AspNetCore.Mvc;
using OpenShock.API.Models.Requests;
using OpenShock.API.Services.Account;
using OpenShock.Common.Errors;
using OpenShock.Common.Problems;
using OpenShock.Common.Results;
using OpenShock.Common.Utils;
using Results = OpenShock.Common.Results;

namespace OpenShock.API.Controller.Account.Authenticated;

Expand Down Expand Up @@ -38,13 +41,16 @@ public async Task<IActionResult> ChangeEmail([FromBody] ChangeEmailRequest body)

var result = await _accountService.CreateEmailChangeFlowAsync(CurrentUser.Id, body.Email, actorId: CurrentUser.Id);

return result.Match<IActionResult>(
success => Ok(),
alreadyInUse => Problem(AccountError.EmailChangeAlreadyInUse),
unchanged => Problem(AccountError.EmailChangeUnchanged),
tooMany => Problem(AccountError.EmailChangeTooMany),
notActivated => throw new UnreachableException("Authenticated user is not activated"),
deactivated => throw new UnreachableException("Authenticated user is deactivated"),
notFound => throw new UnreachableException("Authenticated user not found in database"));
return result switch
{
Success => Ok(),
EmailAlreadyInUse => Problem(AccountError.EmailChangeAlreadyInUse),
EmailUnchanged => Problem(AccountError.EmailChangeUnchanged),
TooManyEmailChanges => Problem(AccountError.EmailChangeTooMany),
AccountNotActivated => throw new UnreachableException("Authenticated user is not activated"),
AccountDeactivated => throw new UnreachableException("Authenticated user is deactivated"),
Results.NotFound => throw new UnreachableException("Authenticated user not found in database"),
_ => throw new UnreachableException()
};
}
}
16 changes: 11 additions & 5 deletions API/Controller/Account/Authenticated/ChangePassword.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
using System.Net.Mime;
using Microsoft.AspNetCore.Mvc;
using OpenShock.API.Models.Requests;
using OpenShock.API.Services.Account;
using OpenShock.Common.Errors;
using OpenShock.Common.Problems;
using OpenShock.Common.Results;
using OpenShock.Common.Utils;
using Results = OpenShock.Common.Results;

namespace OpenShock.API.Controller.Account.Authenticated;

Expand Down Expand Up @@ -38,10 +41,13 @@ public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordRequest

var result = await _accountService.ChangePasswordAsync(CurrentUser.Id, body.NewPassword, actorId: CurrentUser.Id);

return result.Match<IActionResult>(
success => Ok(),
notActivated => throw new UnreachableException("Authenticated user is not activated"),
deactivated => throw new UnreachableException("Authenticated user is deactivated"),
notFound => throw new UnreachableException("Authenticated user not found in database"));
return result switch
{
Success => Ok(),
AccountNotActivated => throw new UnreachableException("Authenticated user is not activated"),
AccountDeactivated => throw new UnreachableException("Authenticated user is deactivated"),
Results.NotFound => throw new UnreachableException("Authenticated user not found in database"),
_ => throw new UnreachableException()
};
}
}
24 changes: 16 additions & 8 deletions API/Controller/Account/Authenticated/ChangeUsername.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
using System.Net.Mime;
using System.Diagnostics;
using System.Net.Mime;
using Microsoft.AspNetCore.Mvc;
using OpenShock.API.Models.Requests;
using OpenShock.API.Services.Account;
using OpenShock.Common.Errors;
using OpenShock.Common.OpenShockDb;
using OpenShock.Common.Problems;
using OpenShock.Common.Results;
using OpenShock.Common.Validation;
using Results = OpenShock.Common.Results;

namespace OpenShock.API.Controller.Account.Authenticated;

Expand All @@ -26,12 +31,15 @@ public async Task<IActionResult> ChangeUsername([FromBody] ChangeUsernameRequest
var result = await _accountService.ChangeUsernameAsync(CurrentUser.Id, body.Username, actorId: CurrentUser.Id,
ignoreLimit: CurrentUser.Roles.Any(r => r is RoleType.Staff or RoleType.Admin or RoleType.System));

return result.Match<IActionResult>(
success => Ok(),
usernametaken => Problem(AccountError.UsernameTaken),
usernameerror => Problem(AccountError.UsernameInvalid(usernameerror)),
recentlychanged => Problem(AccountError.UsernameRecentlyChanged),
accountdeactivated => Problem(AccountError.AccountDeactivated),
notfound => throw new Exception("Unexpected result, apparently our current user does not exist..."));
return result switch
{
Success => Ok(),
UsernameTaken => Problem(AccountError.UsernameTaken),
UsernameError usernameError => Problem(AccountError.UsernameInvalid(usernameError)),
RecentlyChanged => Problem(AccountError.UsernameRecentlyChanged),
AccountDeactivated => Problem(AccountError.AccountDeactivated),
Results.NotFound => throw new Exception("Unexpected result, apparently our current user does not exist..."),
_ => throw new UnreachableException()
};
}
}
21 changes: 14 additions & 7 deletions API/Controller/Account/Authenticated/Deactivate.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Net.Mime;
using OpenShock.API.Services.Account;
using OpenShock.Common.Errors;
using OpenShock.Common.Problems;
using OpenShock.Common.Results;
using AccountSvc = OpenShock.API.Services.Account;
using Results = OpenShock.Common.Results;

namespace OpenShock.API.Controller.Account.Authenticated;

Expand All @@ -17,12 +22,14 @@ public sealed partial class AuthenticatedAccountController
public async Task<IActionResult> Deactivate()
{
var deactivationResult = await _accountService.DeactivateAccountAsync(CurrentUser.Id, CurrentUser.Id, deleteLater: true);
return deactivationResult.Match<IActionResult>(
success => NoContent(),
cannotDeactivatePrivledged => Problem(AccountActivationError.CannotDeactivateOrDeletePrivledgedAccount),
alreadyDeactivated => Problem(AccountActivationError.AlreadyDeactivated),
unauthorized => Problem(AccountActivationError.Unauthorized),
notFound => throw new Exception("This is not supposed to happen, wtf?")
);
return deactivationResult switch
{
Success => NoContent(),
CannotDeactivatePrivilegedAccount => Problem(AccountActivationError.CannotDeactivateOrDeletePrivledgedAccount),
AccountDeactivationAlreadyInProgress => Problem(AccountActivationError.AlreadyDeactivated),
AccountSvc.Unauthorized => Problem(AccountActivationError.Unauthorized),
Results.NotFound => throw new Exception("This is not supposed to happen, wtf?"),
_ => throw new UnreachableException()
};
}
}
17 changes: 11 additions & 6 deletions API/Controller/Account/CheckUsername.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Net.Mime;
using Microsoft.AspNetCore.Mvc;
using OpenShock.API.Models.Requests;
using OpenShock.API.Services.Account;
using OpenShock.Common.Results;
using OpenShock.Common.Validation;

namespace OpenShock.API.Controller.Account;
Expand All @@ -20,11 +23,13 @@ public async Task<UsernameCheckResponse> CheckUsername([FromBody] ChangeUsername
{
var result = await _accountService.CheckUsernameAvailabilityAsync(body.Username, cancellationToken);

return result.Match(
success => new UsernameCheckResponse(UsernameAvailability.Available),
taken => new UsernameCheckResponse(UsernameAvailability.Taken),
invalid => new UsernameCheckResponse(UsernameAvailability.Invalid, invalid)
);
return result switch
{
Success => new UsernameCheckResponse(UsernameAvailability.Available),
UsernameTaken => new UsernameCheckResponse(UsernameAvailability.Taken),
UsernameError invalid => new UsernameCheckResponse(UsernameAvailability.Invalid, invalid),
_ => throw new UnreachableException()
};
}
}

Expand Down
20 changes: 13 additions & 7 deletions API/Controller/Account/LoginV2.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using OpenShock.API.Models.Requests;
using System.Diagnostics;
using System.Net.Mime;
using Asp.Versioning;
using Microsoft.AspNetCore.RateLimiting;
using OpenShock.API.Services.Account;
using OpenShock.Common.Errors;
using OpenShock.Common.OpenShockDb;
using OpenShock.Common.Problems;
using OpenShock.API.Models.Response;
using OpenShock.API.Services.Turnstile;
using Results = OpenShock.Common.Results;

namespace OpenShock.API.Controller.Account;

Expand Down Expand Up @@ -36,14 +40,16 @@ public async Task<IActionResult> LoginV2(
if (turnstileError is not null) return turnstileError;

var getAccountResult = await _accountService.GetAccountByCredentialsAsync(body.UsernameOrEmail, body.Password, cancellationToken);
if (!getAccountResult.TryPickT0(out var account, out var errors))
if (getAccountResult is not User account)
{
return errors.Match(
notFound => Problem(LoginError.InvalidCredentials),
deactivated => Problem(AccountError.AccountDeactivated),
notActivated => Problem(AccountError.AccountNotActivated),
oauthOnly => Problem(AccountError.AccountOAuthOnly)
);
return getAccountResult switch
{
Results.NotFound => Problem(LoginError.InvalidCredentials),
AccountDeactivated => Problem(AccountError.AccountDeactivated),
AccountNotActivated => Problem(AccountError.AccountNotActivated),
AccountIsOAuthOnly => Problem(AccountError.AccountOAuthOnly),
_ => throw new UnreachableException()
};
}

await CreateSession(account.Id, cookieDomain);
Expand Down
16 changes: 11 additions & 5 deletions API/Controller/Account/PasswordResetCheckValid.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using System.Net.Mime;
using Asp.Versioning;
using Microsoft.AspNetCore.RateLimiting;
using OpenShock.API.Services.Account;
using OpenShock.Common.Errors;
using OpenShock.Common.Problems;
using OpenShock.Common.Models;
using OpenShock.Common.Results;
using Results = OpenShock.Common.Results;

namespace OpenShock.API.Controller.Account;

Expand Down Expand Up @@ -39,10 +43,12 @@ public IActionResult PasswordResetCheckValidLegacy([FromRoute] Guid passwordRese
public async Task<IActionResult> PasswordResetCheckValid([FromRoute] Guid passwordResetId, [FromRoute] string secret, CancellationToken cancellationToken)
{
var passwordResetExists = await _accountService.CheckPasswordResetExistsAsync(passwordResetId, secret, cancellationToken);
return passwordResetExists.Match(
success => LegacyEmptyOk("Valid password reset process"),
notFound => Problem(PasswordResetError.PasswordResetNotFound),
invalid => Problem(PasswordResetError.PasswordResetNotFound)
);
return passwordResetExists switch
{
Success => LegacyEmptyOk("Valid password reset process"),
Results.NotFound => Problem(PasswordResetError.PasswordResetNotFound),
SecretInvalid => Problem(PasswordResetError.PasswordResetNotFound),
_ => throw new UnreachableException()
};
}
}
20 changes: 13 additions & 7 deletions API/Controller/Account/PasswordResetComplete.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using System.Net.Mime;
using Asp.Versioning;
using Microsoft.AspNetCore.RateLimiting;
using OpenShock.API.Services.Account;
using OpenShock.Common.Errors;
using OpenShock.Common.Problems;
using OpenShock.Common.Models;
using OpenShock.Common.Results;
using Results = OpenShock.Common.Results;

namespace OpenShock.API.Controller.Account;

Expand Down Expand Up @@ -42,13 +46,15 @@ public async Task<IActionResult> PasswordResetComplete([FromRoute] Guid password
{
var passwordResetComplete = await _accountService.CompletePasswordResetFlowAsync(passwordResetId, secret, body.Password);

return passwordResetComplete.Match(
success => LegacyEmptyOk("Password successfully changed"),
notFound => Problem(PasswordResetError.PasswordResetNotFound),
notActivated => Problem(AccountError.AccountNotActivated),
deactivated => Problem(AccountError.AccountDeactivated),
invalid => Problem(PasswordResetError.PasswordResetNotFound)
);
return passwordResetComplete switch
{
Success => LegacyEmptyOk("Password successfully changed"),
Results.NotFound => Problem(PasswordResetError.PasswordResetNotFound),
AccountNotActivated => Problem(AccountError.AccountNotActivated),
AccountDeactivated => Problem(AccountError.AccountDeactivated),
SecretInvalid => Problem(PasswordResetError.PasswordResetNotFound),
_ => throw new UnreachableException()
};
}


Expand Down
14 changes: 10 additions & 4 deletions API/Controller/Account/SignupV2.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using OpenShock.API.Models.Requests;
using OpenShock.API.Services.Account;
using System.Diagnostics;
using System.Net.Mime;
using Asp.Versioning;
using Microsoft.AspNetCore.RateLimiting;
using OpenShock.API.Services.Turnstile;
using OpenShock.Common.Errors;
using OpenShock.Common.OpenShockDb;
using OpenShock.Common.Options;
using OpenShock.Common.Problems;
using OpenShock.Common.Results;

namespace OpenShock.API.Controller.Account;

Expand Down Expand Up @@ -41,9 +45,11 @@ public async Task<IActionResult> SignUpV2(
if (turnstileError is not null) return turnstileError;

var creationAction = await _accountService.CreateAccountWithActivationFlowAsync(body.Email, body.Username, body.Password);
return creationAction.Match<IActionResult>(
_ => Ok(),
_ => Problem(SignupError.UsernameOrEmailExists)
);
return creationAction switch
{
Success<User> => Ok(),
AccountWithEmailOrUsernameExists => Problem(SignupError.UsernameOrEmailExists),
_ => throw new UnreachableException()
};
}
}
Loading
Loading