chaw / branches / master / models / permission.php

history
<?php
/**
 * Chaw : source code and project management
 *
 * @copyright  Copyright 2009, Garrett J. Woodworth (gwoohoo@gmail.com)
 * @license    GNU AFFERO GENERAL PUBLIC LICENSE v3 (http://opensource.org/licenses/agpl-v3.html)
 *
 */
/**
 * undocumented class
 *
 * @package default
 */
class Permission extends AppModel {

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $name = 'Permission';

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $belongsTo = array('User', 'Project');

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $__rules = array();

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $__config = array();

	/**
	 * undocumented function
	 *
	 * @param string $user
	 * @return void
	 */
	function user($user = null) {
		if (!is_numeric($user)) {
			$user = $this->User->field('id', array('username' => $user));
		}
		return $user;
	}

	/**
	 * undocumented function
	 *
	 * @param string $project
	 * @param string $user
	 * @return void
	 */
	function group($project, $user = null) {
		if (is_array($project)) {
			extract($project);
		}

		$user = $this->user($user);

		if (!$user || !$project) {
			return false;
		}

		return $this->field('group', array('project_id' => $project, 'user_id' => $user));
	}

	/**
	 * undocumented function
	 *
	 * @param string $config
	 * @return void
	 */
	function saveFile($config = array()) {
		if (empty($config['repo'])) {
			$this->set($config);
			$config = $this->config();
		} else {
			$config = $this->config($config);
		}

		if (!is_dir($config['repo']['path'])) {
			$Folder = new Folder($config['repo']['path'], true, 0775);
		}

		$File = $this->__getFile();
		$File->create();

		if (!$File->exists() || !$File->writable()) {
			return false;
		}

		if (empty($this->data['Permission']['fine_grained']) && empty($this->data['Permission']['username'])) {
			return false;
		}

		if (empty($this->data['Permission']['fine_grained'])) {
			$repo = $config['url'] . ':/';
			if ($config['repo']['type'] == 'git') {
				$repo = 'refs/heads/master';
			}

			if ($config['repo']['type'] == 'svn') {
				$perms = $this->find('all', array(
					'fields' => array('Permission.group', 'User.username'),
					'conditions' => array('Permission.project_id' => $config['id']),
					'recursive' => 0
				));
				$groups = array();
				if (!empty($perms)) {
					foreach ($perms as $perm) {
						$groups[$perm['Permission']['group']][] = $perm['User']['username'];
					}
				} else {
					$groups = array_flip(array_keys($this->Project->groups()));
				}
			}

			$username = $this->data['Permission']['username'];
			ob_start();
			include(CONFIGS . 'templates' . DS . $config['repo']['type'] . DS . 'permissions.ini');
			$this->data['Permission']['fine_grained'] = ob_get_clean();
		}
		$result = $File->write(trim($this->data['Permission']['fine_grained']));
		$this->data = array();
		$this->__rules = array();
		return $result;
	}

	/**
	 * undocumented function
	 *
	 * @param string $config
	 * @return void
	 */
	function config($config = array()) {
		if (!empty($config)) {
			return $this->__config = array_merge($this->__config, $config);
		}
		if (empty($this->__config)) {
			$this->__config = Configure::read('Project');
		}
		return $this->__config;
	}

	/**
	 * undocumented function
	 *
	 * @param string $path
	 * @param string $options
	 * @return void
	 */
	function check($path, $options = array()) {
		$defaults = array(
			'user' => null, 'group' => null, 'access' => null,
			'project' => null, 'default' => false
		);
		$options = array_merge($defaults, $options);
		extract($options);

		if ($project === null) {
			$config = $this->config();
			$project = $config['url'];
		}

		$rules = $this->rules($project);

		if (!empty($rules[$project])) {

			foreach ((array)$rules[$project] as $rule => $perms) {

				$isMatch = ltrim($rule, '/') == ltrim($path, '/');

				/* for multi paths
				$paths = explode('/', $path);

				if (strpos($rule, '/') !== false) {
					if (substr($rule, -1) == '*') {

					}
				}
				*/
				if ($isMatch) {

					$check = null;

					if (isset($perms['*'])) {
						$check = $perms['*'];
					}

					if (!empty($rules['groups'])) {
						foreach ($rules['groups'] as $agroup => $users) {
							if (in_array($user, $users)) {
								if(isset($perms['@' . $agroup])) {
									$check .= $perms['@' . $agroup];
									break;
								}
							}
						}
					}

					if(isset($perms['@' . $group])) {
						$check .= $perms['@' . $group];
					}

					if (isset($perms[$user])) {
						$check .= $perms[$user];
					}

					if ($check) {
						foreach ((array)$access as $perm) {
							if (strpos($check, $perm) !== false) {
								return true;
							}
							if ($perm == 'c' || $perm == 'u' || $perm == 'd') {
								if (strpos($check, 'w') !== false) {
									return true;
								}
							}
							if ($perm == 'w') {
								if (strpos($check, 'c') !== false || strpos($check, 'u') !== false) {
									return true;
								}
							}
						}
						return false;
					}
				}
			}
		}

		if ($access == 'd') {
			return false;
		}
		return $default;
	}

	/**
	 * undocumented function
	 *
	 * @param string $rules
	 * @return void
	 */
	function groups($rules = null) {
		if ($rules === null) {
			$rules = $this->rules();
		}

		if (empty($rules['groups'])) {
			return false;
		}

		$result = array();
		foreach ((array)$rules['groups'] as $group => $users) {
			$result[]['Group'] = array(
				'name' => $group,
				'users' => $users
			);
		}

		return $result;
	}

	/**
	 * undocumented function
	 *
	 * @param string $project
	 * @param string $atomic
	 * @return void
	 */
	function rules($project = null, $atomic = array()) {
		$config = $this->config();

		if ($project === null) {
			$project = $config['url'];
		}

		if (empty($this->__rules[$project])) {
			$parent = array($project => array(), 'groups' => array());

			if ($config['id'] != 1) {
				if (!empty($this->__rules[1])) {
					$parent = $this->__rules[1];
				} else {
					if ($file = $this->parent()) {
						$parent = $this->__rules[1] = $this->toArray($file);
					}

					if ($root = $this->root()) {
						$root = $this->toArray($root);
						$parent = $this->__rules[1] = Set::merge($parent, $root);
					}
				}
			}

			$rules = $this->toArray($this->file());

			if (empty($rules[$project])) {
				$rules[$project] = array();
			}

			if (!empty($parent[$project])) {
				$rules[$project] = Set::merge($rules[$project], $parent[$project]);
			}

			if (!empty($rules['groups']) && !empty($parent['groups'])) {
				$rules['groups'] = array_merge($rules['groups'], $parent['groups']);
			}

			$this->__rules[$project] = $rules;
		}

		if (!empty($atomic)) {
			$this->__rules[$project] = Set::merge($this->__rules[$project], array($project => $atomic));
		}

		return $this->__rules[$project];
	}

	/**
	 * undocumented function
	 *
	 * @param string $string
	 * @return void
	 */
	function toArray($string = null) {
		if (!$string) {
			return array();
		}
		$config = $this->config();

		$result = array();
		$lines = explode("\n", $string);
		foreach ($lines as $line) {
			$data = trim($line);
			$first = substr($data, 0, 1);
			if ($first != ';' && $data != '') {
				if ($first == '[' && substr($data, -1, 1) == ']') {
					$project = $config['url'];
					$section = preg_replace('/[\[\]]/', '', $data);
					if (strpos($section, ':') !== false) {
						list($project, $section) = explode(':', $section);
					}
				} else if (!empty($project) && !empty($section)) {
					$delimiter = strpos($data, '=');

					if ($delimiter > 0) {
						$key = trim(substr($data, 0, $delimiter));
						$value = trim(substr($data, $delimiter + 1));

						if (substr($value, 0, 1) == '"' && substr($value, -1) == '"') {
							$value = substr($value, 1, -1);
						}
						if ($section == 'groups') {
							$result[$section][$key] = array_map('trim', explode(',', stripcslashes($value)));
						} else {
							$result[$project][$section][$key] = stripcslashes($value);
						}
					} else {
						if (!isset($section)) {
							$section = '';
						}
						$result[$project][$section][$data] = '';
					}
				}
			}
		}
		return $result;
	}

	/**
	 * undocumented function
	 *
	 * @return void
	 */
	function fileExists() {
		$File = $this->__getFile();
		return $File->exists();
	}

	/**
	 * undocumented function
	 *
	 * @return void
	 */
	function file() {
		$File = $this->__getFile();
		if (!$File->readable()) {
			if (!$File->create()) {
				return false;
			}
		}
		return $File->read();
	}

	/**
	 * undocumented function
	 *
	 * @return void
	 */
	function root() {
		$path = Configure::read("Content.base");
		$File = new File($path . 'permissions.ini');
		if (!$File->readable()) {
			return null;
		}
		return $File->read();
	}

	/**
	 * undocumented function
	 *
	 * @return void
	 */
	function parent() {
		$config = $this->config();
		if($config['id'] == 1 || empty($config['fork'])) {
			return array();
		}
		if(!empty($config['fork'])) {
			$path = Configure::read("Content.{$config['repo']['type']}") . 'repo' . DS .  $config['url'] . '.git' . DS;
		}

		$File = new File($path . 'permissions.ini');
		if (!$File->readable()) {
			if (!$File->create()) {
				return false;
			}
		}
		return $File->read();
	}

	/**
	 * undocumented
	 *
	 */
	function &__getFile() {
		$config = $this->config();
		$path = $config['repo']['path'] . DS;
		if($config['id'] == 1) {
			$path = Configure::read("Content.base");
		}
		$File = new File($path . 'permissions.ini');
		return $File;
	}
}
?>