Version 8 #43
|
@ -234,25 +234,25 @@ let private renderPageTitle viewInfo pgTitle =
|
||||||
/// Render the messages that may need to be displayed to the user
|
/// Render the messages that may need to be displayed to the user
|
||||||
let private messages viewInfo =
|
let private messages viewInfo =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
viewInfo.Messages
|
if List.isEmpty viewInfo.Messages then []
|
||||||
|> List.map (fun msg ->
|
else
|
||||||
table [ _class $"pt-msg {MessageLevel.toCssClass msg.Level}" ] [
|
viewInfo.Messages
|
||||||
tr [] [
|
|> List.map (fun msg ->
|
||||||
td [] [
|
div [ _class $"pt-msg {MessageLevel.toCssClass msg.Level}" ] [
|
||||||
match msg.Level with
|
match msg.Level with
|
||||||
| Info -> ()
|
| Info -> ()
|
||||||
| lvl ->
|
| lvl ->
|
||||||
strong [] [ locStr s[MessageLevel.toString lvl] ]
|
strong [] [ locStr s[MessageLevel.toString lvl] ]
|
||||||
rawText " » "
|
rawText " » "
|
||||||
rawText msg.Text.Value
|
rawText msg.Text.Value
|
||||||
match msg.Description with
|
match msg.Description with
|
||||||
| Some desc ->
|
| Some desc ->
|
||||||
br []
|
br []
|
||||||
div [ _class "description" ] [ rawText desc.Value ]
|
div [ _class "description" ] [ rawText desc.Value ]
|
||||||
| None -> ()
|
| None -> ()
|
||||||
]
|
])
|
||||||
]
|
|> div [ _class "pt-messages" ]
|
||||||
])
|
|> List.singleton
|
||||||
|
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
|
|
@ -32,7 +32,8 @@ type ISession with
|
||||||
with get () = this.GetObject<User> Key.Session.currentUser |> Option.fromObject
|
with get () = this.GetObject<User> Key.Session.currentUser |> Option.fromObject
|
||||||
and set (v : User option) =
|
and set (v : User option) =
|
||||||
match v with
|
match v with
|
||||||
| Some user -> this.SetObject Key.Session.currentUser user
|
| Some user ->
|
||||||
|
this.SetObject Key.Session.currentUser { user with PasswordHash = ""; SmallGroups = ResizeArray() }
|
||||||
| None -> this.Remove Key.Session.currentUser
|
| None -> this.Remove Key.Session.currentUser
|
||||||
|
|
||||||
/// Current messages for the session
|
/// Current messages for the session
|
||||||
|
@ -102,8 +103,7 @@ type HttpContext with
|
||||||
// Set last seen for user
|
// Set last seen for user
|
||||||
this.Db.UpdateEntry { user with LastSeen = Some DateTime.UtcNow }
|
this.Db.UpdateEntry { user with LastSeen = Some DateTime.UtcNow }
|
||||||
let! _ = this.Db.SaveChangesAsync ()
|
let! _ = this.Db.SaveChangesAsync ()
|
||||||
this.Session.CurrentUser <-
|
this.Session.CurrentUser <- Some user
|
||||||
Some { user with PasswordHash = ""; SmallGroups = ResizeArray<UserSmallGroup> () }
|
|
||||||
return Some user
|
return Some user
|
||||||
| None -> return None
|
| None -> return None
|
||||||
| None -> return None
|
| None -> return None
|
||||||
|
|
|
@ -53,16 +53,16 @@ module Hashing =
|
||||||
|
|
||||||
/// Retrieve a user from the database by password, upgrading password hashes if required
|
/// Retrieve a user from the database by password, upgrading password hashes if required
|
||||||
let private findUserByPassword model (db : AppDbContext) = task {
|
let private findUserByPassword model (db : AppDbContext) = task {
|
||||||
let bareUser user = Some { user with PasswordHash = ""; SmallGroups = ResizeArray<UserSmallGroup>() }
|
|
||||||
match! db.TryUserByEmailAndGroup model.Email (idFromShort SmallGroupId model.SmallGroupId) with
|
match! db.TryUserByEmailAndGroup model.Email (idFromShort SmallGroupId model.SmallGroupId) with
|
||||||
| Some user ->
|
| Some user ->
|
||||||
let hasher = PrayerTrackerPasswordHasher ()
|
let hasher = PrayerTrackerPasswordHasher ()
|
||||||
match hasher.VerifyHashedPassword (user, user.PasswordHash, model.Password) with
|
match hasher.VerifyHashedPassword (user, user.PasswordHash, model.Password) with
|
||||||
| PasswordVerificationResult.Success -> return bareUser user
|
| PasswordVerificationResult.Success -> return Some user
|
||||||
| PasswordVerificationResult.SuccessRehashNeeded ->
|
| PasswordVerificationResult.SuccessRehashNeeded ->
|
||||||
db.UpdateEntry { user with PasswordHash = hasher.HashPassword (user, model.Password) }
|
let upgraded = { user with PasswordHash = hasher.HashPassword (user, model.Password) }
|
||||||
|
db.UpdateEntry upgraded
|
||||||
let! _ = db.SaveChangesAsync ()
|
let! _ = db.SaveChangesAsync ()
|
||||||
return bareUser user
|
return Some upgraded
|
||||||
| _ -> return None
|
| _ -> return None
|
||||||
| None -> return None
|
| None -> return None
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,8 @@ let doLogOn : HttpHandler = requireAccess [ AccessLevel.Public ] >=> validateCsr
|
||||||
AuthenticationProperties (
|
AuthenticationProperties (
|
||||||
IssuedUtc = DateTimeOffset.UtcNow,
|
IssuedUtc = DateTimeOffset.UtcNow,
|
||||||
IsPersistent = defaultArg model.RememberMe false))
|
IsPersistent = defaultArg model.RememberMe false))
|
||||||
|
ctx.Db.UpdateEntry { user with LastSeen = Some DateTime.UtcNow }
|
||||||
|
let! _ = ctx.Db.SaveChangesAsync ()
|
||||||
addHtmlInfo ctx s["Log On Successful • Welcome to {0}", s["PrayerTracker"]]
|
addHtmlInfo ctx s["Log On Successful • Welcome to {0}", s["PrayerTracker"]]
|
||||||
return! redirectTo false (sanitizeUrl model.RedirectUrl "/small-group") next ctx
|
return! redirectTo false (sanitizeUrl model.RedirectUrl "/small-group") next ctx
|
||||||
| None -> return! fourOhFour ctx
|
| None -> return! fourOhFour ctx
|
||||||
|
|
|
@ -266,31 +266,35 @@ footer a:hover {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
.pt-table tr:hover {
|
.pt-table thead {
|
||||||
|
background-image: linear-gradient(to bottom, var(--dark), var(--lighter-dark));
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.pt-table tbody tr:hover {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
.pt-table tr th,
|
.pt-table tr th,
|
||||||
.pt-table tr td {
|
.pt-table tr td {
|
||||||
padding: .25rem .5rem;
|
padding: .25rem .5rem;
|
||||||
}
|
}
|
||||||
.pt-table tr td {
|
.pt-table tbody tr td {
|
||||||
border-bottom: dotted 1px #444;
|
border-bottom: solid 1px var(--lighter-dark);
|
||||||
}
|
}
|
||||||
.pt-action-table tr td:first-child {
|
.pt-action-table tbody tr td:first-child {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.pt-action-table tr td:first-child a {
|
.pt-action-table tbody tr td:first-child a {
|
||||||
background-color: lightgray;
|
background-color: gray;
|
||||||
color: white;
|
color: white;
|
||||||
border-radius: .5rem;
|
border-radius: .5rem;
|
||||||
padding: .125rem .5rem .5rem .5rem;
|
padding: .125rem .5rem .5rem .5rem;
|
||||||
margin: 0 .125rem;
|
margin: 0 .125rem;
|
||||||
}
|
}
|
||||||
.pt-action-table tr:hover td:first-child a {
|
.pt-action-table tbody tr:hover td:first-child a {
|
||||||
background-color: navy;
|
background-color: var(--dark);
|
||||||
}
|
}
|
||||||
.pt-action-table tr td:first-child a:hover {
|
.pt-action-table tbody tr td:first-child a:hover {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
/* TODO: Figure out nice CSS transitions for these; these don't work */
|
/* TODO: Figure out nice CSS transitions for these; these don't work */
|
||||||
|
@ -339,6 +343,12 @@ article.pt-overview section div p {
|
||||||
.pt-editor {
|
.pt-editor {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
.pt-messages {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.pt-msg {
|
.pt-msg {
|
||||||
margin: .5rem auto;
|
margin: .5rem auto;
|
||||||
border-top-right-radius: .5rem;
|
border-top-right-radius: .5rem;
|
||||||
|
@ -346,15 +356,12 @@ article.pt-overview section div p {
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-collapse: inherit;
|
border-collapse: inherit;
|
||||||
|
padding: 5px 30px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
.pt-msg ul {
|
.pt-msg ul {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
.pt-msg td {
|
|
||||||
padding: 5px 30px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.pt-msg.error {
|
.pt-msg.error {
|
||||||
background-color: #ffb6c1;
|
background-color: #ffb6c1;
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user