parent
07aff16c3a
commit
425223a3a8
|
@ -300,7 +300,7 @@ module Map =
|
||||||
passwordHash = getString "password_hash" rdr
|
passwordHash = getString "password_hash" rdr
|
||||||
salt = getGuid "salt" rdr
|
salt = getGuid "salt" rdr
|
||||||
url = tryString "url" rdr
|
url = tryString "url" rdr
|
||||||
authorizationLevel = AuthorizationLevel.parse (getString "authorization_level" rdr)
|
accessLevel = AccessLevel.parse (getString "access_level" rdr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a possibly-missing parameter, substituting null for None
|
/// Add a possibly-missing parameter, substituting null for None
|
||||||
|
|
|
@ -20,7 +20,7 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
|
||||||
cmd.Parameters.AddWithValue ("@passwordHash", user.passwordHash)
|
cmd.Parameters.AddWithValue ("@passwordHash", user.passwordHash)
|
||||||
cmd.Parameters.AddWithValue ("@salt", user.salt)
|
cmd.Parameters.AddWithValue ("@salt", user.salt)
|
||||||
cmd.Parameters.AddWithValue ("@url", maybe user.url)
|
cmd.Parameters.AddWithValue ("@url", maybe user.url)
|
||||||
cmd.Parameters.AddWithValue ("@authorizationLevel", AuthorizationLevel.toString user.authorizationLevel)
|
cmd.Parameters.AddWithValue ("@accessLevel", AccessLevel.toString user.accessLevel)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
// IMPLEMENTATION FUNCTIONS
|
// IMPLEMENTATION FUNCTIONS
|
||||||
|
@ -31,10 +31,10 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
|
||||||
cmd.CommandText <- """
|
cmd.CommandText <- """
|
||||||
INSERT INTO web_log_user (
|
INSERT INTO web_log_user (
|
||||||
id, web_log_id, user_name, first_name, last_name, preferred_name, password_hash, salt, url,
|
id, web_log_id, user_name, first_name, last_name, preferred_name, password_hash, salt, url,
|
||||||
authorization_level
|
access_level
|
||||||
) VALUES (
|
) VALUES (
|
||||||
@id, @webLogId, @userName, @firstName, @lastName, @preferredName, @passwordHash, @salt, @url,
|
@id, @webLogId, @userName, @firstName, @lastName, @preferredName, @passwordHash, @salt, @url,
|
||||||
@authorizationLevel
|
@accessLevel
|
||||||
)"""
|
)"""
|
||||||
addWebLogUserParameters cmd user
|
addWebLogUserParameters cmd user
|
||||||
do! write cmd
|
do! write cmd
|
||||||
|
@ -103,7 +103,7 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
|
||||||
password_hash = @passwordHash,
|
password_hash = @passwordHash,
|
||||||
salt = @salt,
|
salt = @salt,
|
||||||
url = @url,
|
url = @url,
|
||||||
authorization_level = @authorizationLevel
|
access_level = @accessLevel
|
||||||
WHERE id = @id
|
WHERE id = @id
|
||||||
AND web_log_id = @webLogId"""
|
AND web_log_id = @webLogId"""
|
||||||
addWebLogUserParameters cmd user
|
addWebLogUserParameters cmd user
|
||||||
|
|
|
@ -174,7 +174,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>) =
|
||||||
password_hash TEXT NOT NULL,
|
password_hash TEXT NOT NULL,
|
||||||
salt TEXT NOT NULL,
|
salt TEXT NOT NULL,
|
||||||
url TEXT,
|
url TEXT,
|
||||||
authorization_level TEXT NOT NULL);
|
access_level TEXT NOT NULL);
|
||||||
CREATE INDEX web_log_user_web_log_idx ON web_log_user (web_log_id);
|
CREATE INDEX web_log_user_web_log_idx ON web_log_user (web_log_id);
|
||||||
CREATE INDEX web_log_user_user_name_idx ON web_log_user (web_log_id, user_name)"""
|
CREATE INDEX web_log_user_user_name_idx ON web_log_user (web_log_id, user_name)"""
|
||||||
do! write cmd
|
do! write cmd
|
||||||
|
|
|
@ -436,8 +436,8 @@ type WebLogUser =
|
||||||
/// The URL of the user's personal site
|
/// The URL of the user's personal site
|
||||||
url : string option
|
url : string option
|
||||||
|
|
||||||
/// The user's authorization level
|
/// The user's access level
|
||||||
authorizationLevel : AuthorizationLevel
|
accessLevel : AccessLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Functions to support web log users
|
/// Functions to support web log users
|
||||||
|
@ -454,7 +454,7 @@ module WebLogUser =
|
||||||
passwordHash = ""
|
passwordHash = ""
|
||||||
salt = Guid.Empty
|
salt = Guid.Empty
|
||||||
url = None
|
url = None
|
||||||
authorizationLevel = User
|
accessLevel = Author
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the user's displayed name
|
/// Get the user's displayed name
|
||||||
|
@ -463,3 +463,7 @@ module WebLogUser =
|
||||||
seq { match user.preferredName with "" -> user.firstName | n -> n; " "; user.lastName }
|
seq { match user.preferredName with "" -> user.firstName | n -> n; " "; user.lastName }
|
||||||
|> Seq.reduce (+)
|
|> Seq.reduce (+)
|
||||||
name.Trim ()
|
name.Trim ()
|
||||||
|
|
||||||
|
/// Does a user have the required access level?
|
||||||
|
let hasAccess level user =
|
||||||
|
AccessLevel.hasAccess level user.accessLevel
|
||||||
|
|
|
@ -12,6 +12,51 @@ module private Helpers =
|
||||||
Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace('/', '_').Replace('+', '-').Substring (0, 22)
|
Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace('/', '_').Replace('+', '-').Substring (0, 22)
|
||||||
|
|
||||||
|
|
||||||
|
/// A user's access level
|
||||||
|
type AccessLevel =
|
||||||
|
/// The user may create and publish posts and edit the ones they have created
|
||||||
|
| Author
|
||||||
|
/// The user may edit posts they did not create, but may not delete them
|
||||||
|
| Editor
|
||||||
|
/// The user may delete posts and configure web log settings
|
||||||
|
| WebLogAdmin
|
||||||
|
/// The user may manage themes (which affects all web logs for an installation)
|
||||||
|
| Administrator
|
||||||
|
|
||||||
|
/// Functions to support access levels
|
||||||
|
module AccessLevel =
|
||||||
|
|
||||||
|
/// Weightings for access levels
|
||||||
|
let private weights =
|
||||||
|
[ Author, 10
|
||||||
|
Editor, 20
|
||||||
|
WebLogAdmin, 30
|
||||||
|
Administrator, 40
|
||||||
|
]
|
||||||
|
|> Map.ofList
|
||||||
|
|
||||||
|
/// Convert an access level to its string representation
|
||||||
|
let toString =
|
||||||
|
function
|
||||||
|
| Author -> "Author"
|
||||||
|
| Editor -> "Editor"
|
||||||
|
| WebLogAdmin -> "WebLogAdmin"
|
||||||
|
| Administrator -> "Administrator"
|
||||||
|
|
||||||
|
/// Parse an access level from its string representation
|
||||||
|
let parse it =
|
||||||
|
match it with
|
||||||
|
| "Author" -> Author
|
||||||
|
| "Editor" -> Editor
|
||||||
|
| "WebLogAdmin" -> WebLogAdmin
|
||||||
|
| "Administrator" -> Administrator
|
||||||
|
| _ -> invalidOp $"{it} is not a valid access level"
|
||||||
|
|
||||||
|
/// Does a given access level allow an action that requires a certain access level?
|
||||||
|
let hasAccess needed held =
|
||||||
|
weights[needed] <= weights[held]
|
||||||
|
|
||||||
|
|
||||||
/// An identifier for a category
|
/// An identifier for a category
|
||||||
type CategoryId = CategoryId of string
|
type CategoryId = CategoryId of string
|
||||||
|
|
||||||
|
@ -607,26 +652,6 @@ module WebLogId =
|
||||||
let create () = WebLogId (newId ())
|
let create () = WebLogId (newId ())
|
||||||
|
|
||||||
|
|
||||||
/// A level of authorization for a given web log
|
|
||||||
type AuthorizationLevel =
|
|
||||||
/// <summary>The user may administer all aspects of a web log</summary>
|
|
||||||
| Administrator
|
|
||||||
/// <summary>The user is a known user of a web log</summary>
|
|
||||||
| User
|
|
||||||
|
|
||||||
/// Functions to support authorization levels
|
|
||||||
module AuthorizationLevel =
|
|
||||||
|
|
||||||
/// Convert an authorization level to a string
|
|
||||||
let toString = function Administrator -> "Administrator" | User -> "User"
|
|
||||||
|
|
||||||
/// Parse a string into an authorization level
|
|
||||||
let parse value =
|
|
||||||
match value with
|
|
||||||
| "Administrator" -> Administrator
|
|
||||||
| "User" -> User
|
|
||||||
| it -> invalidOp $"{it} is not a valid authorization level"
|
|
||||||
|
|
||||||
|
|
||||||
/// An identifier for a web log user
|
/// An identifier for a web log user
|
||||||
type WebLogUserId = WebLogUserId of string
|
type WebLogUserId = WebLogUserId of string
|
||||||
|
|
|
@ -47,7 +47,7 @@ let doLogOn : HttpHandler = fun next ctx -> task {
|
||||||
Claim (ClaimTypes.NameIdentifier, WebLogUserId.toString user.id)
|
Claim (ClaimTypes.NameIdentifier, WebLogUserId.toString user.id)
|
||||||
Claim (ClaimTypes.Name, $"{user.firstName} {user.lastName}")
|
Claim (ClaimTypes.Name, $"{user.firstName} {user.lastName}")
|
||||||
Claim (ClaimTypes.GivenName, user.preferredName)
|
Claim (ClaimTypes.GivenName, user.preferredName)
|
||||||
Claim (ClaimTypes.Role, user.authorizationLevel.ToString ())
|
Claim (ClaimTypes.Role, AccessLevel.toString user.accessLevel)
|
||||||
}
|
}
|
||||||
let identity = ClaimsIdentity (claims, CookieAuthenticationDefaults.AuthenticationScheme)
|
let identity = ClaimsIdentity (claims, CookieAuthenticationDefaults.AuthenticationScheme)
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ let private doCreateWebLog (args : string[]) (sp : IServiceProvider) = task {
|
||||||
preferredName = "Admin"
|
preferredName = "Admin"
|
||||||
passwordHash = Handlers.User.hashedPassword args[4] args[3] salt
|
passwordHash = Handlers.User.hashedPassword args[4] args[3] salt
|
||||||
salt = salt
|
salt = salt
|
||||||
authorizationLevel = Administrator
|
accessLevel = Administrator
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the default home page
|
// Create the default home page
|
||||||
|
|
Loading…
Reference in New Issue
Block a user