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