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