/[suikacvs]/test/suika-accounts/edit.cgi
Suika

Contents of /test/suika-accounts/edit.cgi

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show annotations) (download)
Sat Nov 1 10:13:14 2008 UTC (16 years ago) by wakaba
Branch: MAIN
Changes since 1.5: +10 -0 lines
Send a mail message when a significant change occurs

1 #!/usr/bin/perl
2 use strict;
3
4 use lib qw[/home/httpd/html/www/markup/html/whatpm
5 /home/wakaba/work/manakai2/lib];
6
7 use CGI::Carp qw[fatalsToBrowser];
8 require Message::CGI::Carp;
9
10 require 'users.pl';
11 require 'texts.pl';
12
13 our $subject_prefix;
14
15 require Message::CGI::HTTP;
16 require Encode;
17 my $cgi = Message::CGI::HTTP->new;
18 $cgi->{decoder}->{'#default'} = sub {
19 return Encode::decode ('utf-8', $_[1]);
20 };
21
22 our $Lang = 'ja'
23 if $cgi->get_meta_variable ('HTTP_ACCEPT_LANGUAGE') =~ /\bja\b/; ## TODO: ...
24
25 require Message::DOM::DOMImplementation;
26 my $dom = Message::DOM::DOMImplementation->new;
27
28 my $path = $cgi->path_info;
29 $path = '' unless defined $path;
30
31 my @path = split m#/#, percent_decode ($path), -1;
32 shift @path;
33
34 if (@path == 3 and
35 $path[0] eq 'users' and
36 $path[1] =~ /\A[0-9a-z-]+\z/) {
37 my $user_id = $path[1];
38 my $ac = check_access_right (allowed_users => {$user_id => 1},
39 allowed_groups => {'admin-users' => 1});
40
41 if ($path[2] eq '') {
42 my $user_prop = get_user_prop ($user_id);
43 if ($user_prop) {
44 binmode STDOUT, ':encoding(utf-8)';
45
46 my $e_user_id = htescape ($user_id);
47
48 print q[Content-Type: text/html; charset=utf-8
49
50 <!DOCTYPE HTML>
51 <html lang=en>
52 <title>];
53 print_text ('User %s', sub { print $e_user_id });
54 print q[</title>
55 <link rel=stylesheet href="/www/style/html/xhtml">
56 <h1>];
57 print_text ('User %s', sub { print $e_user_id });
58 print q[</h1>];
59
60 my @joined;
61 my @requested;
62 my @invited;
63 my @can_join;
64 my @can_request;
65 for my $group_id (get_all_groups ()) {
66 my $gs = $user_prop->{'group.' . $group_id};
67 if ($gs->{member}) {
68 push @joined, $group_id;
69 } elsif ($gs->{no_approval}) {
70 push @requested, $group_id;
71 } elsif ($gs->{invited}) {
72 push @invited, $group_id;
73 } else {
74 my $group_prop = get_group_prop ($group_id);
75 if ($group_prop->{join_condition}->{invitation}) {
76 #
77 } elsif ($group_prop->{join_condition}->{approval}) {
78 push @can_request, $group_id;
79 } else {
80 push @can_join, $group_id;
81 }
82 }
83 }
84
85 print q[<section id=groups><h2>];
86 print_text ('Groups');
87 print q[</h2>];
88
89 if (@joined) {
90 print_list_section
91 (id => 'groups-joined',
92 title => 'Groups you have joined',
93 items => \@joined,
94 print_item => sub {
95 my $group_id = shift;
96 print q[<form action="group.] . htescape ($group_id);
97 print q[" accept-charset=utf-8 method=post>];
98 print q[<a href="../../groups/].htescape ($group_id) . '/';
99 print q[">] . htescape ($group_id), q[</a> ];
100 print q[<input type=hidden name=action value=leave>];
101 print q[<input type=submit value="];
102 print_text ('Leave this group');
103 print q["></form>];
104 });
105 }
106
107 if (@requested) {
108 print_list_section
109 (id => 'groups-requested',
110 title => 'Groups you have requested to join but not approved yet',
111 items => \@requested,
112 print_item => sub {
113 my $group_id = shift;
114 print q[<form action="group.] . htescape ($group_id);
115 print q[" accept-charset=utf-8 method=post>];
116 print q[<a href="../../groups/].htescape ($group_id) . '/';
117 print q[">] . htescape ($group_id), q[</a> ];
118 print q[<input type=hidden name=action value=leave>];
119 print q[<input type=submit value="];
120 print_text ('Cancel the request');
121 print q["></form>];
122 });
123 }
124
125 if (@invited) {
126 print_list_section
127 (id => 'groups-invited',
128 title => 'Groups you have been invited but not joined yet, or you have left',
129 items => \@invited,
130 print_item => sub {
131 my $group_id = shift;
132 print q[<form action="group.] . htescape ($group_id);
133 print q[" accept-charset=utf-8 method=post>];
134 print q[<a href="../../groups/].htescape ($group_id) . '/';
135 print q[">] . htescape ($group_id), q[</a> ];
136 print q[<input type=hidden name=action value=join>];
137 print q[<input type=submit value="];
138 print_text ('Join this group');
139 print q["></form>];
140 });
141 }
142
143 if (@can_join) {
144 print_list_section
145 (id => 'groups-can-join',
146 title => 'Groups you can join now (without approval)',
147 items => \@can_join,
148 print_item => sub {
149 my $group_id = shift;
150 print q[<form action="group.] . htescape ($group_id);
151 print q[" accept-charset=utf-8 method=post>];
152 print q[<a href="../../groups/].htescape ($group_id) . '/';
153 print q[">] . htescape ($group_id), q[</a>];
154 print q[<input type=hidden name=action value=join> ];
155 print q[<input type=submit value="];
156 print_text ('Join this group');
157 print q["></form>];
158 });
159 }
160
161 if (@can_request) {
162 print_list_section
163 (id => 'groups-can-request',
164 title => 'Groups you can request to join (approval required to join)',
165 items => \@can_request,
166 print_item => sub {
167 my $group_id = shift;
168 print q[<form action="group.] . htescape ($group_id);
169 print q[" accept-charset=utf-8 method=post>];
170 print q[<a href="../../groups/].htescape ($group_id) . '/';
171 print q[">] . htescape ($group_id), q[</a> ];
172 print q[<input type=hidden name=action value=join>];
173 print q[<input type=submit value="];
174 print_text ('Join this group');
175 print q["></form>];
176 });
177 }
178
179 print q[</section><section id=props><h2>];
180 print_text ('Properties');
181 print q[</h2><p><em>];
182 print_text (q[Don't expose any confidential data.]);
183 print q[</em>];
184
185 print_prop_list ($ac, $user_prop,
186 {
187 name => 'full_name',
188 label => 'Full name',
189 field_type => 'text',
190 },
191 {
192 name => 'mail_addr',
193 label => 'Mail address',
194 field_type => 'email',
195 },
196 {
197 name => 'home_url',
198 label => 'Web site URL',
199 field_type => 'url',
200 },
201 );
202
203 print qq[</section><section id=password><h2>];
204 print_text ('Password');
205 print q[</h2>
206
207 <form action=password method=post accept-charset=utf-8>
208
209 <p>];
210 print_text ('You can change the password.');
211
212 print q[<p><strong>];
213 print_text ('New password');
214 print q[</strong>: <input type=password name=user-pass
215 size=10 required pattern=".{4,}"> (];
216 print_text ('Type 4 characters at minimum');
217 print q[) <p><strong>];
218 print_text ('New password');
219 print q[</strong> (];
220 print_text ('type again');
221 print q[): <input type=password
222 name=user-pass2 size=10 required pattern=".{4,}">
223
224 <p><input type=submit value="];
225 print_text ('Change');
226 print q[">
227
228 </form>
229 </section>
230
231 <section id=disable-account><h2>];
232 print_text ('Disable account');
233 print q[</h2>
234
235 <form action=disabled method=post accept-charset=utf-8>
236
237 <p><label><input type=checkbox name=action value=enable ];
238 print 'checked' unless $user_prop->{disabled};
239 print q[> ];
240 print_text ('Enable this account');
241 print q[</label>
242
243 <p><strong>];
244 print_text ('Caution!');
245 print q[</strong> ];
246 print_text ('Once you disable your own account, you cannot enable your account by yourself.');
247
248 print q[<p><input type=submit value="];
249 print_text ('Change');
250
251 print q["></form></section>];
252
253 exit;
254 }
255 } elsif ($path[2] =~ /\Agroup\.([0-9a-z-]+)\z/) {
256 my $group_id = $1;
257 if ($cgi->request_method eq 'POST') {
258 lock_start ();
259 binmode STDOUT, ':encoding(utf-8)';
260
261 my $user_prop = get_user_prop ($user_id);
262 my $group_prop = get_group_prop ($group_id);
263
264 if ($user_prop and $group_prop) {
265 my $gs = ($user_prop->{'group.' . $group_id} ||= {});
266
267 my $action = $cgi->get_parameter ('action');
268 my $status;
269 if ($action eq 'join') {
270 if (scalar $cgi->get_parameter ('agreed')) {
271 if ($gs->{member}) {
272 $status = q[You are a member];
273 #
274 } elsif ($gs->{no_approval}) {
275 $status = q[You are waiting for an approval];
276 #
277 } elsif ($gs->{invited}) {
278 $gs->{member} = 1;
279 $status = q[Registered];
280 #
281 } else {
282 if ($group_prop->{join_condition}->{invitation}) {
283 print_error (403, 'You are not invited to this group');
284 exit;
285 } elsif ($group_prop->{join_condition}->{approval}) {
286 $gs->{no_approval} = 1;
287 $status = q[Request submitted];
288 #
289 } else {
290 $gs->{member} = 1;
291 $status = q[Registered];
292 #
293 }
294 }
295 } else {
296 my $e_group_id = htescape ($group_id);
297 print q[Content-Type: text/html; charset=utf-8
298
299 <!DOCTYPE HTML>
300 <html lang=en>
301 <title>];
302 print_text ('Joining the group %s', sub { print $e_group_id });
303 print q[</title>
304 <link rel=stylesheet href="/www/style/html/xhtml">
305 <h1>];
306 print_text ('Joining the group %s', sub { print $e_group_id });
307 print q[</h1>
308
309 <dl>
310 <dt>];
311 print_text ('Description');
312 print qq[<dd>@{[$group_prop->{desc}]}
313 </dl>
314
315 <form action="@{[htescape ($cgi->request_uri)]}" accept-charset=utf-8 method=post>
316 <input type=hidden name=action value=join>
317
318 <p>];
319 print_text ('Do you really want to join this group?');
320 print q[ <input type=submit name=agreed value="];
321 print_text ('Yes');
322 print q["> <input type=button value="];
323 print_text ('No');
324 print q[" onclick="history.back ()"></form>];
325 exit;
326 }
327 } elsif ($action eq 'leave') {
328 if ($gs->{member}) {
329 delete $gs->{member};
330 $gs->{invited} = 1;
331 $status = 'Unregistered';
332 #
333 } elsif ($gs->{no_approval}) {
334 delete $gs->{no_approval};
335 delete $gs->{invited};
336 $status = 'Request canceled';
337 #
338 } else {
339 $status = 'You are not a member';
340 #
341 }
342 } else {
343 print_error (400, 'Bad action parameter');
344 exit;
345 }
346
347 set_user_prop ($user_id, $user_prop);
348 send_mail ("$subject_prefix $group_id membership action",
349 "Group: $group_id\nUser: $user_id\nAction: $action\nStatus: $status\n");
350 regenerate_htpasswd_and_htgroup ();
351 commit ();
352
353 redirect (303, $status, './#groups');
354 exit;
355 }
356 }
357 } elsif ($path[2] eq 'password') {
358 if ($cgi->request_method eq 'POST') {
359 lock_start ();
360 binmode STDOUT, ':encoding(utf-8)';
361
362 my $user_prop = get_user_prop ($user_id);
363
364 if ($user_prop) {
365 $user_prop->{pass_crypted} = check_password ($cgi);
366
367 set_user_prop ($user_id, $user_prop);
368 regenerate_htpasswd_and_htgroup ();
369 commit ();
370
371 ## Browsers do not support 205.
372 #print qq[Status: 205 Password changed\n\n];
373 print qq[Status: 204 Password changed\n\n];
374 exit;
375 }
376 }
377 } elsif ($path[2] eq 'disabled') {
378 if ($cgi->request_method eq 'POST') {
379 lock_start ();
380 binmode STDOUT, ':encoding(utf-8)';
381
382 my $user_prop = get_user_prop ($user_id);
383
384 if ($user_prop) {
385 my $action = $cgi->get_parameter ('action');
386 if (defined $action and $action eq 'enable') {
387 delete $user_prop->{disabled};
388 } else {
389 $user_prop->{disabled} = 1;
390 }
391
392 set_user_prop ($user_id, $user_prop);
393 send_mail ("$subject_prefix $user_id disabledness action",
394 "User: $user_id\nNew value: @{[$user_prop->{disabled} ? 'disabled' : 'enabled']}\n");
395 regenerate_htpasswd_and_htgroup ();
396 commit ();
397
398 print "Status: 204 Property updated\n\n";
399 exit;
400 }
401 }
402 } elsif ($path[2] eq 'prop') {
403 if ($cgi->request_method eq 'POST') {
404 lock_start ();
405 my $user_prop = get_user_prop ($user_id);
406 if ($user_prop) {
407 binmode STDOUT, ':encoding(utf-8)';
408
409 my $prop_name = $cgi->get_parameter ('name');
410 if (defined $prop_name and
411 {
412 full_name => 1,
413 mail_addr => 1,
414 home_url => 1,
415 }->{$prop_name}) {
416 $user_prop->{$prop_name} = $cgi->get_parameter ('value');
417
418 set_user_prop ($user_id, $user_prop);
419 commit ();
420
421 print "Status: 204 Property updated\n\n";
422 exit;
423 } else {
424 print_error (400, 'Bad property');
425 exit;
426 }
427 }
428 }
429 }
430 } elsif (@path == 3 and
431 $path[0] eq 'groups' and
432 $path[1] =~ /\A[0-9a-z-]+\z/) {
433 my $group_id = $path[1];
434 my $ac = check_access_right (allowed_groups => {'admin-groups' => 1},
435 group_context => $group_id);
436
437 if ($path[2] eq '') {
438 my $group_prop = get_group_prop ($group_id);
439 if ($group_prop) {
440 binmode STDOUT, ':encoding(utf-8)';
441
442 my $e_group_id = htescape ($group_id);
443
444 print q[Content-Type: text/html; charset=utf-8
445
446 <!DOCTYPE HTML>
447 <html lang=en>
448 <title>];
449 print_text ('Group %s', sub { print $e_group_id });
450 print q[</title>
451 <link rel=stylesheet href="/www/style/html/xhtml">];
452 if (defined $group_prop->{favicon_url}) {
453 print q[<link rel=icon href="], htescape ($group_prop->{favicon_url});
454 print q[">];
455 }
456 print q[<h1>];
457 if (defined $group_prop->{favicon_url}) {
458 print q[<img src="], htescape ($group_prop->{favicon_url});
459 print q[" alt="">];
460 }
461 print_text ('Group %s', sub { print $e_group_id });
462 print q[</h1>];
463
464 print q[<section id=props><h2>];
465 print_text ('Properties');
466 print q[</h2>];
467
468 print_prop_list ($ac, $group_prop,
469 {
470 name => 'desc',
471 label => 'Description',
472 field_type => 'textarea',
473 public => 1,
474 },
475 {
476 name => 'admin_group',
477 label => 'Administrative group',
478 field_type => 'text',
479 },
480 {
481 name => 'favicon_url',
482 label => 'Group icon URL',
483 field_type => 'url',
484 },
485 );
486
487 print q[</section><section id=members><h2>];
488 print_text ('Members');
489 print q[</h2>];
490
491 if ($ac->{read_group_member_list}) {
492 my @members;
493 my @apps;
494 my @invited;
495 for my $user_id (get_all_users ()) {
496 my $user_prop = get_user_prop ($user_id);
497 my $gs = $user_prop->{'group.' . $group_id};
498 if ($gs->{member}) {
499 push @members, $user_id;
500 } elsif ($gs->{no_approval}) {
501 push @apps, $user_id;
502 } elsif ($gs->{invited}) {
503 push @invited, $user_id;
504 }
505 }
506
507 if (@members) {
508 print_list_section
509 (id => 'formal-members',
510 title => 'Formal members',
511 items => \@members,
512 print_item => sub {
513 my $user_id = shift;
514 print q[<form action="user.] . htescape ($user_id);
515 print q[" accept-charset=utf-8 method=post>];
516 print qq[<a href="../../users/@{[htescape ($user_id)]}/">];
517 print '' . htescape ($user_id) . q[</a> ];
518 print q[<input type=hidden name=action value=unapprove>];
519 print q[<input type=submit value="];
520 print_text ('Kick');
521 print q["></form>];
522 });
523 }
524
525 if (@apps) {
526 print_list_section
527 (id => 'non-approved-users',
528 title => 'Users who are waiting for the approval to join',
529 items => \@apps,
530 print_item => sub {
531 my $user_id = shift;
532 print q[<form action="user.] . htescape ($user_id);
533 print q[" accept-charset=utf-8 method=post>];
534 print qq[<a href="../../users/@{[htescape ($user_id)]}/">];
535 print '' . htescape ($user_id) . q[</a> ];
536 print q[<input type=hidden name=action value=approve>];
537 print q[<input type=submit value="];
538 print_text ('Approve');
539 print q["></form>];
540 });
541 }
542
543 if (@invited) {
544 print_list_section
545 (id => 'invited-users',
546 title => 'Users who are invited but not joined or are leaved',
547 items => \@invited,
548 print_item => sub {
549 my $user_id = shift;
550 print q[<form action="user.] . htescape ($user_id);
551 print q[" accept-charset=utf-8 method=post>];
552 print qq[<a href="../../users/@{[htescape ($user_id)]}/">];
553 print '' . htescape ($user_id), q[</a> ];
554 print q[<input type=hidden name=action value=unapprove>];
555 print q[<input type=submit value="];
556 print_text ('Cancel invitation');
557 print q["></form>];
558 });
559 }
560 }
561
562 my $join_condition = $group_prop->{join_condition};
563 my $disabled = $ac->{write} ? '' : 'disabled';
564 print qq[<section id=member-approval><h3>];
565 print_text ('Member approval policy');
566 print qq[</h3>
567
568 <form action=join-condition method=post accept-charset=utf-8>
569
570 <p><label><input type=radio name=condition value=invitation $disabled
571 @{[$join_condition->{invitation} ? 'checked' : '']}> ];
572 print_text ('A user who is invited by an administrator of the group can join the group.');
573 print qq[</label>
574
575 <p><label><input type=radio name=condition value=approval $disabled
576 @{[(not $join_condition->{invitation} and $join_condition->{approval})
577 ? 'checked' : '']}> ];
578 print_text ('A user who is invited or approved by an administrator of the group can join the group.');
579 print qq[</label>
580
581 <p><label><input type=radio name=condition value=anyone $disabled
582 @{[(not $join_condition->{invitation} and not
583 $join_condition->{approval}) ? 'checked' : '']}> ];
584 print_text ('Any user can join the group.');
585 print q[</label>];
586 unless ($disabled) {
587 print q[<p><input type=submit value="];
588 print_text ('Change');
589 print q[">];
590 }
591 print q[</form></section>];
592
593 if ($ac->{write}) {
594 print q[<section id=member-invitation><h3>];
595 print_text ('Invite a user');
596 print q[</h3>
597
598 <form action=invite-user accept-charset=utf-8 method=post>
599
600 <p><strong>];
601 print_text ('User id');
602 print q[</strong>: <input type=text name=user-id
603 maxlength=20 size=10 required pattern="[0-9a-z-]{4,20}">
604
605 <p><input type=submit value="];
606 print_text ('Invite');
607 print q["></form></section>];
608 }
609
610 print q[</section>];
611
612 exit;
613 }
614 } elsif ($path[2] eq 'join-condition') {
615 forbidden () unless $ac->{write};
616
617 if ($cgi->request_method eq 'POST') {
618 lock_start ();
619 my $group_prop = get_group_prop ($group_id);
620 if ($group_prop) {
621 binmode STDOUT, ':encoding(utf-8)';
622
623 my $new_condition = $cgi->get_parameter ('condition');
624 if ($new_condition eq 'invitation') {
625 $group_prop->{join_condition}->{invitation} = 1;
626 $group_prop->{join_condition}->{approval} = 1;
627 } elsif ($new_condition eq 'approval') {
628 $group_prop->{join_condition}->{approval} = 1;
629 delete $group_prop->{join_condition}->{invitation};
630 } else {
631 delete $group_prop->{join_condition}->{invitation};
632 delete $group_prop->{join_condition}->{approval};
633 }
634
635 set_group_prop ($group_id, $group_prop);
636 commit ();
637
638 print "Status: 204 join-condition property updated\n\n";
639 exit;
640 }
641 }
642 } elsif ($path[2] eq 'prop') {
643 forbidden () unless $ac->{write};
644
645 if ($cgi->request_method eq 'POST') {
646 lock_start ();
647 my $group_prop = get_group_prop ($group_id);
648 if ($group_prop) {
649 binmode STDOUT, ':encoding(utf-8)';
650
651 my $prop_name = $cgi->get_parameter ('name');
652 if (defined $prop_name and
653 {desc => 1, admin_group => 1,
654 favicon_url => 1}->{$prop_name}) {
655 $group_prop->{$prop_name} = $cgi->get_parameter ('value');
656
657 set_group_prop ($group_id, $group_prop);
658 commit ();
659
660 print "Status: 204 Property updated\n\n";
661 exit;
662 } else {
663 print_error (400, 'Bad property');
664 exit;
665 }
666 }
667 }
668 } elsif ($path[2] =~ /\Auser\.([0-9a-z-]+)\z/ or
669 $path[2] eq 'invite-user') {
670 my $user_id = $1 // $cgi->get_parameter ('user-id') // '';
671 if ($user_id =~ /\A[0-9a-z-]+\z/ and
672 $cgi->request_method eq 'POST') {
673 forbidden () unless $ac->{write};
674
675 lock_start ();
676 my $group_prop = get_group_prop ($group_id);
677 my $user_prop = get_user_prop ($user_id);
678 if ($group_prop and $user_prop) {
679 binmode STDOUT, ':encoding(utf-8)';
680
681 my $gs = ($user_prop->{'group.' . $group_id} ||= {});
682
683 my $action = $cgi->get_parameter ('action');
684 $action = 'approve' if $path[2] eq 'invite-user';
685 my $status;
686 if ($action eq 'approve') {
687 if ($gs->{member}) {
688 $status = 'He is a member';
689 #
690 } elsif ($gs->{no_approval}) {
691 $gs->{member} = 1;
692 delete $gs->{no_approval};
693 $status = 'Registered';
694 #
695 } elsif ($gs->{invited}) {
696 $status = 'He has been invited';
697 #
698 } else {
699 $gs->{invited} = 1;
700 $status = 'Invited';
701 #
702 }
703 } elsif ($action eq 'unapprove') {
704 if ($gs->{member}) {
705 delete $gs->{member};
706 delete $gs->{invited};
707 $status = 'Unregistered';
708 #
709 } elsif ($gs->{invited}) {
710 delete $gs->{invited};
711 $status = 'Invitation canceled';
712 #
713 } else {
714 $status = 'Not a member';
715 #
716 }
717 } else {
718 print_error (400, 'Bad action parameter');
719 exit;
720 }
721
722 set_user_prop ($user_id, $user_prop);
723 send_mail ("$subject_prefix $group_id membership action",
724 "Group: $group_id\nUser: $user_id\nAction: $action\nStatus: $status\n");
725 regenerate_htpasswd_and_htgroup ();
726 commit ();
727
728 #print "Status: 204 $status\n\n";
729 redirect (303, $status, './#members');
730 exit;
731 }
732 }
733 }
734 } elsif (@path == 1 and $path[0] eq 'new-group') {
735 check_access_right (allowed_groups => {'admin-groups' => 1});
736
737 if ($cgi->request_method eq 'POST') {
738 lock_start ();
739 binmode STDOUT, ':encoding(utf-8)';
740
741 my $group_id = $cgi->get_parameter ('group-id');
742
743 if ($group_id !~ /\A[0-9a-z-]{4,20}\z/) {
744 print_error (400,
745 q[Group id %s is invalid; use characters [0-9a-z-]{4,20}],
746 $group_id);
747 exit;
748 }
749
750 if (get_group_prop ($group_id)) {
751 print_error (400, q[Group id %s is already used], $group_id);
752 exit;
753 }
754
755 my $group_prop = {id => $group_id};
756 set_group_prop ($group_id, $group_prop);
757
758 send_mail ("$subject_prefix Group $group_id created",
759 "Group: $group_id\nStatus: Group registered\n");
760 commit ();
761
762 my $group_url = get_absolute_url ('groups/' . $group_id . '/');
763
764 print qq[Status: 201 Group registered
765 Location: $group_url
766 Content-Type: text/html; charset=utf-8
767
768 <!DOCTYPE HTML>
769 <html lang=en>
770 <title>];
771 print_text ('Group %s registered', sub { print '', htescape ($group_id) });
772 print q[</title>
773 <link rel=stylesheet href="/www/style/html/xhtml">
774 <h1>];
775 print_text ('Group %s registered', sub { print '', htescape ($group_id) });
776 print q[</h1><p>];
777 print_text ('The new group is created successfully.');
778 print q[<p>];
779 print_text ('See %s.', sub {
780 print qq[<a href="@{[htescape ($group_url)]}">];
781 print_text ('the group information page');
782 print qq[</a>];
783 });
784 exit;
785 } else {
786 binmode STDOUT, ":encoding(utf-8)";
787 print q[Content-Type: text/html; charset=utf-8
788
789 <!DOCTYPE HTML>
790 <html lang=en>
791 <title>];
792 print_text ('Create a new group');
793 print q[</title>
794 <link rel=stylesheet href="/www/style/html/xhtml">
795 <h1>];
796 print_text ('Create a new group');
797 print q[</h1>
798
799 <form action=new-group accept-charset=utf-8 method=post>
800
801 <p><strong>];
802 print_text ('Group id');
803 print q[</strong>: <input type=text name=group-id
804 maxlength=20 size=10 required pattern="[0-9a-z-]{4,20}"> (];
805 print_text ('Use [0-9a-z-]{4,20}.');
806 print q[) <p><input type=submit value="];
807 print_text ('Create');
808 print q["></form>];
809 exit;
810 }
811 } elsif (@path == 1 and $path[0] eq '') {
812 my $user_id = $cgi->remote_user;
813 forbidden () if not defined $user_id or $user_id !~ /\A[0-9a-z-]+\z/;
814
815 redirect (303, 'See other', 'users/' . $user_id . '/');
816 exit;
817 } elsif (@path == 0) {
818 redirect (301, 'Moved', 'edit/');
819 exit;
820 }
821
822 print_error (404, 'Not found');
823 exit;
824
825 sub print_list_section (%) {
826 my %opt = @_;
827 $opt{level} ||= 3;
828
829 print q[<section id="] . htescape ($opt{id});
830 print q["><h] . $opt{level} . q[>];
831 print_text ($opt{title});
832 print q[</h] . $opt{level} . q[><ul>];
833 for my $item (sort {$a cmp $b} @{$opt{items}}) {
834 print q[<li>];
835 $opt{print_item}->($item);
836 }
837 print q[</ul></section>];
838 } # print_list_section
839
840 sub print_prop_list ($$@) {
841 my $ac = shift;
842 my $prop_hash = shift;
843
844 for my $prop (@_) {
845 if ($prop->{public}) {
846 print q[<p><strong>];
847 print_text ($prop->{label});
848 print q[</strong>: ];
849 print $prop_hash->{$prop->{name}};
850 }
851
852 if ($ac->{write}) {
853 print q[<form action="prop" accept-charset=utf-8 method=post>];
854 print q[<input type=hidden name=name value="], htescape ($prop->{name}), q[">];
855 if ($prop->{field_type} eq 'textarea') {
856 print q[<p><label><strong>];
857 print_text ($prop->{label});
858 print q[</strong>: <br><textarea name="value"];
859 print q[>], htescape ($prop_hash->{$prop->{name}} // '');
860 print q[</textarea></label>];
861 print q[<p><input type=submit value="];
862 print_text ('Save');
863 print q[">];
864 } else {
865 print q[<p><label><strong>];
866 print_text ($prop->{label});
867 print q[</strong>: <input type="] . $prop->{field_type};
868 print q[" name="value" ];
869 print q[value="], htescape ($prop_hash->{$prop->{name}} // '');
870 print q["></label> ];
871 print q[<input type=submit value="];
872 print_text ('Save');
873 print q[">];
874 }
875 print q[</form>];
876 }
877 }
878 } # print_prop_list
879
880 sub check_access_right (%) {
881 my %opt = @_;
882
883 my $user_id = $cgi->remote_user;
884 forbidden () if not defined $user_id or $user_id !~ /\A[0-9a-z-]+\z/;
885
886 my $user_prop = get_user_prop ($user_id);
887 forbidden () unless $user_prop;
888
889 my $ac = {};
890 my $return_ac;
891
892 if ($opt{allowed_users}->{$user_id}) {
893 $ac->{write} = 1;
894 $return_ac = 1;
895 }
896
897 for my $group_id (keys %{$opt{allowed_groups} or {}}) {
898 my $group_prop = get_group_prop ($group_id);
899 next unless $group_prop;
900
901 my $gs = $user_prop->{'group.' . $group_id};
902 if ($gs->{member}) {
903 return {write => 1, read_group_member_list => 1};
904 }
905 }
906
907 if (defined $opt{group_context}) {
908 my $group_prop = get_group_prop ($opt{group_context});
909 if ($group_prop) {
910 if (defined $group_prop->{admin_group}) {
911 my $ag_prop = get_group_prop ($group_prop->{admin_group});
912 if ($ag_prop and
913 $user_prop->{'group.' . $group_prop->{admin_group}}->{member}) {
914 return {write => 1, read_group_member_list => 1};
915 }
916 }
917
918 my $gs = $user_prop->{'group.' . $opt{group_context}};
919 if ($gs->{member}) {
920 $return_ac = 1;
921 } elsif ($gs->{invited}) {
922 $return_ac = 1;
923 } elsif ($group_prop->{join_condition}->{acception}) {
924 $return_ac = 1;
925 } elsif (not $group_prop->{join_condition}->{invitation}) {
926 $return_ac = 1;
927 }
928 }
929 }
930
931 return $ac if $return_ac;
932
933 forbidden ();
934 } # check_access_right
935
936 sub forbidden () {
937 my $user = $cgi->remote_user;
938 if (defined $user) {
939 print_error (403, q[Forbidden (you've logged in as %s)], $user);
940 } else {
941 print_error (403, 'Forbidden');
942 }
943 exit;
944 } # forbidden
945
946 sub redirect ($$$) {
947 my ($code, $status, $url) = @_;
948
949 my $abs_url = get_absolute_url ($url);
950
951 print qq[Status: $code $status
952 Location: $abs_url
953 Content-Type: text/html; charset=us-ascii
954
955 See <a href="@{[htescape ($abs_url)]}">other page</a>.];
956 } # redirect
957
958 sub percent_decode ($) {
959 return $dom->create_uri_reference ($_[0])
960 ->get_iri_reference
961 ->uri_reference;
962 } # percent_decode
963
964 sub get_absolute_url ($) {
965 return $dom->create_uri_reference ($_[0])
966 ->get_absolute_reference ($cgi->request_uri)
967 ->get_iri_reference
968 ->uri_reference;
969 } # get_absolute_url

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24