199 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
						|
/*
 | 
						|
# ***** BEGIN LICENSE BLOCK *****
 | 
						|
# This file is part of InDefero, an open source project management application.
 | 
						|
# Copyright (C) 2008 Céondo Ltd and contributors.
 | 
						|
#
 | 
						|
# InDefero is free software; you can redistribute it and/or modify
 | 
						|
# it under the terms of the GNU General Public License as published by
 | 
						|
# the Free Software Foundation; either version 2 of the License, or
 | 
						|
# (at your option) any later version.
 | 
						|
#
 | 
						|
# InDefero is distributed in the hope that it will be useful,
 | 
						|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
# GNU General Public License for more details.
 | 
						|
#
 | 
						|
# You should have received a copy of the GNU General Public License
 | 
						|
# along with this program; if not, write to the Free Software
 | 
						|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
						|
#
 | 
						|
# ***** END LICENSE BLOCK ***** */
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * 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 plugin.
 | 
						|
     */
 | 
						|
    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;
 | 
						|
        }
 | 
						|
        include_once 'File/Passwd/Authdigest.php'; // $ pear install File_Passwd
 | 
						|
        $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']);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Run svnadmin command to create the corresponding Subversion
 | 
						|
     * repository.
 | 
						|
     *
 | 
						|
     * @param IDF_Project 
 | 
						|
     * @return bool Success
 | 
						|
     */
 | 
						|
    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 (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 Pluf_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->load();
 | 
						|
        $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 IDF_Project
 | 
						|
     */
 | 
						|
    function processSyncAuthz($project)
 | 
						|
    {
 | 
						|
        $this->SyncAccess();
 | 
						|
        $this->generateProjectPasswd($project);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the repository password for the 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)
 | 
						|
    {
 | 
						|
        $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->setMode(FILE_PASSWD_SHA); 
 | 
						|
        $ht->load();
 | 
						|
        $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()
 | 
						|
    {
 | 
						|
        $authz_file = Pluf::f('idf_plugin_syncsvn_authz_file');
 | 
						|
        $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' 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 .= '* = '.$access_public_priv."\n";
 | 
						|
            } else {
 | 
						|
                $fcontent .= '* = '.$access_public."\n";
 | 
						|
            }
 | 
						|
            $fcontent .= "\n";
 | 
						|
        }
 | 
						|
        file_put_contents($authz_file, $fcontent, LOCK_EX);
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
}
 |