Updated the plugin to match InDefero's coding standards.

dev
Loic d'Anterroches 2008-12-03 23:02:59 +01:00
parent 39cf9f985a
commit b60aeb0ca1
5 changed files with 205 additions and 113 deletions

View File

@ -5,4 +5,5 @@ Much appreciated contributors:
Nicolas Lassalle <http://www.beroot.org/> - Subversion support
bohwaz <http://bohwaz.net/>
Benjamin Jorand <benjamin.jorand@gmail.com> - Mercurial support
Benjamin Jorand <benjamin.jorand@gmail.com> - Mercurial support
Baptiste Michaud <bactisme@gmail.com> - Subversion synchronization

75
doc/syncsvn.mdtext 100644
View File

@ -0,0 +1,75 @@
# Plugin SyncSvn by Baptiste Michaud
The SyncSvn plugin allow the direct creation and synchronisation of
subversion repositories with the InDefero database. This requires
giving access to the repositories using the DAV_SVN module of Apache2.
## To Contact the Author
Baptiste Michaud
bactisme@gmail.com
webplay.fr - frandroid.com - lost-in-translation.fr
## Apache configuration
You will first need to install the DAV_SVN module for Apache. On
Debian/Ubuntu based systems just run:
$ sudo apt-get install libapache2-svn
$ sudo a2enmod dav_svn
Then, you need to configure dav_svn, this is an example of
configuration:
<Location /svn>
DAV svn
SVNParentPath /home/svn/repositories
AuthzSVNAccessFile /home/svn/dav_svn.authz
Satisfy Any
Require valid-user
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /home/svn/dav_svn.passwd
</Location>
Be sure to [read the documentation before](http://svnbook.red-bean.com/en/1.5/svn.serverconfig.httpd.html).
The files `/home/svn/dav_svn.authz`, `/home/svn/dav_svn.passwd` and
the directory `/home/svn/repositories` must be writable by your
webserver process. To ensure that, do:
$ sudo mkdir --parents /home/svn/repositories
$ sudo touch /home/svn/dav_svn.authz
$ sudo touch /home/svn/dav_svn.passwd
$ sudo chown -R www-data:www-data /home/svn
Now, you need to restart apache:
$ sudo /etc/init.d/apache2 force-reload
## InDefero Configuration
Based on the paths provided in the Apache configuration and if your
Apache server is serving the domain `www.mydomain.com`, the you need
to put the following in your configuration file:
$cfg['svn_repositories'] = 'file:///home/svn/repositories/%s';
// We add "trunk" to invite people to checkout the trunk of the
// project.
$cfg['svn_remote_url'] = 'http://www.mydomain.com/svn/%s/trunk';
// Synchronisation specific configuration variables
$cfg['idf_plugin_syncsvn_authz_file'] = '/home/svn/dav_svn.authz';
$cfg['idf_plugin_syncsvn_passwd_file'] = '/home/svn/dav_svn.passwd';
$cfg['idf_plugin_syncsvn_svn_path'] = '/home/svn/repositories';
You can have more control over the permissions given to the owners,
members, extra authorized users and anonymous users if you want with
the following configuration variables:
* **idf_plugin_syncsvn_access_owners ('rw')**: Access for the project owners.
* **idf_plugin_syncsvn_access_members ('rw')**: Access for the project members.
* **idf_plugin_syncsvn_access_extra ('r')**: Access for the extra authorized people in case of a private project.
* **idf_plugin_syncsvn_access_public ('r')**: Anonymous access.
* **idf_plugin_syncsvn_access_private ('')**: Anonymous access in the case of a private project.

View File

@ -97,6 +97,7 @@ class IDF_Form_TabsConf extends Pluf_Form
$this->project->private = 0;
}
$this->project->update();
$this->project->membershipsUpdated();
}
}

View File

@ -24,171 +24,175 @@
require_once 'File/Passwd/Authdigest.php'; // $ pear install File_Passwd
/**
* This classes is a plugin which allows to synchronise access rights between indefero
* and a DAV powered SVN repository.
* This classes is a plugin which allows to synchronise access rights
* between indefero and a DAV powered Subversion repository.
*/
class IDF_Plugin_SyncSvn
{
/**
* Entry point of the each plugins.
* Entry point of the plugin.
*/
static function entry($signal, $params){
// if not actif, do nothing
if ($signal == 'IDF_Project::created'){
$project = $params['project'];
$plug = new IDF_Plugin_SyncSVN();
//$plug->processSVNCreate($project->shortname);
}else if ($signal == 'IDF_Project::membershipsUpdated'){
$project = $params['project'];
$plug = new IDF_Plugin_SyncSVN();
$plug->processSyncAuthz($project);
}else if ($signal == 'IDF_User::passwordUpdated'){
$plug = new IDF_Plugin_SyncSVN();
static public function entry($signal, $params)
{
// First check for the 3 mandatory config variables.
if (!Pluf::f('idf_plugin_syncsvn_authz_file', false) or
!Pluf::f('idf_plugin_syncsvn_passwd_file', false) or
!Pluf::f('idf_plugin_syncsvn_svn_path'. false)) {
return;
}
$plug = new IDF_Plugin_SyncSvn();
switch ($signal) {
case 'IDF_Project::created':
$plug->processSvnCreate($params['project']);
break;
case 'IDF_Project::membershipsUpdated':
$plug->processSyncAuthz($params['project']);
break;
case 'Pluf_User::passwordUpdated':
$plug->processSyncPasswd($params['user']);
}else {
// do nothing
break;
}
}
/**
* Run svnadmin command to create a usable SVN repository
* @param Project name
* Run svnadmin command to create the corresponding Subversion
* repository.
*
* @param IDF_Project
* @return bool Success
*/
function processSVNCreate($shortname){
$svn_path = Pluf::f('idf_plugin_syncsvn_svn_path');
$svn_import_path = Pluf::f('idf_plugin_syncsvn_svn_import_path');
$chown_user = Pluf::f('idf_plugin_syncsvn_svn_import_path');
$c = 0;
$createsvn = "svnadmin create ".$svn_path."/".$shortname;
Pluf_Utils::runExternal($createsvn, $c);
if ($svn_import_path != ""){
//perform initial import
// TODO
function processSvnCreate($project)
{
$shortname = $project->shortname;
if (false===($svn_path=Pluf::f('idf_plugin_syncsvn_svn_path',false))) {
throw new Pluf_Exception_SettingError("'idf_plugin_syncsvn_svn_path' must be defined in your configuration file.");
}
if ($chown_user != ""){
$chown = "chown ".$chown_user." ".$svn_path."/".$shortname." -R";
Pluf_Utils::runExternal($chown, $c);
if (file_exists($svn_path.'/'.$shortname)) {
throw new Exception(sprintf(__('The repository %s already exists.'),
$svn_path.'/'.$shortname));
}
$return = 0;
$output = array();
$cmd = sprintf('svnadmin create %s',
escapeshellarg($svn_path.'/'.$shortname));
$ll = exec($cmd, $output, $return);
return ($return == 0);
}
/**
* Synchronise an user's password
* @param $user Pluf_User
* Synchronise an user's password.
*
* @param Pluf_User
*/
function processSyncPasswd($user){
function processSyncPasswd($user)
{
$passwd_file = Pluf::f('idf_plugin_syncsvn_passwd_file');
if (!file_exists($passwd_file) or !is_writable($passwd_file)) {
return false;
}
$ht = new File_Passwd_Authbasic($passwd_file);
$ht->parse();
$ht->setMode(FILE_PASSWD_SHA); // not anymore a option
$ht->addUser($user, $this->getSVNPass($user));
$ht->setMode(FILE_PASSWD_SHA);
if ($ht->userExists($user->login)) {
$ht->changePasswd($user->login, $this->getSvnPass($user));
} else {
$ht->addUser($user->login, $this->getSvnPass($user));
}
$ht->save();
return true;
}
/**
* Synchronize the authz file and the passwd file for the project
* @param $project IDF_Project
* Synchronize the authz file and the passwd file for the project.
*
* @param IDF_Project
*/
function processSyncAuthz($project){
//synchronise authz file
function processSyncAuthz($project)
{
$this->SyncAccess();
//synchronise pass file for
$this->generateProjectPasswd($project);
}
/**
* Get the repository password for the user
*/
function getSVNPass($user){
function getSvnPass($user){
return substr(sha1($user->password.Pluf::f('secret_key')), 0, 8);
}
/**
* For a particular project: update all passwd information
*/
function generateProjectPasswd($project){
function generateProjectPasswd($project)
{
$passwd_file = Pluf::f('idf_plugin_syncsvn_passwd_file');
$ht = new File_Passwd_Authbasic($passwd_file);
$ht->setMode(FILE_PASSWD_SHA); // not anymore a option
$ht->parse();
$mem = $project->getMembershipData();
$members = $mem['members'];
$owners = $mem['owners'];
foreach($owners as $v){
$ht->addUser($v->login, $this->getSVNPass($v));
if (!file_exists($passwd_file) or !is_writable($passwd_file)) {
return false;
}
foreach($members as $v){
$ht->addUser($v->login, $this->getSVNPass($v));
$ht = new File_Passwd_Authbasic($passwd_file);
$ht->setMode(FILE_PASSWD_SHA);
$ht->parse();
$mem = $project->getMembershipData();
$members = array_merge((array)$mem['members'], (array)$mem['owners'],
(array)$mem['authorized']);
foreach($members as $user) {
if ($ht->userExists($user->login)) {
$ht->changePasswd($user->login, $this->getSvnPass($user));
} else {
$ht->addUser($user->login, $this->getSvnPass($user));
}
}
$ht->save();
}
/**
* Generate the dav_svn.authz file
*
* We rebuild the complete file each time. This is just to be sure
* not to bork the rights when trying to just edit part of the
* file.
*/
function SyncAccess(){
function SyncAccess()
{
$authz_file = Pluf::f('idf_plugin_syncsvn_authz_file');
$access_owners = Pluf::f('idf_plugin_syncsvn_access_owners');
$access_members = Pluf::f('idf_plugin_syncsvn_access_members');
$access_all = Pluf::f('idf_plugin_syncsvn_access_all');
$access_all_pivate = Pluf::f('idf_plugin_syncsvn_access_all_pivate');
$projects = Pluf::factory('IDF_Project')->getList();
$fcontent = "";
// for each project
foreach($projects as $project){
$access_owners = Pluf::f('idf_plugin_syncsvn_access_owners', 'rw');
$access_members = Pluf::f('idf_plugin_syncsvn_access_members', 'rw');
$access_extra = Pluf::f('idf_plugin_syncsvn_access_extra', 'r');
$access_public = Pluf::f('idf_plugin_syncsvn_access_public', 'r');
$access_public_priv = Pluf::f('idf_plugin_syncsvn_access_private', '');
if (!file_exists($authz_file) or !is_writable($authz_file)) {
return false;
}
$fcontent = '';
foreach (Pluf::factory('IDF_Project')->getList() as $project) {
$conf = new IDF_Conf();
$conf->setProject($project);
if ($conf->getVal('scm', "") == "svn"){
$mem = $project->getMembershipData();
$members = $mem['members'];
$owners = $mem['owners'];
// [shortname:/]
$fcontent .= "[".$project->shortname.":/]\n";
// login = rw
foreach($owners as $v){
$fcontent .= $v->login." = ".$access_owners."\n";
}
// login = rw
foreach($members as $v){
$fcontent .= $v->login." = ".$access_members."\n";
}
// access for all users
if ($project->private == true){
$fcontent .= "* = ".$access_all_pivate."\n";
}else{
$fcontent .= "* = ".$access_all."\n";
if ($conf->getVal('scm') != 'svn' or
strlen($conf->getVal('svn_remote_url')) > 0) {
continue;
}
$mem = $project->getMembershipData();
// [shortname:/]
$fcontent .= '['.$project->shortname.':/]'."\n";
foreach ($mem['owners'] as $v) {
$fcontent .= $v->login.' = '.$access_owners."\n";
}
foreach ($mem['members'] as $v) {
$fcontent .= $v->login.' = '.$access_members."\n";
}
// access for all users
if ($project->private == true) {
foreach ($mem['authorized'] as $v) {
$fcontent .= $v->login.' = '.$access_extra."\n";
}
$fcontent .= "\n";
} //end if SVN
$fcontent .= '* = '.$access_public_priv."\n";
} else {
$fcontent .= '* = '.$access_public."\n";
}
$fcontent .= "\n";
}
file_put_contents($authz_file, $fcontent, LOCK_EX);
return 0;
return true;
}
}
?>

View File

@ -38,4 +38,15 @@ $m['IDF_Review'] = array('relate_to' => array('IDF_Project', 'Pluf_User', 'IDF_T
$m['IDF_Review_Patch'] = array('relate_to' => array('IDF_Review', 'Pluf_User'));
$m['IDF_Review_FileComment'] = array('relate_to' => array('IDF_Review_Patch', 'Pluf_User'));
# -- Standard plugins, they will run only if configured --
#
# Subversion synchronization
Pluf_Signal::connect('IDF_Project::membershipsUpdated',
array('IDF_Plugin_SyncSvn', 'entry'));
Pluf_Signal::connect('IDF_Project::created',
array('IDF_Plugin_SyncSvn', 'entry'));
Pluf_Signal::connect('Pluf_User::passwordUpdated',
array('IDF_Plugin_SyncSvn', 'entry'));
return $m;