Version 3 #40

Merged
danieljsummers merged 67 commits from version-2-3 into main 2023-02-02 23:47:28 +00:00
4 changed files with 53 additions and 6 deletions
Showing only changes of commit 93f64f4a2d - Show all commits

View File

@ -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>
}

View File

@ -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

View File

@ -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"

View File

@ -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"