Limited DNS nodes
[hcoop/domtool2.git] / src / acl.sml
CommitLineData
12adf55a
AC
1(* HCoop Domtool (http://hcoop.sourceforge.net/)
2 * Copyright (c) 2006, Adam Chlipala
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *)
18
19(* Per-user access control lists for resources various *)
20
21structure Acl :> ACL = struct
22
23type acl = {user : string,
24 class : string,
25 value : string}
26
27structure SM = DataStructures.StringMap
28structure SS = DataStructures.StringSet
29
30val acl : SS.set SM.map SM.map ref = ref SM.empty
31
32fun query {user, class, value} =
33 case SM.find (!acl, user) of
34 NONE => false
35 | SOME classes =>
36 case SM.find (classes, class) of
37 NONE => false
38 | SOME values => SS.member (values, value)
39
08a04eb4
AC
40fun queryAll user =
41 case SM.find (!acl, user) of
42 NONE => []
43 | SOME classes => SM.foldri (fn (class, values, out) =>
44 (class, SS.foldr (op::) [] values) :: out)
45 [] classes
46
094877b1
AC
47fun whoHas {class, value} =
48 SM.foldri (fn (user, classes, users) =>
49 case SM.find (classes, class) of
50 NONE => users
51 | SOME values =>
52 if SS.member (values, value) then
53 user :: users
54 else
55 users) [] (!acl)
56
12adf55a
AC
57fun class {user, class} =
58 case SM.find (!acl, user) of
59 NONE => SS.empty
60 | SOME classes =>
61 case SM.find (classes, class) of
62 NONE => SS.empty
63 | SOME values => values
64
65fun grant {user, class, value} =
66 let
67 val classes = Option.getOpt (SM.find (!acl, user), SM.empty)
68 val values = Option.getOpt (SM.find (classes, class), SS.empty)
69 in
70 acl := SM.insert (!acl, user,
71 SM.insert (classes, class,
72 SS.add (values, value)))
73 end
74
75fun revoke {user, class, value} =
76 let
77 val classes = Option.getOpt (SM.find (!acl, user), SM.empty)
78 val values = Option.getOpt (SM.find (classes, class), SS.empty)
79
80 val values = if SS.member (values, value) then
81 SS.delete (values, value)
82 else
83 values
84 in
85 acl := SM.insert (!acl, user,
86 SM.insert (classes, class,
87 values))
88 end
89
90fun read fname =
91 let
92 val inf = TextIO.openIn fname
93
94 fun users usrs =
95 case TextIO.inputLine inf of
96 NONE => usrs
97 | SOME line =>
98 case String.tokens Char.isSpace line of
99 [user] =>
100 let
101 fun classes clss =
102 case TextIO.inputLine inf of
103 NONE => clss
104 | SOME line =>
105 case String.tokens Char.isSpace line of
106 [] => clss
107 | class :: values =>
108 classes (SM.insert (clss, class,
109 foldl SS.add' SS.empty values))
110 in
111 users (SM.insert (usrs, user, classes SM.empty))
112 end
113 | _ => raise Fail "Unexpected ACL file format"
114 in
115 acl := users SM.empty
116 before TextIO.closeIn inf
117 end
118
119fun write fname =
120 let
121 val outf = TextIO.openOut fname
122
123 val writeValues = SS.app (fn value =>
124 (TextIO.output (outf, " ");
125 TextIO.output (outf, value)))
126
127 val writeClasses = SM.appi (fn (class, values) =>
e2ef704e
AC
128 if SS.isEmpty values then
129 ()
130 else
131 (TextIO.output (outf, class);
132 writeValues values;
133 TextIO.output (outf, "\n")))
12adf55a
AC
134
135 val writeUsers = SM.appi (fn (user, classes) =>
e2ef704e
AC
136 if SM.numItems classes = 0 then
137 ()
138 else
139 (TextIO.output (outf, user);
140 TextIO.output (outf, "\n");
141 writeClasses classes;
142 TextIO.output (outf, "\n")))
12adf55a
AC
143 in
144 writeUsers (!acl);
145 TextIO.closeOut outf
146 end
147
148end