File Coverage

blib/lib/Role/Pg/Roles.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Role::Pg::Roles;
2             $Role::Pg::Roles::VERSION = '0.001';
3 1     1   5176 use Moose::Role;
  0            
  0            
4             use DBI;
5             use Digest::MD5 qw/md5_hex/;
6              
7             has 'roles_dbh' => (
8             is => 'ro',
9             isa => 'DBI::db',
10             lazy_build => 1,
11             );
12              
13             sub _build_roles_dbh {
14             my $self = shift;
15             return $self->dbh if $self->can('dbh');
16             return $self->schema->storage->dbh if $self->can('schema');
17             }
18              
19             sub create {
20             my ($self, %args) = @_;
21             my $dbh = $self->roles_dbh;
22             my $role = $dbh->quote_identifier($args{role}) or return;
23             my $sql = qq{
24             CREATE ROLE $role
25             };
26             my @values;
27             if (my $password = $args{password}) {
28             $sql .= ' WITH ENCRYPTED PASSWORD ?';
29             push @values, $password;
30             }
31             $self->roles_dbh->do($sql, undef, @values);
32             }
33              
34             sub drop {
35             my ($self, %args) = @_;
36             my $dbh = $self->roles_dbh;
37             my $role = $dbh->quote_identifier($args{role}) or return;
38             my $sql = qq{
39             DROP ROLE $role
40             };
41             $self->roles_dbh->do($sql);
42             }
43              
44             sub add {
45             my ($self, %args) = @_;
46             my $dbh = $self->roles_dbh;
47             my ($group, $member) = map {$dbh->quote_identifier($args{$_}) // return} qw/group member/;
48             my $sql = qq{
49             GRANT $group TO $member
50             };
51             $self->roles_dbh->do($sql);
52             }
53              
54             sub remove {
55             my ($self, %args) = @_;
56             my $dbh = $self->roles_dbh;
57             my ($group, $member) = map {$dbh->quote_identifier($args{$_}) // return} qw/group member/;
58             my $sql = qq{
59             REVOKE $group FROM $member
60             };
61             $self->roles_dbh->do($sql);
62             }
63              
64             sub check_user {
65             my ($self, %args) = @_;
66             my $dbh = $self->roles_dbh;
67             my ($user, $password) = map {$args{$_} // return} qw/user password/;
68             my $sql = qq{
69             SELECT 1 FROM pg_catalog.pg_authid
70             WHERE rolname = ? AND rolpassword = ?
71             };
72             push my @values, $user, 'md5' . md5_hex($password . $user);
73             return $self->roles_dbh->selectrow_arrayref($sql, undef, @values) ? 1 : 0;
74             }
75              
76             sub roles {
77             my ($self, %args) = @_;
78             my $sql = q{
79             SELECT rolname
80             FROM pg_authid a
81             WHERE pg_has_role(?, a.oid, 'member')
82             };
83             my @values = map {$args{$_} // return} qw/user/;
84              
85             return [ sort map {shift @$_} @{ $self->roles_dbh->selectall_arrayref($sql, undef, @values) } ];
86             }
87              
88             sub member_of {
89             my ($self, %args) = @_;
90             my ($user, $group) = map {$args{$_} // return} qw/user group/;
91             my $roles = $self->roles(user => $user);
92              
93             return grep {$group eq $_} @$roles;
94             }
95              
96             sub set {
97             my ($self, %args) = @_;
98             my $dbh = $self->roles_dbh;
99             my $role = $dbh->quote_identifier($args{role}) or return;
100             my $sql = qq{
101             SET ROLE $role
102             };
103             $self->roles_dbh->do($sql);
104             }
105              
106             sub reset {
107             my ($self) = @_;
108             my $sql = qq{
109             RESET ROLE
110             };
111             $self->roles_dbh->do($sql);
112             }
113              
114             1;
115              
116             =pod
117              
118             =encoding UTF-8
119              
120             =head1 NAME
121              
122             Role::Pg::Roles - Client Role for handling PostgreSQL Roles
123              
124             =head1 VERSION
125              
126             version 0.001
127              
128             =head1 name
129              
130             role::pg::roles
131              
132             =head1 description
133              
134             this role handles the use of roles in a postgresql database.
135              
136             =head1 attributes
137              
138             =head2 roles_dbh
139              
140             role::pg::roles tries to guess your dbh. if it isn't a standard dbi::db named dbh, or
141             constructed in a dbix::class schema called schema, you have to return the dbh from
142             _build_roles_dbh.
143              
144             =head1 METHODS
145              
146             =head2 create
147              
148             $self->create(role => 'me', password => 'safety');
149              
150             Creates a role. The role can be seen as either a user or a group.
151              
152             An optional password can be added. The user is then created with an encrypted password.
153              
154             =head2 drop
155              
156             $self->drop(role => 'me');
157              
158             Drops a role.
159              
160             =head2 add
161              
162             $self->add(group => 'group', member => 'me');
163              
164             Adds a member to a group. A member can be a user or a group
165              
166             =head2 remove
167              
168             $self->remove(group => 'group', member => 'me');
169              
170             Removes a member from a group.
171              
172             =head2 check_user
173              
174             my $roles = $self->check_user(user => 'me', password => 'trust me!');
175              
176             Checks if there is a user with the given password
177              
178             =head2 roles
179              
180             my $roles = $self->roles(user => 'me');
181              
182             Returns an arrayref with all the roles the user is a member of.
183              
184             =head2 member_of
185              
186             print "yep" if $self->member_of(user => 'me', group => 'group');
187              
188             Returns true if user is member of group.
189              
190             =head2 set
191              
192             $self->set(role => 'elvis');
193              
194             Assume another role.
195              
196             =head2 reset
197              
198             $self->reset;
199              
200             Back to your old self.
201              
202             =head1 AUTHOR
203              
204             Kaare Rasmussen <kaare@cpan.org>.
205              
206             =head1 COPYRIGHT
207              
208             Copyright (C) 2014, Kaare Rasmussen
209              
210             This module is free software; you can redistribute it or modify it
211             under the same terms as Perl itself.
212              
213             =head1 AUTHOR
214              
215             Kaare Rasmussen <kaare at cpan dot net>
216              
217             =head1 COPYRIGHT AND LICENSE
218              
219             This software is copyright (c) 2014 by Kaare Rasmussen.
220              
221             This is free software; you can redistribute it and/or modify it under
222             the same terms as the Perl 5 programming language system itself.
223              
224             =cut
225              
226             __END__
227              
228             # ABSTRACT: Client Role for handling PostgreSQL Roles
229