File Coverage

blib/lib/DJabberd/Authen/SQLite.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1            
2             package DJabberd::Authen::SQLite;
3 1     1   726 use strict;
  1         2  
  1         33  
4 1     1   5 use base 'DJabberd::Authen';
  1         2  
  1         537  
5            
6 1     1   408 use DJabberd::Log;
  0            
  0            
7             our $logger = DJabberd::Log->get_logger;
8             use DBI;
9            
10             use vars qw($VERSION);
11             $VERSION = '0.01';
12            
13             sub log {
14             $logger;
15             }
16            
17             =head1 NAME
18            
19             DJabberd::Authen::SQLite - A SQLite authentication module for DJabberd
20            
21             =head1 VERSION
22            
23             Version 0.01
24            
25             =head1 SYNOPSIS
26            
27            
28            
29             [...]
30            
31            
32             DBName djabberd
33             DBTable user
34             DBUsernameColumn username
35             DBPasswordColumn password
36             DBWhere canjabber = 1
37            
38            
39            
40             DBName, DBTable, DBUsernameColumn and DBPasswordColumn are required.
41             Everything else is optional.
42            
43            
44             =head1 AUTHOR
45            
46             Piers Harding, piers@cpan.org.
47            
48            
49             =cut
50            
51            
52             sub set_config_database {
53             my ($self, $dbfile) = @_;
54             $self->{dbfile} = $dbfile;
55             $logger->info("Loaded SQLite Authen using file '$dbfile'");
56             }
57            
58             sub check_install_schema {
59             my $self = shift;
60             my $dbh = $self->{sqlite_dbh};
61            
62             eval {
63             $dbh->do(qq{
64             CREATE TABLE $self->{sqlite_table} (
65             $self->{sqlite_usernamecolumn} VARCHAR(255),
66             $self->{sqlite_passwordcolumn} VARCHAR(255),
67             PRIMARY KEY ($self->{sqlite_usernamecolumn})
68             )});
69             };
70             if ($@ && $@ !~ /table \w+ already exists/) {
71             $logger->logdie("SQL error $@");
72             die "SQL error: $@\n";
73             }
74            
75             $logger->info("Created SQLite users tables");
76            
77             }
78            
79             sub blocking { 1 };
80            
81             sub set_config_dbtable {
82             my ($self, $dbtable) = @_;
83             $self->{'sqlite_table'} = $dbtable;
84             }
85            
86             sub set_config_dbusernamecolumn {
87             my ($self, $dbusernamecolumn) = @_;
88             $self->{'sqlite_usernamecolumn'} = $dbusernamecolumn;
89             }
90            
91             sub set_config_dbpasswordcolumn {
92             my ($self, $dbpasswordcolumn) = @_;
93             $self->{'sqlite_passwordcolumn'} = $dbpasswordcolumn;
94             }
95            
96             sub set_config_dbwhere {
97             my ($self, $dbwhere) = @_;
98             $self->{'sqlite_where'} = $dbwhere;
99             }
100            
101             sub finalize {
102             my $self = shift;
103             die "No 'Database' configured'" unless $self->{dbfile};
104             my $dsn = "dbi:SQLite:dbname=$self->{'dbfile'}";
105             my $dbh = DBI->connect($dsn, "", "", { RaiseError => 1, PrintError => 0, AutoCommit => 1 });
106             $self->{'sqlite_dbh'} = $dbh;
107             $self->check_install_schema;
108             return $self;
109             }
110            
111             sub can_register_jids {
112             1;
113             }
114            
115             sub can_unregister_jids {
116             1;
117             }
118            
119             sub can_retrieve_cleartext {
120             my $self = shift;
121             return 1;
122             }
123            
124             sub get_password {
125             my ($self, $cb, %args) = @_;
126            
127             my $user = $args{'username'};
128             my $dbh = $self->{'sqlite_dbh'};
129            
130             my $sql_username = "SELECT $self->{'sqlite_usernamecolumn'}, $self->{'sqlite_passwordcolumn'} FROM $self->{'sqlite_table'} WHERE $self->{'sqlite_usernamecolumn'} = ".$dbh->quote($user);
131             my $sql_where = (defined $self->{'sqlite_where'} ? " AND $self->{'sqlite_where'}" : "");
132            
133             my ($username, $password) = $dbh->selectrow_array("$sql_username $sql_where");
134             if (defined $username) {
135             $logger->debug("Fetched password for '$username'");
136             $cb->set($password);
137             return;
138             }
139             $logger->info("Can't fetch password for '$username': user does not exist or did not satisfy WHERE clause");
140             $cb->decline;
141             }
142            
143             sub register_jid {
144             my ($self, $cb, %args) = @_;
145             my $username = $args{'username'};
146             my $password = $args{'password'};
147             my $dbh = $self->{'sqlite_dbh'};
148            
149             if (defined(($dbh->selectrow_array("SELECT * FROM $self->{'sqlite_table'} WHERE $self->{'sqlite_usernamecolumn'} = " . $dbh->quote($username)))[0])) { # if user exists
150             $logger->info("Registration failed for user '$username': user exists");
151             $cb->conflict;
152             return 0;
153             } else {
154             eval {
155             $dbh->do("INSERT INTO $self->{'sqlite_table'} ( $self->{'sqlite_usernamecolumn'}, $self->{'sqlite_passwordcolumn'} ) VALUES ( " . $dbh->quote($username) . ", " . $dbh->quote($password) ." )");
156             };
157             if ($@) {
158             $logger->info("Registration failed for user '$username': database query failed: $@");
159             $cb->error;
160             return 0;
161             } else {
162             $logger->debug("User '$username' registered successfully");
163             $cb->saved;
164             return 1;
165             }
166             }
167             }
168            
169             sub unregister_jid {
170             my ($self, $cb, %args) = @_;
171             my $username = $args{'username'};
172             my $dbh = $self->{'sqlite_dbh'};
173            
174             if (defined(($dbh->selectrow_array("SELECT * FROM $self->{'sqlite_table'} WHERE $self->{'sqlite_usernamecolumn'} = " . $dbh->quote($username)))[0])) { # if user exists
175             eval {
176             $dbh->do("DELETE FROM $self->{'sqlite_table'} WHERE $self->{'sqlite_usernamecolumn'} = " . $dbh->quote($username));
177             };
178             if ($@) {
179             $logger->info("Cancellation of registration failed for user '$username': database query failed");
180             $cb->error;
181             return 0;
182             } else {
183             $logger->debug("User '$username' canceled registration successfully");
184             $cb->deleted;
185             return 1;
186             }
187             } else {
188             $logger->info("Cancellation of registration failed for user '$username': user not found");
189             $cb->notfound;
190             return 0;
191             }
192             }
193            
194             sub check_cleartext {
195             my ($self, $cb, %args) = @_;
196             my $username = $args{username};
197             my $password = $args{password};
198             my $conn = $args{conn};
199             unless ($username =~ /^\w+$/) {
200             $cb->reject;
201             return;
202             }
203            
204             my $dbh = $self->{'sqlite_dbh'};
205             my $sql_username = "SELECT $self->{'sqlite_usernamecolumn'} FROM $self->{'sqlite_table'} WHERE $self->{'sqlite_usernamecolumn'} = ".$dbh->quote($username);
206             my $sql_password = " AND $self->{'sqlite_passwordcolumn'} = ". $dbh->quote($password);
207             my $sql_where = (defined $self->{'sqlite_where'} ? " AND $self->{'sqlite_where'}" : "");
208            
209             if (defined(($dbh->selectrow_array("$sql_username $sql_password $sql_where"))[0])) {
210             $cb->accept;
211             $logger->debug("User '$username' authenticated successfully");
212             return 1;
213             } else {
214             $cb->reject();
215             if (defined(($dbh->selectrow_array("$sql_username $sql_where"))[0])) { # if user exists
216             $logger->info("Auth failed for user '$username': password error");
217             return 0;
218             } else {
219             $logger->info("Auth failed for user '$username': user does not exist or did not satisfy WHERE clause");
220             return 1;
221             }
222             }
223             }
224            
225             =head1 COPYRIGHT & LICENSE
226            
227             Original work Copyright 2006 Alexander Karelas, Martin Atkins, Brad Fitzpatrick and Aleksandar Milanov. All rights reserved.
228             Copyright 2007 Piers Harding.
229            
230             This program is free software; you can redistribute it and/or modify it
231             under the same terms as Perl itself.
232            
233             =cut
234            
235             1;