<commit_before>(* Account role datatype *)
datatype role = Owner | Admin | Moderator


fun int_of_role role =
  case role of
  | Owner => 2
  | Admin => 1
  | Moderator => 0

fun role_of_int role =
  case role of
  | 2 => Owner
  | 1 => Admin
  | 0 => Moderator
  | _ => error <xml>Invalid role</xml>

(* Some typeclass implementations for roles *)
val ord_role =
  mkOrd { Lt = (fn x y => lt (int_of_role x) (int_of_role y))
        , Le = (fn x y => le (int_of_role x) (int_of_role y)) }

val read_role = let
    fun read' x =
      case x of
      | "owner"     => Some Owner
      | "admin"     => Some Admin
      | "moderator" => Some Moderator
      | _ => None
  in
    mkRead
      (fn x => case read' x of
        | None => error <xml>Invalid role: {[x]}</xml>
        | Some x => x)
      read'
  end

val show_role =
  mkShow (fn x =>
    case x of
    | Owner     => "owner"
    | Admin     => "admin"
    | Moderator => "moderator")


(* Admin management *)
table admins :
  { Nam  : string
  , Role : int
  , Hash : string }
  PRIMARY KEY (Nam),


fun create name pass role =
  hash <- Bcrypt.hash pass;
  dml (INSERT INTO admins (Nam, Role, Hash)
       VALUES ( {[name]}, {[int_of_role role]}, {[hash]} ))


fun changeName oldName newName =
  dml (UPDATE admins SET Nam = {[newName]} WHERE Nam = {[oldName]})


fun changePassword name newPass =
  hash <- Bcrypt.hash newPass;
  dml (UPDATE admins SET Hash = {[hash]}
       WHERE Nam = {[name]})


fun delete name =
  dml (DELETE FROM admins WHERE Nam = {[name]})


fun validate name pass =
  x <- oneOrNoRows1 (SELECT admins.Hash FROM admins
                     WHERE admins.Nam = {[name]});
  case x of
  | Some { Hash = hash } =>
    return (Bcrypt.check pass hash)
  | None =>
    return False


fun roleOf name =
  r <- oneOrNoRows1 (SELECT admins.Role FROM admins WHERE admins.Nam = {[name]});
  case r of
  | Some { Role = role } => return (Some (role_of_int role))
  | None => return None


(* Add an owner account if there is none *)
task initialize = fn () =>
  x <- oneOrNoRows1 (SELECT * FROM admins WHERE admins.Role = {[0]});
  case x of
  | Some _ => return ()
  | None => create "owner" "password" Owner



cookie loginToken :
  { User  : string
  , Token : string }


table logged :
  { User : string
  , Hash : string }
  CONSTRAINT User FOREIGN KEY User
    REFERENCES admins(Nam)
    ON UPDATE CASCADE
    ON DELETE CASCADE


fun getHash name token =
  tokens <- queryL1 (SELECT logged.Hash FROM logged
                     WHERE logged.User = {[name]});
  case List.find (fn x => Bcrypt.check token x.Hash) tokens of
  | Some { Hash = hash, ... } => return (Some hash)
  | None => return None


val getAuth =
  tok <- getCookie loginToken;<commit_msg>fixed initializer task crash after reversing role numbers<commit_after>(* Account role datatype *)
datatype role = Owner | Admin | Moderator


fun int_of_role role =
  case role of
  | Owner => 2
  | Admin => 1
  | Moderator => 0

fun role_of_int role =
  case role of
  | 2 => Owner
  | 1 => Admin
  | 0 => Moderator
  | _ => error <xml>Invalid role</xml>

(* Some typeclass implementations for roles *)
val ord_role =
  mkOrd { Lt = (fn x y => lt (int_of_role x) (int_of_role y))
        , Le = (fn x y => le (int_of_role x) (int_of_role y)) }

val read_role = let
    fun read' x =
      case x of
      | "owner"     => Some Owner
      | "admin"     => Some Admin
      | "moderator" => Some Moderator
      | _ => None
  in
    mkRead
      (fn x => case read' x of
        | None => error <xml>Invalid role: {[x]}</xml>
        | Some x => x)
      read'
  end

val show_role =
  mkShow (fn x =>
    case x of
    | Owner     => "owner"
    | Admin     => "admin"
    | Moderator => "moderator")


(* Admin management *)
table admins :
  { Nam  : string
  , Role : int
  , Hash : string }
  PRIMARY KEY (Nam),


fun create name pass role =
  hash <- Bcrypt.hash pass;
  dml (INSERT INTO admins (Nam, Role, Hash)
       VALUES ( {[name]}, {[int_of_role role]}, {[hash]} ))


fun changeName oldName newName =
  dml (UPDATE admins SET Nam = {[newName]} WHERE Nam = {[oldName]})


fun changePassword name newPass =
  hash <- Bcrypt.hash newPass;
  dml (UPDATE admins SET Hash = {[hash]}
       WHERE Nam = {[name]})


fun delete name =
  dml (DELETE FROM admins WHERE Nam = {[name]})


fun validate name pass =
  x <- oneOrNoRows1 (SELECT admins.Hash FROM admins
                     WHERE admins.Nam = {[name]});
  case x of
  | Some { Hash = hash } =>
    return (Bcrypt.check pass hash)
  | None =>
    return False


fun roleOf name =
  r <- oneOrNoRows1 (SELECT admins.Role FROM admins WHERE admins.Nam = {[name]});
  case r of
  | Some { Role = role } => return (Some (role_of_int role))
  | None => return None


(* Add an owner account if there is none *)
task initialize = fn () =>
  x <- oneOrNoRows1 (SELECT * FROM admins WHERE admins.Role = {[int_of_role Owner]});
  case x of
  | Some _ => return ()
  | None => create "owner" "password" Owner



cookie loginToken :
  { User  : string
  , Token : string }


table logged :
  { User : string
  , Hash : string }
  CONSTRAINT User FOREIGN KEY User
    REFERENCES admins(Nam)
    ON UPDATE CASCADE
    ON DELETE CASCADE


fun getHash name token =
  tokens <- queryL1 (SELECT logged.Hash FROM logged
                     WHERE logged.User = {[name]});
  case List.find (fn x => Bcrypt.check token x.Hash) tokens of
  | Some { Hash = hash, ... } => return (Some hash)
  | None => return None


val getAuth =
  tok <- getCookie loginToken;
{'fraction_non_alphanumeric': 0.12418772563176896, 'fraction_numerical': 0.0037906137184115524, 'mean_word_length': 2.4739811912225704, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '55990', 'n_tokens_mistral': 1978, 'n_tokens_neox': 1876, 'n_words': 659}