adamc@1004: open Meta adamc@1001: adamc@1001: functor Make(M : sig adamc@1003: con paper :: {(Type * Type)} adamc@1010: constraint [Id, Document, Authors] ~ paper adamc@1003: val paper : $(map meta paper) adamc@1007: val paperFolder : folder paper adamc@1003: adamc@1001: con review :: {(Type * Type)} adamc@1003: constraint [Paper, User] ~ review adamc@1003: val review : $(map meta review) adamc@1011: val reviewFolder : folder review adamc@1006: adamc@1006: val submissionDeadline : time adamc@1009: val summarizePaper : $(map fst paper) -> xbody adamc@1001: end) = struct adamc@1001: adamc@1003: table user : {Id : int, Nam : string, Password : string, Chair : bool, OnPc : bool} adamc@1003: PRIMARY KEY Id, adamc@1003: CONSTRAINT Nam UNIQUE Nam adamc@1003: sequence userId adamc@1003: adamc@1008: con paper = [Id = int, Document = blob] ++ map fst M.paper adamc@1003: table paper : paper adamc@1003: PRIMARY KEY Id adamc@1003: sequence paperId adamc@1003: adamc@1010: table authorship : {Paper : int, User : int} adamc@1010: PRIMARY KEY (Paper, User), adamc@1011: CONSTRAINT Paper FOREIGN KEY Paper REFERENCES paper(Id) ON DELETE CASCADE, adamc@1010: CONSTRAINT User FOREIGN KEY User REFERENCES user(Id) adamc@1010: adamc@1003: con review = [Paper = int, User = int] ++ map fst M.review adamc@1003: table review : review adamc@1003: PRIMARY KEY (Paper, User), adamc@1003: CONSTRAINT Paper FOREIGN KEY Paper REFERENCES paper(Id), adamc@1003: CONSTRAINT User FOREIGN KEY User REFERENCES user(Id) adamc@1003: sequence reviewId adamc@1003: adamc@1003: cookie login : {Id : int, Password : string} adamc@1003: adamc@1004: val checkLogin = adamc@1003: r <- getCookie login; adamc@1003: case r of adamc@1003: None => return None adamc@1003: | Some r => adamc@1003: oneOrNoRows1 (SELECT user.Id, user.Nam, user.Chair, user.OnPc adamc@1003: FROM user adamc@1003: WHERE user.Id = {[r.Id]} adamc@1003: AND user.Password = {[r.Password]}) adamc@1003: adamc@1010: val getLogin = adamc@1010: ro <- checkLogin; adamc@1010: case ro of adamc@1010: None => error You must be logged in to do that. adamc@1010: | Some r => return r adamc@1010: adamc@1009: fun checkPaper id = adamc@1010: r <- getLogin; adamc@1010: if r.OnPc then adamc@1009: return () adamc@1009: else adamc@1010: error You aren't authorized to see that paper. adamc@1009: adamc@1004: structure Users = BulkEdit.Make(struct adamc@1004: con keyName = #Id adamc@1004: val visible = {Nam = string "Name", adamc@1004: Chair = bool "Chair?", adamc@1004: OnPc = bool "On PC?"} adamc@1004: adamc@1004: val title = "Users" adamc@1004: val isAllowed = adamc@1004: me <- checkLogin; adamc@1004: return (Option.isSome me) adamc@1004: adamc@1004: val t = user adamc@1004: end) adamc@1004: adamc@1010: datatype dnat = O | S of source dnat adamc@1010: type dnatS = source dnat adamc@1010: adamc@1010: fun inc n = adamc@1010: v <- get n; adamc@1010: case v of adamc@1010: O => adamc@1010: n' <- source O; adamc@1010: set n (S n') adamc@1010: | S n => inc n adamc@1010: adamc@1010: fun dec n = adamc@1010: let adamc@1010: fun dec' last n = adamc@1010: v <- get n; adamc@1010: case v of adamc@1010: O => (case last of adamc@1010: None => return () adamc@1010: | Some n' => set n' O) adamc@1010: | S n' => dec' (Some n) n' adamc@1010: in adamc@1010: dec' None n adamc@1010: end adamc@1004: adamc@1003: fun doRegister r = adamc@1003: n <- oneRowE1 (SELECT COUNT( * ) AS N adamc@1003: FROM user adamc@1003: WHERE user.Nam = {[r.Nam]}); adamc@1003: if n > 0 then adamc@1003: register (Some "Sorry; that username is taken.") adamc@1003: else adamc@1003: id <- nextval userId; adamc@1003: dml (INSERT INTO user (Id, Nam, Password, Chair, OnPc) adamc@1003: VALUES ({[id]}, {[r.Nam]}, {[r.Password]}, FALSE, FALSE)); adamc@1003: setCookie login {Id = id, Password = r.Password}; adamc@1003: main () adamc@1003: adamc@1003: and register msg = return adamc@1003:

Registering a New Account

adamc@1003: adamc@1003: {case msg of adamc@1003: None => adamc@1003: | Some msg =>
{[msg]}
} adamc@1003: adamc@1003:
adamc@1003: adamc@1003: adamc@1003: adamc@1003:
Username:
Password:
adamc@1003:
adamc@1003: adamc@1006: and signin r = adamc@1006: ro <- oneOrNoRowsE1 (SELECT user.Id AS N adamc@1006: FROM user adamc@1006: WHERE user.Nam = {[r.Nam]} adamc@1006: AND user.Password = {[r.Password]}); adamc@1006: (case ro of adamc@1006: None => return () adamc@1006: | Some id => setCookie login {Id = id, Password = r.Password}); adamc@1006: m <- main' (); adamc@1006: return adamc@1006: {case ro of adamc@1006: None =>
Invalid username or password.
adamc@1006: | _ => } adamc@1006: adamc@1006: {m} adamc@1006: adamc@1006: adamc@1006: and main' () = adamc@1004: me <- checkLogin; adamc@1006: now <- now; adamc@1006: return
    adamc@1003: {case me of adamc@1006: None => adamc@1006:
  • Register for access
  • adamc@1006:
  • Log in:
    adamc@1006: adamc@1006: adamc@1006: adamc@1006:
    Username:
    Password:
  • adamc@1006:
    adamc@1004: | Some me => adamc@1004:
    Welcome, {[me.Nam]}!
    adamc@1004: adamc@1004: {if me.Chair then adamc@1004:
  • Manage users
  • adamc@1004: else adamc@1004: } adamc@1006: adamc@1009: {if me.OnPc then adamc@1009:
  • All papers
  • adamc@1009: else adamc@1009: } adamc@1009: adamc@1006: {if now < M.submissionDeadline then adamc@1007:
  • Submit
  • adamc@1006: else adamc@1006: } adamc@1004: } adamc@1006:
adamc@1006: adamc@1006: and main () = adamc@1006: m <- main' (); adamc@1006: return {m} adamc@1001: adamc@1008: and submit () = adamc@1008: let adamc@1009: fun doSubmit r = adamc@1010: me <- getLogin; adamc@1010: coauthors <- List.mapM (fn name => oneOrNoRowsE1 (SELECT user.Id AS N adamc@1010: FROM user adamc@1010: WHERE user.Nam = {[name.Nam]})) r.Authors; adamc@1010: if List.exists Option.isNone coauthors then adamc@1010: error At least one of those coauthor usernames isn't registered. adamc@1010: else adamc@1010: id <- nextval paperId; adamc@1010: dml (insert paper ({Id = sql_inject id, Document = sql_inject (fileData r.Document)} adamc@1010: ++ ensql M.paper (r -- #Authors -- #Document) M.paperFolder)); adamc@1010: List.app (fn uid => adamc@1010: case uid of adamc@1010: None => error Impossible empty uid! adamc@1010: | Some uid => dml (INSERT INTO authorship (Paper, User) adamc@1010: VALUES ({[id]}, {[uid]}))) adamc@1010: (Some me.Id :: coauthors); adamc@1010: return adamc@1010: Thanks for submitting! adamc@1010: adamc@1010: adamc@1010: fun authorBlanks n = adamc@1010: case n of adamc@1010: O => adamc@1010: | S n => adamc@1010: Author:
adamc@1010: adamc@1010:
adamc@1010: adamc@1010: and authorBlanksS n = adamc@1010: n <- signal n; adamc@1010: return (authorBlanks n) adamc@1008: in adamc@1010: me <- getLogin; adamc@1010: numAuthors <- source O; adamc@1010: adamc@1008: return adamc@1008:

Submit a Paper

adamc@1008: adamc@1008:
adamc@1010: Author: {[me.Nam]}
adamc@1010: adamc@1010: adamc@1010: adamc@1010: