msg : string }
val lookupApp : int -> app
- val listPending : unit -> app list
+ val listApps : status -> app list
val votes : int -> (int * string) list
val vote : int * int -> unit
val deny : int * string -> bool
val approve : int * string -> bool
+ val add : int -> unit
+ val abortAdd : int -> unit
end
\ No newline at end of file
SOME row => mkAppRow row
| NONE => raise Fail "Membership application not found"
-fun listPending () =
+fun listApps status =
C.map (getDb ()) mkAppRow ($`SELECT id, name, rname, email, forward, uses, other, passwd, status, applied, confirmed, decided, msg
FROM MemberApp
- WHERE status = 1
+ WHERE status = ^(statusToSql status)
ORDER BY applied`)
fun mkVoteRow [id, name] = (C.intFromSql id, C.stringFromSql name)
OS.Process.isSuccess (Mail.mclose mail)
end
+fun add app =
+ ignore (C.dml (getDb ()) ($`UPDATE MemberApp
+ SET status = 3
+ WHERE id = ^(C.intToSql app)`))
+
+fun abortAdd app =
+ ignore (C.dml (getDb ()) ($`UPDATE MemberApp
+ SET status = 2
+ WHERE id = ^(C.intToSql app)`))
+
end
\ No newline at end of file
else
%><h3><b>Application approved</b></h3><%
end
+elseif $"cmd" = "approved" then
+ showNormal := false
+
+ %><h3><b>Pending applications</b></h3><%
+
+ foreach appl in App.listApps App.ACCEPTED do %>
+ <br><hr><br>
+ <table>
+ <tr> <td align="right"><b>Received</b>:</td> <td><% #applied appl %></td> </tr>
+ <tr> <td align="right"><b>Approved by</b>:</td> <td><%
+ ref first = true;
+ ref found = false;
+ foreach (id, name) in App.votes (#id appl) do
+ if first then
+ first := false
+ else
+ %>, <%
+ end
+ %><a href="user?id=<% id %>"><% name %></a><%
+ end %> </td> </tr>
+ <tr> <td align="right"><b>Username</b>:</td> <td><% #name appl %></td> </tr>
+ <tr> <td align="right"><b>Real name</b>:</td> <td><% Web.html (#rname appl) %></td> </tr>
+ <tr> <td align="right"><b>E-mail address</b>:</td> <td><a href="mailto:<% #email appl %>"><% #email appl %></a></td> </tr>
+ <tr> <td align="right"><b>Forward e-mail?</b></td> <td><% if #forward appl then %>yes<% else %>no<% end %></td> </tr>
+ <tr> <td align="right" valign="top"><b>Proposed uses</b>:</td> <td><% Web.htmlNl (#uses appl) %></td> </tr>
+ <tr> <td align="right" valign="top"><b>Other information</b>:</td> <td><% Web.htmlNl (#other appl) %></td> </tr>
+ </table>
+
+ <% if root then %>
+ <a href="apps?add=<% #id appl %>">Add this member.</a><br>
+ <% end
+ end
+elseif $"add" <> "" then
+ Group.requireGroupNum 0;
+ showNormal := false;
+ val id = Web.stoi ($"add");
+ val appl = App.lookupApp id;
+ App.add id %>
+
+First, create this UNIX user:
+<blockquote><tt>adduser <% #name appl %> "<% #rname appl %>"<% if #forward appl then %>" <% #email appl %>"<% end %></tt></blockquote>
+
+<form action="users">
+<table>
+<tr> <td align="right"><b>Name</b>:</td> <td><input name="name" value="<% Web.html (#name appl) %>"></td> </tr>
+<tr> <td align="right"><b>Real name</b>:</td> <td><input name="rname" value="<% Web.html (#rname appl) %>"></td> </tr>
+<tr> <td align="right" valign="top"><b>Funded by</b>:</td> <td><select name="bal">
+ <option value="">A new balance</option>
+<% foreach bal in Balance.listBalances () do %>
+ <option value="<% #id bal %>"><% Web.html (#name bal) %></option>
+<% end %>
+</select></td></tr>
+<tr> <td align="right"><b>Initial transaction amount</b>:</td> <td><input name="amount"></td> </tr>
+<tr> <td align="right"><b>Initial transaction description</b>:</td> <td><input name="descr"></td> </tr>
+<tr> <td align="right"><input type="checkbox" name="subscribe" checked></td> <td>Subscribe to hcoop-announce</td> </tr>
+<tr> <td align="right"><b>Groups</b>:</td> <td><select name="grp" size="5" multiple>
+<% foreach group in Group.listGroups () do %>
+ <option value="<% #id group %>"<% if #name group = "paying" then %> selected<% end %>><% Web.html (#name group) %></option>
+<% end %>
+</select></td></tr>
+<tr> <td><input type="submit" name="cmd" value="Create"></td> </tr>
+</table>
+</form>
+
+<a href="apps?abort=<% #id appl %>">Abort adding this member</a>
+
+<% elseif $"abort" <> "" then
+ App.abortAdd (Web.stoi ($"abort"))
+ %><h3><b>Aborted</b></h3><%
+
end %>
<% if showNormal then %>
<h3><b>Pending applications</b></h3>
-<% foreach appl in App.listPending () do %>
+<% foreach appl in App.listApps App.PENDING do %>
<br><hr><br>
<table>
<tr> <td align="right"><b>Received</b>:</td> <td><% #applied appl %></td> </tr>
</table>
<% if board then %>
- <a href="apps?approve=<% #id appl %>">Add this member.</a><br>
+ <a href="apps?approve=<% #id appl %>">Approve this member.</a><br>
<a href="apps?deny=<% #id appl %>">Deny this application.</a>
<% end %>
<% end
val getUser : unit -> user
val getUserId : unit -> int
val getUserName : unit -> string
+
+ val dateString : unit -> string
end
\ No newline at end of file
SOME [id] => SOME (C.intFromSql id)
| _ => NONE
+fun dateString () =
+ case C.oneRow (getDb ()) "SELECT CURRENT_DATE" of
+ [d] => C.stringFromSql d
+ | r => rowError ("dateString", r)
+
end
\ No newline at end of file
-portalsub:
+portalsub: portalsub.sml
mlton portalsub.sml
\ No newline at end of file
fun main () =
case CommandLine.arguments () of
[list, cmd, addr] =>
- if list <> "hcoop-discuss" andalso list <> "hcoop-misc" then
+ if list <> "hcoop-discuss" andalso list <> "hcoop-misc" andalso list <> "hcoop-announce" then
(print "Bad mailing list name\n";
OS.Process.failure)
else if not (validEmail addr) then
else
OS.Process.system (String.concat ["echo ", addr, " | /usr/sbin/add_members -r - ", list])
| "rm" =>
- if isMember (list, addr) then
+ if list = "hcoop-announce" then
+ (print "You can't remove anyone from hcoop-announce.\n";
+ OS.Process.failure)
+ else if isMember (list, addr) then
OS.Process.system (String.concat ["/usr/sbin/remove_members ", list, " ", addr])
else
OS.Process.success
FROM WebUser JOIN Membership ON (usr = id AND grp = ^(C.intToSql (#grp cat)))`
else
$`SELECT name
- FROM WebUser JOIN SupSubscription ON (usr = id AND cat = ^(C.intToSql (#id cat)))`
+ FROM WebUser JOIN SupSubscription ON (usr = id AND cat = ^(C.intToSql (#id cat)))
+ UNION SELECT name
+ FROM WebUser JOIN Membership ON (usr = id AND grp = ^(C.intToSql (#grp cat)))`
fun doOne [name] =
let
| s => Web.stoi s);
val id = Init.addUser ($"name", $"rname", bal);
- Group.addToGroups (id, map Web.stoi (Web.getMultiParam "grp")) %>
+ Group.addToGroups (id, map Web.stoi (Web.getMultiParam "grp"));
+
+ if $"amount" <> "" then
+ val amount = Web.stor ($"amount");
+ val trn = Money.addTransaction ($"descr", amount, Init.dateString ());
+ Money.addCharge {trn = trn, usr = id, amount = amount};
+ Money.applyCharges trn
+ end;
+
+ if $"subscribe" = "on" then
+ if not (Pref.subscribe ("hcoop-announce", $"name" ^ "@hcoop.net")) then
+ %><h3><b>Error subscribing to hcoop-announce</b></h3><%
+ end
+ end %>
<h3><b>Member added</b></h3>
<% end
end
<option value="<% #id bal %>"><% Web.html (#name bal) %></option>
<% end %>
</select></td></tr>
+<tr> <td align="right"><b>Initial transaction amount</b>:</td> <td><input name="amount"></td> </tr>
+<tr> <td align="right"><b>Initial transaction description</b>:</td> <td><input name="descr"></td> </tr>
+<tr> <td align="right"><input type="checkbox" name="subscribe" checked></td> <td>Subscribe to hcoop-announce</td> </tr>
<tr> <td align="right"><b>Groups</b>:</td> <td><select name="grp" size="5" multiple>
<% foreach group in Group.listGroups () do %>
<option value="<% #id group %>"><% Web.html (#name group) %></option>