use base qw(PVE::RESTHandler);
__PACKAGE__->register_method ({
- subclass => "PVE::API2::User",
+ subclass => "PVE::API2::User",
path => 'users',
});
__PACKAGE__->register_method ({
- subclass => "PVE::API2::Group",
+ subclass => "PVE::API2::Group",
path => 'groups',
});
__PACKAGE__->register_method ({
- subclass => "PVE::API2::Role",
+ subclass => "PVE::API2::Role",
path => 'roles',
});
__PACKAGE__->register_method ({
- subclass => "PVE::API2::ACL",
+ subclass => "PVE::API2::ACL",
path => 'acl',
});
__PACKAGE__->register_method ({
- subclass => "PVE::API2::Domains",
+ subclass => "PVE::API2::Domains",
path => 'domains',
});
__PACKAGE__->register_method ({
- name => 'index',
- path => '',
+ name => 'index',
+ path => '',
method => 'GET',
description => "Directory index.",
- permissions => {
+ permissions => {
user => 'all',
},
parameters => {
},
code => sub {
my ($param) = @_;
-
+
my $res = [];
my $ma = __PACKAGE__->method_attributes();
access => qr/(User|Group)\.|Permissions\.Modify/,
storage => qr/Datastore\.|Permissions\.Modify/,
nodes => qr/Sys\.|Permissions\.Modify/,
- dc => qr/Sys\.Audit/,
+ sdn => qr/SDN\.|Permissions\.Modify/,
+ dc => qr/Sys\.Audit|SDN\./,
};
map { $res->{$_} = {} } keys %$priv_re_map;
- my $required_paths = ['/', '/nodes', '/access/groups', '/vms', '/storage'];
+ my $required_paths = ['/', '/nodes', '/access/groups', '/vms', '/storage', '/sdn'];
my $checked_paths = {};
foreach my $path (@$required_paths, keys %{$usercfg->{acl}}) {
};
__PACKAGE__->register_method ({
- name => 'get_ticket',
- path => 'ticket',
+ name => 'get_ticket',
+ path => 'ticket',
method => 'GET',
permissions => { user => 'world' },
description => "Dummy. Useful for formatters which want to provide a login page.",
},
returns => { type => "null" },
code => sub { return undef; }});
-
+
__PACKAGE__->register_method ({
- name => 'create_ticket',
- path => 'ticket',
+ name => 'create_ticket',
+ path => 'ticket',
method => 'POST',
- permissions => {
+ permissions => {
description => "You need to pass valid credientials.",
- user => 'world'
+ user => 'world'
},
protected => 1, # else we can't access shadow files
+ allowtoken => 0, # we don't want tokens to create tickets
description => "Create or verify authentication ticket.",
parameters => {
additionalProperties => 0,
optional => 1,
completion => \&PVE::AccessControl::complete_realm,
}),
- password => {
+ password => {
description => "The secret password. This can also be a valid ticket.",
type => 'string',
},
optional => 1,
maxLength => 64,
},
- privs => {
+ privs => {
description => "Verify ticket, and check if user have access 'privs' on 'path'",
type => 'string' , format => 'pve-priv-list',
requires => 'path',
},
code => sub {
my ($param) = @_;
-
+
my $username = $param->{username};
$username .= "\@$param->{realm}" if $param->{realm};
+ $username = PVE::AccessControl::lookup_username($username);
my $rpcenv = PVE::RPCEnvironment::get();
my $res;
__PACKAGE__->register_method ({
name => 'change_password',
- path => 'password',
+ path => 'password',
method => 'PUT',
- permissions => {
+ permissions => {
description => "Each user is allowed to change his own password. A user can change the password of another user if he has 'Realm.AllocateUser' (on the realm of user <userid>) and 'User.Modify' permission on /access/groups/<group> on a group where user <userid> is member of.",
- check => [ 'or',
+ check => [ 'or',
['userid-param', 'self'],
[ 'and',
[ 'userid-param', 'Realm.AllocateUser'],
],
},
protected => 1, # else we can't access shadow files
+ allowtoken => 0, # we don't want tokens to change the regular user password
description => "Change user password.",
parameters => {
additionalProperties => 0,
properties => {
userid => get_standard_option('userid-completed'),
- password => {
+ password => {
description => "The new password.",
type => 'string',
- minLength => 5,
+ minLength => 5,
maxLength => 64,
},
}
],
},
protected => 1, # else we can't access shadow files
+ allowtoken => 0, # we don't want tokens to change the regular user's TFA settings
description => "Change user u2f authentication.",
parameters => {
additionalProperties => 0,
method => 'POST',
permissions => { user => 'all' },
protected => 1, # else we can't access shadow files
+ allowtoken => 0, # we don't want tokens to access TFA information
description => 'Finish a u2f challenge.',
parameters => {
additionalProperties => 0,
}
}});
+__PACKAGE__->register_method({
+ name => 'permissions',
+ path => 'permissions',
+ method => 'GET',
+ description => 'Retrieve effective permissions of given user/token.',
+ permissions => {
+ description => "Each user/token is allowed to dump their own permissions. A user can dump the permissions of another user if they have 'Sys.Audit' permission on /access.",
+ user => 'all',
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ userid => {
+ type => 'string',
+ description => "User ID or full API token ID",
+ pattern => $PVE::AccessControl::userid_or_token_regex,
+ optional => 1,
+ },
+ path => get_standard_option('acl-path', {
+ description => "Only dump this specific path, not the whole tree.",
+ optional => 1,
+ }),
+ },
+ },
+ returns => {
+ type => 'object',
+ description => 'Map of "path" => (Map of "privilege" => "propagate boolean").',
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+
+ my $userid = $param->{userid};
+ if (defined($userid)) {
+ $rpcenv->check($rpcenv->get_user(), '/access', ['Sys.Audit']);
+ } else {
+ $userid = $rpcenv->get_user();
+ }
+
+ my $res;
+
+ if (my $path = $param->{path}) {
+ my $perms = $rpcenv->permissions($userid, $path);
+ if ($perms) {
+ $res = { $path => $perms };
+ } else {
+ $res = {};
+ }
+ } else {
+ $res = $rpcenv->get_effective_permissions($userid);
+ }
+
+ return $res;
+ }});
+
1;