type id = string let id s = s let id_to_string s = s type username = string type username_error = Too_short | Too_long let username_min_length = 4 let username_max_length = 20 let pp_username_error ppf = function | Too_short -> Format.fprintf ppf "a username needs at least %d characters" username_min_length | Too_long -> Format.fprintf ppf "a username can have at most %d characters" username_max_length let username raw = let normalized = String.trim raw |> String.lowercase_ascii in let n = String.length normalized in if n < username_min_length then Error Too_short else if n > username_max_length then Error Too_long else Ok normalized let username_to_string u = u type credential = string (* the bcrypt hash string *) let credential_of_hash h = h let credential_to_hash h = h let hash_password password = Bcrypt.string_of_hash (Bcrypt.hash password) let verify_password credential password = match Bcrypt.hash_of_string credential with | hash -> Bcrypt.verify password hash | exception _ -> false type t = { id : id; username : username; credential : credential }