Add profile page for users to change username/email, download saves, change password.
This commit is contained in:
parent
07a41aeaf5
commit
8f853fab56
7 changed files with 295 additions and 5 deletions
|
@ -24,6 +24,26 @@ namespace LANCommander.Areas.Identity.Pages.Account
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGet(string returnUrl = null, bool force = false)
|
||||
{
|
||||
if (force)
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
_logger.LogInformation("User logged out.");
|
||||
|
||||
if (returnUrl != null)
|
||||
{
|
||||
return LocalRedirect(returnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LocalRedirect("/Identity/Account/Login");
|
||||
}
|
||||
}
|
||||
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPost(string returnUrl = null)
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
|
|
36
LANCommander/Controllers/SavesController.cs
Normal file
36
LANCommander/Controllers/SavesController.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
using LANCommander.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LANCommander.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class SavesController : Controller
|
||||
{
|
||||
private readonly GameSaveService GameSaveService;
|
||||
|
||||
public SavesController(GameSaveService gameSaveService)
|
||||
{
|
||||
GameSaveService = gameSaveService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Download(Guid id)
|
||||
{
|
||||
var save = await GameSaveService.Get(id);
|
||||
|
||||
if (User == null || User.Identity?.Name != save.User?.UserName)
|
||||
return Unauthorized();
|
||||
|
||||
if (save == null)
|
||||
return NotFound();
|
||||
|
||||
var filename = GameSaveService.GetSavePath(save);
|
||||
|
||||
if (!System.IO.File.Exists(filename))
|
||||
return NotFound();
|
||||
|
||||
return File(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), "application/zip", $"{save.User?.UserName} - {save.Game?.Title} - {save.CreatedOn.ToString("MM-dd-yyyy.hh-mm")}");
|
||||
}
|
||||
}
|
||||
}
|
70
LANCommander/Pages/Profile/ChangePassword.razor
Normal file
70
LANCommander/Pages/Profile/ChangePassword.razor
Normal file
|
@ -0,0 +1,70 @@
|
|||
@page "/Profile/ChangePassword"
|
||||
@using Microsoft.AspNetCore.Components.Authorization;
|
||||
@layout ProfileLayout
|
||||
@inject UserManager<User> UserManager
|
||||
@inject IMessageService MessageService
|
||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||
|
||||
<PageHeader Title="Change Password" />
|
||||
|
||||
<div style="padding: 0 24px;">
|
||||
<Form Model="Model" Layout="@FormLayout.Vertical">
|
||||
<FormItem Label="Current Password">
|
||||
<InputPassword @bind-Value="context.CurrentPassword" />
|
||||
</FormItem>
|
||||
<FormItem Label="New Password">
|
||||
<InputPassword @bind-Value="context.NewPassword" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label="Confirm Password">
|
||||
<InputPassword @bind-Value="context.NewPasswordConfirm" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem>
|
||||
<Button OnClick="Change" Type="@ButtonType.Primary">Change</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
User User;
|
||||
ChangePasswordModel Model = new ChangePasswordModel();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||
|
||||
if (authState.User.Identity.IsAuthenticated)
|
||||
User = await UserManager.FindByNameAsync(authState.User.Identity.Name);
|
||||
}
|
||||
|
||||
async void Change()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Model.NewPassword == Model.NewPasswordConfirm)
|
||||
{
|
||||
var result = await UserManager.ChangePasswordAsync(User, Model.CurrentPassword, Model.NewPassword);
|
||||
|
||||
if (result.Succeeded)
|
||||
await MessageService.Success("Password changed!");
|
||||
else
|
||||
foreach (var error in result.Errors)
|
||||
await MessageService.Error(error.Description);
|
||||
}
|
||||
else
|
||||
await MessageService.Error("Passwords don't match!");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await MessageService.Error("Password could not be changed!");
|
||||
}
|
||||
}
|
||||
|
||||
public class ChangePasswordModel
|
||||
{
|
||||
public string CurrentPassword { get; set; }
|
||||
public string NewPassword { get; set; }
|
||||
public string NewPasswordConfirm { get; set; }
|
||||
}
|
||||
}
|
60
LANCommander/Pages/Profile/Index.razor
Normal file
60
LANCommander/Pages/Profile/Index.razor
Normal file
|
@ -0,0 +1,60 @@
|
|||
@page "/Profile"
|
||||
@using Microsoft.AspNetCore.Components.Authorization;
|
||||
@layout ProfileLayout
|
||||
@inject UserManager<User> UserManager
|
||||
@inject SignInManager<User> SignInManager
|
||||
@inject IMessageService MessageService
|
||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<PageHeader Title="Profile" />
|
||||
|
||||
<div style="padding: 0 24px;">
|
||||
<p>Changing your username or email will force you to log out.</p>
|
||||
<Form @ref="Form" Model="User" Layout="@FormLayout.Vertical" OnFinish="Save" ValidateOnChange="true">
|
||||
<FormItem Label="Username">
|
||||
<Input @bind-Value="context.UserName" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label="Email Address">
|
||||
<Input @bind-Value="context.Email" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem>
|
||||
<Button HtmlType="submit" Type="@ButtonType.Primary" Disabled="!Form.IsModified">Save</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
User User = new User();
|
||||
Form<User> Form;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||
|
||||
if (authState.User.Identity.IsAuthenticated)
|
||||
User = await UserManager.FindByNameAsync(authState.User.Identity.Name);
|
||||
}
|
||||
|
||||
private async Task Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Form.IsModified)
|
||||
{
|
||||
await UserManager.UpdateAsync(User);
|
||||
|
||||
MessageService.Success("Profile updated!");
|
||||
|
||||
NavigationManager.NavigateTo("/Identity/Account/Logout?force=true", true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await MessageService.Error("An unknown error occurred.");
|
||||
}
|
||||
}
|
||||
}
|
16
LANCommander/Pages/Profile/ProfileLayout.razor
Normal file
16
LANCommander/Pages/Profile/ProfileLayout.razor
Normal file
|
@ -0,0 +1,16 @@
|
|||
@inherits LayoutComponentBase
|
||||
@layout MainLayout
|
||||
|
||||
<Layout Class="panel-layout" Style="padding: 24px 0;">
|
||||
<Sider Width="200">
|
||||
<Menu Mode=@MenuMode.Inline Style="height: 100%">
|
||||
<MenuItem RouterLink="/Profile">General</MenuItem>
|
||||
<MenuItem RouterLink="/Profile/ChangePassword">Change Password</MenuItem>
|
||||
<MenuItem RouterLink="/Profile/Saves">Saves</MenuItem>
|
||||
</Menu>
|
||||
</Sider>
|
||||
|
||||
<Content>
|
||||
@Body
|
||||
</Content>
|
||||
</Layout>
|
69
LANCommander/Pages/Profile/Saves.razor
Normal file
69
LANCommander/Pages/Profile/Saves.razor
Normal file
|
@ -0,0 +1,69 @@
|
|||
@page "/Profile/Saves"
|
||||
@using LANCommander.Models;
|
||||
@using Microsoft.AspNetCore.Components.Authorization;
|
||||
@using Microsoft.EntityFrameworkCore;
|
||||
@layout ProfileLayout
|
||||
@inject UserManager<User> UserManager
|
||||
@inject IMessageService MessageService
|
||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||
@inject GameSaveService GameSaveService
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<PageHeader Title="Game Saves" />
|
||||
|
||||
<div style="padding: 0 24px;">
|
||||
<Table TItem="GameSave" DataSource="@GameSaves">
|
||||
<PropertyColumn Property="s => s.Game.Title" Sortable />
|
||||
<PropertyColumn Property="s => s.CreatedOn" Format="MM/dd/yyyy hh:mm tt" Sortable />
|
||||
<ActionColumn Title="">
|
||||
<Space Direction="DirectionVHType.Horizontal">
|
||||
<SpaceItem>
|
||||
<Button Icon="@IconType.Outline.Download" Type="@ButtonType.Text" OnClick="() => Download(context.Id)" />
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<Popconfirm OnConfirm="() => Delete(context)" Title="Are you sure you want to delete this game save?">
|
||||
<Button Icon="@IconType.Outline.Close" Type="@ButtonType.Text" Danger />
|
||||
</Popconfirm>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</ActionColumn>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
User User;
|
||||
ICollection<GameSave> GameSaves = new List<GameSave>();
|
||||
|
||||
bool Loading = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||
|
||||
if (authState.User.Identity.IsAuthenticated)
|
||||
User = await UserManager.FindByNameAsync(authState.User.Identity.Name);
|
||||
|
||||
if (User != null)
|
||||
GameSaves = User.GameSaves.OrderBy(s => s.Game.Title).ThenBy(s => s.CreatedOn).ToList();
|
||||
|
||||
Loading = false;
|
||||
}
|
||||
|
||||
private async Task Download(Guid id)
|
||||
{
|
||||
await JSRuntime.InvokeAsync<object>("open", $"/Saves/Download/{id}", "_blank");
|
||||
}
|
||||
|
||||
private async Task Delete(GameSave gameSave)
|
||||
{
|
||||
GameSaves = new List<GameSave>();
|
||||
|
||||
Loading = true;
|
||||
|
||||
await GameSaveService.Delete(gameSave);
|
||||
|
||||
GameSaves = await GameSaveService.Get(gs => gs.UserId == User.Id).OrderBy(gs => gs.Game.Title).ThenByDescending(gs => gs.UpdatedOn).ToListAsync();
|
||||
|
||||
Loading = false;
|
||||
}
|
||||
}
|
|
@ -1,15 +1,34 @@
|
|||
@inherits LayoutComponentBase
|
||||
@using Microsoft.AspNetCore.Components.Authorization;
|
||||
@using System.Security.Claims;
|
||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||
|
||||
<Layout Class="layout">
|
||||
<MainMenu>
|
||||
<MenuItem RouterLink="/Dashboard">Dashboard</MenuItem>
|
||||
@if (User != null && User.IsInRole("Administrator"))
|
||||
{
|
||||
<MenuItem RouterLink="/Games">Games</MenuItem>
|
||||
<MenuItem RouterLink="/Servers">Servers</MenuItem>
|
||||
<MenuItem RouterLink="/Files">Files</MenuItem>
|
||||
<MenuItem RouterLink="/Settings">Settings</MenuItem>
|
||||
}
|
||||
<MenuItem RouterLink="/Profile">Profile</MenuItem>
|
||||
</MainMenu>
|
||||
|
||||
<Content Style="padding: 24px; min-height: 100vh;">
|
||||
@Body
|
||||
</Content>
|
||||
</Layout>
|
||||
|
||||
@code {
|
||||
ClaimsPrincipal User;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||
|
||||
if (authState.User.Identity.IsAuthenticated)
|
||||
User = authState.User;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue