Migrate profile/account deletion
This commit is contained in:
parent
415cbbf650
commit
3593d84fe6
|
@ -74,19 +74,6 @@ const routes: Array<RouteRecordRaw> = [
|
||||||
component: () => import(/* webpackChunkName: "joblist" */ "../views/listing/MyListings.vue"),
|
component: () => import(/* webpackChunkName: "joblist" */ "../views/listing/MyListings.vue"),
|
||||||
meta: { auth: true, title: "My Job Listings" }
|
meta: { auth: true, title: "My Job Listings" }
|
||||||
},
|
},
|
||||||
// "So Long" URLs
|
|
||||||
{
|
|
||||||
path: "/so-long/options",
|
|
||||||
name: "DeletionOptions",
|
|
||||||
component: () => import(/* webpackChunkName: "so-long" */ "../views/so-long/DeletionOptions.vue"),
|
|
||||||
meta: { auth: true, title: "Account Deletion Options" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/so-long/success",
|
|
||||||
name: "DeletionSuccess",
|
|
||||||
component: () => import(/* webpackChunkName: "so-long" */ "../views/so-long/DeletionSuccess.vue"),
|
|
||||||
meta: { auth: false, title: "Account Deletion Success" }
|
|
||||||
},
|
|
||||||
// Success Story URLs
|
// Success Story URLs
|
||||||
{
|
{
|
||||||
path: "/success-story/list",
|
path: "/success-story/list",
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
<template>
|
|
||||||
<article>
|
|
||||||
<h3 class="pb-3">Account Deletion Options</h3>
|
|
||||||
<h4 class="pb-3">Option 1 – Delete Your Profile</h4>
|
|
||||||
<p>
|
|
||||||
Utilizing this option will remove your current employment profile and skills. This will preserve any job listings
|
|
||||||
you may have posted, or 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" @click.prevent="deleteProfile">Delete Your Profile</button>
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
<h4 class="pb-3">Option 2 – Delete Your Account</h4>
|
|
||||||
<p>
|
|
||||||
This option will make it like you never visited this site. It will delete your profile, skills, job listings,
|
|
||||||
success stories, and account. This is what you want to use if you want to disappear from this application.
|
|
||||||
</p>
|
|
||||||
<p class="text-center">
|
|
||||||
<button class="btn btn-danger" @click.prevent="deleteAccount">Delete Your Entire Account</button>
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { useRouter } from "vue-router"
|
|
||||||
|
|
||||||
import api, { LogOnSuccess } from "@/api"
|
|
||||||
import { toastError, toastSuccess } from "@/components/layout/AppToaster.vue"
|
|
||||||
import { useStore, Mutations } from "@/store"
|
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
/** The currently logged-on user */
|
|
||||||
const user = store.state.user as LogOnSuccess
|
|
||||||
|
|
||||||
/** Delete the profile only; redirect to home page on success */
|
|
||||||
const deleteProfile = async () => {
|
|
||||||
const resp = await api.profile.delete(user)
|
|
||||||
if (typeof resp === "string") {
|
|
||||||
toastError(resp, "Deleting Profile")
|
|
||||||
} else {
|
|
||||||
toastSuccess("Profile Deleted Successfully")
|
|
||||||
await router.push("/citizen/dashboard")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete everything pertaining to the user's account */
|
|
||||||
const deleteAccount = async () => {
|
|
||||||
const resp = await api.citizen.delete(user)
|
|
||||||
if (typeof resp === "string") {
|
|
||||||
toastError(resp, "Deleting Account")
|
|
||||||
} else {
|
|
||||||
store.commit(Mutations.ClearUser)
|
|
||||||
toastSuccess("Account Deleted Successfully")
|
|
||||||
await router.push("/so-long/success")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<template>
|
|
||||||
<article>
|
|
||||||
<h3 class="pb-3">Account Deletion Success</h3>
|
|
||||||
<p> </p>
|
|
||||||
<p>Your account has been successfully deleted.</p>
|
|
||||||
<p> </p>
|
|
||||||
<p>Thank you for participating, and thank you for your courage. #GitmoNation</p>
|
|
||||||
</article>
|
|
||||||
</template>
|
|
|
@ -289,6 +289,13 @@ module Citizen =
|
||||||
return! Citizen.dashboard citizen.Value profile prfCount |> render "Dashboard" next ctx
|
return! Citizen.dashboard citizen.Value profile prfCount |> render "Dashboard" next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST: /citizen/delete
|
||||||
|
let delete : HttpHandler = requireUser >=> validateCsrf >=> fun next ctx -> task {
|
||||||
|
do! Citizens.deleteById (currentCitizenId ctx)
|
||||||
|
do! ctx.SignOutAsync ()
|
||||||
|
return! render "Account Deleted Successfully" next ctx Citizen.deleted
|
||||||
|
}
|
||||||
|
|
||||||
// GET: /citizen/deny/[token]
|
// GET: /citizen/deny/[token]
|
||||||
let deny token next ctx = task {
|
let deny token next ctx = task {
|
||||||
let! wasDeleted = Citizens.denyAccount token
|
let! wasDeleted = Citizens.denyAccount token
|
||||||
|
@ -402,6 +409,10 @@ module Citizen =
|
||||||
return! refreshPage () next ctx
|
return! refreshPage () next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET: /citizen/so-long
|
||||||
|
let soLong : HttpHandler = requireUser >=> fun next ctx ->
|
||||||
|
Citizen.deletionOptions (csrf ctx) |> render "Account Deletion Options" next ctx
|
||||||
|
|
||||||
|
|
||||||
/// Handlers for /api/citizen routes
|
/// Handlers for /api/citizen routes
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
|
@ -442,12 +453,6 @@ module CitizenApi =
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE: /api/citizen
|
|
||||||
let delete : HttpHandler = authorize >=> fun next ctx -> task {
|
|
||||||
do! Citizens.deleteById (currentCitizenId ctx)
|
|
||||||
return! ok next ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Handlers for /api/continent routes
|
/// Handlers for /api/continent routes
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
|
@ -590,6 +595,13 @@ module Listing =
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module Profile =
|
module Profile =
|
||||||
|
|
||||||
|
// POST: /profile/delete
|
||||||
|
let delete : HttpHandler = requireUser >=> validateCsrf >=> fun next ctx -> task {
|
||||||
|
do! Profiles.deleteById (currentCitizenId ctx)
|
||||||
|
do! addSuccess "Profile deleted successfully" ctx
|
||||||
|
return! redirectToGet "/citizen/dashboard" next ctx
|
||||||
|
}
|
||||||
|
|
||||||
// GET: /profile/edit
|
// GET: /profile/edit
|
||||||
let edit : HttpHandler = requireUser >=> fun next ctx -> task {
|
let edit : HttpHandler = requireUser >=> fun next ctx -> task {
|
||||||
let citizenId = currentCitizenId ctx
|
let citizenId = currentCitizenId ctx
|
||||||
|
@ -743,12 +755,6 @@ module ProfileApi =
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE: /api/profile
|
|
||||||
let delete : HttpHandler = authorize >=> fun next ctx -> task {
|
|
||||||
do! Profiles.deleteById (currentCitizenId ctx)
|
|
||||||
return! ok next ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Handlers for /api/success routes
|
/// Handlers for /api/success routes
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
|
@ -811,8 +817,10 @@ let allEndpoints = [
|
||||||
route "/log-off" Citizen.logOff
|
route "/log-off" Citizen.logOff
|
||||||
route "/log-on" Citizen.logOn
|
route "/log-on" Citizen.logOn
|
||||||
route "/register" Citizen.register
|
route "/register" Citizen.register
|
||||||
|
route "/so-long" Citizen.soLong
|
||||||
]
|
]
|
||||||
POST [
|
POST [
|
||||||
|
route "/delete" Citizen.delete
|
||||||
route "/log-on" Citizen.doLogOn
|
route "/log-on" Citizen.doLogOn
|
||||||
route "/register" Citizen.doRegistration
|
route "/register" Citizen.doRegistration
|
||||||
]
|
]
|
||||||
|
@ -826,7 +834,10 @@ let allEndpoints = [
|
||||||
route "/search" Profile.search
|
route "/search" Profile.search
|
||||||
route "/seeking" Profile.seeking
|
route "/seeking" Profile.seeking
|
||||||
]
|
]
|
||||||
POST [ route "/save" Profile.save ]
|
POST [
|
||||||
|
route "/delete" Profile.delete
|
||||||
|
route "/save" Profile.save
|
||||||
|
]
|
||||||
]
|
]
|
||||||
GET_HEAD [ route "/terms-of-service" Home.termsOfService ]
|
GET_HEAD [ route "/terms-of-service" Home.termsOfService ]
|
||||||
|
|
||||||
|
@ -836,9 +847,6 @@ let allEndpoints = [
|
||||||
PATCH [
|
PATCH [
|
||||||
route "/account" CitizenApi.account
|
route "/account" CitizenApi.account
|
||||||
]
|
]
|
||||||
DELETE [
|
|
||||||
route "" CitizenApi.delete
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
GET_HEAD [ route "/continents" Continent.all ]
|
GET_HEAD [ route "/continents" Continent.all ]
|
||||||
subRoute "/listing" [
|
subRoute "/listing" [
|
||||||
|
|
|
@ -94,6 +94,46 @@ let dashboard (citizen : Citizen) (profile : Profile option) profileCount =
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
/// The account deletion success page
|
||||||
|
let deleted =
|
||||||
|
article [] [
|
||||||
|
h3 [ _class "pb-3" ] [ rawText "Account Deletion Success" ]
|
||||||
|
p [] [ rawText " " ]
|
||||||
|
p [] [ rawText "Your account has been successfully deleted." ]
|
||||||
|
p [] [ rawText " " ]
|
||||||
|
p [] [ rawText "Thank you for participating, and thank you for your courage. #GitmoNation" ]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
/// The profile or account deletion page
|
||||||
|
let deletionOptions csrf =
|
||||||
|
article [] [
|
||||||
|
h3 [ _class "pb-3" ] [ rawText "Account Deletion Options" ]
|
||||||
|
h4 [ _class "pb-3" ] [ rawText "Option 1 – Delete Your Profile" ]
|
||||||
|
p [] [
|
||||||
|
rawText "Utilizing this option will remove your current employment profile and skills. This will preserve "
|
||||||
|
rawText "any job listings you may have posted, or any success stories you may have written, and preserves "
|
||||||
|
rawText "this application’s knowledge of you. This is what you want to use if you want to clear out "
|
||||||
|
rawText "your profile and start again (and remove the current one from others’ view)."
|
||||||
|
]
|
||||||
|
form [ _class "text-center"; _method "POST"; _action "/profile/delete" ] [
|
||||||
|
antiForgery csrf
|
||||||
|
button [ _type "submit"; _class "btn btn-danger" ] [ rawText "Delete Your Profile" ]
|
||||||
|
]
|
||||||
|
hr []
|
||||||
|
h4 [ _class "pb-3" ] [ rawText "Option 2 – Delete Your Account" ]
|
||||||
|
p [] [
|
||||||
|
rawText "This option will make it like you never visited this site. It will delete your profile, skills, "
|
||||||
|
rawText "job listings, success stories, and account. This is what you want to use if you want to disappear "
|
||||||
|
rawText "from this application."
|
||||||
|
]
|
||||||
|
form [ _class "text-center"; _method "POST"; _action "/citizen/delete" ] [
|
||||||
|
antiForgery csrf
|
||||||
|
button [ _type "submit"; _class "btn btn-danger" ] [ rawText "Delete Your Entire Account" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
/// The account denial page
|
/// The account denial page
|
||||||
let denyAccount wasDeleted =
|
let denyAccount wasDeleted =
|
||||||
article [] [
|
article [] [
|
||||||
|
@ -179,11 +219,11 @@ let register q1 q2 (m : RegisterViewModel) csrf =
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
div [ _class "col-12 col-xl-6" ] [
|
div [ _class "col-12 col-xl-6" ] [
|
||||||
textBox [ _type "text"; _maxlength "30" ] (nameof m.Question1Answer) m.Question1Answer "Question 1" true
|
textBox [ _type "text"; _maxlength "30" ] (nameof m.Question1Answer) m.Question1Answer q1 true
|
||||||
input [ _type "hidden"; _name (nameof m.Question1Index); _value (string m.Question1Index ) ]
|
input [ _type "hidden"; _name (nameof m.Question1Index); _value (string m.Question1Index ) ]
|
||||||
]
|
]
|
||||||
div [ _class "col-12 col-xl-6" ] [
|
div [ _class "col-12 col-xl-6" ] [
|
||||||
textBox [ _type "text"; _maxlength "30" ] (nameof m.Question2Answer) m.Question2Answer "Question 2" true
|
textBox [ _type "text"; _maxlength "30" ] (nameof m.Question2Answer) m.Question2Answer q2 true
|
||||||
input [ _type "hidden"; _name (nameof m.Question2Index); _value (string m.Question2Index ) ]
|
input [ _type "hidden"; _name (nameof m.Question2Index); _value (string m.Question2Index ) ]
|
||||||
]
|
]
|
||||||
div [ _class "col-12" ] [
|
div [ _class "col-12" ] [
|
||||||
|
|
|
@ -117,7 +117,7 @@ let edit (m : EditProfileViewModel) continents isNew citizenId csrf =
|
||||||
hr []
|
hr []
|
||||||
p [ _class "text-muted fst-italic" ] [
|
p [ _class "text-muted fst-italic" ] [
|
||||||
rawText "(If you want to delete your profile, or your entire account, "
|
rawText "(If you want to delete your profile, or your entire account, "
|
||||||
a [ _href "/so-long/options" ] [ rawText "see your deletion options here" ]; rawText ".)"
|
a [ _href "/citizen/so-long" ] [ rawText "see your deletion options here" ]; rawText ".)"
|
||||||
]
|
]
|
||||||
script [] [
|
script [] [
|
||||||
rawText """addEventListener("DOMContentLoaded", function () {"""
|
rawText """addEventListener("DOMContentLoaded", function () {"""
|
||||||
|
|
Loading…
Reference in New Issue
Block a user