New member application e-mails include applicant's e-mail address in body text
[hcoop/zz_old/portal.git] / app.sml
CommitLineData
20a679fc 1structure App :> APP =
2struct
3
4open Init Sql Util
5
6datatype status =
7 CONFIRMING
8 | PENDING
9 | ACCEPTED
10 | REJECTED
453d7579 11 | ADDED
20a679fc 12
13val statusFromInt =
14 fn 0 => CONFIRMING
15 | 1 => PENDING
16 | 2 => ACCEPTED
17 | 3 => REJECTED
453d7579 18 | 4 => ADDED
20a679fc 19 | _ => raise C.Sql "Bad status"
20
21val statusToInt =
22 fn CONFIRMING => 0
23 | PENDING => 1
24 | ACCEPTED => 2
25 | REJECTED => 3
453d7579 26 | ADDED => 4
20a679fc 27
28fun statusFromSql v = statusFromInt (C.intFromSql v)
29fun statusToSql s = C.intToSql (statusToInt s)
30
5146e435 31type app = { id : int, name : string, rname : string, gname : string option, email : string,
20a679fc 32 forward : bool, uses : string, other : string,
5146e435 33 passwd : string, status : status, applied : C.timestamp, ipaddr : string option,
453d7579 34 confirmed : C.timestamp option, decided : C.timestamp option,
35 msg : string}
20a679fc 36
5146e435 37fun mkAppRow [id, name, rname, gname, email, forward, uses, other, passwd, status,
38 applied, ipaddr, confirmed, decided, msg] =
20a679fc 39 { id = C.intFromSql id, name = C.stringFromSql name, rname = C.stringFromSql rname,
5146e435 40 gname = (if C.isNull gname then NONE else SOME (C.stringFromSql gname)),
20a679fc 41 email = C.stringFromSql email, forward = C.boolFromSql forward,
42 uses = C.stringFromSql uses, other = C.stringFromSql other, passwd = C.stringFromSql passwd,
453d7579 43 status = statusFromSql status, applied = C.timestampFromSql applied,
5146e435 44 ipaddr = (if C.isNull ipaddr then NONE else SOME (C.stringFromSql ipaddr)),
453d7579 45 confirmed = if C.isNull confirmed then NONE else SOME (C.timestampFromSql confirmed),
46 decided = if C.isNull decided then NONE else SOME (C.timestampFromSql decided),
47 msg = C.stringFromSql msg}
20a679fc 48 | mkAppRow r = rowError ("app", r)
49
50fun lookupApp id =
5146e435 51 case C.oneOrNoRows (getDb ()) ($`SELECT id, name, rname, gname, email, forward, uses, other, passwd, status, applied, ipaddr, confirmed, decided, msg
453d7579 52 FROM MemberApp
53 WHERE id = ^(C.intToSql id)`) of
20a679fc 54 SOME row => mkAppRow row
55 | NONE => raise Fail "Membership application not found"
56
4b8df0b1 57fun listApps status =
5146e435 58 C.map (getDb ()) mkAppRow ($`SELECT id, name, rname, gname, email, forward, uses, other, passwd, status, applied, ipaddr, confirmed, decided, msg
453d7579 59 FROM MemberApp
4b8df0b1 60 WHERE status = ^(statusToSql status)
453d7579 61 ORDER BY applied`)
62
63fun mkVoteRow [id, name] = (C.intFromSql id, C.stringFromSql name)
64 | mkVoteRow row = rowError ("app.vote", row)
65
66fun votes id = C.map (getDb ()) mkVoteRow ($`SELECT usr, name
67 FROM AppVote JOIN WebUser ON usr = id
5146e435 68 WHERE AppVote.app = ^(C.intToSql id)
453d7579 69 ORDER BY name`)
70
71fun vote (usr, app) = ignore (C.dml (getDb ()) ($`INSERT INTO AppVote (app, usr)
72 VALUES (^(C.intToSql app), ^(C.intToSql usr))`))
73
74fun unvote (usr, app) = ignore (C.dml (getDb ()) ($`DELETE FROM AppVote WHERE app = ^(C.intToSql app) AND usr = ^(C.intToSql usr)`))
75
76fun deny (app, msg) =
77 let
78 val entry = lookupApp app
79 val _ = C.dml (getDb ()) ($`UPDATE MemberApp
80 SET status = 3, msg = ^(C.stringToSql msg), decided = CURRENT_TIMESTAMP
81 WHERE id = ^(C.intToSql app)`)
82
83 val mail = Mail.mopen ()
84 in
646dca75 85 Mail.mwrite (mail, "From: Hcoop Application System <join");
86 Mail.mwrite (mail, emailSuffix);
87 Mail.mwrite (mail, ">\nTo: ");
453d7579 88 Mail.mwrite (mail, #email entry);
89 Mail.mwrite (mail, "\nCc: ");
90 Mail.mwrite (mail, boardEmail);
91 Mail.mwrite (mail, "\nSubject: Application denied\n\nYour application for membership has been denied. Reason:\n\n");
92 Mail.mwrite (mail, msg);
93 OS.Process.isSuccess (Mail.mclose mail)
94 end
95
96fun approve (app, msg) =
97 let
98 val entry = lookupApp app
99 val _ = C.dml (getDb ()) ($`UPDATE MemberApp
100 SET status = 2, msg = ^(C.stringToSql msg), decided = CURRENT_TIMESTAMP
101 WHERE id = ^(C.intToSql app)`)
102
103 val mail = Mail.mopen ()
104 in
ce7b516a 105 Mail.mwrite (mail, "To: ");
453d7579 106 Mail.mwrite (mail, #email entry);
ce7b516a 107 Mail.mwrite (mail, "\n");
108 Mail.mwrite (mail, Util.readFile "/home/hcoop/portal/welcome.txt");
453d7579 109 Mail.mwrite (mail, msg);
110 OS.Process.isSuccess (Mail.mclose mail)
111 end
112
4b8df0b1 113fun add app =
114 ignore (C.dml (getDb ()) ($`UPDATE MemberApp
115 SET status = 3
116 WHERE id = ^(C.intToSql app)`))
117
118fun abortAdd app =
119 ignore (C.dml (getDb ()) ($`UPDATE MemberApp
120 SET status = 2
121 WHERE id = ^(C.intToSql app)`))
122
5146e435 123fun readFile fname =
124 let
125 val inf = TextIO.openIn fname
126
127 fun readLines lines =
128 case TextIO.inputLine inf of
129 NONE => String.concat (List.rev lines)
130 | SOME line => readLines (line :: lines)
131 in
132 readLines []
133 before TextIO.closeIn inf
134 end
135
f038f26c 136fun readTosBody () = readFile "/home/hcoop/public_html/tos.body.html"
137fun readTosAgree () = readFile "/home/hcoop/public_html/tos.agree.html"
138fun readTosMinorAgree () = readFile "/home/hcoop/public_html/tos.agree.minor.html"
5146e435 139
646dca75 140end