]> git.proxmox.com Git - pmg-api.git/blob - src/PMG/API2/Users.pm
243d19a736410cc689c9e2328aa0ed80a98244d8
[pmg-api.git] / src / PMG / API2 / Users.pm
1 package PMG::API2::Users;
2
3 use strict;
4 use warnings;
5 use Data::Dumper;
6
7 use PVE::SafeSyslog;
8 use PVE::Tools qw(extract_param);
9 use PVE::JSONSchema qw(get_standard_option);
10 use PVE::RESTHandler;
11 use PVE::INotify;
12 use PVE::Exception qw(raise_perm_exc);
13
14 use PMG::RESTEnvironment;
15 use PMG::UserConfig;
16 use PMG::TFAConfig;
17
18 use base qw(PVE::RESTHandler);
19
20 my $extract_userdata = sub {
21 my ($entry) = @_;
22
23 my $res = {};
24 foreach my $k (keys %$entry) {
25 $res->{$k} = $entry->{$k} if $k ne 'crypt_pass';
26 }
27
28 return $res;
29 };
30
31 __PACKAGE__->register_method ({
32 name => 'index',
33 path => '',
34 method => 'GET',
35 description => "List users.",
36 proxyto => 'master',
37 protected => 1,
38 permissions => { check => [ 'admin', 'qmanager', 'audit' ] },
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 enable => { type => 'boolean'},
50 role => { type => 'string'},
51 comment => { type => 'string', optional => 1},
52 },
53 },
54 links => [ { rel => 'child', href => "{userid}" } ],
55 },
56 code => sub {
57 my ($param) = @_;
58
59 my $cfg = PMG::UserConfig->new();
60
61 my $rpcenv = PMG::RESTEnvironment->get();
62 my $authuser = $rpcenv->get_user();
63 my $role = $rpcenv->get_role();
64
65 my $res = [];
66
67 foreach my $userid (sort keys %$cfg) {
68 next if $role eq 'qmanager' && $authuser ne $userid;
69 push @$res, $extract_userdata->($cfg->{$userid});
70 }
71
72 return $res;
73 }});
74
75 __PACKAGE__->register_method ({
76 name => 'create',
77 path => '',
78 method => 'POST',
79 proxyto => 'master',
80 protected => 1,
81 description => "Create new user",
82 parameters => $PMG::UserConfig::create_schema,
83 returns => { type => 'null' },
84 code => sub {
85 my ($param) = @_;
86
87 my $code = sub {
88
89 my $cfg = PMG::UserConfig->new();
90
91 die "User '$param->{userid}' already exists\n"
92 if $cfg->{$param->{userid}};
93
94 my $entry = {};
95 foreach my $k (keys %$param) {
96 my $v = $param->{$k};
97 if ($k eq 'password') {
98 $entry->{crypt_pass} = PVE::Tools::encrypt_pw($v);
99 } else {
100 $entry->{$k} = $v;
101 }
102 }
103
104 $entry->{enable} //= 0;
105 $entry->{expire} //= 0;
106 $entry->{role} //= 'audit';
107
108 $cfg->{$param->{userid}} = $entry;
109
110 $cfg->write();
111 };
112
113 PMG::UserConfig::lock_config($code, "create user failed");
114
115 return undef;
116 }});
117
118 __PACKAGE__->register_method ({
119 name => 'read',
120 path => '{userid}',
121 method => 'GET',
122 description => "Read User data.",
123 permissions => { check => [ 'admin', 'qmanager', 'audit' ] },
124 proxyto => 'master',
125 protected => 1,
126 parameters => {
127 additionalProperties => 0,
128 properties => {
129 userid => get_standard_option('userid'),
130 },
131 },
132 returns => {
133 type => "object",
134 properties => {},
135 },
136 code => sub {
137 my ($param) = @_;
138
139 my $cfg = PMG::UserConfig->new();
140
141 my $rpcenv = PMG::RESTEnvironment->get();
142 my $authuser = $rpcenv->get_user();
143 my $role = $rpcenv->get_role();
144
145 raise_perm_exc()
146 if $role eq 'qmanager' && $authuser ne $param->{userid};
147
148 my $data = $cfg->lookup_user_data($param->{userid});
149
150 my $res = $extract_userdata->($data);
151
152 return $res;
153 }});
154
155 __PACKAGE__->register_method ({
156 name => 'write',
157 path => '{userid}',
158 method => 'PUT',
159 description => "Update user data.",
160 protected => 1,
161 proxyto => 'master',
162 parameters => $PMG::UserConfig::update_schema,
163 returns => { type => 'null' },
164 code => sub {
165 my ($param) = @_;
166
167 my $code = sub {
168
169 my $cfg = PMG::UserConfig->new();
170
171 my $userid = extract_param($param, 'userid');
172
173 my $entry = $cfg->lookup_user_data($userid);
174
175 my $delete_str = extract_param($param, 'delete');
176 die "no options specified\n"
177 if !$delete_str && !scalar(keys %$param);
178
179 foreach my $k (PVE::Tools::split_list($delete_str)) {
180 delete $entry->{$k};
181 }
182
183 foreach my $k (keys %$param) {
184 my $v = $param->{$k};
185 if ($k eq 'password') {
186 $entry->{crypt_pass} = PVE::Tools::encrypt_pw($v);
187 } else {
188 $entry->{$k} = $v;
189 }
190 }
191
192 $cfg->write();
193 };
194
195 PMG::UserConfig::lock_config($code, "update user failed");
196
197 return undef;
198 }});
199
200 __PACKAGE__->register_method ({
201 name => 'delete',
202 path => '{userid}',
203 method => 'DELETE',
204 description => "Delete a user.",
205 protected => 1,
206 proxyto => 'master',
207 parameters => {
208 additionalProperties => 0,
209 properties => {
210 userid => get_standard_option('userid'),
211 }
212 },
213 returns => { type => 'null' },
214 code => sub {
215 my ($param) = @_;
216
217 my $code = sub {
218
219 my $cfg = PMG::UserConfig->new();
220
221 $cfg->lookup_user_data($param->{userid}); # user exists?
222
223 delete $cfg->{$param->{userid}};
224
225 $cfg->write();
226 };
227
228 PMG::UserConfig::lock_config($code, "delete user failed");
229
230 return undef;
231 }});
232
233 __PACKAGE__->register_method ({
234 name => 'unlock_tfa',
235 path => '{userid}/unlock-tfa',
236 method => 'PUT',
237 protected => 1,
238 description => "Unlock a user's TFA authentication.",
239 permissions => { check => [ 'admin' ] },
240 parameters => {
241 additionalProperties => 0,
242 properties => {
243 userid => get_standard_option('userid'),
244 },
245 },
246 returns => { type => 'boolean' },
247 code => sub {
248 my ($param) = @_;
249
250 my $userid = extract_param($param, "userid");
251
252 my $user_was_locked = PMG::TFAConfig::lock_config(sub {
253 my $tfa_cfg = PMG::TFAConfig->new();
254 my $was_locked = $tfa_cfg->api_unlock_tfa($userid);
255 $tfa_cfg->write() if $was_locked;
256 return $was_locked;
257 });
258
259 return $user_was_locked;
260 }});
261
262
263 1;