Add deletion options (#9)
This commit is contained in:
parent
7c6804c2af
commit
7784ee66ea
|
@ -3,6 +3,6 @@
|
||||||
@inject NavigationManager nav
|
@inject NavigationManager nav
|
||||||
@inject AppState state
|
@inject AppState state
|
||||||
|
|
||||||
<PageTitle Title="Logging in..." />
|
<PageTitle Title="Logging on..." />
|
||||||
|
|
||||||
<p>@Message</p>
|
<p>@Message</p>
|
||||||
|
|
|
@ -115,4 +115,8 @@
|
||||||
<br><a href="/profile/view/@state.User!.Id"><span class="oi oi-file"></span> View Your User Profile</a>
|
<br><a href="/profile/view/@state.User!.Id"><span class="oi oi-file"></span> View Your User Profile</a>
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
|
<p>
|
||||||
|
<br>If you want to delete your profile, or your entire account,
|
||||||
|
<a href="/so-long/options">see your deletion options here</a>.
|
||||||
|
</p>
|
||||||
</Loading>
|
</Loading>
|
||||||
|
|
39
src/JobsJobsJobs/Client/Pages/SoLong/Options.razor
Normal file
39
src/JobsJobsJobs/Client/Pages/SoLong/Options.razor
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
@page "/so-long/options"
|
||||||
|
@inject HttpClient http
|
||||||
|
@inject AppState state
|
||||||
|
@inject NavigationManager nav
|
||||||
|
@inject IToastService toast
|
||||||
|
|
||||||
|
<PageTitle Title="Account Deletion Options" />
|
||||||
|
|
||||||
|
<h3>Account Deletion Options</h3>
|
||||||
|
|
||||||
|
<h4>Option 1 – Delete Your Profile</h4>
|
||||||
|
<p>
|
||||||
|
Utilizing this option will remove your current employment profile and skills. This will preserve any success stories
|
||||||
|
you may have written, and preserves this application’s knowledge of you. This is what you want to use if you
|
||||||
|
want to clear out your profile and start again (and remove the current one from others’ view).
|
||||||
|
</p>
|
||||||
|
<p class="text-center">
|
||||||
|
<button class="btn btn-danger" @onclick=@DeleteProfile>Delete Your Profile</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h4>Option 2 – Delete Your Account</h4>
|
||||||
|
<p>
|
||||||
|
This option will make it like you never visited this site. It will delete your profile, skills, success stories, and
|
||||||
|
account. This is what you want to use if you want to disappear from this application. Clicking the button below
|
||||||
|
<strong>will not</strong> affect your No Agenda Social account in any way; its effects are limited to Jobs, Jobs,
|
||||||
|
Jobs.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em>
|
||||||
|
(This will not revoke this application’s permissions on No Agenda Social; you will have to remove this
|
||||||
|
yourself. The confirmation message has a link where you can do this; once the page loads, find the
|
||||||
|
<strong>Jobs, Jobs, Jobs</strong> entry, and click the <strong>× Revoke</strong> link for that entry.)
|
||||||
|
</em>
|
||||||
|
</p>
|
||||||
|
<p class="text-center">
|
||||||
|
<button class="btn btn-danger" @onclick=@DeleteAccount>Delete Your Entire Account</button>
|
||||||
|
</p>
|
54
src/JobsJobsJobs/Client/Pages/SoLong/Options.razor.cs
Normal file
54
src/JobsJobsJobs/Client/Pages/SoLong/Options.razor.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace JobsJobsJobs.Client.Pages.SoLong
|
||||||
|
{
|
||||||
|
public partial class Options : ComponentBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extract an error phrase from a response similar to <code>404 - Not Found</code>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="response">The HTTP response</param>
|
||||||
|
/// <returns>The formatted error code</returns>
|
||||||
|
private static string ErrorPhrase(HttpResponseMessage response) =>
|
||||||
|
$"{response.StatusCode}{(string.IsNullOrEmpty(response.ReasonPhrase) ? "" : $" - {response.ReasonPhrase }")}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete the profile only; redirect to home page on success
|
||||||
|
/// </summary>
|
||||||
|
private async Task DeleteProfile()
|
||||||
|
{
|
||||||
|
ServerApi.SetJwt(http, state);
|
||||||
|
var result = await http.DeleteAsync("/api/profile/");
|
||||||
|
if (result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
toast.ShowSuccess("Profile Deleted Successfully");
|
||||||
|
nav.NavigateTo("/citizen/dashboard");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toast.ShowError(ErrorPhrase(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete everything pertaining to the user's account
|
||||||
|
/// </summary>
|
||||||
|
private async Task DeleteAccount()
|
||||||
|
{
|
||||||
|
ServerApi.SetJwt(http, state);
|
||||||
|
var result = await http.DeleteAsync("/api/citizen/");
|
||||||
|
if (result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
state.Jwt = "";
|
||||||
|
state.User = null;
|
||||||
|
nav.NavigateTo("/so-long/success");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toast.ShowError(ErrorPhrase(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
src/JobsJobsJobs/Client/Pages/SoLong/Success.razor
Normal file
15
src/JobsJobsJobs/Client/Pages/SoLong/Success.razor
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
@page "/so-long/success"
|
||||||
|
|
||||||
|
<PageTitle Title="Account Deletion Success" />
|
||||||
|
|
||||||
|
<h3>Account Deletion Success</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Your account has been successfully deleted. To revoke the permissions you have previously granted to this
|
||||||
|
application, find it in <a href="https://noagendasocial.com/oauth/authorized_applications">this list</a> and click
|
||||||
|
<strong>× Revoke</strong>. Otherwise, clicking “Log On” will create a new, empty account without
|
||||||
|
prompting you further.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Thank you for participating, and thank you for your courage. #GitmoNation
|
||||||
|
</p>
|
|
@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace JobsJobsJobs.Server.Areas.Api.Controllers
|
namespace JobsJobsJobs.Server.Areas.Api.Controllers
|
||||||
|
@ -44,6 +45,11 @@ namespace JobsJobsJobs.Server.Areas.Api.Controllers
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current citizen ID
|
||||||
|
/// </summary>
|
||||||
|
private CitizenId CurrentCitizenId => CitizenId.Parse(User.FindFirst(ClaimTypes.NameIdentifier)!.Value);
|
||||||
|
|
||||||
[HttpGet("log-on/{authCode}")]
|
[HttpGet("log-on/{authCode}")]
|
||||||
public async Task<IActionResult> LogOn([FromRoute] string authCode)
|
public async Task<IActionResult> LogOn([FromRoute] string authCode)
|
||||||
{
|
{
|
||||||
|
@ -87,5 +93,15 @@ namespace JobsJobsJobs.Server.Areas.Api.Controllers
|
||||||
var citizen = await _db.FindCitizenById(CitizenId.Parse(id));
|
var citizen = await _db.FindCitizenById(CitizenId.Parse(id));
|
||||||
return citizen == null ? NotFound() : Ok(citizen);
|
return citizen == null ? NotFound() : Ok(citizen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
[HttpDelete("")]
|
||||||
|
public async Task<IActionResult> Remove()
|
||||||
|
{
|
||||||
|
await _db.DeleteCitizen(CurrentCitizenId);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,14 @@ namespace JobsJobsJobs.Server.Areas.Api.Controllers
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpDelete("")]
|
||||||
|
public async Task<IActionResult> Remove()
|
||||||
|
{
|
||||||
|
await _db.DeleteProfileByCitizen(CurrentCitizenId);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace JobsJobsJobs.Server.Data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="citizen">The citizen to be added</param>
|
/// <param name="citizen">The citizen to be added</param>
|
||||||
public static async Task AddCitizen(this JobsDbContext db, Citizen citizen) =>
|
public static async Task AddCitizen(this JobsDbContext db, Citizen citizen) =>
|
||||||
await db.Citizens.AddAsync(citizen);
|
await db.Citizens.AddAsync(citizen).ConfigureAwait(false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update a citizen after they have logged on (update last seen, sync display name)
|
/// Update a citizen after they have logged on (update last seen, sync display name)
|
||||||
|
@ -42,5 +42,20 @@ namespace JobsJobsJobs.Server.Data
|
||||||
/// <param name="citizen">The updated citizen</param>
|
/// <param name="citizen">The updated citizen</param>
|
||||||
public static void UpdateCitizen(this JobsDbContext db, Citizen citizen) =>
|
public static void UpdateCitizen(this JobsDbContext db, Citizen citizen) =>
|
||||||
db.Entry(citizen).State = EntityState.Modified;
|
db.Entry(citizen).State = EntityState.Modified;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete a citizen
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="citizenId">The ID of the citizen to be deleted</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task DeleteCitizen(this JobsDbContext db, CitizenId citizenId)
|
||||||
|
{
|
||||||
|
var id = citizenId.ToString();
|
||||||
|
await db.DeleteProfileByCitizen(citizenId).ConfigureAwait(false);
|
||||||
|
await db.Database.ExecuteSqlInterpolatedAsync($"DELETE FROM jjj.success WHERE citizen_id = {id}")
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
await db.Database.ExecuteSqlInterpolatedAsync($"DELETE FROM jjj.citizen WHERE id = {id}")
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,5 +160,18 @@ namespace JobsJobsJobs.Server.Data
|
||||||
x.Profile.SeekingEmployment, x.Profile.RemoteWork, x.Profile.FullTime, x.Profile.LastUpdatedOn))
|
x.Profile.SeekingEmployment, x.Profile.RemoteWork, x.Profile.FullTime, x.Profile.LastUpdatedOn))
|
||||||
.ToListAsync().ConfigureAwait(false);
|
.ToListAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete skills and profile for the given citizen
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="citizenId">The ID of the citizen whose profile should be deleted</param>
|
||||||
|
public static async Task DeleteProfileByCitizen(this JobsDbContext db, CitizenId citizenId)
|
||||||
|
{
|
||||||
|
var id = citizenId.ToString();
|
||||||
|
await db.Database.ExecuteSqlInterpolatedAsync($"DELETE FROM jjj.skill WHERE citizen_id = {id}")
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
await db.Database.ExecuteSqlInterpolatedAsync($"DELETE FROM jjj.profile WHERE citizen_id = {id}")
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user