瀏覽代碼

Lots o' stuff

Nathaniel van Diepen 8 年之前
父節點
當前提交
bc8a222725

+ 15 - 0
install/db_install/01_triggers/issue_insert.sql

@@ -0,0 +1,15 @@
+DROP TRIGGER IF EXISTS `issue_insert`;
+CREATE TRIGGER `issue_insert`
+BEFORE INSERT ON `issues`
+	FOR EACH ROW
+		IF NEW.p_id IS NOT NULL AND NEW.name IN (
+			SELECT name
+			FROM issues
+			WHERE p_id = NEW.p_id
+		) THEN
+			SET @error = CONCAT('An issue with the name "',NEW.name,'"" already exists on the project "',project_name(NEW.p_id),'"');
+			SIGNAL SQLSTATE '45000'
+			SET MESSAGE_TEXT = @error;
+		ELSE
+			SET new.date_modified = NOW();
+		END IF;

+ 0 - 5
install/db_install/01_triggers/issue_insert_date_modified.sql

@@ -1,5 +0,0 @@
-DROP TRIGGER IF EXISTS `issue_insert_date_modified`;
-CREATE TRIGGER `issue_insert_date_modified`
-BEFORE INSERT ON `issues`
-	FOR EACH ROW
-		SET new.date_modified = NOW();

+ 15 - 0
install/db_install/01_triggers/issue_update.sql

@@ -0,0 +1,15 @@
+DROP TRIGGER IF EXISTS `issue_update`;
+CREATE TRIGGER `issue_update`
+BEFORE UPDATE ON `issues`
+	FOR EACH ROW
+		IF NEW.p_id IS NOT NULL AND NEW.name IN (
+			SELECT name
+			FROM issues
+			WHERE p_id = NEW.p_id
+		) THEN
+			SET @error = CONCAT('An issue with the name "',NEW.name,'"" already exists on the project "',project_name(NEW.p_id),'"');
+			SIGNAL SQLSTATE '45000'
+			SET MESSAGE_TEXT = @error;
+		ELSE
+			SET new.date_modified = NOW();
+		END IF;

+ 0 - 5
install/db_install/01_triggers/issue_update_date_modified.sql

@@ -1,5 +0,0 @@
-DROP TRIGGER IF EXISTS `issue_update_date_modified`;
-CREATE TRIGGER `issue_update_date_modified`
-BEFORE UPDATE ON `issues`
-	FOR EACH ROW
-		SET new.date_modified = NOW();

+ 5 - 0
install/db_install/01_triggers/user_insert.sql

@@ -0,0 +1,5 @@
+DROP TRIGGER IF EXISTS `user_insert`;
+CREATE TRIGGER `user_insert`
+BEFORE INSERT ON `users`
+	FOR EACH ROW
+		SET new.date_modified = NOW();

+ 0 - 5
install/db_install/01_triggers/user_insert_date_modified.sql

@@ -1,5 +0,0 @@
-DROP TRIGGER IF EXISTS `user_insert_date_modified`;
-CREATE TRIGGER `user_insert_date_modified`
-BEFORE INSERT ON `users`
-	FOR EACH ROW
-		SET new.date_modified = NOW();

+ 5 - 0
install/db_install/01_triggers/user_update.sql

@@ -0,0 +1,5 @@
+DROP TRIGGER IF EXISTS `user_update`;
+CREATE TRIGGER `user_update`
+BEFORE UPDATE ON `users`
+	FOR EACH ROW
+		SET new.date_modified = NOW();

+ 0 - 5
install/db_install/01_triggers/user_update_date_modified.sql

@@ -1,5 +0,0 @@
-DROP TRIGGER IF EXISTS `user_update_date_modified`;
-CREATE TRIGGER `user_update_date_modified`
-BEFORE UPDATE ON `users`
-	FOR EACH ROW
-		SET new.date_modified = NOW();

+ 19 - 0
install/db_install/03_functions/project_name.sql

@@ -0,0 +1,19 @@
+CREATE FUNCTION `project_name`(
+	a_id INT(10)
+) RETURNS VARCHAR(50)
+DETERMINISTIC
+READS SQL DATA
+SQL SECURITY INVOKER
+BEGIN
+	DECLARE t_name VARCHAR(50);
+	SELECT name
+	INTO t_name
+	FROM projects
+	WHERE id = a_id;
+	IF t_name IS NULL THEN
+		SET @error := CONCAT('Project with id ',a_id,' does not exist');
+		SIGNAL SQLSTATE '45000'
+		SET MESSAGE_TEXT = @error;
+	END IF;
+	return t_name;
+END;

+ 1 - 0
install/db_uninstall/99_cleanup/functions.sql

@@ -2,5 +2,6 @@ DROP FUNCTION IF EXISTS `getsetting`;
 DROP FUNCTION IF EXISTS `setsetting`;
 DROP FUNCTION IF EXISTS `permission`;
 DROP FUNCTION IF EXISTS `project_role`;
+DROP FUNCTION IF EXISTS `project_name`;
 DROP FUNCTION IF EXISTS `issue_role`;
 DROP FUNCTION IF EXISTS `action`;

+ 5 - 1
js/issue.js

@@ -15,7 +15,11 @@ ready(function(){
 			})
 			.then(function(data){
 				if(data.error){
-					alert(data.error);
+					if(data.error.message){
+						alert(data.error.message);
+					}else{
+						alert(data.error);
+					}
 				}else{
 					form.reset();
 					location.assign(BASE_URL+'/!'+data.id);

+ 5 - 1
js/project.js

@@ -15,7 +15,11 @@ ready(function(){
 			})
 			.then(function(data){
 				if(data.error){
-					alert(data.error);
+					if(data.error.message){
+						alert(data.error.message);
+					}else{
+						alert(data.error);
+					}
 				}else{
 					form.reset();
 					location.assign(BASE_URL+'/project/'+data.name);

+ 5 - 1
js/sessions.js

@@ -10,7 +10,11 @@ ready(function(){
 			})
 			.then(function(data){
 				if(data.error){
-					alert(data.error);
+					if(data.error.message){
+						alert(data.error.message);
+					}else{
+						alert(data.error);
+					}
 				}else{
 					location.reload();
 				}

+ 5 - 1
js/user.js

@@ -15,7 +15,11 @@ ready(function(){
 			})
 			.then(function(data){
 				if(data.error){
-					alert(data.error);
+					if(data.error.message){
+						alert(data.error.message);
+					}else{
+						alert(data.error);
+					}
 				}else{
 					form.reset();
 					location.assign('~'+data.name);

+ 7 - 0
lib/bugs.class.php

@@ -245,6 +245,13 @@
 		static function permission($permission){
 			return static::$user->permission($permission);
 		}
+		static function authorized(){
+			foreach(func_get_args() as $permission){
+				if(!static::permission($permission)){
+					trigger_error("Access denied. You do not have the {$permission} permission");
+				}
+			}
+		}
 	}
 	register_shutdown_function(function(){
 		$emails = Bugs::$sql->query("

+ 1 - 0
lib/issue.class.php

@@ -62,6 +62,7 @@
 				'id'=> $this->id,
 				'name'=> $this->name,
 				'description'=> $this->description,
+				'p_id'=> $this->p_id,
 				'date_created'=> $this->date_created,
 				'date_modified'=> $this->date_modified
 			);

+ 4 - 0
paths/issue.php

@@ -6,6 +6,7 @@
 	);
 	Router::paths(array(
 		'/!{issue}'=>function($res,$args){
+			Bugs::authorized('issue.read');
 			$res->write(
 				Bugs::template('issue')
 					->run(Bugs::issue($args->issue))
@@ -16,6 +17,7 @@
 		},
 		'/issue/{issue}/update'=>function($res,$args){
 			error_handle_type('json');
+			Bugs::authorized('issue.update');
 			if(!empty($_POST['name'])&&!empty($_POST['description'])){
 				$issue = Bugs::issue($args->issue);
 				$issue->name = $_POST['name'];
@@ -31,10 +33,12 @@
 			}
 		},
 		'/create/issue'=>function($res,$args){
+			Bugs::authorized('issue.create');
 			$res->write(Bugs::template('issue'));
 		},
 		'/create/issue/complete'=>function($res,$args){
 			error_handle_type('json');
+			Bugs::authorized('issue.create');
 			if(!empty($_POST['name'])&&!empty($_POST['description'])){
 				$issue = Bugs::issue($_POST['name'],$_POST['description']);
 				$res->json(array(

+ 4 - 0
paths/project.php

@@ -7,6 +7,7 @@
 	);
 	Router::paths(array(
 		'/project/{project}'=>function($res,$args){
+			Bugs::authorized('project.read');
 			$res->write(
 				Bugs::template('project')
 					->run(Bugs::project(is_numeric($args->project)?intval($args->project):$args->project)
@@ -21,6 +22,7 @@
 		},
 		'/project/{project}/update'=>function($res,$args){
 			error_handle_type('json');
+			Bugs::authorized('project.update');
 			if(!empty($_POST['name'])&&!empty($_POST['description'])){
 				$project = Bugs::project(is_numeric($args->project)?intval($args->project):$args->project);
 				$project->name = $_POST['name'];
@@ -54,10 +56,12 @@
 			}
 		},
 		'/create/project'=>function($res,$args){
+			bugs::authorized('project.create');
 			$res->write(Bugs::template('project'));
 		},
 		'/create/project/complete'=>function($res,$args){
 			error_handle_type('json');
+			Bugs::authorized('project.create');
 			if(!empty($_POST['name'])){
 				if(!Bugs::project_id($_POST['name'])){
 					$project = Bugs::project($_POST['name'],$_POST['description']);

+ 4 - 0
paths/user.php

@@ -15,6 +15,7 @@
 			}
 		},
 		'/user/{user}'=>function($res,$args){
+			Bugs::authorized('user.read');
 			Router::redirect(Router::url(Router::$base.'/~'.$args->user));
 		},
 		'/user/{user}/update'=>function($res,$args){
@@ -22,6 +23,9 @@
 			if(Bugs::$user){
 					if(!empty($_POST['password'])&&!empty($_POST['id'])&&!empty($_POST['name'])&&!empty($_POST['email'])){
 					$user = Bugs::user(intval($args->user));
+					if($user->id != Bugs::$user->id){
+						Bugs::authorized('user.update');
+					}
 					if($user->password == $user->hash($_POST['password'])){
 						$user->name = $_POST['name'];
 						$user->email = $_POST['email'];

+ 0 - 0
templates/sub.activity.php → templates/activities/default.php


+ 16 - 0
templates/activities/issue.create.php

@@ -0,0 +1,16 @@
+<?php
+	global $context;
+	if(is_null($context->data->p_id)){
+		$project = false;
+	}else{
+		$project = Bugs::project(intval($context->data->p_id));
+	}
+?>
+<div>
+	<time datetime="<?=date('c',$context->date);?>">
+		<?=date('Y-m-d g:i:s A',$context->date);?>
+	</time>
+	<div>
+		Issue <a href="<?=Router::url(Router::$base."/!{$context->data->id}")?>"><?=$context->data->id?></a> created<?=$project?" on Project <a href=\"".Router::url(Router::$base."/project/{$project->name}")."\">{$project->name}</a>":'.'?>
+	</div>
+</div>

+ 16 - 0
templates/activities/issue.delete.php

@@ -0,0 +1,16 @@
+<?php
+	global $context;
+	if(is_null($context->data->p_id)){
+		$project = false;
+	}else{
+		$project = Bugs::project(intval($context->data->p_id));
+	}
+?>
+<div>
+	<time datetime="<?=date('c',$context->date);?>">
+		<?=date('Y-m-d g:i:s A',$context->date);?>
+	</time>
+	<div>
+		Issue <?=$context->data->id?> deleted<?=$project?" from Project <a href=\"".Router::url(Router::$base."/project/{$project->name}")."\">{$project->name}</a>":'.'?>
+	</div>
+</div>

+ 16 - 0
templates/activities/issue.update.php

@@ -0,0 +1,16 @@
+<?php
+	global $context;
+	if(is_null($context->data->p_id)){
+		$project = false;
+	}else{
+		$project = Bugs::project(intval($context->data->p_id));
+	}
+?>
+<div>
+	<time datetime="<?=date('c',$context->date);?>">
+		<?=date('Y-m-d g:i:s A',$context->date);?>
+	</time>
+	<div>
+		Issue <a href="<?=Router::url(Router::$base."/!{$context->data->id}")?>"><?=$context->data->id?></a> updated<?=$project?" on Project <a href=\"".Router::url(Router::$base."/project/{$project->name}")."\">{$project->name}</a>":'.'?>
+	</div>
+</div>

+ 11 - 0
templates/activities/project.create.php

@@ -0,0 +1,11 @@
+<?php
+	global $context;
+?>
+<div>
+	<time datetime="<?=date('c',$context->date);?>">
+		<?=date('Y-m-d g:i:s A',$context->date);?>
+	</time>
+	<div>
+		Project <a href="<?=Router::url(Router::$base."/project/{$context->data->name}")?>"><?=$context->data->name?></a> created.
+	</div>
+</div>

+ 11 - 0
templates/activities/project.delete.php

@@ -0,0 +1,11 @@
+<?php
+	global $context;
+?>
+<div>
+	<time datetime="<?=date('c',$context->date);?>">
+		<?=date('Y-m-d g:i:s A',$context->date);?>
+	</time>
+	<div>
+		Project <?=$context->data->name?> deleted.
+	</div>
+</div>

+ 11 - 0
templates/activities/project.update.php

@@ -0,0 +1,11 @@
+<?php
+	global $context;
+?>
+<div>
+	<time datetime="<?=date('c',$context->date);?>">
+		<?=date('Y-m-d g:i:s A',$context->date);?>
+	</time>
+	<div>
+		Project <a href="<?=Router::url(Router::$base."/project/{$context->data->name}")?>"><?=$context->data->name?></a> updated.
+	</div>
+</div>

+ 1 - 1
templates/sub.issues.php

@@ -15,7 +15,7 @@
 			)
 		){
 	?>
-		<a href="<?=Router::url(Router::$base.'/create/issue')?>">New</a>
+		<a href="<?=Router::url(Router::$base.($context instanceof Project?"/project/{$context->name}/":'').'/create/issue')?>">New</a>
 	<?php
 		}
 	?>

+ 11 - 6
templates/timeline.php

@@ -33,12 +33,17 @@
 		<div>
 			<?php
 				foreach($activities as $activity){
-					echo Bugs::template('sub.activity')
-						->run(new Arguments(array(
-							'date'=> strtotime($activity['date']),
-							'action'=> $actions[intval($activity['a_id'])],
-							'data'=> new Arguments(json_decode($activity['data']))
-						)));
+					$activity = new Arguments(array(
+						'date'=> strtotime($activity['date']),
+						'action'=> $actions[intval($activity['a_id'])],
+						'data'=> new Arguments(json_decode($activity['data'],true)),
+						'template'=> 'default'
+					));
+					if(file_exists("templates/activities/{$activity->action}.php")){
+						$activity->template = $activity->action;
+					}
+					echo Bugs::template("activities/{$activity->template}")
+						->run($activity);
 				}
 			?>
 		</div>