]>
Commit | Line | Data |
---|---|---|
2c3a6c0a DM |
1 | package PVE::API2::User; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use PVE::Cluster qw (cfs_read_file cfs_write_file); | |
6 | use PVE::Tools qw(split_list); | |
7 | use PVE::AccessControl; | |
8 | use PVE::JSONSchema qw(get_standard_option); | |
9 | ||
10 | use PVE::SafeSyslog; | |
11 | ||
12 | use Data::Dumper; # fixme: remove | |
13 | ||
14 | use PVE::RESTHandler; | |
15 | ||
16 | use base qw(PVE::RESTHandler); | |
17 | ||
18 | my $extract_user_data = sub { | |
19 | my ($data, $full) = @_; | |
20 | ||
21 | my $res = {}; | |
22 | ||
23 | foreach my $prop (qw(enable expire firstname lastname email comment)) { | |
24 | $res->{$prop} = $data->{$prop} if defined($data->{$prop}); | |
25 | } | |
26 | ||
27 | return $res if !$full; | |
28 | ||
29 | $res->{groups} = $data->{groups} ? [ keys %{$data->{groups}} ] : []; | |
30 | ||
31 | return $res; | |
32 | }; | |
33 | ||
34 | __PACKAGE__->register_method ({ | |
35 | name => 'index', | |
36 | path => '', | |
37 | method => 'GET', | |
38 | description => "User index.", | |
39 | parameters => { | |
40 | additionalProperties => 0, | |
41 | properties => {}, | |
42 | }, | |
43 | returns => { | |
44 | type => 'array', | |
45 | items => { | |
46 | type => "object", | |
47 | properties => { | |
48 | userid => { type => 'string' }, | |
49 | }, | |
50 | }, | |
51 | links => [ { rel => 'child', href => "{userid}" } ], | |
52 | }, | |
53 | code => sub { | |
54 | my ($param) = @_; | |
55 | ||
56 | my $res = []; | |
57 | ||
58 | my $usercfg = cfs_read_file("user.cfg"); | |
59 | ||
60 | foreach my $user (keys %{$usercfg->{users}}) { | |
61 | next if $user eq 'root'; | |
62 | ||
63 | my $entry = &$extract_user_data($usercfg->{users}->{$user}); | |
64 | $entry->{userid} = $user; | |
65 | push @$res, $entry; | |
66 | } | |
67 | ||
68 | return $res; | |
69 | }}); | |
70 | ||
71 | __PACKAGE__->register_method ({ | |
72 | name => 'create_user', | |
73 | protected => 1, | |
74 | path => '', | |
75 | method => 'POST', | |
76 | description => "Create new user.", | |
77 | parameters => { | |
78 | additionalProperties => 0, | |
79 | properties => { | |
80 | userid => get_standard_option('userid'), | |
81 | password => { type => 'string', optional => 1 }, | |
82 | groups => { type => 'string', optional => 1, format => 'pve-groupid-list'}, | |
83 | firstname => { type => 'string', optional => 1 }, | |
84 | lastname => { type => 'string', optional => 1 }, | |
85 | email => { type => 'string', optional => 1, format => 'email-opt' }, | |
86 | comment => { type => 'string', optional => 1 }, | |
87 | expire => { | |
88 | description => "Account expiration date (seconds since epoch). '0' means no expiration date.", | |
89 | type => 'integer', | |
90 | minimum => 0, | |
91 | optional => 1, | |
92 | }, | |
93 | enable => { | |
94 | description => "Enable the account (default). You can set this to '0' to disable the accout", | |
95 | type => 'boolean', | |
96 | optional => 1, | |
97 | default => 1, | |
98 | }, | |
99 | }, | |
100 | }, | |
101 | returns => { type => 'null' }, | |
102 | code => sub { | |
103 | my ($param) = @_; | |
104 | ||
105 | PVE::AccessControl::lock_user_config( | |
106 | sub { | |
107 | ||
108 | my ($username, $ruid, $realm) = PVE::AccessControl::verify_username($param->{userid}); | |
109 | ||
110 | my $usercfg = cfs_read_file("user.cfg"); | |
111 | ||
112 | die "user '$username' already exists\n" | |
113 | if $usercfg->{users}->{$username}; | |
114 | ||
115 | PVE::AccessControl::domain_set_password($realm, $ruid, $param->{password}) | |
116 | if $param->{password}; | |
117 | ||
118 | my $enable = defined($param->{enable}) ? $param->{enable} : 1; | |
119 | $usercfg->{users}->{$username} = { enable => $enable }; | |
120 | $usercfg->{users}->{$username}->{expire} = $param->{expire} if $param->{expire}; | |
121 | ||
122 | if ($param->{groups}) { | |
123 | foreach my $group (split_list($param->{groups})) { | |
124 | if ($usercfg->{groups}->{$group}) { | |
125 | PVE::AccessControl::add_user_group($username, $usercfg, $group); | |
126 | } else { | |
127 | die "no such group '$group'\n"; | |
128 | } | |
129 | } | |
130 | } | |
131 | ||
132 | $usercfg->{users}->{$username}->{firstname} = $param->{firstname} if $param->{firstname}; | |
133 | $usercfg->{users}->{$username}->{lastname} = $param->{lastname} if $param->{lastname}; | |
134 | $usercfg->{users}->{$username}->{email} = $param->{email} if $param->{email}; | |
135 | $usercfg->{users}->{$username}->{comment} = $param->{comment} if $param->{comment}; | |
136 | ||
137 | cfs_write_file("user.cfg", $usercfg); | |
138 | }, "create user failed"); | |
139 | ||
140 | return undef; | |
141 | }}); | |
142 | ||
143 | __PACKAGE__->register_method ({ | |
144 | name => 'read_user', | |
145 | path => '{userid}', | |
146 | method => 'GET', | |
147 | description => "Get user configuration.", | |
148 | parameters => { | |
149 | additionalProperties => 0, | |
150 | properties => { | |
151 | userid => get_standard_option('userid'), | |
152 | }, | |
153 | }, | |
154 | returns => { | |
155 | additionalProperties => 0, | |
156 | properties => { | |
157 | enable => { type => 'boolean' }, | |
158 | expire => { type => 'integer', optional => 1 }, | |
159 | firstname => { type => 'string', optional => 1 }, | |
160 | lastname => { type => 'string', optional => 1 }, | |
161 | email => { type => 'string', optional => 1 }, | |
162 | comment => { type => 'string', optional => 1 }, | |
163 | groups => { type => 'array' }, | |
164 | } | |
165 | }, | |
166 | code => sub { | |
167 | my ($param) = @_; | |
168 | ||
169 | my ($username, undef, $domain) = | |
170 | PVE::AccessControl::verify_username($param->{userid}); | |
171 | ||
172 | my $usercfg = cfs_read_file("user.cfg"); | |
173 | ||
174 | my $data = $usercfg->{users}->{$username}; | |
175 | ||
176 | die "user '$username' does not exist\n" if !$data; | |
177 | ||
178 | return &$extract_user_data($data, 1); | |
179 | }}); | |
180 | ||
181 | __PACKAGE__->register_method ({ | |
182 | name => 'update_user', | |
183 | protected => 1, | |
184 | path => '{userid}', | |
185 | method => 'PUT', | |
186 | description => "Update user configuration.", | |
187 | parameters => { | |
188 | additionalProperties => 0, | |
189 | properties => { | |
190 | userid => get_standard_option('userid'), | |
191 | password => { type => 'string', optional => 1 }, | |
192 | groups => { type => 'string', optional => 1, format => 'pve-groupid-list' }, | |
193 | append => { | |
194 | type => 'boolean', | |
195 | optional => 1, | |
196 | requires => 'groups', | |
197 | }, | |
198 | enable => { | |
199 | description => "Enable/disable the account.", | |
200 | type => 'boolean', | |
201 | optional => 1, | |
202 | }, | |
203 | firstname => { type => 'string', optional => 1 }, | |
204 | lastname => { type => 'string', optional => 1 }, | |
205 | email => { type => 'string', optional => 1, format => 'email-opt' }, | |
206 | comment => { type => 'string', optional => 1 }, | |
207 | expire => { | |
208 | description => "Account expiration date (seconds since epoch). '0' means no expiration date.", | |
209 | type => 'integer', | |
210 | minimum => 0, | |
211 | optional => 1 | |
212 | }, | |
213 | }, | |
214 | }, | |
215 | returns => { type => 'null' }, | |
216 | code => sub { | |
217 | my ($param) = @_; | |
218 | ||
219 | PVE::AccessControl::lock_user_config( | |
220 | sub { | |
221 | ||
222 | my ($username, $ruid, $realm) = | |
223 | PVE::AccessControl::verify_username($param->{userid}); | |
224 | ||
225 | my $usercfg = cfs_read_file("user.cfg"); | |
226 | ||
227 | die "user '$username' does not exist\n" | |
228 | if !$usercfg->{users}->{$username}; | |
229 | ||
230 | PVE::AccessControl::domain_set_password($realm, $ruid, $param->{password}) | |
231 | if $param->{password}; | |
232 | ||
233 | $usercfg->{users}->{$username}->{enable} = $param->{enable} if defined($param->{enable}); | |
234 | ||
235 | $usercfg->{users}->{$username}->{expire} = $param->{expire} if defined($param->{expire}); | |
236 | ||
237 | PVE::AccessControl::delete_user_group($username, $usercfg) | |
238 | if (!$param->{append} && $param->{groups}); | |
239 | ||
240 | if ($param->{groups}) { | |
241 | foreach my $group (split_list($param->{groups})) { | |
242 | if ($usercfg->{groups}->{$group}) { | |
243 | PVE::AccessControl::add_user_group($username, $usercfg, $group); | |
244 | } else { | |
245 | die "no such group '$group'\n"; | |
246 | } | |
247 | } | |
248 | } | |
249 | ||
250 | $usercfg->{users}->{$username}->{firstname} = $param->{firstname} if defined($param->{firstname}); | |
251 | $usercfg->{users}->{$username}->{lastname} = $param->{lastname} if defined($param->{lastname}); | |
252 | $usercfg->{users}->{$username}->{email} = $param->{email} if defined($param->{email}); | |
253 | $usercfg->{users}->{$username}->{comment} = $param->{comment} if defined($param->{comment}); | |
254 | ||
255 | cfs_write_file("user.cfg", $usercfg); | |
256 | }, "update user failed"); | |
257 | ||
258 | return undef; | |
259 | }}); | |
260 | ||
261 | __PACKAGE__->register_method ({ | |
262 | name => 'delete_user', | |
263 | protected => 1, | |
264 | path => '{userid}', | |
265 | method => 'DELETE', | |
266 | description => "Delete user.", | |
267 | parameters => { | |
268 | additionalProperties => 0, | |
269 | properties => { | |
270 | userid => get_standard_option('userid'), | |
271 | } | |
272 | }, | |
273 | returns => { type => 'null' }, | |
274 | code => sub { | |
275 | my ($param) = @_; | |
276 | ||
277 | PVE::AccessControl::lock_user_config( | |
278 | sub { | |
279 | ||
280 | my ($username, $ruid, $realm) = | |
281 | PVE::AccessControl::verify_username($param->{userid}); | |
282 | ||
283 | my $usercfg = cfs_read_file("user.cfg"); | |
284 | ||
285 | die "user '$username' does not exist\n" | |
286 | if !$usercfg->{users}->{$username}; | |
287 | ||
288 | delete ($usercfg->{users}->{$username}); | |
289 | ||
290 | PVE::AccessControl::delete_shadow_password($ruid) if $realm eq 'pve'; | |
291 | PVE::AccessControl::delete_user_group($username, $usercfg); | |
292 | PVE::AccessControl::delete_user_acl($username, $usercfg); | |
293 | ||
294 | cfs_write_file("user.cfg", $usercfg); | |
295 | }, "delete user failed"); | |
296 | ||
297 | return undef; | |
298 | }}); | |
299 | ||
300 | 1; |