[frontend/components] Add registration page and update login page style (ISH-472)
This commit is contained in:
parent
c84156e946
commit
a130934787
10 changed files with 195 additions and 22 deletions
|
@ -6,6 +6,7 @@ using Iceshrimp.Backend.Core.Configuration;
|
|||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Iceshrimp.Backend.Core.Services;
|
||||
using Iceshrimp.Shared.Schemas.Web;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
|
@ -17,16 +18,18 @@ namespace Iceshrimp.Backend.Controllers.Web;
|
|||
[EnableRateLimiting("sliding")]
|
||||
[Route("/api/iceshrimp/instance")]
|
||||
[Produces(MediaTypeNames.Application.Json)]
|
||||
public class InstanceController(DatabaseContext db, UserRenderer userRenderer, IOptions<Config.InstanceSection> config) : ControllerBase
|
||||
public class InstanceController(DatabaseContext db, UserRenderer userRenderer, IOptions<Config.InstanceSection> instanceConfig, IOptions<Config.SecuritySection> securityConfig, MetaService meta) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesResults(HttpStatusCode.OK)]
|
||||
public InstanceResponse GetInfo()
|
||||
public async Task<InstanceResponse> GetInfo()
|
||||
{
|
||||
return new InstanceResponse
|
||||
{
|
||||
AccountDomain = config.Value.AccountDomain,
|
||||
WebDomain = config.Value.WebDomain,
|
||||
AccountDomain = instanceConfig.Value.AccountDomain,
|
||||
WebDomain = instanceConfig.Value.WebDomain,
|
||||
Registration = (Registrations)securityConfig.Value.Registrations,
|
||||
Name = await meta.GetAsync(MetaEntity.InstanceName)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="page">
|
||||
@Body
|
||||
</div>
|
8
Iceshrimp.Frontend/Layout/UnauthLayout.razor
Normal file
8
Iceshrimp.Frontend/Layout/UnauthLayout.razor
Normal file
|
@ -0,0 +1,8 @@
|
|||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="header">
|
||||
<img class="logo" src="/_content/Iceshrimp.Assets.Branding/welcome-logo.svg" />
|
||||
</div>
|
||||
<div class="page">
|
||||
@Body
|
||||
</div>
|
10
Iceshrimp.Frontend/Layout/UnauthLayout.razor.css
Normal file
10
Iceshrimp.Frontend/Layout/UnauthLayout.razor.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
.header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
object-fit: contain;
|
||||
height: 2rem
|
||||
}
|
|
@ -6,13 +6,16 @@
|
|||
@using Iceshrimp.Frontend.Localization
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inject ApiService Api
|
||||
@inject SessionService SessionService
|
||||
@inject NavigationManager Navigation
|
||||
@inject ApiService Api
|
||||
@inject SessionService SessionService
|
||||
@inject NavigationManager Navigation
|
||||
@inject IStringLocalizer<Localization> Loc;
|
||||
@layout LoginLayout
|
||||
@inject MetadataService Metadata;
|
||||
@layout UnauthLayout
|
||||
<div class="body">
|
||||
<span><h3>Login</h3></span>
|
||||
<img class="logo" src="/_content/Iceshrimp.Assets.Branding/splash.png"/>
|
||||
<span>
|
||||
<h3>@Loc["Login to {0}", Name ?? "this Iceshrimp.NET Instance."]</h3></span>
|
||||
<div class="login-form">
|
||||
<input placeholder="@Loc["Username"]" required="required"
|
||||
@bind="@Username"/>
|
||||
|
@ -30,8 +33,6 @@
|
|||
<span>Authentication Failed</span>
|
||||
}
|
||||
|
||||
<span><p>A login page is being constructed here.</p></span>
|
||||
|
||||
</div>
|
||||
@code {
|
||||
[SupplyParameterFromQuery(Name = "rd")]
|
||||
|
@ -42,6 +43,7 @@
|
|||
private string? Username { get; set; }
|
||||
private bool Loading { get; set; }
|
||||
private bool Failure { get; set; }
|
||||
private string? Name { get; set; }
|
||||
|
||||
private async Task Submit()
|
||||
{
|
||||
|
@ -76,7 +78,7 @@
|
|||
MovedTo = res.User.MovedTo
|
||||
});
|
||||
SessionService.SetSession(res.User.Id);
|
||||
Navigation.NavigateTo(Uri.TryCreate(Redirect, UriKind.Relative, out _) ? Redirect : "/");
|
||||
Navigation.NavigateTo(Uri.TryCreate(Redirect, UriKind.Relative, out _) ? Redirect : "/", true);
|
||||
break;
|
||||
case AuthStatusEnum.Guest:
|
||||
Failure = true;
|
||||
|
@ -94,4 +96,10 @@
|
|||
StateHasChanged(); // Manually triggering a state update, else component will not re-render.
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var metadata = await Metadata.Instance.Value;
|
||||
Name = metadata.Name;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,12 @@
|
|||
}
|
||||
|
||||
.login-form {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 3rem;
|
||||
}
|
117
Iceshrimp.Frontend/Pages/Register.razor
Normal file
117
Iceshrimp.Frontend/Pages/Register.razor
Normal file
|
@ -0,0 +1,117 @@
|
|||
@page "/register"
|
||||
@using Iceshrimp.Frontend.Core.Miscellaneous
|
||||
@using Iceshrimp.Frontend.Core.Schemas
|
||||
@using Iceshrimp.Frontend.Core.Services
|
||||
@using Iceshrimp.Shared.Schemas.Web
|
||||
@using Microsoft.Extensions.Localization
|
||||
@layout UnauthLayout
|
||||
@inject IStringLocalizer<Register> Loc;
|
||||
@inject MetadataService Metadata;
|
||||
@inject ApiService Api;
|
||||
@inject SessionService SessionService;
|
||||
@inject NavigationManager Navigation;
|
||||
@if (State is State.Loaded)
|
||||
{
|
||||
<div class="body">
|
||||
<img class="logo" src="/_content/Iceshrimp.Assets.Branding/splash.png"/>
|
||||
<span>
|
||||
<h3>@Loc["Register on {0}", Name ?? "this Iceshrimp.NET Instance."]</h3></span>
|
||||
@if (RegistrationAvailability is not Registrations.Closed)
|
||||
{
|
||||
<div class="register-form">
|
||||
<input placeholder="@Loc["Username"]" required="required"
|
||||
@bind="@Username"/>
|
||||
<input type="password" required="required" placeholder="@Loc["Password"]"
|
||||
@bind="@Password"/>
|
||||
@if (RegistrationAvailability is Registrations.Invite)
|
||||
{
|
||||
<input required="required" placeholder="@Loc["Invite"]" @bind="@Invite"/>
|
||||
}
|
||||
<button class="button" @onclick="Submit" disabled="@Loading">@Loc["Register"]</button>
|
||||
</div>
|
||||
@if (Result is RegistrationResult.Failure)
|
||||
{
|
||||
<div>@Loc[RegistrationError ?? string.Empty]</div>
|
||||
}
|
||||
}
|
||||
@if (RegistrationAvailability is Registrations.Closed)
|
||||
{
|
||||
<div>@Loc["Registrations for this instance are closed."]</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private string? Username { get; set; }
|
||||
private string? Password { get; set; }
|
||||
private string? Invite { get; set; }
|
||||
private bool Loading { get; set; }
|
||||
private RegistrationResult Result { get; set; }
|
||||
private Registrations RegistrationAvailability { get; set; }
|
||||
private State State { get; set; } = State.Loading;
|
||||
private string? RegistrationError { get; set; }
|
||||
private string? Name { get; set; }
|
||||
|
||||
private async Task Submit()
|
||||
{
|
||||
Loading = true;
|
||||
StateHasChanged();
|
||||
if (Username is null || Password is null)
|
||||
{
|
||||
Result = RegistrationResult.Failure;
|
||||
RegistrationError = "Please fill out all fields";
|
||||
Loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var registration = new RegistrationRequest { Username = Username, Password = Password, Invite = Invite, };
|
||||
try
|
||||
{
|
||||
var res = await Api.Auth.RegisterAsync(registration);
|
||||
if (res.Status is AuthStatusEnum.Authenticated)
|
||||
{
|
||||
SessionService.AddUser(new StoredUser
|
||||
{ // Token nor user will ever be null on an authenticated response
|
||||
Id = res.User!.Id,
|
||||
Username = res.User.Username,
|
||||
DisplayName = res.User.DisplayName,
|
||||
AvatarUrl = res.User.AvatarUrl,
|
||||
BannerUrl = res.User.BannerUrl,
|
||||
InstanceName = res.User.InstanceName,
|
||||
InstanceIconUrl = res.User.InstanceIconUrl,
|
||||
Token = res.Token!,
|
||||
Host = res.User.Host,
|
||||
IsAdmin = res.IsAdmin ?? false,
|
||||
Emojis = res.User.Emojis,
|
||||
MovedTo = res.User.MovedTo
|
||||
});
|
||||
SessionService.SetSession(res.User.Id);
|
||||
Navigation.NavigateTo("/");
|
||||
}
|
||||
|
||||
Loading = false;
|
||||
}
|
||||
catch (ApiException e)
|
||||
{
|
||||
RegistrationError = e.Response.Message;
|
||||
Result = RegistrationResult.Failure;
|
||||
Loading = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private enum RegistrationResult
|
||||
{
|
||||
Incomplete,
|
||||
Success,
|
||||
Failure
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var metadata = await Metadata.Instance.Value;
|
||||
RegistrationAvailability = metadata.Registration;
|
||||
State = State.Loaded;
|
||||
Name = metadata.Name;
|
||||
}
|
||||
}
|
20
Iceshrimp.Frontend/Pages/Register.razor.css
Normal file
20
Iceshrimp.Frontend/Pages/Register.razor.css
Normal file
|
@ -0,0 +1,20 @@
|
|||
.body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.register-form {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
input:invalid {
|
||||
border: 0.1rem solid var(--highlight-color);
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 3rem;
|
||||
}
|
|
@ -2,10 +2,10 @@ namespace Iceshrimp.Shared.Schemas.Web;
|
|||
|
||||
public class InstanceResponse
|
||||
{
|
||||
public required string AccountDomain { get; set; }
|
||||
public required string WebDomain { get; set; }
|
||||
|
||||
// TODO: Add more instance metadata
|
||||
public required string AccountDomain { get; set; }
|
||||
public required string WebDomain { get; set; }
|
||||
public required Registrations Registration { get; set; }
|
||||
public required string? Name { get; set; }
|
||||
}
|
||||
|
||||
public class StaffResponse
|
||||
|
@ -13,3 +13,10 @@ public class StaffResponse
|
|||
public required List<UserResponse> Admins { get; set; }
|
||||
public required List<UserResponse> Moderators { get; set; }
|
||||
}
|
||||
|
||||
public enum Registrations
|
||||
{
|
||||
Closed = 0,
|
||||
Invite = 1,
|
||||
Open = 2
|
||||
}
|
Loading…
Add table
Reference in a new issue