Version 3 #40
|
@ -197,3 +197,13 @@ let trySecurityByToken token = backgroundTask {
|
||||||
|> Sql.executeAsync toDocument<SecurityInfo>
|
|> Sql.executeAsync toDocument<SecurityInfo>
|
||||||
return List.tryHead results
|
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>
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,15 @@ module private Auth =
|
||||||
| PasswordVerificationResult.SuccessRehashNeeded -> Some true
|
| PasswordVerificationResult.SuccessRehashNeeded -> Some true
|
||||||
| _ -> None
|
| _ -> 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
|
// GET: /citizen/account
|
||||||
let account : HttpHandler = fun next ctx -> task {
|
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 ->
|
let soLong : HttpHandler = requireUser >=> fun next ctx ->
|
||||||
Views.deletionOptions (csrf ctx) |> render "Account Deletion Options" 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
|
open Giraffe.EndpointRouting
|
||||||
|
|
||||||
|
@ -342,6 +358,7 @@ let endpoints =
|
||||||
route "/register" register
|
route "/register" register
|
||||||
routef "/reset-password/%s" resetPassword
|
routef "/reset-password/%s" resetPassword
|
||||||
route "/so-long" soLong
|
route "/so-long" soLong
|
||||||
|
route "/legacy/list" listLegacy
|
||||||
]
|
]
|
||||||
POST [
|
POST [
|
||||||
route "/delete" delete
|
route "/delete" delete
|
||||||
|
|
|
@ -393,3 +393,23 @@ let resetPassword (m : ResetPasswordForm) isHtmx csrf =
|
||||||
jsOnLoad $"jjj.citizen.validatePasswords('{nameof m.Password}', 'ConfirmPassword', true)" isHtmx
|
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"
|
||||||
|
|
|
@ -93,7 +93,7 @@ task {
|
||||||
let! _ =
|
let! _ =
|
||||||
pgConn
|
pgConn
|
||||||
|> Sql.executeTransactionAsync [
|
|> Sql.executeTransactionAsync [
|
||||||
$"INSERT INTO jjj.{Table.SecurityInfo} VALUES (@id, @data)",
|
$"INSERT INTO {Table.SecurityInfo} VALUES (@id, @data)",
|
||||||
newCitizens |> List.map (fun c ->
|
newCitizens |> List.map (fun c ->
|
||||||
let info = { SecurityInfo.empty with Id = c.Id; AccountLocked = true }
|
let info = { SecurityInfo.empty with Id = c.Id; AccountLocked = true }
|
||||||
[ "@id", Sql.string (CitizenId.toString c.Id)
|
[ "@id", Sql.string (CitizenId.toString c.Id)
|
||||||
|
@ -114,7 +114,7 @@ task {
|
||||||
let! _ =
|
let! _ =
|
||||||
pgConn
|
pgConn
|
||||||
|> Sql.executeTransactionAsync [
|
|> Sql.executeTransactionAsync [
|
||||||
"INSERT INTO jjj.continent VALUES (@id, @data)",
|
$"INSERT INTO {Table.Continent} VALUES (@id, @data)",
|
||||||
newContinents |> List.map (fun c -> [
|
newContinents |> List.map (fun c -> [
|
||||||
"@id", Sql.string (ContinentId.toString c.Id)
|
"@id", Sql.string (ContinentId.toString c.Id)
|
||||||
"@data", Sql.jsonb (JsonSerializer.Serialize (c, Json.options))
|
"@data", Sql.jsonb (JsonSerializer.Serialize (c, Json.options))
|
||||||
|
@ -204,10 +204,10 @@ task {
|
||||||
let! deleted =
|
let! deleted =
|
||||||
pgConn
|
pgConn
|
||||||
|> Sql.query $"
|
|> Sql.query $"
|
||||||
DELETE FROM jjj.{Table.Citizen}
|
DELETE FROM {Table.Citizen}
|
||||||
WHERE id NOT IN (SELECT id FROM jjj.{Table.Profile})
|
WHERE id NOT IN (SELECT id FROM {Table.Profile})
|
||||||
AND id NOT IN (SELECT DISTINCT data->>'citizenId' FROM jjj.{Table.Listing})
|
AND id NOT IN (SELECT DISTINCT data ->> 'citizenId' FROM {Table.Listing})
|
||||||
AND id NOT IN (SELECT DISTINCT data->>'citizenId' FROM jjj.{Table.Success})"
|
AND id NOT IN (SELECT DISTINCT data ->> 'citizenId' FROM {Table.Success})"
|
||||||
|> Sql.executeNonQueryAsync
|
|> Sql.executeNonQueryAsync
|
||||||
printfn $"** Deleted {deleted} citizens who had no profile, listings, or success stories"
|
printfn $"** Deleted {deleted} citizens who had no profile, listings, or success stories"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user