156d3b89bc4015060ae851bd180bd10a7ce2c394
[pve-access-control.git] / PVE / API2 / Role.pm
1 package PVE::API2::Role;
2
3 use strict;
4 use warnings;
5 use PVE::Cluster qw (cfs_read_file cfs_write_file);
6 use PVE::AccessControl;
7 use PVE::JSONSchema qw(get_standard_option register_standard_option);
8
9 use PVE::SafeSyslog;
10
11 use PVE::RESTHandler;
12
13 use base qw(PVE::RESTHandler);
14
15 register_standard_option('role-id', {
16     type => 'string',
17     format => 'pve-roleid',
18     title => 'Role ID',
19     print_width => 30
20 });
21 register_standard_option('role-privs', {
22     type => 'string' ,
23     format => 'pve-priv-list',
24     optional => 1, title => 'Privileges',
25 });
26
27 __PACKAGE__->register_method ({
28     name => 'index',
29     path => '',
30     method => 'GET',
31     description => "Role index.",
32     permissions => {
33         user => 'all',
34     },
35     parameters => {
36         additionalProperties => 0,
37         properties => {},
38     },
39     returns => {
40         type => 'array',
41         items => {
42             type => "object",
43             properties => {
44                 roleid => get_standard_option('role-id'),
45                 privs =>  get_standard_option('role-privs'),
46                 special => { type => 'boolean', optional => 1, default => 0, title => 'Built-In' },
47             },
48         },
49         links => [ { rel => 'child', href => "{roleid}" } ],
50     },
51     code => sub {
52         my ($param) = @_;
53
54         my $res = [];
55
56         my $usercfg = cfs_read_file("user.cfg");
57
58         foreach my $role (keys %{$usercfg->{roles}}) {
59             my $privs = join(',', sort keys %{$usercfg->{roles}->{$role}});
60             push @$res, {
61                 roleid => $role,
62                 privs => $privs,
63                 special => PVE::AccessControl::role_is_special($role),
64             };
65         }
66
67         return $res;
68 }});
69
70 __PACKAGE__->register_method ({
71     name => 'create_role',
72     protected => 1,
73     path => '',
74     method => 'POST',
75     permissions => {
76         check => ['perm', '/access', ['Sys.Modify']],
77     },
78     description => "Create new role.",
79     parameters => {
80         additionalProperties => 0,
81         properties => {
82             roleid => get_standard_option('role-id'),
83             privs =>  get_standard_option('role-privs'),
84         },
85     },
86     returns => { type => 'null' },
87     code => sub {
88         my ($param) = @_;
89
90         PVE::AccessControl::lock_user_config(
91             sub {
92
93                 my $usercfg = cfs_read_file("user.cfg");
94
95                 my $role = $param->{roleid};
96
97                 die "role '$role' already exists\n"
98                     if $usercfg->{roles}->{$role};
99
100                 $usercfg->{roles}->{$role} = {};
101
102                 PVE::AccessControl::add_role_privs($role, $usercfg, $param->{privs});
103
104                 cfs_write_file("user.cfg", $usercfg);
105             }, "create role failed");
106
107         return undef;
108 }});
109
110 __PACKAGE__->register_method ({
111     name => 'update_role',
112     protected => 1,
113     path => '{roleid}',
114     method => 'PUT',
115     permissions => {
116         check => ['perm', '/access', ['Sys.Modify']],
117     },
118     description => "Update an existing role.",
119     parameters => {
120         additionalProperties => 0,
121         properties => {
122             roleid => get_standard_option('role-id'),
123             privs =>  get_standard_option('role-privs'),
124             append => { type => 'boolean', optional => 1, requires => 'privs' },
125         },
126     },
127     returns => { type => 'null' },
128     code => sub {
129         my ($param) = @_;
130
131         PVE::AccessControl::lock_user_config(
132             sub {
133
134                 my $role = $param->{roleid};
135
136                 my $usercfg = cfs_read_file("user.cfg");
137
138                 die "role '$role' does not exist\n"
139                     if !$usercfg->{roles}->{$role};
140
141                 $usercfg->{roles}->{$role} = {} if !$param->{append};
142
143                 PVE::AccessControl::add_role_privs($role, $usercfg, $param->{privs});
144
145                 cfs_write_file("user.cfg", $usercfg);
146             }, "update role failed");
147
148         return undef;
149 }});
150
151 __PACKAGE__->register_method ({
152     name => 'read_role',
153     path => '{roleid}',
154     method => 'GET',
155     permissions => {
156         user => 'all',
157     },
158     description => "Get role configuration.",
159     parameters => {
160         additionalProperties => 0,
161         properties => {
162             roleid => get_standard_option('role-id'),
163         },
164     },
165     returns => {
166         type => "object",
167         additionalProperties => 0,
168         properties => {
169             privs =>  get_standard_option('role-privs'),
170         },
171     },
172     code => sub {
173         my ($param) = @_;
174
175         my $usercfg = cfs_read_file("user.cfg");
176
177         my $role = $param->{roleid};
178
179         my $data = $usercfg->{roles}->{$role};
180
181         die "role '$role' does not exist\n" if !$data;
182
183         return $data;
184     }
185 });
186
187 __PACKAGE__->register_method ({
188     name => 'delete_role',
189     protected => 1,
190     path => '{roleid}',
191     method => 'DELETE',
192     permissions => {
193         check => ['perm', '/access', ['Sys.Modify']],
194     },
195     description => "Delete role.",
196     parameters => {
197         additionalProperties => 0,
198         properties => {
199             roleid => get_standard_option('role-id'),
200         },
201     },
202     returns => { type => 'null' },
203     code => sub {
204         my ($param) = @_;
205
206         my $role = $param->{roleid};
207
208         die "auto-generated role '$role' cannot be deleted\n"
209             if PVE::AccessControl::role_is_special($role);
210
211         PVE::AccessControl::lock_user_config(
212             sub {
213                 my $usercfg = cfs_read_file("user.cfg");
214
215                 die "role '$role' does not exist\n"
216                     if !$usercfg->{roles}->{$role};
217
218                 delete ($usercfg->{roles}->{$role});
219
220                 # fixme: delete role from acl?
221
222                 cfs_write_file("user.cfg", $usercfg);
223             }, "delete role failed");
224
225         return undef;
226     }
227 });
228
229 1;