Updated the plugin to match InDefero's coding standards.
This commit is contained in:
parent
39cf9f985a
commit
b60aeb0ca1
1
AUTHORS
1
AUTHORS
@ -6,3 +6,4 @@ Much appreciated contributors:
|
|||||||
Nicolas Lassalle <http://www.beroot.org/> - Subversion support
|
Nicolas Lassalle <http://www.beroot.org/> - Subversion support
|
||||||
bohwaz <http://bohwaz.net/>
|
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
Normal file
75
doc/syncsvn.mdtext
Normal 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.
|
||||||
|
|
@ -97,6 +97,7 @@ class IDF_Form_TabsConf extends Pluf_Form
|
|||||||
$this->project->private = 0;
|
$this->project->private = 0;
|
||||||
}
|
}
|
||||||
$this->project->update();
|
$this->project->update();
|
||||||
|
$this->project->membershipsUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,171 +24,175 @@
|
|||||||
require_once 'File/Passwd/Authdigest.php'; // $ pear install File_Passwd
|
require_once 'File/Passwd/Authdigest.php'; // $ pear install File_Passwd
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This classes is a plugin which allows to synchronise access rights between indefero
|
* This classes is a plugin which allows to synchronise access rights
|
||||||
* and a DAV powered SVN repository.
|
* between indefero and a DAV powered Subversion repository.
|
||||||
*/
|
*/
|
||||||
class IDF_Plugin_SyncSvn
|
class IDF_Plugin_SyncSvn
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point of the each plugins.
|
* Entry point of the plugin.
|
||||||
*/
|
*/
|
||||||
static function entry($signal, $params){
|
static public function entry($signal, $params)
|
||||||
// if not actif, do nothing
|
{
|
||||||
|
// First check for the 3 mandatory config variables.
|
||||||
if ($signal == 'IDF_Project::created'){
|
if (!Pluf::f('idf_plugin_syncsvn_authz_file', false) or
|
||||||
$project = $params['project'];
|
!Pluf::f('idf_plugin_syncsvn_passwd_file', false) or
|
||||||
|
!Pluf::f('idf_plugin_syncsvn_svn_path'. false)) {
|
||||||
$plug = new IDF_Plugin_SyncSVN();
|
return;
|
||||||
//$plug->processSVNCreate($project->shortname);
|
}
|
||||||
|
$plug = new IDF_Plugin_SyncSvn();
|
||||||
}else if ($signal == 'IDF_Project::membershipsUpdated'){
|
switch ($signal) {
|
||||||
$project = $params['project'];
|
case 'IDF_Project::created':
|
||||||
|
$plug->processSvnCreate($params['project']);
|
||||||
$plug = new IDF_Plugin_SyncSVN();
|
break;
|
||||||
$plug->processSyncAuthz($project);
|
case 'IDF_Project::membershipsUpdated':
|
||||||
|
$plug->processSyncAuthz($params['project']);
|
||||||
}else if ($signal == 'IDF_User::passwordUpdated'){
|
break;
|
||||||
$plug = new IDF_Plugin_SyncSVN();
|
case 'Pluf_User::passwordUpdated':
|
||||||
$plug->processSyncPasswd($params['user']);
|
$plug->processSyncPasswd($params['user']);
|
||||||
}else {
|
break;
|
||||||
// do nothing
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run svnadmin command to create a usable SVN repository
|
* Run svnadmin command to create the corresponding Subversion
|
||||||
* @param Project name
|
* repository.
|
||||||
|
*
|
||||||
|
* @param IDF_Project
|
||||||
|
* @return bool Success
|
||||||
*/
|
*/
|
||||||
function processSVNCreate($shortname){
|
function processSvnCreate($project)
|
||||||
|
{
|
||||||
$svn_path = Pluf::f('idf_plugin_syncsvn_svn_path');
|
$shortname = $project->shortname;
|
||||||
$svn_import_path = Pluf::f('idf_plugin_syncsvn_svn_import_path');
|
if (false===($svn_path=Pluf::f('idf_plugin_syncsvn_svn_path',false))) {
|
||||||
$chown_user = Pluf::f('idf_plugin_syncsvn_svn_import_path');
|
throw new Pluf_Exception_SettingError("'idf_plugin_syncsvn_svn_path' must be defined in your configuration file.");
|
||||||
|
|
||||||
$c = 0;
|
|
||||||
$createsvn = "svnadmin create ".$svn_path."/".$shortname;
|
|
||||||
Pluf_Utils::runExternal($createsvn, $c);
|
|
||||||
|
|
||||||
if ($svn_import_path != ""){
|
|
||||||
//perform initial import
|
|
||||||
// TODO
|
|
||||||
}
|
}
|
||||||
|
if (file_exists($svn_path.'/'.$shortname)) {
|
||||||
if ($chown_user != ""){
|
throw new Exception(sprintf(__('The repository %s already exists.'),
|
||||||
$chown = "chown ".$chown_user." ".$svn_path."/".$shortname." -R";
|
$svn_path.'/'.$shortname));
|
||||||
Pluf_Utils::runExternal($chown, $c);
|
|
||||||
}
|
}
|
||||||
|
$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
|
* Synchronise an user's password.
|
||||||
* @param $user Pluf_User
|
*
|
||||||
|
* @param Pluf_User
|
||||||
*/
|
*/
|
||||||
function processSyncPasswd($user){
|
function processSyncPasswd($user)
|
||||||
|
{
|
||||||
$passwd_file = Pluf::f('idf_plugin_syncsvn_passwd_file');
|
$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 = new File_Passwd_Authbasic($passwd_file);
|
||||||
$ht->parse();
|
$ht->parse();
|
||||||
$ht->setMode(FILE_PASSWD_SHA); // not anymore a option
|
$ht->setMode(FILE_PASSWD_SHA);
|
||||||
$ht->addUser($user, $this->getSVNPass($user));
|
if ($ht->userExists($user->login)) {
|
||||||
|
$ht->changePasswd($user->login, $this->getSvnPass($user));
|
||||||
|
} else {
|
||||||
|
$ht->addUser($user->login, $this->getSvnPass($user));
|
||||||
|
}
|
||||||
$ht->save();
|
$ht->save();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronize the authz file and the passwd file for the project
|
* Synchronize the authz file and the passwd file for the project.
|
||||||
* @param $project IDF_Project
|
*
|
||||||
|
* @param IDF_Project
|
||||||
*/
|
*/
|
||||||
function processSyncAuthz($project){
|
function processSyncAuthz($project)
|
||||||
//synchronise authz file
|
{
|
||||||
$this->SyncAccess();
|
$this->SyncAccess();
|
||||||
//synchronise pass file for
|
|
||||||
$this->generateProjectPasswd($project);
|
$this->generateProjectPasswd($project);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the repository password for the user
|
* Get the repository password for the user
|
||||||
*/
|
*/
|
||||||
function getSVNPass($user){
|
function getSvnPass($user){
|
||||||
return substr(sha1($user->password.Pluf::f('secret_key')), 0, 8);
|
return substr(sha1($user->password.Pluf::f('secret_key')), 0, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For a particular project: update all passwd information
|
* For a particular project: update all passwd information
|
||||||
*/
|
*/
|
||||||
function generateProjectPasswd($project){
|
function generateProjectPasswd($project)
|
||||||
|
{
|
||||||
$passwd_file = Pluf::f('idf_plugin_syncsvn_passwd_file');
|
$passwd_file = Pluf::f('idf_plugin_syncsvn_passwd_file');
|
||||||
$ht = new File_Passwd_Authbasic($passwd_file);
|
if (!file_exists($passwd_file) or !is_writable($passwd_file)) {
|
||||||
|
return false;
|
||||||
$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));
|
|
||||||
}
|
}
|
||||||
|
$ht = new File_Passwd_Authbasic($passwd_file);
|
||||||
foreach($members as $v){
|
$ht->setMode(FILE_PASSWD_SHA);
|
||||||
$ht->addUser($v->login, $this->getSVNPass($v));
|
$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();
|
$ht->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the dav_svn.authz file
|
* 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');
|
$authz_file = Pluf::f('idf_plugin_syncsvn_authz_file');
|
||||||
$access_owners = Pluf::f('idf_plugin_syncsvn_access_owners');
|
$access_owners = Pluf::f('idf_plugin_syncsvn_access_owners', 'rw');
|
||||||
$access_members = Pluf::f('idf_plugin_syncsvn_access_members');
|
$access_members = Pluf::f('idf_plugin_syncsvn_access_members', 'rw');
|
||||||
$access_all = Pluf::f('idf_plugin_syncsvn_access_all');
|
$access_extra = Pluf::f('idf_plugin_syncsvn_access_extra', 'r');
|
||||||
$access_all_pivate = Pluf::f('idf_plugin_syncsvn_access_all_pivate');
|
$access_public = Pluf::f('idf_plugin_syncsvn_access_public', 'r');
|
||||||
|
$access_public_priv = Pluf::f('idf_plugin_syncsvn_access_private', '');
|
||||||
$projects = Pluf::factory('IDF_Project')->getList();
|
if (!file_exists($authz_file) or !is_writable($authz_file)) {
|
||||||
|
return false;
|
||||||
$fcontent = "";
|
}
|
||||||
|
$fcontent = '';
|
||||||
// for each project
|
foreach (Pluf::factory('IDF_Project')->getList() as $project) {
|
||||||
foreach($projects as $project){
|
|
||||||
|
|
||||||
$conf = new IDF_Conf();
|
$conf = new IDF_Conf();
|
||||||
$conf->setProject($project);
|
$conf->setProject($project);
|
||||||
|
if ($conf->getVal('scm') != 'svn' or
|
||||||
if ($conf->getVal('scm', "") == "svn"){
|
strlen($conf->getVal('svn_remote_url')) > 0) {
|
||||||
|
continue;
|
||||||
$mem = $project->getMembershipData();
|
}
|
||||||
$members = $mem['members'];
|
$mem = $project->getMembershipData();
|
||||||
$owners = $mem['owners'];
|
// [shortname:/]
|
||||||
|
$fcontent .= '['.$project->shortname.':/]'."\n";
|
||||||
// [shortname:/]
|
foreach ($mem['owners'] as $v) {
|
||||||
$fcontent .= "[".$project->shortname.":/]\n";
|
$fcontent .= $v->login.' = '.$access_owners."\n";
|
||||||
|
}
|
||||||
// login = rw
|
foreach ($mem['members'] as $v) {
|
||||||
foreach($owners as $v){
|
$fcontent .= $v->login.' = '.$access_members."\n";
|
||||||
$fcontent .= $v->login." = ".$access_owners."\n";
|
}
|
||||||
}
|
// access for all users
|
||||||
// login = rw
|
if ($project->private == true) {
|
||||||
foreach($members as $v){
|
foreach ($mem['authorized'] as $v) {
|
||||||
$fcontent .= $v->login." = ".$access_members."\n";
|
$fcontent .= $v->login.' = '.$access_extra."\n";
|
||||||
}
|
|
||||||
|
|
||||||
// access for all users
|
|
||||||
if ($project->private == true){
|
|
||||||
$fcontent .= "* = ".$access_all_pivate."\n";
|
|
||||||
}else{
|
|
||||||
$fcontent .= "* = ".$access_all."\n";
|
|
||||||
}
|
}
|
||||||
|
$fcontent .= '* = '.$access_public_priv."\n";
|
||||||
$fcontent .= "\n";
|
} else {
|
||||||
} //end if SVN
|
$fcontent .= '* = '.$access_public."\n";
|
||||||
|
}
|
||||||
|
$fcontent .= "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents($authz_file, $fcontent, LOCK_EX);
|
file_put_contents($authz_file, $fcontent, LOCK_EX);
|
||||||
|
return true;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
@ -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_Patch'] = array('relate_to' => array('IDF_Review', 'Pluf_User'));
|
||||||
$m['IDF_Review_FileComment'] = array('relate_to' => array('IDF_Review_Patch', '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;
|
return $m;
|
||||||
|
Loading…
Reference in New Issue
Block a user