11 type request
= { id
: int, usr
: int, pkgs
: string, msg
: string, status
: status
, stamp
: C
.timestamp
}
17 | _
=> raise C
.Sql
"Bad APT request status"
24 fun statusFromSql v
= statusFromInt (C
.intFromSql v
)
25 fun statusToSql s
= C
.intToSql (statusToInt s
)
27 fun mkRequestRow
[id
, usr
, pkgs
, msg
, status
, stamp
] =
28 {id
= C
.intFromSql id
, usr
= C
.intFromSql usr
, pkgs
= C
.stringFromSql pkgs
,
29 msg
= C
.stringFromSql msg
, status
= statusFromSql status
, stamp
= C
.timestampFromSql stamp
}
30 | mkRequestRow r
= rowError ("APT request", r
)
32 fun addRequest (usr
, pkgs
, msg
) =
35 val id
= nextSeq (db
, "AptSeq")
37 C
.dml
db ($`INSERT INTO
Apt (id
, usr
, pkgs
, msg
, status
, stamp
)
38 VALUES (^
(C
.intToSql id
), ^
(C
.intToSql usr
), ^
(C
.stringToSql pkgs
), ^
(C
.stringToSql msg
),
39 0, CURRENT_TIMESTAMP
)`
);
43 fun modRequest (req
: request
) =
47 ignore (C
.dml
db ($`UPDATE Apt SET
48 usr
= ^
(C
.intToSql (#usr req
)), pkgs
= ^
(C
.stringToSql (#pkgs req
)),
49 msg
= ^
(C
.stringToSql (#msg req
)), status
= ^
(statusToSql (#status req
))
50 WHERE id
= ^
(C
.intToSql (#id req
))`
))
53 fun deleteRequest id
=
54 ignore (C
.dml (getDb ()) ($`DELETE FROM Apt WHERE id
= ^
(C
.intToSql id
)`
))
56 fun lookupRequest id
=
57 case C
.oneOrNoRows (getDb ()) ($`SELECT id
, usr
, pkgs
, msg
, status
, stamp
59 WHERE id
= ^
(C
.intToSql id
)`
) of
60 SOME row
=> mkRequestRow row
61 | NONE
=> raise Fail
"APT request not found"
63 fun mkRequestRow
' (name
:: rest
) = (C
.stringFromSql name
, mkRequestRow rest
)
64 | mkRequestRow
' r
= rowError ("Apt.request'", r
)
67 C
.map (getDb ()) mkRequestRow
' ($`SELECT name
, Apt
.id
, usr
, pkgs
, msg
, status
, stamp
68 FROM Apt JOIN WebUser ON usr
= WebUser
.id
71 fun listOpenRequests () =
72 C
.map (getDb ()) mkRequestRow
' ($`SELECT name
, Apt
.id
, usr
, pkgs
, msg
, status
, stamp
73 FROM Apt JOIN WebUser ON usr
= WebUser
.id
80 case Group
.groupNameToId
"server" of
84 val req
= lookupRequest req
85 val user
= Init
.lookupUser (#usr req
)
87 val mail
= Mail
.mopen ()
91 val name
= C
.stringFromSql name
93 if name
= #name user
then
96 (Mail
.mwrite (mail
, name
);
97 Mail
.mwrite (mail
, ","))
99 | doOne r
= rowError ("apt.doOne", r
)
101 fun rightJustify (n
, s
) =
107 (Mail
.mwrite (mail
, " ");
111 Mail
.mwrite (mail
, s
)
114 val pkgs
= String.tokens
Char.isSpace (#pkgs req
)
115 val infos
= map (valOf
o AptQuery
.query
) pkgs
117 Mail
.mwrite (mail
, "From: Hcoop Portal <portal@hcoop.net>\nTo: ");
118 Mail
.mwrite (mail
, #name user
);
119 Mail
.mwrite (mail
, "@hcoop.net\n");
120 Mail
.mwrite (mail
, "Bcc: ");
121 C
.app (getDb ()) doOne ($`SELECT name
122 FROM WebUser JOIN Membership
ON (usr
= id AND grp
= ^
(C
.intToSql grp
))`
);
123 Mail
.mwrite (mail
, "\nSubject: Apt package installation request\n\n");
128 (rightJustify (10, #name info
);
129 Mail
.mwrite (mail
, " ");
130 Mail
.mwrite (mail
, #descr info
);
131 Mail
.mwrite (mail
, "\n"))) infos
;
133 Mail
.mwrite (mail
, "\n");
134 Mail
.mwrite (mail
, #msg req
);
136 Mail
.mwrite (mail
, "\n\nOpen requests: ");
137 Mail
.mwrite (mail
, urlPrefix
);
138 Mail
.mwrite (mail
, "apt?cmd=open\n");
140 OS
.Process
.isSuccess (Mail
.mclose mail
)
143 val notifyNew
= notify (fn (user
, mail
) =>
144 (Mail
.mwrite (mail
, #name user
);
145 Mail
.mwrite (mail
, " has requested the following packages:\n\n")))
149 | INSTALLED
=> "Installed"
150 | REJECTED
=> "Rejected"
152 fun notifyMod (oldStatus
, newStatus
, changer
, req
) =
153 notify (fn (_
, mail
) =>
154 (Mail
.mwrite (mail
, changer
);
155 Mail
.mwrite (mail
, " has changed the status of this request from ");
156 Mail
.mwrite (mail
, statusToString oldStatus
);
157 Mail
.mwrite (mail
, " to ");
158 Mail
.mwrite (mail
, statusToString newStatus
);
159 Mail
.mwrite (mail
, ".\n\n"))) req