Release 7.4 #21
@ -3,7 +3,6 @@ module PrayerTracker.DataAccess
|
|||||||
|
|
||||||
open FSharp.Control.Tasks.ContextInsensitive
|
open FSharp.Control.Tasks.ContextInsensitive
|
||||||
open Microsoft.EntityFrameworkCore
|
open Microsoft.EntityFrameworkCore
|
||||||
open Microsoft.FSharpLu
|
|
||||||
open PrayerTracker.Entities
|
open PrayerTracker.Entities
|
||||||
open System.Collections.Generic
|
open System.Collections.Generic
|
||||||
open System.Linq
|
open System.Linq
|
||||||
@ -11,17 +10,29 @@ open System.Linq
|
|||||||
[<AutoOpen>]
|
[<AutoOpen>]
|
||||||
module private Helpers =
|
module private Helpers =
|
||||||
|
|
||||||
|
open Microsoft.FSharpLu
|
||||||
|
open System.Threading.Tasks
|
||||||
|
|
||||||
/// Central place to append sort criteria for prayer request queries
|
/// Central place to append sort criteria for prayer request queries
|
||||||
let reqSort sort (query : IQueryable<PrayerRequest>) =
|
let reqSort sort (q : IQueryable<PrayerRequest>) =
|
||||||
match sort with
|
match sort with
|
||||||
| SortByDate ->
|
| SortByDate ->
|
||||||
query.OrderByDescending(fun pr -> pr.updatedDate)
|
query {
|
||||||
.ThenByDescending(fun pr -> pr.enteredDate)
|
for req in q do
|
||||||
.ThenBy(fun pr -> pr.requestor)
|
sortByDescending req.updatedDate
|
||||||
|
thenByDescending req.enteredDate
|
||||||
|
thenBy req.requestor
|
||||||
|
}
|
||||||
| SortByRequestor ->
|
| SortByRequestor ->
|
||||||
query.OrderBy(fun pr -> pr.requestor)
|
query {
|
||||||
.ThenByDescending(fun pr -> pr.updatedDate)
|
for req in q do
|
||||||
.ThenByDescending(fun pr -> pr.enteredDate)
|
sortBy req.requestor
|
||||||
|
thenByDescending req.updatedDate
|
||||||
|
thenByDescending req.enteredDate
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a possibly-null object to an option, wrapped as a task
|
||||||
|
let toOptionTask<'T> (item : 'T) = (Option.fromObject >> Task.FromResult) item
|
||||||
|
|
||||||
|
|
||||||
type AppDbContext with
|
type AppDbContext with
|
||||||
@ -44,15 +55,22 @@ type AppDbContext with
|
|||||||
|
|
||||||
/// Find a church by its Id
|
/// Find a church by its Id
|
||||||
member this.TryChurchById cId =
|
member this.TryChurchById cId =
|
||||||
task {
|
query {
|
||||||
let! church = this.Churches.AsNoTracking().FirstOrDefaultAsync (fun c -> c.churchId = cId)
|
for ch in this.Churches.AsNoTracking () do
|
||||||
return Option.fromObject church
|
where (ch.churchId = cId)
|
||||||
|
exactlyOneOrDefault
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Find all churches
|
/// Find all churches
|
||||||
member this.AllChurches () =
|
member this.AllChurches () =
|
||||||
task {
|
task {
|
||||||
let! churches = this.Churches.AsNoTracking().OrderBy(fun c -> c.name).ToListAsync ()
|
let q =
|
||||||
|
query {
|
||||||
|
for ch in this.Churches.AsNoTracking () do
|
||||||
|
sortBy ch.name
|
||||||
|
}
|
||||||
|
let! churches = q.ToListAsync ()
|
||||||
return List.ofSeq churches
|
return List.ofSeq churches
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,19 +78,24 @@ type AppDbContext with
|
|||||||
|
|
||||||
/// Get a small group member by its Id
|
/// Get a small group member by its Id
|
||||||
member this.TryMemberById mId =
|
member this.TryMemberById mId =
|
||||||
task {
|
query {
|
||||||
let! mbr = this.Members.AsNoTracking().FirstOrDefaultAsync (fun m -> m.memberId = mId)
|
for mbr in this.Members.AsNoTracking () do
|
||||||
return Option.fromObject mbr
|
where (mbr.memberId = mId)
|
||||||
|
select mbr
|
||||||
|
exactlyOneOrDefault
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Find all members for a small group
|
/// Find all members for a small group
|
||||||
member this.AllMembersForSmallGroup gId =
|
member this.AllMembersForSmallGroup gId =
|
||||||
task {
|
task {
|
||||||
let! mbrs =
|
let q =
|
||||||
this.Members.AsNoTracking()
|
query {
|
||||||
.Where(fun m -> m.smallGroupId = gId)
|
for mbr in this.Members.AsNoTracking () do
|
||||||
.OrderBy(fun m -> m.memberName)
|
where (mbr.smallGroupId = gId)
|
||||||
.ToListAsync ()
|
sortBy mbr.memberName
|
||||||
|
}
|
||||||
|
let! mbrs = q.ToListAsync ()
|
||||||
return List.ofSeq mbrs
|
return List.ofSeq mbrs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,32 +107,44 @@ type AppDbContext with
|
|||||||
|
|
||||||
/// Get a prayer request by its Id
|
/// Get a prayer request by its Id
|
||||||
member this.TryRequestById reqId =
|
member this.TryRequestById reqId =
|
||||||
task {
|
query {
|
||||||
let! req = this.PrayerRequests.AsNoTracking().FirstOrDefaultAsync (fun pr -> pr.prayerRequestId = reqId)
|
for req in this.PrayerRequests.AsNoTracking () do
|
||||||
return Option.fromObject req
|
where (req.prayerRequestId = reqId)
|
||||||
|
exactlyOneOrDefault
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Get all (or active) requests for a small group as of now or the specified date
|
/// Get all (or active) requests for a small group as of now or the specified date
|
||||||
|
// TODO: why not make this an async list like the rest of these methods?
|
||||||
member this.AllRequestsForSmallGroup (grp : SmallGroup) clock listDate activeOnly pageNbr : PrayerRequest seq =
|
member this.AllRequestsForSmallGroup (grp : SmallGroup) clock listDate activeOnly pageNbr : PrayerRequest seq =
|
||||||
let theDate = match listDate with Some dt -> dt | _ -> grp.localDateNow clock
|
let theDate = match listDate with Some dt -> dt | _ -> grp.localDateNow clock
|
||||||
upcast (
|
query {
|
||||||
this.PrayerRequests.AsNoTracking().Where(fun pr -> pr.smallGroupId = grp.smallGroupId)
|
for req in this.PrayerRequests.AsNoTracking () do
|
||||||
|> function
|
where (req.smallGroupId = grp.smallGroupId)
|
||||||
| query when activeOnly ->
|
}
|
||||||
let asOf = theDate.AddDays(-(float grp.preferences.daysToExpire)).Date
|
|> function
|
||||||
query.Where(fun pr ->
|
| q when activeOnly ->
|
||||||
( pr.updatedDate > asOf
|
let asOf = theDate.AddDays(-(float grp.preferences.daysToExpire)).Date
|
||||||
|| pr.expiration = Manual
|
query {
|
||||||
|| pr.requestType = LongTermRequest
|
for req in q do
|
||||||
|| pr.requestType = Expecting)
|
where ( ( req.updatedDate > asOf
|
||||||
&& pr.expiration <> Forced)
|
|| req.expiration = Manual
|
||||||
| query -> query
|
|| req.requestType = LongTermRequest
|
||||||
|> reqSort grp.preferences.requestSort
|
|| req.requestType = Expecting)
|
||||||
|> function
|
&& req.expiration <> Forced)
|
||||||
| query ->
|
}
|
||||||
match activeOnly with
|
| q -> q
|
||||||
| true -> query.Skip 0
|
|> reqSort grp.preferences.requestSort
|
||||||
| false -> query.Skip((pageNbr - 1) * grp.preferences.pageSize).Take grp.preferences.pageSize)
|
|> function
|
||||||
|
| q ->
|
||||||
|
match activeOnly with
|
||||||
|
| true -> upcast q
|
||||||
|
| false ->
|
||||||
|
upcast query {
|
||||||
|
for req in q do
|
||||||
|
skip ((pageNbr - 1) * grp.preferences.pageSize)
|
||||||
|
take grp.preferences.pageSize
|
||||||
|
}
|
||||||
|
|
||||||
/// Count prayer requests for the given small group Id
|
/// Count prayer requests for the given small group Id
|
||||||
member this.CountRequestsBySmallGroup gId =
|
member this.CountRequestsBySmallGroup gId =
|
||||||
@ -120,57 +155,64 @@ type AppDbContext with
|
|||||||
this.PrayerRequests.CountAsync (fun pr -> pr.smallGroup.churchId = cId)
|
this.PrayerRequests.CountAsync (fun pr -> pr.smallGroup.churchId = cId)
|
||||||
|
|
||||||
/// Get all (or active) requests for a small group as of now or the specified date
|
/// Get all (or active) requests for a small group as of now or the specified date
|
||||||
|
// TODO: same as above...
|
||||||
member this.SearchRequestsForSmallGroup (grp : SmallGroup) (searchTerm : string) pageNbr : PrayerRequest seq =
|
member this.SearchRequestsForSmallGroup (grp : SmallGroup) (searchTerm : string) pageNbr : PrayerRequest seq =
|
||||||
let pgSz = grp.preferences.pageSize
|
let pgSz = grp.preferences.pageSize
|
||||||
let skip = (pageNbr - 1) * pgSz
|
let toSkip = (pageNbr - 1) * pgSz
|
||||||
let sql =
|
let sql =
|
||||||
""" SELECT * FROM pt."PrayerRequest" WHERE "SmallGroupId" = {0} AND "Text" ILIKE {1}
|
""" SELECT * FROM pt."PrayerRequest" WHERE "SmallGroupId" = {0} AND "Text" ILIKE {1}
|
||||||
UNION
|
UNION
|
||||||
SELECT * FROM pt."PrayerRequest" WHERE "SmallGroupId" = {0} AND COALESCE("Requestor", '') ILIKE {1}"""
|
SELECT * FROM pt."PrayerRequest" WHERE "SmallGroupId" = {0} AND COALESCE("Requestor", '') ILIKE {1}"""
|
||||||
|> RawSqlString
|
|> RawSqlString
|
||||||
let like = sprintf "%%%s%%"
|
let like = sprintf "%%%s%%"
|
||||||
upcast (
|
this.PrayerRequests.FromSql(sql, grp.smallGroupId, like searchTerm).AsNoTracking ()
|
||||||
this.PrayerRequests.FromSql(sql, grp.smallGroupId, like searchTerm).AsNoTracking ()
|
|> reqSort grp.preferences.requestSort
|
||||||
|> reqSort grp.preferences.requestSort
|
|> function
|
||||||
|> function query -> (query.Skip skip).Take pgSz)
|
| q ->
|
||||||
|
upcast query {
|
||||||
|
for req in q do
|
||||||
|
skip toSkip
|
||||||
|
take pgSz
|
||||||
|
}
|
||||||
|
|
||||||
(*-- SMALL GROUP EXTENSIONS --*)
|
(*-- SMALL GROUP EXTENSIONS --*)
|
||||||
|
|
||||||
/// Find a small group by its Id
|
/// Find a small group by its Id
|
||||||
member this.TryGroupById gId =
|
member this.TryGroupById gId =
|
||||||
task {
|
query {
|
||||||
let! grp =
|
for grp in this.SmallGroups.AsNoTracking().Include (fun sg -> sg.preferences) do
|
||||||
this.SmallGroups.AsNoTracking()
|
where (grp.smallGroupId = gId)
|
||||||
.Include(fun sg -> sg.preferences)
|
exactlyOneOrDefault
|
||||||
.FirstOrDefaultAsync (fun sg -> sg.smallGroupId = gId)
|
|
||||||
return Option.fromObject grp
|
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Get small groups that are public or password protected
|
/// Get small groups that are public or password protected
|
||||||
member this.PublicAndProtectedGroups () =
|
member this.PublicAndProtectedGroups () =
|
||||||
task {
|
task {
|
||||||
let! grps =
|
let smallGroups = this.SmallGroups.AsNoTracking().Include(fun sg -> sg.preferences).Include (fun sg -> sg.church)
|
||||||
this.SmallGroups.AsNoTracking()
|
let q =
|
||||||
.Include(fun sg -> sg.preferences)
|
query {
|
||||||
.Include(fun sg -> sg.church)
|
for grp in smallGroups do
|
||||||
.Where(fun sg ->
|
where ( grp.preferences.isPublic
|
||||||
sg.preferences.isPublic || (sg.preferences.groupPassword <> null && sg.preferences.groupPassword <> ""))
|
|| (grp.preferences.groupPassword <> null && grp.preferences.groupPassword <> ""))
|
||||||
.OrderBy(fun sg -> sg.church.name)
|
sortBy grp.church.name
|
||||||
.ThenBy(fun sg -> sg.name)
|
thenBy grp.name
|
||||||
.ToListAsync ()
|
}
|
||||||
|
let! grps = q.ToListAsync ()
|
||||||
return List.ofSeq grps
|
return List.ofSeq grps
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get small groups that are password protected
|
/// Get small groups that are password protected
|
||||||
member this.ProtectedGroups () =
|
member this.ProtectedGroups () =
|
||||||
task {
|
task {
|
||||||
let! grps =
|
let q =
|
||||||
this.SmallGroups.AsNoTracking()
|
query {
|
||||||
.Include(fun sg -> sg.church)
|
for grp in this.SmallGroups.AsNoTracking().Include (fun sg -> sg.church) do
|
||||||
.Where(fun sg -> sg.preferences.groupPassword <> null && sg.preferences.groupPassword <> "")
|
where (grp.preferences.groupPassword <> null && grp.preferences.groupPassword <> "")
|
||||||
.OrderBy(fun sg -> sg.church.name)
|
sortBy grp.church.name
|
||||||
.ThenBy(fun sg -> sg.name)
|
thenBy grp.name
|
||||||
.ToListAsync ()
|
}
|
||||||
|
let! grps = q.ToListAsync ()
|
||||||
return List.ofSeq grps
|
return List.ofSeq grps
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,12 +232,13 @@ type AppDbContext with
|
|||||||
/// Get a small group list by their Id, with their church prepended to their name
|
/// Get a small group list by their Id, with their church prepended to their name
|
||||||
member this.GroupList () =
|
member this.GroupList () =
|
||||||
task {
|
task {
|
||||||
let! grps =
|
let q =
|
||||||
this.SmallGroups.AsNoTracking()
|
query {
|
||||||
.Include(fun sg -> sg.church)
|
for grp in this.SmallGroups.AsNoTracking().Include (fun sg -> sg.church) do
|
||||||
.OrderBy(fun sg -> sg.church.name)
|
sortBy grp.church.name
|
||||||
.ThenBy(fun sg -> sg.name)
|
thenBy grp.name
|
||||||
.ToListAsync ()
|
}
|
||||||
|
let! grps = q.ToListAsync ()
|
||||||
return grps
|
return grps
|
||||||
|> Seq.map (fun grp -> grp.smallGroupId.ToString "N", sprintf "%s | %s" grp.church.name grp.name)
|
|> Seq.map (fun grp -> grp.smallGroupId.ToString "N", sprintf "%s | %s" grp.church.name grp.name)
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
@ -204,24 +247,22 @@ type AppDbContext with
|
|||||||
/// Log on a small group
|
/// Log on a small group
|
||||||
member this.TryGroupLogOnByPassword gId pw =
|
member this.TryGroupLogOnByPassword gId pw =
|
||||||
task {
|
task {
|
||||||
let! grp = this.TryGroupById gId
|
match! this.TryGroupById gId with
|
||||||
match grp with
|
|
||||||
| None -> return None
|
| None -> return None
|
||||||
| Some g ->
|
| Some grp ->
|
||||||
match pw = g.preferences.groupPassword with
|
match pw = grp.preferences.groupPassword with
|
||||||
| true -> return grp
|
| true -> return Some grp
|
||||||
| _ -> return None
|
| _ -> return None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check a cookie log on for a small group
|
/// Check a cookie log on for a small group
|
||||||
member this.TryGroupLogOnByCookie gId pwHash (hasher : string -> string) =
|
member this.TryGroupLogOnByCookie gId pwHash (hasher : string -> string) =
|
||||||
task {
|
task {
|
||||||
let! grp = this.TryGroupById gId
|
match! this.TryGroupById gId with
|
||||||
match grp with
|
|
||||||
| None -> return None
|
| None -> return None
|
||||||
| Some g ->
|
| Some grp ->
|
||||||
match pwHash = hasher g.preferences.groupPassword with
|
match pwHash = hasher grp.preferences.groupPassword with
|
||||||
| true -> return grp
|
| true -> return Some grp
|
||||||
| _ -> return None
|
| _ -> return None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,15 +274,22 @@ type AppDbContext with
|
|||||||
|
|
||||||
/// Get a time zone by its Id
|
/// Get a time zone by its Id
|
||||||
member this.TryTimeZoneById tzId =
|
member this.TryTimeZoneById tzId =
|
||||||
task {
|
query {
|
||||||
let! tz = this.TimeZones.FirstOrDefaultAsync (fun t -> t.timeZoneId = tzId)
|
for tz in this.TimeZones do
|
||||||
return Option.fromObject tz
|
where (tz.timeZoneId = tzId)
|
||||||
|
exactlyOneOrDefault
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Get all time zones
|
/// Get all time zones
|
||||||
member this.AllTimeZones () =
|
member this.AllTimeZones () =
|
||||||
task {
|
task {
|
||||||
let! tzs = this.TimeZones.OrderBy(fun t -> t.sortOrder).ToListAsync ()
|
let q =
|
||||||
|
query {
|
||||||
|
for tz in this.TimeZones do
|
||||||
|
sortBy tz.sortOrder
|
||||||
|
}
|
||||||
|
let! tzs = q.ToListAsync ()
|
||||||
return List.ofSeq tzs
|
return List.ofSeq tzs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,67 +297,79 @@ type AppDbContext with
|
|||||||
|
|
||||||
/// Find a user by its Id
|
/// Find a user by its Id
|
||||||
member this.TryUserById uId =
|
member this.TryUserById uId =
|
||||||
task {
|
query {
|
||||||
let! user = this.Users.AsNoTracking().FirstOrDefaultAsync (fun u -> u.userId = uId)
|
for usr in this.Users.AsNoTracking () do
|
||||||
return Option.fromObject user
|
where (usr.userId = uId)
|
||||||
|
exactlyOneOrDefault
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Find a user by its e-mail address and authorized small group
|
/// Find a user by its e-mail address and authorized small group
|
||||||
member this.TryUserByEmailAndGroup email gId =
|
member this.TryUserByEmailAndGroup email gId =
|
||||||
task {
|
query {
|
||||||
let! user =
|
for usr in this.Users.AsNoTracking () do
|
||||||
this.Users.AsNoTracking().FirstOrDefaultAsync (fun u ->
|
where (usr.emailAddress = email && usr.smallGroups.Any (fun xref -> xref.smallGroupId = gId))
|
||||||
u.emailAddress = email
|
exactlyOneOrDefault
|
||||||
&& u.smallGroups.Any (fun xref -> xref.smallGroupId = gId))
|
|
||||||
return Option.fromObject user
|
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Find a user by its Id (tracked entity), eagerly loading the user's groups
|
/// Find a user by its Id (tracked entity), eagerly loading the user's groups
|
||||||
member this.TryUserByIdWithGroups uId =
|
member this.TryUserByIdWithGroups uId =
|
||||||
task {
|
query {
|
||||||
let! user = this.Users.Include(fun u -> u.smallGroups).FirstOrDefaultAsync (fun u -> u.userId = uId)
|
for usr in this.Users.AsNoTracking().Include (fun u -> u.smallGroups) do
|
||||||
return Option.fromObject user
|
where (usr.userId = uId)
|
||||||
|
exactlyOneOrDefault
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Get a list of all users
|
/// Get a list of all users
|
||||||
member this.AllUsers () =
|
member this.AllUsers () =
|
||||||
task {
|
task {
|
||||||
let! usrs = this.Users.AsNoTracking().OrderBy(fun u -> u.lastName).ThenBy(fun u -> u.firstName).ToListAsync ()
|
let q =
|
||||||
|
query {
|
||||||
|
for usr in this.Users.AsNoTracking () do
|
||||||
|
sortBy usr.lastName
|
||||||
|
thenBy usr.firstName
|
||||||
|
}
|
||||||
|
let! usrs = q.ToListAsync ()
|
||||||
return List.ofSeq usrs
|
return List.ofSeq usrs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get all PrayerTracker users as members (used to send e-mails)
|
/// Get all PrayerTracker users as members (used to send e-mails)
|
||||||
member this.AllUsersAsMembers () =
|
member this.AllUsersAsMembers () =
|
||||||
task {
|
task {
|
||||||
let! usrs =
|
let q =
|
||||||
this.Users.AsNoTracking().OrderBy(fun u -> u.lastName).ThenBy(fun u -> u.firstName).ToListAsync ()
|
query {
|
||||||
return usrs
|
for usr in this.Users.AsNoTracking () do
|
||||||
|> Seq.map (fun u -> { Member.empty with email = u.emailAddress; memberName = u.fullName })
|
sortBy usr.lastName
|
||||||
|> List.ofSeq
|
thenBy usr.firstName
|
||||||
|
select { Member.empty with email = usr.emailAddress; memberName = usr.fullName }
|
||||||
|
}
|
||||||
|
let! usrs = q.ToListAsync ()
|
||||||
|
return List.ofSeq usrs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a user based on their credentials
|
/// Find a user based on their credentials
|
||||||
member this.TryUserLogOnByPassword email pwHash gId =
|
member this.TryUserLogOnByPassword email pwHash gId =
|
||||||
task {
|
query {
|
||||||
let! user =
|
for usr in this.Users.AsNoTracking () do
|
||||||
this.Users.FirstOrDefaultAsync (fun u ->
|
where ( usr.emailAddress = email
|
||||||
u.emailAddress = email
|
&& usr.passwordHash = pwHash
|
||||||
&& u.passwordHash = pwHash
|
&& usr.smallGroups.Any (fun xref -> xref.smallGroupId = gId))
|
||||||
&& u.smallGroups.Any (fun xref -> xref.smallGroupId = gId))
|
exactlyOneOrDefault
|
||||||
return Option.fromObject user
|
|
||||||
}
|
}
|
||||||
|
|> toOptionTask
|
||||||
|
|
||||||
/// Find a user based on credentials stored in a cookie
|
/// Find a user based on credentials stored in a cookie
|
||||||
member this.TryUserLogOnByCookie uId gId pwHash =
|
member this.TryUserLogOnByCookie uId gId pwHash =
|
||||||
task {
|
task {
|
||||||
let! user = this.TryUserByIdWithGroups uId
|
match! this.TryUserByIdWithGroups uId with
|
||||||
match user with
|
|
||||||
| None -> return None
|
| None -> return None
|
||||||
| Some u ->
|
| Some usr ->
|
||||||
match pwHash = u.passwordHash && u.smallGroups |> Seq.exists (fun xref -> xref.smallGroupId = gId) with
|
match pwHash = usr.passwordHash && usr.smallGroups |> Seq.exists (fun xref -> xref.smallGroupId = gId) with
|
||||||
| true ->
|
| true ->
|
||||||
this.Entry<User>(u).State <- EntityState.Detached
|
this.Entry<User>(usr).State <- EntityState.Detached
|
||||||
return Some { u with passwordHash = ""; salt = None; smallGroups = List<UserSmallGroup>() }
|
return Some { usr with passwordHash = ""; salt = None; smallGroups = List<UserSmallGroup>() }
|
||||||
| _ -> return None
|
| _ -> return None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user