namespace MyWebLog.Data.SQLite open BitBadger.Documents open BitBadger.Documents.Sqlite open Microsoft.Data.Sqlite open Microsoft.Extensions.Logging open MyWebLog open MyWebLog.Data /// SQLite myWebLog user data implementation type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) = /// Add a user let add user = log.LogTrace "WebLogUser.add" conn.insert Table.WebLogUser user /// Find a user by their ID for the given web log let findById (userId: WebLogUserId) webLogId = log.LogTrace "WebLogUser.findById" conn.findFirstByFields Table.WebLogUser All [ idField userId; webLogField webLogId ] /// Delete a user if they have no posts or pages let delete userId webLogId = backgroundTask { log.LogTrace "WebLogUser.delete" match! findById userId webLogId with | Some _ -> let author = [ Field.Equal (nameof Page.Empty.AuthorId) (string userId) ] let! pageCount = conn.countByFields Table.Page Any author let! postCount = conn.countByFields Table.Post Any author if pageCount + postCount > 0 then return Error "User has pages or posts; cannot delete" else do! conn.deleteById Table.WebLogUser userId return Ok true | None -> return Error "User does not exist" } /// Find a user by their e-mail address for the given web log let findByEmail (email: string) webLogId = log.LogTrace "WebLogUser.findByEmail" conn.findFirstByFields Table.WebLogUser All [ webLogField webLogId; Field.Equal (nameof WebLogUser.Empty.Email) email ] /// Get all users for the given web log let findByWebLog webLogId = backgroundTask { log.LogTrace "WebLogUser.findByWebLog" let! users = conn.findByFields Table.WebLogUser Any [ webLogField webLogId ] return users |> List.sortBy _.PreferredName.ToLowerInvariant() } /// Find the names of users by their IDs for the given web log let findNames webLogId (userIds: WebLogUserId list) = log.LogTrace "WebLogUser.findNames" let fields = [ webLogField webLogId; Field.In (nameof WebLogUser.Empty.Id) (List.map (string >> box) userIds) ] let query = Query.statementWhere (Query.find Table.WebLogUser) (Query.whereByFields All fields) conn.customList query (addFieldParams fields []) (fun rdr -> let user = fromData rdr { Name = string user.Id; Value = user.DisplayName }) /// Restore users from a backup let restore users = backgroundTask { log.LogTrace "WebLogUser.restore" for user in users do do! add user } /// Set a user's last seen date/time to now let setLastSeen userId webLogId = backgroundTask { log.LogTrace "WebLogUser.setLastSeen" match! findById userId webLogId with | Some _ -> do! conn.patchById Table.WebLogUser userId {| LastSeenOn = Noda.now () |} | None -> () } /// Update a user let update (user: WebLogUser) = log.LogTrace "WebLogUser.update" conn.updateById Table.WebLogUser user.Id user interface IWebLogUserData with member _.Add user = add user member _.Delete userId webLogId = delete userId webLogId member _.FindByEmail email webLogId = findByEmail email webLogId member _.FindById userId webLogId = findById userId webLogId member _.FindByWebLog webLogId = findByWebLog webLogId member _.FindNames webLogId userIds = findNames webLogId userIds member _.Restore users = restore users member _.SetLastSeen userId webLogId = setLastSeen userId webLogId member _.Update user = update user