1 package PVE::API2::User;
5 use PVE::Exception qw(raise raise_perm_exc);
6 use PVE::Cluster qw (cfs_read_file cfs_write_file);
7 use PVE::Tools qw(split_list);
8 use PVE::AccessControl;
9 use PVE::JSONSchema qw(get_standard_option);
13 use Data::Dumper; # fixme: remove
17 use base qw(PVE::RESTHandler);
19 my $extract_user_data = sub {
20 my ($data, $full) = @_;
24 foreach my $prop (qw(enable expire firstname lastname email comment)) {
25 $res->{$prop} = $data->{$prop} if defined($data->{$prop});
28 return $res if !$full;
30 $res->{groups} = $data->{groups} ? [ keys %{$data->{groups}} ] : [];
35 __PACKAGE__->register_method ({
39 description => "User index.",
40 permissions => { user => 'all' },
42 additionalProperties => 0,
46 description => "Optional filter for enable property.",
56 userid => { type => 'string' },
59 links => [ { rel => 'child', href => "{userid}" } ],
64 my $rpcenv = PVE::RPCEnvironment::get();
65 my $usercfg = $rpcenv->{user_cfg};
66 my $authuser = $rpcenv->get_user();
70 my $privs = [ 'User.Modify', 'User.Delete' ];
72 my $canUserMod = $rpcenv->check_any($authuser, "/access", $privs, 1);
73 my $groups = $rpcenv->filter_groups($authuser, $privs, 1);
74 my $allowed_users = $rpcenv->group_member_join([keys %$groups]);
76 foreach my $user (keys %{$usercfg->{users}}) {
78 if (!($canUserMod || $user eq $authuser)) {
79 next if !$allowed_users->{$user};
82 my $entry = &$extract_user_data($usercfg->{users}->{$user});
84 if (defined($param->{enabled})) {
85 next if $entry->{enable} && !$param->{enabled};
86 next if !$entry->{enable} && $param->{enabled};
89 $entry->{userid} = $user;
96 __PACKAGE__->register_method ({
97 name => 'create_user',
101 description => "Create new user.",
103 additionalProperties => 0,
105 userid => get_standard_option('userid'),
107 description => "Initial password.",
113 groups => { type => 'string', optional => 1, format => 'pve-groupid-list'},
114 firstname => { type => 'string', optional => 1 },
115 lastname => { type => 'string', optional => 1 },
116 email => { type => 'string', optional => 1, format => 'email-opt' },
117 comment => { type => 'string', optional => 1 },
119 description => "Account expiration date (seconds since epoch). '0' means no expiration date.",
125 description => "Enable the account (default). You can set this to '0' to disable the accout",
132 returns => { type => 'null' },
136 PVE::AccessControl::lock_user_config(
139 my ($username, $ruid, $realm) = PVE::AccessControl::verify_username($param->{userid});
141 my $usercfg = cfs_read_file("user.cfg");
143 die "user '$username' already exists\n"
144 if $usercfg->{users}->{$username};
146 PVE::AccessControl::domain_set_password($realm, $ruid, $param->{password})
147 if defined($param->{password});
149 my $enable = defined($param->{enable}) ? $param->{enable} : 1;
150 $usercfg->{users}->{$username} = { enable => $enable };
151 $usercfg->{users}->{$username}->{expire} = $param->{expire} if $param->{expire};
153 if ($param->{groups}) {
154 foreach my $group (split_list($param->{groups})) {
155 if ($usercfg->{groups}->{$group}) {
156 PVE::AccessControl::add_user_group($username, $usercfg, $group);
158 die "no such group '$group'\n";
163 $usercfg->{users}->{$username}->{firstname} = $param->{firstname} if $param->{firstname};
164 $usercfg->{users}->{$username}->{lastname} = $param->{lastname} if $param->{lastname};
165 $usercfg->{users}->{$username}->{email} = $param->{email} if $param->{email};
166 $usercfg->{users}->{$username}->{comment} = $param->{comment} if $param->{comment};
168 cfs_write_file("user.cfg", $usercfg);
169 }, "create user failed");
174 __PACKAGE__->register_method ({
178 description => "Get user configuration.",
180 additionalProperties => 0,
182 userid => get_standard_option('userid'),
186 additionalProperties => 0,
188 enable => { type => 'boolean' },
189 expire => { type => 'integer', optional => 1 },
190 firstname => { type => 'string', optional => 1 },
191 lastname => { type => 'string', optional => 1 },
192 email => { type => 'string', optional => 1 },
193 comment => { type => 'string', optional => 1 },
194 groups => { type => 'array' },
200 my ($username, undef, $domain) =
201 PVE::AccessControl::verify_username($param->{userid});
203 my $usercfg = cfs_read_file("user.cfg");
205 my $data = PVE::AccessControl::check_user_exist($usercfg, $username);
207 return &$extract_user_data($data, 1);
210 __PACKAGE__->register_method ({
211 name => 'update_user',
215 description => "Update user configuration.",
217 additionalProperties => 0,
219 userid => get_standard_option('userid'),
220 groups => { type => 'string', optional => 1, format => 'pve-groupid-list' },
224 requires => 'groups',
227 description => "Enable/disable the account.",
231 firstname => { type => 'string', optional => 1 },
232 lastname => { type => 'string', optional => 1 },
233 email => { type => 'string', optional => 1, format => 'email-opt' },
234 comment => { type => 'string', optional => 1 },
236 description => "Account expiration date (seconds since epoch). '0' means no expiration date.",
243 returns => { type => 'null' },
247 my ($username, $ruid, $realm) =
248 PVE::AccessControl::verify_username($param->{userid});
250 PVE::AccessControl::lock_user_config(
253 my $usercfg = cfs_read_file("user.cfg");
255 PVE::AccessControl::check_user_exist($usercfg, $username);
257 $usercfg->{users}->{$username}->{enable} = $param->{enable} if defined($param->{enable});
259 $usercfg->{users}->{$username}->{expire} = $param->{expire} if defined($param->{expire});
261 PVE::AccessControl::delete_user_group($username, $usercfg)
262 if (!$param->{append} && defined($param->{groups}));
264 if ($param->{groups}) {
265 foreach my $group (split_list($param->{groups})) {
266 if ($usercfg->{groups}->{$group}) {
267 PVE::AccessControl::add_user_group($username, $usercfg, $group);
269 die "no such group '$group'\n";
274 $usercfg->{users}->{$username}->{firstname} = $param->{firstname} if defined($param->{firstname});
275 $usercfg->{users}->{$username}->{lastname} = $param->{lastname} if defined($param->{lastname});
276 $usercfg->{users}->{$username}->{email} = $param->{email} if defined($param->{email});
277 $usercfg->{users}->{$username}->{comment} = $param->{comment} if defined($param->{comment});
279 cfs_write_file("user.cfg", $usercfg);
280 }, "update user failed");
285 __PACKAGE__->register_method ({
286 name => 'delete_user',
290 description => "Delete user.",
292 check => ['userid-group', ['User.Delete']],
295 additionalProperties => 0,
297 userid => get_standard_option('userid'),
300 returns => { type => 'null' },
304 my $rpcenv = PVE::RPCEnvironment::get();
305 my $authuser = $rpcenv->get_user();
307 my ($userid, $ruid, $realm) =
308 PVE::AccessControl::verify_username($param->{userid});
310 PVE::AccessControl::lock_user_config(
313 my $usercfg = cfs_read_file("user.cfg");
315 delete ($usercfg->{users}->{$userid});
317 PVE::AccessControl::delete_shadow_password($ruid) if $realm eq 'pve';
319 PVE::AccessControl::delete_user_group($userid, $usercfg);
320 PVE::AccessControl::delete_user_acl($userid, $usercfg);
322 cfs_write_file("user.cfg", $usercfg);
323 }, "delete user failed");