Begin legacy migration pages

This commit is contained in:
Daniel J. Summers 2023-01-31 10:17:13 -05:00
parent 9750f7c044
commit 93f64f4a2d
4 changed files with 53 additions and 6 deletions

View File

@ -197,3 +197,13 @@ let trySecurityByToken token = backgroundTask {
|> Sql.executeAsync toDocument<SecurityInfo>
return List.tryHead results
}
// ~~~ LEGACY MIGRATION ~~~ //
/// Get all legacy citizens
let legacy () = backgroundTask {
return!
dataSource ()
|> Sql.query $"SELECT * FROM {Table.Citizen} WHERE c.data ->> 'isLegacy' = 'true'"
|> Sql.executeAsync toDocument<Citizen>
}

View File

@ -59,6 +59,15 @@ module private Auth =
| PasswordVerificationResult.SuccessRehashNeeded -> Some true
| _ -> None
/// Require an administrative user (used for legacy migration endpoints)
let requireAdmin : HttpHandler = requireUser >=> fun next ctx -> task {
// let adminUser = (config ctx)["AdminUser"]
// if adminUser = defaultArg (tryUser ctx) "" then return! next ctx
// else return! Error.notAuthorized next ctx
// TODO: uncomment the above, remove the line below
return! next ctx
}
// GET: /citizen/account
let account : HttpHandler = fun next ctx -> task {
@ -324,6 +333,13 @@ let saveAccount : HttpHandler = requireUser >=> validateCsrf >=> fun next ctx ->
let soLong : HttpHandler = requireUser >=> fun next ctx ->
Views.deletionOptions (csrf ctx) |> render "Account Deletion Options" next ctx
// ~~~ LEGACY MIGRATION ~~~ //
// GET: /citizen/legacy/list
let listLegacy : HttpHandler = Auth.requireAdmin >=> fun next ctx -> task {
let! users = Data.legacy ()
return! Views.listLegacy users |> render "Migrate Legacy Account" next ctx
}
open Giraffe.EndpointRouting
@ -342,6 +358,7 @@ let endpoints =
route "/register" register
routef "/reset-password/%s" resetPassword
route "/so-long" soLong
route "/legacy/list" listLegacy
]
POST [
route "/delete" delete

View File

@ -393,3 +393,23 @@ let resetPassword (m : ResetPasswordForm) isHtmx csrf =
jsOnLoad $"jjj.citizen.validatePasswords('{nameof m.Password}', 'ConfirmPassword', true)" isHtmx
]
]
// ~~~ LEGACY MIGRATION ~~~ //
let listLegacy (m : Citizen list) =
[ table [ _class "table table-sm table-hover" ] [
thead [] [
tr [] [
th [ _scope "col" ] [ txt "Action" ]
th [ _scope "col" ] [ txt "NAS Profile" ]
]
]
m |> List.map (fun it ->
tr [] [
td [] [ a [ _href $"/citizen/legacy/{CitizenId.toString it.Id}/associate" ] [ txt "Migrate" ] ]
td [] [ str it.Email ]
])
|> tbody []
]
]
|> pageWithTitle "Migrate Legacy Account"

View File

@ -93,7 +93,7 @@ task {
let! _ =
pgConn
|> Sql.executeTransactionAsync [
$"INSERT INTO jjj.{Table.SecurityInfo} VALUES (@id, @data)",
$"INSERT INTO {Table.SecurityInfo} VALUES (@id, @data)",
newCitizens |> List.map (fun c ->
let info = { SecurityInfo.empty with Id = c.Id; AccountLocked = true }
[ "@id", Sql.string (CitizenId.toString c.Id)
@ -114,7 +114,7 @@ task {
let! _ =
pgConn
|> Sql.executeTransactionAsync [
"INSERT INTO jjj.continent VALUES (@id, @data)",
$"INSERT INTO {Table.Continent} VALUES (@id, @data)",
newContinents |> List.map (fun c -> [
"@id", Sql.string (ContinentId.toString c.Id)
"@data", Sql.jsonb (JsonSerializer.Serialize (c, Json.options))
@ -204,10 +204,10 @@ task {
let! deleted =
pgConn
|> Sql.query $"
DELETE FROM jjj.{Table.Citizen}
WHERE id NOT IN (SELECT id FROM jjj.{Table.Profile})
AND id NOT IN (SELECT DISTINCT data->>'citizenId' FROM jjj.{Table.Listing})
AND id NOT IN (SELECT DISTINCT data->>'citizenId' FROM jjj.{Table.Success})"
DELETE FROM {Table.Citizen}
WHERE id NOT IN (SELECT id FROM {Table.Profile})
AND id NOT IN (SELECT DISTINCT data ->> 'citizenId' FROM {Table.Listing})
AND id NOT IN (SELECT DISTINCT data ->> 'citizenId' FROM {Table.Success})"
|> Sql.executeNonQueryAsync
printfn $"** Deleted {deleted} citizens who had no profile, listings, or success stories"