source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Acls/Acl.pm

Last change on this file was 2381, checked in by nanardon, 4 years ago

Fix ACL, replace $ROOT by @ROOT: '$' has special meaning here

File size: 4.2 KB
Line 
1package LATMOS::Accounts::Acls::Acl;
2use strict;
3use warnings;
4
5=head1 NAME
6
7LATMOS::Accounts::Acls::Acl - Single acl entry
8
9=head1 DESCRIPTION
10
11Manage a single acl entry
12
13=head1 FUNCTIONS
14
15=head2 new ($objdotatt, $list)
16
17Create new sub acl where C<$objdotatt> is object in form C<Object.Attribute> and
18C<$list> the list of permission.
19
20=cut
21
22sub new {
23    my ($class, $objdotatt, $list) = @_;
24    my ($obj, $attr) = $objdotatt =~ /^([^.]+)\.(.*)/ or return;
25    my @attrs = ($attr =~ /^\{(.*)\}$/)
26        ? (split(/\s*,\s*/, $1))
27        : ($attr);
28    @attrs or return;
29    my $acl = {
30        obj => lc($obj),
31        attr => [ map { lc } @attrs ],
32        users => [], # user->{r} = 1
33    };
34    bless($acl, $class);
35    foreach my $k (@{ $list || [] }) {
36        $acl->add_perm($k) or return;
37    }
38    $acl
39}
40
41=head2 add_perm($perm)
42
43Add a permission to this sub acl
44
45=cut
46
47sub add_perm {
48    my ($self, $perm) = @_;
49    my ($username, $perms) = $perm =~ /^\s*(\S*):\s*(.*)$/;
50    $username && $perms or return;
51    my $user = { user => $username };
52    foreach (split(/\s*,\s*/, $perms)) {
53        /^read$/i  and do { $user->{r} = 1; next; };
54        /^write$/i and do { $user->{w} = 1; next; };
55        /^deny$/i and do {
56            # reseting...
57            $user->{r} = 0;
58            $user->{w} = 0;
59            last; # we end here, life is hard
60        };
61        return;
62    }
63    push(@{$self->{users}}, $user);
64    1
65}
66
67=head2 match($obj, $attr, $perm, $who, $groups, $base)
68
69Return true is this sub acl apply to C<$obj>/C<$attr> for C<$perm> by user
70C<$who> in groups C<$groups>.
71
72=cut
73
74sub match {
75    my ($self, $obj, $attr, $perm, $who, $groups, $base) = @_;
76    my $objtype = ref $obj ? lc($obj->type) : $obj;
77    $attr = lc($attr);
78
79    # Does this ACL series concern this object:
80    if (!($self->{obj} eq '*' || $self->{obj} eq $objtype)) {
81        return
82    }
83    # Does this ACL series concern this attribute:
84    grep { $_ eq '*' || $_ eq $attr } @{$self->{attr}} or return;
85
86    # Foreach user, testing if this permission match:
87    foreach my $u (@{ $self->{users} }) {
88        defined($u->{$perm}) or next;
89        # Obj have attr eq login user
90        if (substr($u->{user}, 0, 1) eq '$') { # check attr content
91            my $attribute = substr($u->{user}, 1);
92            my $val = (ref $obj ? $obj->_get_c_field($attribute) : undef)  or return;
93            my @vals = ref $val ? (@{ $val }) : ($val);
94            foreach (@vals) {
95                return $u->{$perm} if ($self->_objId('user', $_, $base) eq $who);
96            }
97        # user is in group
98        } elsif (substr($u->{user}, 0, 1) eq '%') { # group
99            my $group = substr($u->{user}, 1);
100            return $u->{$perm} if (grep { $self->_objId('group', $group, $base) eq $_ } grep { $_ } @{$groups ||[]});
101        # any user
102        } elsif ($u->{user} eq '*' || $u->{user} eq $who) {
103            # TODO deference alias for SQL base
104            # $obj->base->get_objects(...) ?
105            return $u->{$perm};
106        # any authenticated user
107        } elsif (lc($u->{user}) eq '@authenticated' && $who) {
108            return $u->{$perm};
109        # not login
110        } elsif (lc($u->{user}) eq '@anonymous' && $who eq '') {
111            return $u->{$perm};
112        }
113    }
114    return;
115}
116
117sub _objId {
118    my ( $self, $otype, $id, $base ) = @_;
119
120    $base or return $id;
121
122    my $obj = $base->get_object( $otype, $id ) or return $id;
123
124    return $obj->AclID;
125}
126
127=head2 dump
128
129Return a textual dump of the sub acl
130
131=cut
132
133sub dump {
134    my ($self) = @_;
135    my $dump = sprintf("%s.{%s}\n", $self->{obj}, join(', ', @{$self->{attr}}));
136    foreach my $u (@{ $self->{users} }) {
137        $dump .= sprintf("\t%s: %s\n",
138            $u->{user},
139            join(', ', ($u->{r} ? 'read' : ()), ($u->{w} ? 'write' : ())) ||
140            'deny');
141    }
142    $dump
143}
144
1451;
146
147__END__
148
149=head1 SEE ALSO
150
151L<LATMOS::Accounts::Acls>
152
153=head1 AUTHOR
154
155Thauvin Olivier, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
156
157=head1 COPYRIGHT AND LICENSE
158
159Copyright (C) 2009, 2010, 2011, 2012 by Thauvin Olivier
160
161This library is free software; you can redistribute it and/or modify
162it under the same terms as Perl itself, either Perl version 5.10.0 or,
163at your option, any later version of Perl 5 you may have available.
164
165=cut
Note: See TracBrowser for help on using the repository browser.