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