##// END OF EJS Templates
Added user status criteria in Redmine.pm...
Jean-Philippe Lang -
r917:f2a12d9eb5ae
parent child
Show More
@@ -1,210 +1,210
1 package Apache::Authn::Redmine;
1 package Apache::Authn::Redmine;
2
2
3 =head1 Apache::Authn::Redmine
3 =head1 Apache::Authn::Redmine
4
4
5 Redmine - a mod_perl module to authenticate webdav subversion users
5 Redmine - a mod_perl module to authenticate webdav subversion users
6 against redmine database
6 against redmine database
7
7
8 =head1 SYNOPSIS
8 =head1 SYNOPSIS
9
9
10 This module allow anonymous users to browse public project and
10 This module allow anonymous users to browse public project and
11 registred users to browse and commit their project. authentication is
11 registred users to browse and commit their project. authentication is
12 done on the redmine database.
12 done on the redmine database.
13
13
14 This method is far simpler than the one with pam_* and works with all
14 This method is far simpler than the one with pam_* and works with all
15 database without an hassle but you need to have apache/mod_perl on the
15 database without an hassle but you need to have apache/mod_perl on the
16 svn server.
16 svn server.
17
17
18 =head1 INSTALLATION
18 =head1 INSTALLATION
19
19
20 For this to automagically work, you need to have a recent reposman.rb
20 For this to automagically work, you need to have a recent reposman.rb
21 (after r860) and if you already use reposman, read the last section to
21 (after r860) and if you already use reposman, read the last section to
22 migrate.
22 migrate.
23
23
24 Sorry ruby users but you need some perl modules, at least mod_perl2,
24 Sorry ruby users but you need some perl modules, at least mod_perl2,
25 DBI and DBD::mysql (or the DBD driver for you database as it should
25 DBI and DBD::mysql (or the DBD driver for you database as it should
26 work on allmost all databases).
26 work on allmost all databases).
27
27
28 On debian/ubuntu you must do :
28 On debian/ubuntu you must do :
29
29
30 aptitude install libapache-dbi-perl libapache2-mod-perl2 libdbd-mysql-perl
30 aptitude install libapache-dbi-perl libapache2-mod-perl2 libdbd-mysql-perl
31
31
32 =head1 CONFIGURATION
32 =head1 CONFIGURATION
33
33
34 ## if the module isn't in your perl path
34 ## if the module isn't in your perl path
35 PerlRequire /usr/local/apache/Redmine.pm
35 PerlRequire /usr/local/apache/Redmine.pm
36 ## else
36 ## else
37 # PerlModule Apache::Authn::Redmine
37 # PerlModule Apache::Authn::Redmine
38 <Location /svn>
38 <Location /svn>
39 DAV svn
39 DAV svn
40 SVNParentPath "/var/svn"
40 SVNParentPath "/var/svn"
41
41
42 AuthType Basic
42 AuthType Basic
43 AuthName redmine
43 AuthName redmine
44 Require valid-user
44 Require valid-user
45
45
46 PerlAccessHandler Apache::Authn::Redmine::access_handler
46 PerlAccessHandler Apache::Authn::Redmine::access_handler
47 PerlAuthenHandler Apache::Authn::Redmine::authen_handler
47 PerlAuthenHandler Apache::Authn::Redmine::authen_handler
48
48
49 ## for mysql
49 ## for mysql
50 PerlSetVar dsn DBI:mysql:database=databasename;host=my.db.server
50 PerlSetVar dsn DBI:mysql:database=databasename;host=my.db.server
51 ## for postgres
51 ## for postgres
52 # PerlSetVar dsn DBI:Pg:dbname=databasename;host=my.db.server
52 # PerlSetVar dsn DBI:Pg:dbname=databasename;host=my.db.server
53
53
54 PerlSetVar db_user redmine
54 PerlSetVar db_user redmine
55 PerlSetVar db_pass password
55 PerlSetVar db_pass password
56 </Location>
56 </Location>
57
57
58 To be able to browse repository inside redmine, you must add something
58 To be able to browse repository inside redmine, you must add something
59 like that :
59 like that :
60
60
61 <Location /svn-private>
61 <Location /svn-private>
62 DAV svn
62 DAV svn
63 SVNParentPath "/var/svn"
63 SVNParentPath "/var/svn"
64 Order deny,allow
64 Order deny,allow
65 Deny from all
65 Deny from all
66 # only allow reading orders
66 # only allow reading orders
67 <Limit GET PROPFIND OPTIONS REPORT>
67 <Limit GET PROPFIND OPTIONS REPORT>
68 Allow from redmine.server.ip
68 Allow from redmine.server.ip
69 </Limit>
69 </Limit>
70 </Location>
70 </Location>
71
71
72 and you will have to use this reposman.rb command line to create repository :
72 and you will have to use this reposman.rb command line to create repository :
73
73
74 reposman.rb --redmine my.redmine.server --svn-dir /var/svn --owner www-data -u http://svn.server/svn-private/
74 reposman.rb --redmine my.redmine.server --svn-dir /var/svn --owner www-data -u http://svn.server/svn-private/
75
75
76 =head1 MIGRATION FROM OLDER RELEASES
76 =head1 MIGRATION FROM OLDER RELEASES
77
77
78 If you use an older reposman.rb (r860 or before), you need to change
78 If you use an older reposman.rb (r860 or before), you need to change
79 rights on repositories to allow the apache user to read and write
79 rights on repositories to allow the apache user to read and write
80 S<them :>
80 S<them :>
81
81
82 sudo chown -R www-data /var/svn/*
82 sudo chown -R www-data /var/svn/*
83 sudo chmod -R u+w /var/svn/*
83 sudo chmod -R u+w /var/svn/*
84
84
85 And you need to upgrade at least reposman.rb (after r860).
85 And you need to upgrade at least reposman.rb (after r860).
86
86
87 =cut
87 =cut
88
88
89 use strict;
89 use strict;
90
90
91 use DBI;
91 use DBI;
92 use Digest::SHA1;
92 use Digest::SHA1;
93
93
94 use Apache2::Module;
94 use Apache2::Module;
95 use Apache2::Access;
95 use Apache2::Access;
96 use Apache2::ServerRec qw();
96 use Apache2::ServerRec qw();
97 use Apache2::RequestRec qw();
97 use Apache2::RequestRec qw();
98 use Apache2::RequestUtil qw();
98 use Apache2::RequestUtil qw();
99 use Apache2::Const qw(:common);
99 use Apache2::Const qw(:common);
100 # use Apache2::Directive qw();
100 # use Apache2::Directive qw();
101
101
102 my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
102 my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
103
103
104 sub access_handler {
104 sub access_handler {
105 my $r = shift;
105 my $r = shift;
106
106
107 unless ($r->some_auth_required) {
107 unless ($r->some_auth_required) {
108 $r->log_reason("No authentication has been configured");
108 $r->log_reason("No authentication has been configured");
109 return FORBIDDEN;
109 return FORBIDDEN;
110 }
110 }
111
111
112 my $method = $r->method;
112 my $method = $r->method;
113 return OK unless 1 == $read_only_methods{$method};
113 return OK unless 1 == $read_only_methods{$method};
114
114
115 my $project_id = get_project_identifier($r);
115 my $project_id = get_project_identifier($r);
116
116
117 $r->set_handlers(PerlAuthenHandler => [\&OK])
117 $r->set_handlers(PerlAuthenHandler => [\&OK])
118 if is_public_project($project_id, $r);
118 if is_public_project($project_id, $r);
119
119
120 return OK
120 return OK
121 }
121 }
122
122
123 sub authen_handler {
123 sub authen_handler {
124 my $r = shift;
124 my $r = shift;
125
125
126 my ($res, $redmine_pass) = $r->get_basic_auth_pw();
126 my ($res, $redmine_pass) = $r->get_basic_auth_pw();
127 return $res unless $res == OK;
127 return $res unless $res == OK;
128
128
129 if (is_member($r->user, $redmine_pass, $r)) {
129 if (is_member($r->user, $redmine_pass, $r)) {
130 return OK;
130 return OK;
131 } else {
131 } else {
132 $r->note_auth_failure();
132 $r->note_auth_failure();
133 return AUTH_REQUIRED;
133 return AUTH_REQUIRED;
134 }
134 }
135 }
135 }
136
136
137 sub is_public_project {
137 sub is_public_project {
138 my $project_id = shift;
138 my $project_id = shift;
139 my $r = shift;
139 my $r = shift;
140
140
141 my $dbh = connect_database($r);
141 my $dbh = connect_database($r);
142 my $sth = $dbh->prepare(
142 my $sth = $dbh->prepare(
143 "SELECT * FROM projects WHERE projects.identifier=? and projects.is_public=true;"
143 "SELECT * FROM projects WHERE projects.identifier=? and projects.is_public=true;"
144 );
144 );
145
145
146 $sth->execute($project_id);
146 $sth->execute($project_id);
147 my $ret = $sth->fetchrow_array ? 1 : 0;
147 my $ret = $sth->fetchrow_array ? 1 : 0;
148 $dbh->disconnect();
148 $dbh->disconnect();
149
149
150 $ret;
150 $ret;
151 }
151 }
152
152
153 # perhaps we should use repository right (other read right) to check public access.
153 # perhaps we should use repository right (other read right) to check public access.
154 # it could be faster BUT it doesn't work for the moment.
154 # it could be faster BUT it doesn't work for the moment.
155 # sub is_public_project_by_file {
155 # sub is_public_project_by_file {
156 # my $project_id = shift;
156 # my $project_id = shift;
157 # my $r = shift;
157 # my $r = shift;
158
158
159 # my $tree = Apache2::Directive::conftree();
159 # my $tree = Apache2::Directive::conftree();
160 # my $node = $tree->lookup('Location', $r->location);
160 # my $node = $tree->lookup('Location', $r->location);
161 # my $hash = $node->as_hash;
161 # my $hash = $node->as_hash;
162
162
163 # my $svnparentpath = $hash->{SVNParentPath};
163 # my $svnparentpath = $hash->{SVNParentPath};
164 # my $repos_path = $svnparentpath . "/" . $project_id;
164 # my $repos_path = $svnparentpath . "/" . $project_id;
165 # return 1 if (stat($repos_path))[2] & 00007;
165 # return 1 if (stat($repos_path))[2] & 00007;
166 # }
166 # }
167
167
168 sub is_member {
168 sub is_member {
169 my $redmine_user = shift;
169 my $redmine_user = shift;
170 my $redmine_pass = shift;
170 my $redmine_pass = shift;
171 my $r = shift;
171 my $r = shift;
172
172
173 my $dbh = connect_database($r);
173 my $dbh = connect_database($r);
174 my $project_id = get_project_identifier($r);
174 my $project_id = get_project_identifier($r);
175
175
176 my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
176 my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
177
177
178 my $sth = $dbh->prepare(
178 my $sth = $dbh->prepare(
179 "SELECT hashed_password FROM members, projects, users WHERE projects.id=members.project_id AND users.id=members.user_id AND login=? AND identifier=?;"
179 "SELECT hashed_password FROM members, projects, users WHERE projects.id=members.project_id AND users.id=members.user_id AND users.status=1 AND login=? AND identifier=?;"
180 );
180 );
181 $sth->execute($redmine_user, $project_id);
181 $sth->execute($redmine_user, $project_id);
182
182
183 my $ret;
183 my $ret;
184 while (my @row = $sth->fetchrow_array) {
184 while (my @row = $sth->fetchrow_array) {
185 if ($row[0] eq $pass_digest) {
185 if ($row[0] eq $pass_digest) {
186 $ret = 1;
186 $ret = 1;
187 last;
187 last;
188 }
188 }
189 }
189 }
190 $dbh->disconnect();
190 $dbh->disconnect();
191
191
192 $ret;
192 $ret;
193 }
193 }
194
194
195 sub get_project_identifier {
195 sub get_project_identifier {
196 my $r = shift;
196 my $r = shift;
197
197
198 my $location = $r->location;
198 my $location = $r->location;
199 my ($identifier) = $r->uri =~ m{$location/*([^/]+)};
199 my ($identifier) = $r->uri =~ m{$location/*([^/]+)};
200 $identifier;
200 $identifier;
201 }
201 }
202
202
203 sub connect_database {
203 sub connect_database {
204 my $r = shift;
204 my $r = shift;
205
205
206 my ($dsn, $db_user, $db_pass) = map { $r->dir_config($_) } qw/dsn db_user db_pass/;
206 my ($dsn, $db_user, $db_pass) = map { $r->dir_config($_) } qw/dsn db_user db_pass/;
207 return DBI->connect($dsn, $db_user, $db_pass);
207 return DBI->connect($dsn, $db_user, $db_pass);
208 }
208 }
209
209
210 1;
210 1;
General Comments 0
You need to be logged in to leave comments. Login now