]> git.proxmox.com Git - pmg-api.git/blob - PMG/API2/Config.pm
add pmg report api call for the gui
[pmg-api.git] / PMG / API2 / Config.pm
1 package PMG::API2::Config;
2
3 use strict;
4 use warnings;
5 use Data::Dumper;
6
7 use PVE::SafeSyslog;
8 use PVE::Tools qw(extract_param);
9 use HTTP::Status qw(:constants);
10 use Storable qw(dclone);
11 use PVE::JSONSchema qw(get_standard_option);
12 use PVE::RESTHandler;
13 use Time::HiRes qw();
14
15 use PMG::Config;
16 use PMG::API2::RuleDB;
17 use PMG::API2::LDAP;
18 use PMG::API2::Domains;
19 use PMG::API2::Transport;
20 use PMG::API2::Cluster;
21 use PMG::API2::MyNetworks;
22 use PMG::API2::SMTPWhitelist;
23 use PMG::API2::MimeTypes;
24 use PMG::API2::Fetchmail;
25 use PMG::API2::DestinationTLSPolicy;
26
27 use base qw(PVE::RESTHandler);
28
29 my $section_type_enum = PMG::Config::Base->lookup_types();
30
31 __PACKAGE__->register_method ({
32 subclass => "PMG::API2::RuleDB",
33 path => 'ruledb',
34 });
35
36 __PACKAGE__->register_method ({
37 subclass => "PMG::API2::SMTPWhitelist",
38 path => 'whitelist',
39 });
40
41 __PACKAGE__->register_method ({
42 subclass => "PMG::API2::LDAP",
43 path => 'ldap',
44 });
45
46 __PACKAGE__->register_method ({
47 subclass => "PMG::API2::Domains",
48 path => 'domains',
49 });
50
51 __PACKAGE__->register_method ({
52 subclass => "PMG::API2::Fetchmail",
53 path => 'fetchmail',
54 });
55
56 __PACKAGE__->register_method ({
57 subclass => "PMG::API2::Transport",
58 path => 'transport',
59 });
60
61 __PACKAGE__->register_method ({
62 subclass => "PMG::API2::MyNetworks",
63 # set fragment delimiter (no subdirs) - we need that, because CIDRs
64 # contain a slash '/'
65 fragmentDelimiter => '',
66 path => 'mynetworks',
67 });
68
69 __PACKAGE__->register_method ({
70 subclass => "PMG::API2::Cluster",
71 path => 'cluster',
72 });
73
74 __PACKAGE__->register_method ({
75 subclass => "PMG::API2::MimeTypes",
76 path => 'mimetypes',
77 });
78
79 __PACKAGE__->register_method ({
80 subclass => "PMG::API2::DestinationTLSPolicy",
81 path => 'tlspolicy',
82 });
83
84 __PACKAGE__->register_method ({
85 name => 'index',
86 path => '',
87 method => 'GET',
88 description => "Directory index.",
89 parameters => {
90 additionalProperties => 0,
91 properties => {},
92 },
93 returns => {
94 type => 'array',
95 items => {
96 type => "object",
97 properties => { section => { type => 'string'} },
98 },
99 links => [ { rel => 'child', href => "{section}" } ],
100 },
101 code => sub {
102 my ($param) = @_;
103
104 my $res = [];
105 foreach my $section (@$section_type_enum) {
106 push @$res, { section => $section };
107 }
108
109 push @$res, { section => 'ldap' };
110 push @$res, { section => 'mynetworks' };
111 push @$res, { section => 'mimetypes' };
112 push @$res, { section => 'users' };
113 push @$res, { section => 'domains' };
114 push @$res, { section => 'fetchmail' };
115 push @$res, { section => 'cluster' };
116 push @$res, { section => 'ruledb' };
117 push @$res, { section => 'transport' };
118 push @$res, { section => 'whitelist' };
119 push @$res, { section => 'regextest' };
120 push @$res, { section => 'tlspolicy' };
121
122 return $res;
123 }});
124
125 my $api_read_config_section = sub {
126 my ($section) = @_;
127
128 my $cfg = PMG::Config->new();
129
130 my $data = dclone($cfg->{ids}->{$section} // {});
131 $data->{digest} = $cfg->{digest};
132 delete $data->{type};
133
134 return $data;
135 };
136
137 my $api_update_config_section = sub {
138 my ($section, $param) = @_;
139
140 my $code = sub {
141 my $cfg = PMG::Config->new();
142 my $ids = $cfg->{ids};
143
144 my $digest = extract_param($param, 'digest');
145 PVE::SectionConfig::assert_if_modified($cfg, $digest);
146
147 my $delete_str = extract_param($param, 'delete');
148 die "no options specified\n"
149 if !$delete_str && !scalar(keys %$param);
150
151 foreach my $opt (PVE::Tools::split_list($delete_str)) {
152 delete $ids->{$section}->{$opt};
153 }
154
155 my $plugin = PMG::Config::Base->lookup($section);
156 my $config = $plugin->check_config($section, $param, 0, 1);
157
158 foreach my $p (keys %$config) {
159 $ids->{$section}->{$p} = $config->{$p};
160 }
161
162 $cfg->write();
163
164 $cfg->rewrite_config(undef, 1);
165 };
166
167 PMG::Config::lock_config($code, "update config section '$section' failed");
168 };
169
170 foreach my $section (@$section_type_enum) {
171
172 my $plugin = PMG::Config::Base->lookup($section);
173
174 __PACKAGE__->register_method ({
175 name => "read_${section}_section",
176 path => $section,
177 method => 'GET',
178 proxyto => 'master',
179 permissions => { check => [ 'admin', 'audit' ] },
180 description => "Read $section configuration properties.",
181 parameters => {
182 additionalProperties => 0,
183 properties => {},
184 },
185 returns => { type => 'object' },
186 code => sub {
187 my ($param) = @_;
188
189 return $api_read_config_section->($section);
190 }});
191
192 __PACKAGE__->register_method ({
193 name => "update_${section}_section",
194 path => $section,
195 method => 'PUT',
196 proxyto => 'master',
197 protected => 1,
198 permissions => { check => [ 'admin' ] },
199 description => "Update $section configuration properties.",
200 parameters => $plugin->updateSchema(1),
201 returns => { type => 'null' },
202 code => sub {
203 my ($param) = @_;
204
205 $api_update_config_section->($section, $param);
206
207 return undef;
208 }});
209 }
210
211 __PACKAGE__->register_method({
212 name => 'regextest',
213 path => 'regextest',
214 method => 'POST',
215 protected => 0,
216 permissions => { check => [ 'admin', 'qmanager', 'audit' ] },
217 description => "Test Regex",
218 parameters => {
219 additionalProperties => 0,
220 properties => {
221 regex => {
222 type => 'string',
223 description => 'The Regex to test',
224 maxLength => 1024,
225 },
226 text => {
227 type => 'string',
228 description => 'The String to test',
229 maxLength => 1024,
230 }
231 },
232 },
233 returns => {
234 type => 'number',
235 },
236 code => sub {
237 my ($param) = @_;
238
239 my $text = $param->{text};
240 my $regex = $param->{regex};
241
242 my $regex_check = sub {
243 my $start_time = [Time::HiRes::gettimeofday];
244 my $match = 0;
245 if ($text =~ /$regex/) {
246 $match = 1;
247 }
248 my $elapsed = Time::HiRes::tv_interval($start_time) * 1000;
249 die "The Regular Expression '$regex' did not match the text '$text' (elapsed time: $elapsed ms)\n"
250 if !$match;
251 return $elapsed;
252 };
253
254 my $elapsed = PVE::Tools::run_fork_with_timeout(2, $regex_check);
255 if ($elapsed eq '') {
256 die "The Regular Expression timed out\n";
257 }
258
259 return $elapsed;
260 }});
261
262 1;