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