Added argument checking system

This commit is contained in:
Marcin Kurczewski 2014-05-12 10:31:34 +02:00
parent 0e6ed74682
commit 484adbbf49
73 changed files with 1072 additions and 261 deletions

View file

@ -14,22 +14,22 @@ abstract class AbstractJob
public abstract function execute();
public function isSatisfied()
public function getRequiredArguments()
{
return true;
return null;
}
public function requiresAuthentication()
public function getRequiredPrivileges()
{
return false;
}
public function requiresConfirmedEmail()
public function isAuthenticationRequired()
{
return false;
}
public function requiresPrivilege()
public function isConfirmedEmailRequired()
{
return false;
}

View file

@ -1,18 +0,0 @@
<?php
abstract class AbstractPostJob extends AbstractJob
{
protected $post;
public function prepare()
{
if ($this->hasArgument(JobArgs::ARG_POST_ENTITY))
{
$this->post = $this->getArgument(JobArgs::ARG_POST_ENTITY);
}
else
{
$postId = $this->getArgument(JobArgs::ARG_POST_ID);
$this->post = PostModel::getByIdOrName($postId);
}
}
}

View file

@ -9,8 +9,7 @@ final class Api
{
$job->setArguments($jobArgs);
if (!$job->isSatisfied())
throw new ApiJobUnsatisfiedException($job);
self::checkArguments($job);
$job->prepare();
@ -20,25 +19,6 @@ final class Api
});
}
public static function checkPrivileges(AbstractJob $job)
{
if ($job->requiresAuthentication())
Access::assertAuthentication();
if ($job->requiresConfirmedEmail())
Access::assertEmailConfirmation();
$privileges = $job->requiresPrivilege();
if ($privileges !== false)
{
if (!is_array($privileges))
$privileges = [$privileges];
foreach ($privileges as $privilege)
Access::assert($privilege);
}
}
public static function runMultiple($jobs)
{
$statuses = [];
@ -52,4 +32,63 @@ final class Api
});
return $statuses;
}
public static function checkArguments(AbstractJob $job)
{
self::runArgumentCheck($job, $job->getRequiredArguments());
}
public static function checkPrivileges(AbstractJob $job)
{
if ($job->isAuthenticationRequired())
Access::assertAuthentication();
if ($job->isConfirmedEmailRequired())
Access::assertEmailConfirmation();
$privileges = $job->getRequiredPrivileges();
if ($privileges !== false)
{
if (!is_array($privileges))
$privileges = [$privileges];
foreach ($privileges as $privilege)
Access::assert($privilege);
}
}
private static function runArgumentCheck($job, $item)
{
if (is_array($item))
throw new Exception('Argument definition cannot be an array.');
elseif ($item instanceof JobArgsNestedStruct)
{
if ($item instanceof JobArgsAlternative)
{
$success = false;
foreach ($item->args as $subItem)
{
try
{
self::runArgumentCheck($job, $subItem);
$success = true;
}
catch (ApiJobUnsatisfiedException $e)
{
}
}
if (!$success)
throw new ApiJobUnsatisfiedException($job);
}
elseif ($item instanceof JobArgsConjunction)
{
foreach ($item->args as $subItem)
!self::runArgumentCheck($job, $subItem);
}
}
elseif ($item === null)
return;
elseif (!$job->hasArgument($item))
throw new ApiJobUnsatisfiedException($job, $item);
}
}

View file

@ -1,8 +1,10 @@
<?php
class ApiJobUnsatisfiedException extends SimpleException
{
public function __construct(AbstractJob $job)
public function __construct(AbstractJob $job, $arg = null)
{
parent::__construct(get_class($job) . ' cannot be run due to unsatisfied execution conditions.');
parent::__construct('%s cannot be run due to unsatisfied execution conditions (%s).',
get_class($job),
$arg);
}
}

View file

@ -8,8 +8,9 @@ class JobArgs
const ARG_TOKEN = 'token';
const ARG_USER_ENTITY = 'user';
const ARG_USER_ID = 'user-id';
#const ARG_USER_ID = 'user-id';
const ARG_USER_NAME = 'user-name';
const ARG_USER_EMAIL = 'user-email';
const ARG_POST_ENTITY = 'post';
const ARG_POST_ID = 'post-id';
@ -18,6 +19,7 @@ class JobArgs
const ARG_TAG_NAME = 'tag-name';
const ARG_TAG_NAMES = 'tag-names';
const ARG_COMMENT_ENTITY = 'comment';
const ARG_COMMENT_ID = 'comment-id';
const ARG_LOG_ID = 'log-id';
@ -44,4 +46,19 @@ class JobArgs
const ARG_NEW_EMAIL = 'new-email';
const ARG_NEW_USER_NAME = 'new-user-name';
const ARG_NEW_PASSWORD = 'new-password';
public static function Alternative()
{
return JobArgsAlternative::factory(func_get_args());
}
public static function Conjunction()
{
return JobArgsConjunction::factory(func_get_args());
}
public static function Optional()
{
return JobArgsOptional::factory(func_get_args());
}
}

View file

@ -0,0 +1,25 @@
<?php
class JobArgsAlternative extends JobArgsNestedStruct
{
/**
* simplifies the structure as much as possible
* and returns new class or existing args.
*/
public static function factory(array $args)
{
$finalArgs = [];
foreach ($args as $arg)
{
if ($arg instanceof self)
$finalArgs = array_merge($finalArgs, $arg->args);
elseif ($arg !== null)
$finalArgs []= $arg;
}
if (count($finalArgs) == 1)
return $finalArgs[0];
else
return new self($finalArgs);
}
}

View file

@ -0,0 +1,25 @@
<?php
class JobArgsConjunction extends JobArgsNestedStruct
{
/**
* Simplifies the structure as much as possible
* and returns new class or existing args.
*/
public static function factory(array $args)
{
$finalArgs = [];
foreach ($args as $arg)
{
if ($arg instanceof self)
$finalArgs = array_merge($finalArgs, $arg->args);
elseif ($arg !== null)
$finalArgs []= $arg;
}
if (count($finalArgs) == 1)
return $finalArgs[0];
else
return new self($finalArgs);
}
}

View file

@ -0,0 +1,19 @@
<?php
class JobArgsNestedStruct
{
public $args;
protected function __construct(array $args)
{
usort($args, function($arg1, $arg2)
{
return strnatcasecmp(serialize($arg1), serialize($arg2));
});
$this->args = $args;
}
public static function factory(array $args)
{
throw new BadMethodCallException('Not implemented');
}
}

View file

@ -0,0 +1,20 @@
<?php
class JobArgsOptional extends JobArgsNestedStruct
{
/**
* Simplifies the structure as much as possible
* and returns new class or existing args.
*/
public static function factory(array $args)
{
$args = array_filter($args, function($arg)
{
return $arg !== null;
});
if (count($args) == 0)
return null;
else
return new self($args);
}
}

View file

@ -5,7 +5,12 @@ class ActivateUserEmailJob extends AbstractJob
{
if (!$this->hasArgument(JobArgs::ARG_TOKEN))
{
$user = UserModel::getByNameOrEmail($this->getArgument(JobArgs::ARG_USER_NAME));
if ($this->hasArgument(JobArgs::ARG_USER_ENTITY))
$user = $this->getArgument(JobArgs::ARG_USER_ENTITY);
elseif ($this->hasArgument(JobArgs::ARG_USER_NAME))
$user = UserModel::getByName($this->getArgument(JobArgs::ARG_USER_NAME));
else
$user = UserModel::getByEmail($this->getArgument(JobArgs::ARG_USER_EMAIL));
if (empty($user->getUnconfirmedEmail()))
{
@ -38,6 +43,16 @@ class ActivateUserEmailJob extends AbstractJob
}
}
public function getRequiredArguments()
{
return JobArgs::Alternative(
JobArgs::ARG_TOKEN,
JobArgs::Alternative(
JobArgs::ARG_USER_ENTITY,
JobArgs::ARG_USER_EMAIL,
JobArgs::ARG_USER_NAME));
}
public static function sendEmail($user)
{
$regConfig = getConfig()->registration;

View file

@ -44,12 +44,17 @@ class AddPostJob extends AbstractJob
return $post;
}
public function requiresPrivilege()
public function getRequiredArguments()
{
return JobArgs::Optional(JobArgs::ARG_ANONYMOUS);
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::AddPost);
}
public function requiresConfirmedEmail()
public function isConfirmedEmailRequired()
{
return getConfig()->registration->needEmailForUploading;
}

View file

@ -46,7 +46,12 @@ class AddUserJob extends AbstractJob
return $user;
}
public function requiresPrivilege()
public function getRequiredArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::RegisterAccount);
}

View file

@ -0,0 +1,29 @@
<?php
abstract class AbstractCommentJob extends AbstractJob
{
protected $comment;
public function prepare()
{
if ($this->hasArgument(JobArgs::ARG_COMMENT_ENTITY))
{
$this->comment = $this->getArgument(JobArgs::ARG_COMMENT_ENTITY);
}
else
{
$commentId = $this->getArgument(JobArgs::ARG_COMMENT_ID);
$this->comment = CommentModel::getById($commentId);
}
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::Alternative(
JobArgs::ARG_COMMENT_ID,
JobArgs::ARG_COMMENT_ENTITY),
$this->getRequiredSubArguments());
}
public abstract function getRequiredSubArguments();
}

View file

@ -1,13 +1,6 @@
<?php
class DeleteCommentJob extends AbstractJob
class DeleteCommentJob extends AbstractCommentJob
{
protected $comment;
public function prepare()
{
$this->comment = CommentModel::getById($this->getArgument(JobArgs::ARG_COMMENT_ID));
}
public function execute()
{
$post = $this->comment->getPost();
@ -19,19 +12,24 @@ class DeleteCommentJob extends AbstractJob
'post' => TextHelper::reprPost($post)]);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::DeleteComment,
Access::getIdentity($this->comment->getCommenter()));
}
public function requiresAuthentication()
public function isAuthenticationRequired()
{
return true;
}
public function requiresConfirmedEmail()
public function isConfirmedEmailRequired()
{
return false;
}

View file

@ -1,13 +1,6 @@
<?php
class EditCommentJob extends AbstractJob
class EditCommentJob extends AbstractCommentJob
{
protected $comment;
public function prepare()
{
$this->comment = CommentModel::getById($this->getArgument(JobArgs::ARG_COMMENT_ID));
}
public function execute()
{
$comment = $this->comment;
@ -23,19 +16,24 @@ class EditCommentJob extends AbstractJob
return $comment;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_TEXT;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::EditComment,
Access::getIdentity($this->comment->getCommenter()));
}
public function requiresAuthentication()
public function isAuthenticationRequired()
{
return true;
}
public function requiresConfirmedEmail()
public function isConfirmedEmailRequired()
{
return false;
}

View file

@ -5,7 +5,10 @@ class GetPostContentJob extends AbstractJob
public function prepare()
{
$this->post = PostModel::getByName($this->getArgument(JobArgs::ARG_POST_NAME));
if ($this->hasArgument(JobArgs::ARG_POST_ENTITY))
$this->post = $this->getArgument(JobArgs::ARG_POST_ENTITY);
else
$this->post = PostModel::getByName($this->getArgument(JobArgs::ARG_POST_NAME));
}
public function execute()
@ -30,7 +33,14 @@ class GetPostContentJob extends AbstractJob
return new ApiFileOutput($path, $fileName);
}
public function requiresPrivilege()
public function getRequiredArguments()
{
return JobArgs::Alternative(
JobArgs::ARG_POST_NAME,
JobArgs::ARG_POST_ENTITY);
}
public function getRequiredPrivileges()
{
$post = $this->post;
$privileges = [];

View file

@ -3,7 +3,14 @@ class GetPostThumbJob extends AbstractJob
{
public function execute()
{
$name = $this->getArgument(JobArgs::ARG_POST_NAME);
if ($this->getArgument(JobArgs::ARG_POST_NAME))
$name = $this->getArgument(JobArgs::ARG_POST_NAME);
else
{
$post = PostModel::getByName($this->getArgument(JobArgs::ARG_POST_ENTITY));
$name = $post->getName();
}
$width = $this->hasArgument(JobArgs::ARG_THUMB_WIDTH) ? $this->getArgument(JobArgs::ARG_THUMB_WIDTH) : null;
$height = $this->hasArgument(JobArgs::ARG_THUMB_HEIGHT) ? $this->getArgument(JobArgs::ARG_THUMB_HEIGHT) : null;
@ -13,7 +20,7 @@ class GetPostThumbJob extends AbstractJob
$path = PostModel::getThumbDefaultPath($name, $width, $height);
if (!file_exists($path))
{
$post = PostModel::getByIdOrName($name);
$post = PostModel::getByName($name);
if ($post->isHidden())
Access::assert(new Privilege(Privilege::ListPosts, 'hidden'));
@ -35,7 +42,17 @@ class GetPostThumbJob extends AbstractJob
return new ApiFileOutput($path, 'thumbnail.jpg');
}
public function requiresPrivilege()
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::Alternative(
JobArgs::ARG_POST_ENTITY,
JobArgs::ARG_POST_NAME),
JobArgs::Optional(JobArgs::ARG_THUMB_WIDTH),
JobArgs::Optional(JobArgs::ARG_THUMB_HEIGHT));
}
public function getRequiredPrivileges()
{
//manually enforced in execute when post is retrieved
return false;

View file

@ -17,7 +17,12 @@ class ListLogsJob extends AbstractJob
return $logs;
}
public function requiresPrivilege()
public function getRequiredArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListLogs);
}

View file

@ -15,7 +15,14 @@ class MergeTagsJob extends AbstractJob
'target' => TextHelper::reprTag($targetTag)]);
}
public function requiresPrivilege()
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::ARG_SOURCE_TAG_NAME,
JobArgs::ARG_TARGET_TAG_NAME);
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::MergeTags);
}

View file

@ -30,4 +30,13 @@ abstract class AbstractPageJob extends AbstractJob
$ret->pageCount = $pageCount;
return $ret;
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::ARG_PAGE_NUMBER,
$this->getRequiredSubArguments());
}
public abstract function getRequiredSubArguments();
}

View file

@ -39,7 +39,14 @@ class GetLogJob extends AbstractPageJob
return intval(getConfig()->browsing->logsPerPage);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::Conjunction(
JobArgs::ARG_LOG_ID,
JobArgs::ARG_QUERY);
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ViewLog);
}

View file

@ -25,7 +25,12 @@ class ListCommentsJob extends AbstractPageJob
return intval(getConfig()->comments->commentsPerPage);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListComments);
}

View file

@ -20,7 +20,12 @@ class ListPostsJob extends AbstractPageJob
return intval(getConfig()->browsing->postsPerPage);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_QUERY;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListPosts);
}

View file

@ -20,4 +20,12 @@ class ListRelatedTagsJob extends ListTagsJob
{
return intval(getConfig()->browsing->tagsRelated);
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
parent::getRequiredArguments(),
Jobargs::ARG_TAG_NAME,
JobArgs::Optional(JobArgs::ARG_TAG_NAMES));
}
}

View file

@ -18,7 +18,12 @@ class ListTagsJob extends AbstractPageJob
return intval(getConfig()->browsing->tagsPerPage);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_QUERY;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListTags);
}

View file

@ -18,7 +18,12 @@ class ListUsersJob extends AbstractPageJob
return intval(getConfig()->browsing->usersPerPage);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_QUERY;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListUsers);
}

View file

@ -5,7 +5,12 @@ class PasswordResetJob extends AbstractJob
{
if (!$this->hasArgument(JobArgs::ARG_TOKEN))
{
$user = UserModel::getByNameOrEmail($this->getArgument(JobArgs::ARG_USER_NAME));
if ($this->hasArgument(JobArgs::ARG_USER_NAME))
$user = UserModel::getByNameOrEmail($this->getArgument(JobArgs::ARG_USER_NAME));
elseif ($this->hasArgument(JobArgs::ARG_USER_EMAIL))
$user = UserModel::getByNameOrEmail($this->getArgument(JobArgs::ARG_USER_EMAIL));
else
$user = $this->getArgument(JobArgs::ARG_USER_ENTITTY);
if (empty($user->getConfirmedEmail()))
throw new SimpleException('This user has no e-mail confirmed; password reset cannot proceed');
@ -42,6 +47,15 @@ class PasswordResetJob extends AbstractJob
}
}
public function getRequiredArguments()
{
return JobArgs::Alternative(
JobArgs::ARG_USER_NAME,
JobArgs::ARG_USER_EMAIL,
JobArgs::ARG_USER_ENTITY,
JobArgs::ARG_TOKEN);
}
public static function sendEmail($user)
{
$regConfig = getConfig()->registration;

View file

@ -0,0 +1,35 @@
<?php
abstract class AbstractPostJob extends AbstractJob
{
protected $post;
public function prepare()
{
if ($this->hasArgument(JobArgs::ARG_POST_ENTITY))
{
$this->post = $this->getArgument(JobArgs::ARG_POST_ENTITY);
}
elseif ($this->hasArgument(JobArgs::ARG_POST_ID))
{
$postId = $this->getArgument(JobArgs::ARG_POST_ID);
$this->post = PostModel::getById($postId);
}
else
{
$postName = $this->getArgument(JobArgs::ARG_POST_NAME);
$this->post = PostModel::getByName($postName);
}
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::Alternative(
JobArgs::ARG_POST_ID,
JobArgs::ARG_POST_NAME,
JobArgs::ARG_POST_ENTITY),
$this->getRequiredSubArguments());
}
public abstract function getRequiredSubArguments();
}

View file

@ -1,10 +1,10 @@
<?php
class AddCommentJob extends AbstractJob
class AddCommentJob extends AbstractPostJob
{
public function execute()
{
$post = $this->post;
$user = Auth::getCurrentUser();
$post = PostModel::getById($this->getArgument(JobArgs::ARG_POST_ID));
$text = $this->getArgument(JobArgs::ARG_NEW_TEXT);
$comment = CommentModel::spawn();
@ -21,17 +21,22 @@ class AddCommentJob extends AbstractJob
return $comment;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_TEXT;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::AddComment);
}
public function requiresAuthentication()
public function isAuthenticationRequired()
{
return false;
}
public function requiresConfirmedEmail()
public function isConfirmedEmailRequired()
{
return getConfig()->registration->needEmailForCommenting;
}

View file

@ -12,19 +12,24 @@ class DeletePostJob extends AbstractPostJob
'post' => TextHelper::reprPost($post)]);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::DeletePost,
Access::getIdentity($this->post->getUploader()));
}
public function requiresAuthentication()
public function isAuthenticationRequired()
{
return true;
}
public function requiresConfirmedEmail()
public function isConfirmedEmailRequired()
{
return false;
}

View file

@ -1,12 +1,6 @@
<?php
class EditPostContentJob extends AbstractPostJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_POST_CONTENT)
or $this->hasArgument(JobArgs::ARG_NEW_POST_CONTENT_URL);
}
public function execute()
{
$post = $this->post;
@ -32,7 +26,14 @@ class EditPostContentJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::Alternative(
JobArgs::ARG_NEW_POST_CONTENT,
JobArgs::ARG_NEW_POST_CONTENT_URL);
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -43,7 +43,12 @@ class EditPostJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -1,11 +1,6 @@
<?php
class EditPostRelationsJob extends AbstractPostJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_RELATED_POST_IDS);
}
public function execute()
{
$post = $this->post;
@ -37,7 +32,12 @@ class EditPostRelationsJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_RELATED_POST_IDS;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -1,11 +1,6 @@
<?php
class EditPostSafetyJob extends AbstractPostJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_SAFETY);
}
public function execute()
{
$post = $this->post;
@ -28,7 +23,12 @@ class EditPostSafetyJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_SAFETY;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -1,11 +1,6 @@
<?php
class EditPostSourceJob extends AbstractPostJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_SOURCE);
}
public function execute()
{
$post = $this->post;
@ -28,7 +23,12 @@ class EditPostSourceJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_SOURCE;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -1,11 +1,6 @@
<?php
class EditPostTagsJob extends AbstractPostJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_TAG_NAMES);
}
public function execute()
{
$post = $this->post;
@ -45,7 +40,12 @@ class EditPostTagsJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_TAG_NAMES;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -1,11 +1,6 @@
<?php
class EditPostThumbJob extends AbstractPostJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_THUMB_CONTENT);
}
public function execute()
{
$post = $this->post;
@ -23,7 +18,12 @@ class EditPostThumbJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_THUMB_CONTENT;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -20,14 +20,19 @@ class FeaturePostJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::Optional(JobArgs::ARG_ANONYMOUS);
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::FeaturePost,
Access::getIdentity($this->post->getUploader()));
}
public function requiresAuthentication()
public function isAuthenticationRequired()
{
return true;
}

View file

@ -19,7 +19,12 @@ class FlagPostJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::FlagPost,

View file

@ -10,7 +10,12 @@ class GetPostJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
$post = $this->post;
$privileges = [];

View file

@ -11,14 +11,19 @@ class ScorePostJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_POST_SCORE;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::ScorePost,
Access::getIdentity($this->post->getUploader()));
}
public function requiresAuthentication()
public function isAuthenticationRequired()
{
return true;
}

View file

@ -19,14 +19,19 @@ class TogglePostFavoriteJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_STATE;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::FavoritePost,
Access::getIdentity($this->post->getUploader()));
}
public function requiresAuthentication()
public function isAuthenticationRequired()
{
return true;
}

View file

@ -50,7 +50,14 @@ class TogglePostTagJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::Conjunction(
JobArgs::ARG_TAG_NAME,
Jobargs::ARG_NEW_STATE);
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::EditPostTags,

View file

@ -19,7 +19,12 @@ class TogglePostVisibilityJob extends AbstractPostJob
return $post;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_STATE;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::HidePost,

View file

@ -26,17 +26,26 @@ class PreviewCommentJob extends AbstractJob
return $comment;
}
public function requiresPrivilege()
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::ARG_NEW_TEXT,
JobArgs::Alternative(
JobArgs::ARG_COMMENT_ID,
JobArgs::ARG_POST_ID));
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::AddComment);
}
public function requiresAuthentication()
public function isAuthenticationRequired()
{
return false;
}
public function requiresConfirmedEmail()
public function isConfirmedEmailRequired()
{
return getConfig()->registration->needEmailForCommenting;
}

View file

@ -15,7 +15,14 @@ class RenameTagsJob extends AbstractJob
'target' => TextHelper::reprTag($targetTag)]);
}
public function requiresPrivilege()
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::ARG_SOURCE_TAG_NAME,
JobArgs::ARG_TARGET_TAG_NAME);
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::RenameTags);
}

View file

@ -15,4 +15,16 @@ abstract class AbstractUserJob extends AbstractJob
$this->user = UserModel::getByNameOrEmail($userName);
}
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::Alternative(
JobArgs::ARG_USER_NAME,
JobArgs::ARG_USER_EMAIL,
JobArgs::ARG_USER_ENTITY),
$this->getRequiredSubArguments());
}
public abstract function getRequiredSubArguments();
}

View file

@ -13,7 +13,12 @@ class AcceptUserRegistrationJob extends AbstractUserJob
'subject' => TextHelper::reprUser($user)]);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::AcceptUserRegistration);
}

View file

@ -13,7 +13,12 @@ class DeleteUserJob extends AbstractUserJob
'subject' => TextHelper::reprUser($name)]);
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::DeleteUser,

View file

@ -1,11 +1,6 @@
<?php
class EditUserAccessRankJob extends AbstractUserJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_ACCESS_RANK);
}
public function execute()
{
$user = $this->user;
@ -28,7 +23,12 @@ class EditUserAccessRankJob extends AbstractUserJob
return $user;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_ACCESS_RANK;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::ChangeUserAccessRank,

View file

@ -1,11 +1,6 @@
<?php
class EditUserEmailJob extends AbstractUserJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_EMAIL);
}
public function execute()
{
if (getConfig()->registration->needEmailForRegistering)
@ -49,7 +44,12 @@ class EditUserEmailJob extends AbstractUserJob
}
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_EMAIL;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -65,7 +65,12 @@ class EditUserJob extends AbstractUserJob
return $user;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return false;
}

View file

@ -1,11 +1,6 @@
<?php
class EditUserNameJob extends AbstractUserJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_USER_NAME);
}
public function execute()
{
$user = $this->user;
@ -28,7 +23,12 @@ class EditUserNameJob extends AbstractUserJob
return $user;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_USER_NAME;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -1,11 +1,6 @@
<?php
class EditUserPasswordJob extends AbstractUserJob
{
public function isSatisfied()
{
return $this->hasArgument(JobArgs::ARG_NEW_PASSWORD);
}
public function execute()
{
$user = $this->user;
@ -27,7 +22,12 @@ class EditUserPasswordJob extends AbstractUserJob
return $user;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_PASSWORD;
}
public function getRequiredPrivileges()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD

View file

@ -19,7 +19,12 @@ class FlagUserJob extends AbstractUserJob
return $user;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::FlagUser,

View file

@ -6,7 +6,12 @@ class GetUserJob extends AbstractUserJob
return $this->user;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return null;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::ViewUser,

View file

@ -22,7 +22,12 @@ class ToggleUserBanJob extends AbstractUserJob
return $user;
}
public function requiresPrivilege()
public function getRequiredSubArguments()
{
return JobArgs::ARG_NEW_STATE;
}
public function getRequiredPrivileges()
{
return new Privilege(
Privilege::BanUser,

View file

@ -17,13 +17,11 @@ class UserController
$context->transport->paginator = $ret;
}
public function genericView($name, $tab = 'favs', $page = 1)
public function genericView($identifier, $tab = 'favs', $page = 1)
{
$user = Api::run(
new GetUserJob(),
[
JobArgs::ARG_USER_NAME => $name,
]);
$this->appendUserIdentifierArgument([], $identifier));
$flagged = in_array(TextHelper::reprUser($user), SessionHelper::get('flagged', []));
@ -69,9 +67,9 @@ class UserController
}
}
public function settingsAction($name)
public function settingsAction($identifier)
{
$this->genericView($name, 'settings');
$this->genericView($identifier, 'settings');
$user = getContext()->transport->user;
@ -97,9 +95,9 @@ class UserController
Messenger::message('Browsing settings updated!');
}
public function editAction($name)
public function editAction($identifier)
{
$this->genericView($name, 'edit');
$this->genericView($identifier, 'edit');
$this->requirePasswordConfirmation();
if (InputHelper::get('password1') != InputHelper::get('password2'))
@ -107,12 +105,12 @@ class UserController
$args =
[
JobArgs::ARG_USER_NAME => $name,
JobArgs::ARG_NEW_USER_NAME => InputHelper::get('name'),
JobArgs::ARG_NEW_PASSWORD => InputHelper::get('password1'),
JobArgs::ARG_NEW_EMAIL => InputHelper::get('email'),
JobArgs::ARG_NEW_ACCESS_RANK => InputHelper::get('access-rank'),
];
$args = $this->appendUserIdentifierArgument($args, $identifier);
$args = array_filter($args);
$user = Api::run(new EditUserJob(), $args);
@ -127,13 +125,14 @@ class UserController
Messenger::message($message);
}
public function deleteAction($name)
public function deleteAction($identifier)
{
$this->genericView($name, 'delete');
$this->genericView($identifier, 'delete');
$this->requirePasswordConfirmation();
Api::run(new DeleteUserJob(), [
JobArgs::ARG_USER_NAME => $name]);
Api::run(
new DeleteUserJob(),
$this->appendUserIdentifierArgument([], $identifier));
$user = UserModel::tryGetById(Auth::getCurrentUser()->getId());
if (!$user)
@ -143,29 +142,36 @@ class UserController
exit;
}
public function flagAction($name)
public function flagAction($identifier)
{
Api::run(new FlagUserJob(), [JobArgs::ARG_USER_NAME => $name]);
Api::run(
new FlagUserJob(),
$this->appendUserIdentifierArgument([], $identifier));
}
public function banAction($name)
public function banAction($identifier)
{
Api::run(new ToggleUserBanJob(), [
JobArgs::ARG_USER_NAME => $name,
JobArgs::ARG_NEW_STATE => true]);
Api::run(
new ToggleUserBanJob(),
$this->appendUserIdentifierArgument([
JobArgs::ARG_NEW_STATE => true
], $identifier));
}
public function unbanAction($name)
public function unbanAction($identifier)
{
Api::run(new ToggleUserBanJob(), [
JobArgs::ARG_USER_NAME => $name,
JobArgs::ARG_NEW_STATE => false]);
Api::run(
new ToggleUserBanJob(),
$this->appendUserIdentifierArgument([
JobArgs::ARG_NEW_STATE => true
], $identifier));
}
public function acceptRegistrationAction($name)
public function acceptRegistrationAction($identifier)
{
Api::run(new AcceptUserRegistrationJob(), [
JobArgs::ARG_USER_NAME => $name]);
Api::run(
new AcceptUserRegistrationJob(),
$this->appendUserIdentifierArgument([], $identifier));
}
public function toggleSafetyAction($safety)
@ -243,17 +249,20 @@ class UserController
$context = getContext();
$context->viewName = 'message';
Assets::setSubTitle('account activation');
$name = InputHelper::get('name');
$identifier = InputHelper::get('identifier');
if (empty($tokenText))
{
Api::run(new ActivateUserEmailJob(), [ JobArgs::ARG_USER_NAME => $name ]);
Api::run(
new ActivateUserEmailJob(),
$this->appendUserIdentifierArgument([], $identifier));
Messenger::message('Activation e-mail resent.');
}
else
{
$user = Api::run(new ActivateUserEmailJob(), [ JobArgs::ARG_TOKEN => $tokenText ]);
$user = Api::run(new ActivateUserEmailJob(), [
JobArgs::ARG_TOKEN => $tokenText ]);
$message = 'Activation completed successfully.';
if (getConfig()->registration->staffActivation)
@ -277,11 +286,13 @@ class UserController
$context = getContext();
$context->viewName = 'message';
Assets::setSubTitle('password reset');
$name = InputHelper::get('name');
$identifier = InputHelper::get('identifier');
if (empty($tokenText))
{
Api::run(new PasswordResetJob(), [ JobArgs::ARG_USER_NAME => $name ]);
Api::run(
new PasswordResetJob(),
$this->appendUserIdentifierArgument([], $identifier));
Messenger::message('E-mail sent. Follow instructions to reset password.');
}
@ -308,4 +319,13 @@ class UserController
throw new SimpleException('Must supply valid password');
}
}
private function appendUserIdentifierArgument(array $arguments, $userIdentifier)
{
if (strpos($userIdentifier, '@') !== false)
$arguments[JobArgs::ARG_USER_EMAIL] = $userIdentifier;
else
$arguments[JobArgs::ARG_USER_NAME] = $userIdentifier;
return $arguments;
}
}

View file

@ -8,7 +8,9 @@ Assets::addScript('comment-edit.js');
<div class="avatar">
<?php $commenter = $this->context->comment->getCommenter() ?>
<?php if ($commenter): ?>
<a href="<?= \Chibi\Router::linkTo(['UserController', 'genericView'], ['name' => $commenter->getName()]) ?>">
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['identifier' => $commenter->getName()]) ?>">
<img src="<?= htmlspecialchars($commenter->getAvatarUrl(40)) ?>" alt="<?= $commenter->getName() ?>"/>
</a>
<?php else: ?>
@ -24,7 +26,7 @@ Assets::addScript('comment-edit.js');
<?php if ($commenter): ?>
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $commenter->getName()]) ?>">
['identifier' => $commenter->getName()]) ?>">
<?= $commenter->getName() ?>
</a>
<?php else: ?>

View file

@ -95,7 +95,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<span class="value" title="<?= $val = $uploader->getName() ?>">
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $uploader->getName()]) ?>">
['identifier' => $uploader->getName()]) ?>">
<img src="<?= htmlentities($uploader->getAvatarUrl(24)) ?>" alt="<?= $uploader->getName() ?>"/>
<?= $val ?>
</a>
@ -245,7 +245,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<li>
<a title="<?= $user->getName() ?>" href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $user->getName()]) ?>">
['identifier' => $user->getName()]) ?>">
<img src="<?= htmlspecialchars($user->getAvatarUrl()) ?>" alt="<?= $user->getName() ?>">
</a>
</li>

View file

@ -43,7 +43,7 @@ Assets::addStylesheet('static-main.css');
by
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $this->context->featuredPostUser->getName()]) ?>">
['identifier' => $this->context->featuredPostUser->getName()]) ?>">
<?= $this->context->featuredPostUser->getName() ?>
</a>,
<?php endif ?>

View file

@ -56,8 +56,8 @@
'Users',
\Chibi\Router::linkTo(['UserController', 'listView']),
$activeController == 'user' and $activeAction != 'registration' and
(!isset($this->context->route->arguments['name']) or
$this->context->route->arguments['name'] != Auth::getCurrentUser()->getName()));
(!isset($this->context->route->arguments['identifier']) or
$this->context->route->arguments['identifier'] != Auth::getCurrentUser()->getName()));
}
if (!Auth::isLoggedIn())
@ -76,9 +76,9 @@
{
$registerNavItem(
'My account',
\Chibi\Router::linkTo(['UserController', 'genericView'], ['name' => Auth::getCurrentUser()->getName()]),
$activeController == 'user' and isset($this->context->route->arguments['name']) and
$this->context->route->arguments['name'] == Auth::getCurrentUser()->getName());
\Chibi\Router::linkTo(['UserController', 'genericView'], ['identifier' => Auth::getCurrentUser()->getName()]),
$activeController == 'user' and isset($this->context->route->arguments['identifier']) and
$this->context->route->arguments['identifier'] == Auth::getCurrentUser()->getName());
$registerNavItem(
'Log out',
@ -119,7 +119,7 @@
TextCaseConverter::CAMEL_CASE,
TextCaseConverter::SPINAL_CASE) ?>">
<a class="<?= Auth::getCurrentUser()->hasEnabledSafety($safety) ? 'enabled' : 'disabled' ?>"
<a class="simple-action <?= Auth::getCurrentUser()->hasEnabledSafety($safety) ? 'enabled' : 'disabled' ?>"
href="<?= \Chibi\Router::linkTo(
['UserController', 'toggleSafetyAction'],
['safety' => $safety->toInteger()]) ?>"

View file

@ -1,7 +1,7 @@
<form
action="<?= \Chibi\Router::linkTo(
['UserController', 'deleteAction'],
['name' => $this->context->transport->user->getName()]) ?>"
['identifier' => $this->context->transport->user->getName()]) ?>"
method="post"
class="delete confirmable"
autocomplete="off"

View file

@ -1,7 +1,7 @@
<form
action="<?= \Chibi\Router::linkTo(
['UserController', 'editAction'],
['name' => $this->context->transport->user->getName()]) ?>"
['identifier' => $this->context->transport->user->getName()]) ?>"
method="post"
class="edit"
autocomplete="off">

View file

@ -44,14 +44,14 @@ if (Auth::getCurrentUser()->hasEnabledEndlessScrolling())
<div class="user">
<a class="avatar" href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $user->getName()]) ?>">
['identifier' => $user->getName()]) ?>">
<img src="<?= htmlspecialchars($user->getAvatarUrl(100)) ?>" alt="<?= $user->getName() ?>"/>
</a>
<div class="details">
<h1>
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $user->getName()]) ?>">
['identifier' => $user->getName()]) ?>">
<?= $user->getName() ?>
</a>
</h1>

View file

@ -13,7 +13,7 @@
<div class="form-row">
<label>User:</label>
<div class="input-wrapper">
<input name="name" placeholder="Name or e-mail address" type="text"/>
<input name="identifier" placeholder="Name or e-mail address" type="text"/>
</div>
</div>

View file

@ -1,7 +1,7 @@
<form
action="<?= \Chibi\Router::linkTo(
['UserController', 'settingsAction'],
['name' => $this->context->transport->user->getName()]) ?>"
['identifier' => $this->context->transport->user->getName()]) ?>"
method="post"
class="settings">

View file

@ -7,7 +7,7 @@ Assets::addStylesheet('user-view.css');
<div class="avatar-wrapper">
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $this->context->transport->user->getName()]) ?>">
['identifier' => $this->context->transport->user->getName()]) ?>">
<img
src="<?= htmlspecialchars($this->context->transport->user->getAvatarUrl(140)) ?>"
@ -98,7 +98,7 @@ Assets::addStylesheet('user-view.css');
'text' => 'Edit account settings',
'link' => \Chibi\Router::linkTo(
['UserController', 'editAction'],
['name' => $this->context->transport->user->getName(), 'tab' => 'edit']),
['identifier' => $this->context->transport->user->getName(), 'tab' => 'edit']),
];
}
@ -112,7 +112,7 @@ Assets::addStylesheet('user-view.css');
'text' => 'Accept registration',
'simple-action' => \Chibi\Router::linkTo(
['UserController', 'acceptRegistrationAction'],
['name' => $this->context->transport->user->getName()]),
['identifier' => $this->context->transport->user->getName()]),
];
}
@ -137,7 +137,7 @@ Assets::addStylesheet('user-view.css');
'text' => 'Flag for moderator attention',
'simple-action' => \Chibi\Router::linkTo(
['UserController', 'flagAction'],
['name' => $this->context->transport->user->getName()]),
['identifier' => $this->context->transport->user->getName()]),
'data-confirm-text' => 'Are you sure you want to flag this user?',
];
}
@ -155,7 +155,7 @@ Assets::addStylesheet('user-view.css');
'text' => 'Ban user',
'simple-action' => \Chibi\Router::linkTo(
['UserController', 'banAction'],
['name' => $this->context->transport->user->getName()]),
['identifier' => $this->context->transport->user->getName()]),
'data-confirm-text' => 'Are you sure you want to ban this user?',
];
}
@ -167,7 +167,7 @@ Assets::addStylesheet('user-view.css');
'text' => 'Unban user',
'simple-action' => \Chibi\Router::linkTo(
['UserController', 'unbanAction'],
['name' => $this->context->transport->user->getName()]),
['identifier' => $this->context->transport->user->getName()]),
'data-confirm-text' => 'Are you sure you want to unban this user?',
];
}
@ -183,7 +183,7 @@ Assets::addStylesheet('user-view.css');
'text' => 'Delete account',
'link' => \Chibi\Router::linkTo(
['UserController', 'deleteAction'],
['name' => $this->context->transport->user->getName(), 'tab' => 'delete']),
['identifier' => $this->context->transport->user->getName(), 'tab' => 'delete']),
];
}
@ -202,7 +202,7 @@ Assets::addStylesheet('user-view.css');
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $this->context->transport->user->getName(),
['identifier' => $this->context->transport->user->getName(),
'tab' => 'favs',
'page' => 1]) ?>">
Favs
@ -216,7 +216,7 @@ Assets::addStylesheet('user-view.css');
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $this->context->transport->user->getName(),
['identifier' => $this->context->transport->user->getName(),
'tab' => 'uploads',
'page' => 1]) ?>">
Uploads
@ -234,7 +234,7 @@ Assets::addStylesheet('user-view.css');
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $this->context->transport->user->getName(),
['identifier' => $this->context->transport->user->getName(),
'tab' => 'settings']) ?>">
Browsing settings
</a>
@ -249,7 +249,7 @@ Assets::addStylesheet('user-view.css');
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $this->context->transport->user->getName(),
['identifier' => $this->context->transport->user->getName(),
'tab' => 'edit']) ?>">
Account settings
</a>
@ -266,7 +266,7 @@ Assets::addStylesheet('user-view.css');
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
['UserController', 'genericView'],
['name' => $this->context->transport->user->getName(),
['identifier' => $this->context->transport->user->getName(),
'tab' => 'delete']) ?>">
Delete account
</a>

View file

@ -88,7 +88,7 @@ $tagValidation =
$userValidation =
[
'name' => '[^\/]+',
'identifier' => '[^\/]+',
'page' => '\d*',
'tab' => 'favs|uploads|settings|edit|delete',
'filter' => '[^\/]+',
@ -97,8 +97,8 @@ $userValidation =
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users', $userValidation);
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{filter}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{identifier}/{tab}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{identifier}/{tab}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'registrationView'], 'GET', '/register', $userValidation);
\Chibi\Router::register(['UserController', 'registrationAction'], 'POST', '/register', $userValidation);
@ -110,11 +110,11 @@ $userValidation =
\Chibi\Router::register(['UserController', 'passwordResetAction'], 'POST', '/password-reset', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetAction'], 'GET', '/password-reset/{tokenText}', $userValidation);
\Chibi\Router::register(['UserController', 'flagAction'], 'POST', '/user/{name}/flag', $userValidation);
\Chibi\Router::register(['UserController', 'banAction'], 'POST', '/user/{name}/ban', $userValidation);
\Chibi\Router::register(['UserController', 'unbanAction'], 'POST', '/user/{name}/unban', $userValidation);
\Chibi\Router::register(['UserController', 'acceptRegistrationAction'], 'POST', '/user/{name}/accept-registration', $userValidation);
\Chibi\Router::register(['UserController', 'deleteAction'], 'POST', '/user/{name}/delete', $userValidation);
\Chibi\Router::register(['UserController', 'settingsAction'], 'POST', '/user/{name}/settings', $userValidation);
\Chibi\Router::register(['UserController', 'editAction'], 'POST', '/user/{name}/edit', $userValidation);
\Chibi\Router::register(['UserController', 'flagAction'], 'POST', '/user/{identifier}/flag', $userValidation);
\Chibi\Router::register(['UserController', 'banAction'], 'POST', '/user/{identifier}/ban', $userValidation);
\Chibi\Router::register(['UserController', 'unbanAction'], 'POST', '/user/{identifier}/unban', $userValidation);
\Chibi\Router::register(['UserController', 'acceptRegistrationAction'], 'POST', '/user/{identifier}/accept-registration', $userValidation);
\Chibi\Router::register(['UserController', 'deleteAction'], 'POST', '/user/{identifier}/delete', $userValidation);
\Chibi\Router::register(['UserController', 'settingsAction'], 'POST', '/user/{identifier}/settings', $userValidation);
\Chibi\Router::register(['UserController', 'editAction'], 'POST', '/user/{identifier}/edit', $userValidation);
\Chibi\Router::register(['UserController', 'toggleSafetyAction'], 'POST', '/user/toggle-safety/{safety}', $userValidation);

View file

@ -0,0 +1,367 @@
<?php
class ApiArgumentTest extends AbstractFullApiTest
{
public function testAcceptUserRegistrationJob()
{
$this->testArguments(new AcceptUserRegistrationJob(),
$this->getUserSelector());
}
public function testActivateUserEmailJob()
{
$this->testArguments(new ActivateUserEmailJob(),
JobArgs::Alternative(
JobArgs::ARG_TOKEN,
$this->getUserSelector()));
}
public function testAddPostJob()
{
$this->testArguments(new AddPostJob(),
JobArgs::Optional(
JobArgs::ARG_ANONYMOUS));
}
public function testAddCommentJob()
{
$this->testArguments(new AddCommentJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_TEXT));
}
public function testAddUserJob()
{
$this->testArguments(new AddUserJob(), null);
}
public function testDeletePostJob()
{
$this->testArguments(new DeletePostJob(),
$this->getPostSelector());
}
public function testDeleteCommentJob()
{
$this->testArguments(new DeleteCommentJob(),
JobArgs::Alternative(
JobArgs::ARG_COMMENT_ENTITY,
JobArgs::ARG_COMMENT_ID));
}
public function testDeleteUserJob()
{
$this->testArguments(new DeleteUserJob(),
$this->getUserSelector());
}
public function testEditCommentJob()
{
$this->testArguments(new EditCommentJob(),
JobArgs::Conjunction(
JobArgs::ARG_NEW_TEXT,
JobArgs::Alternative(
JobArgs::ARG_COMMENT_ENTITY,
JobArgs::ARG_COMMENT_ID)));
}
public function testEditPostContentJob()
{
$this->testArguments(new EditPostContentJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::Alternative(
JobArgs::ARG_NEW_POST_CONTENT,
JobArgs::ARG_NEW_POST_CONTENT_URL)));
}
public function testEditPostJob()
{
$this->testArguments(new EditPostJob(),
$this->getPostSelector());
}
public function testEditPostRelationsJob()
{
$this->testArguments(new EditPostRelationsJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_RELATED_POST_IDS));
}
public function testEditPostSafetyJob()
{
$this->testArguments(new EditPostSafetyJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_SAFETY));
}
public function testEditPostSourceJob()
{
$this->testArguments(new EditPostSourceJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_SOURCE));
}
public function testEditPostTagsJob()
{
$this->testArguments(new EditPostTagsJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_TAG_NAMES));
}
public function testEditPostThumbJob()
{
$this->testArguments(new EditPostThumbJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_THUMB_CONTENT));
}
public function testEditUserAccessRankJob()
{
$this->testArguments(new EditUserAccessRankJob(),
JobArgs::Conjunction(
$this->getUserSelector(),
JobArgs::ARG_NEW_ACCESS_RANK));
}
public function testEditUserEmailJob()
{
$this->testArguments(new EditUserEmailJob(),
JobArgs::Conjunction(
$this->getUserSelector(),
JobArgs::ARG_NEW_EMAIL));
}
public function testEditUserJob()
{
$this->testArguments(new EditUserJob(),
$this->getUserSelector());
}
public function testEditUserNameJob()
{
$this->testArguments(new EditUserNameJob(),
JobArgs::Conjunction(
$this->getUserSelector(),
JobArgs::ARG_NEW_USER_NAME));
}
public function testEditUserPasswordJob()
{
$this->testArguments(new EditUserPasswordJob(),
JobArgs::Conjunction(
$this->getUserSelector(),
JobArgs::ARG_NEW_PASSWORD));
}
public function testFeaturePostJob()
{
$this->testArguments(new FeaturePostJob(),
JobArgs::Conjunction(
JobArgs::Optional(JobArgs::ARG_ANONYMOUS),
$this->getPostSelector()));
}
public function testFlagPostJob()
{
$this->testArguments(new FlagPostJob(),
$this->getPostSelector());
}
public function testFlagUserJob()
{
$this->testArguments(new FlagUserJob(),
$this->getUserSelector());
}
public function testGetLogJob()
{
$this->testArguments(new GetLogJob(),
JobArgs::Conjunction(
JobArgs::ARG_QUERY,
JobArgs::ARG_LOG_ID,
JobArgs::ARG_PAGE_NUMBER));
}
public function testGetPostContentJob()
{
$this->testArguments(new GetPostContentJob(),
$this->getPostSafeSelector());
}
public function testGetPostJob()
{
$this->testArguments(new GetPostJob(),
$this->getPostSelector());
}
public function testGetPostThumbJob()
{
$this->testArguments(new GetPostThumbJob(),
JobArgs::Conjunction(
JobArgs::Optional(JobArgs::ARG_THUMB_WIDTH),
JobArgs::Optional(JobArgs::ARG_THUMB_HEIGHT),
$this->getPostSafeSelector()));
}
public function testGetUserJob()
{
$this->testArguments(new GetUserJob(),
$this->getUserSelector());
}
public function testListCommentsJob()
{
$this->testArguments(new ListCommentsJob(),
JobArgs::ARG_PAGE_NUMBER);
}
public function testListLogsJob()
{
$this->testArguments(new ListLogsJob(),
null);
}
public function testListPostsJob()
{
$this->testArguments(new ListPostsJob(),
JobArgs::Conjunction(
JobArgs::ARG_QUERY,
JobArgs::ARG_PAGE_NUMBER));
}
public function testListRelatedTagsJob()
{
$this->testArguments(new ListRelatedTagsJob(),
JobArgs::Conjunction(
JobArgs::Optional(JobArgs::ARG_TAG_NAMES),
JobArgs::ARG_TAG_NAME,
JobArgs::ARG_QUERY,
JobArgs::ARG_PAGE_NUMBER));
}
public function testListTagsJob()
{
$this->testArguments(new ListTagsJob(),
JobArgs::Conjunction(
JobArgs::ARG_QUERY,
JobArgs::ARG_PAGE_NUMBER));
}
public function testListUsersJob()
{
$this->testArguments(new ListUsersJob(),
JobArgs::Conjunction(
JobArgs::ARG_QUERY,
JobArgs::ARG_PAGE_NUMBER));
}
public function testMergeTagsJob()
{
$this->testArguments(new MergeTagsJob(),
JobArgs::Conjunction(
JobArgs::ARG_SOURCE_TAG_NAME,
JobArgs::ARG_TARGET_TAG_NAME));
}
public function testRenameTagsJob()
{
$this->testArguments(new RenameTagsJob(),
JobArgs::Conjunction(
JobArgs::ARG_SOURCE_TAG_NAME,
JobArgs::ARG_TARGET_TAG_NAME));
}
public function testPasswordResetJob()
{
$this->testArguments(new PasswordResetJob(),
JobArgs::Alternative(
JobArgs::ARG_TOKEN,
$this->getUserSelector()));
}
public function testPreviewCommentJob()
{
$this->testArguments(new PreviewCommentJob(),
JobArgs::Conjunction(
JobArgs::Alternative(
JobArgs::ARG_POST_ID,
JobArgs::ARG_COMMENT_ID),
JobArgs::ARG_NEW_TEXT));
}
public function testScorePostJob()
{
$this->testArguments(new ScorePostJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_POST_SCORE));
}
public function testTogglePostFavoriteJob()
{
$this->testArguments(new TogglePostFavoriteJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_STATE));
}
public function testTogglePostTagJob()
{
$this->testArguments(new TogglePostTagJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_TAG_NAME,
JobArgs::ARG_NEW_STATE));
}
public function testTogglePostVisibilityJob()
{
$this->testArguments(new TogglePostVisibilityJob(),
JobArgs::Conjunction(
$this->getPostSelector(),
JobArgs::ARG_NEW_STATE));
}
public function testToggleUserBanJob()
{
$this->testArguments(new ToggleUserBanJob(),
JobArgs::Conjunction(
$this->getUserSelector(),
JobArgs::ARG_NEW_STATE));
}
protected function testArguments($job, $arguments)
{
$this->testedJobs []= $job;
$this->assert->areEquivalent($arguments, $job->getRequiredArguments());
}
protected function getPostSelector()
{
return JobArgs::Alternative(
JobArgs::ARG_POST_ENTITY,
JobArgs::ARG_POST_ID,
JobArgs::ARG_POST_NAME);
}
protected function getPostSafeSelector()
{
return JobArgs::Alternative(
JobArgs::ARG_POST_NAME,
JobArgs::ARG_POST_ENTITY);
}
protected function getUserSelector()
{
return JobArgs::Alternative(
JobArgs::ARG_USER_EMAIL,
JobArgs::ARG_USER_ENTITY,
JobArgs::ARG_USER_NAME);
}
}

View file

@ -52,7 +52,7 @@ class ApiAuthTest extends AbstractFullApiTest
protected function testAuth($job, $expectedAuth)
{
$this->testedJobs []= $job;
$this->assert->areEqual($expectedAuth, $job->requiresAuthentication());
$this->assert->areEqual($expectedAuth, $job->isAuthenticationRequired());
}
public function testAuthEnforcing()

View file

@ -52,7 +52,7 @@ class ApiEmailRequirementsTest extends AbstractFullApiTest
protected function testRegularEmailRequirement($job)
{
$this->testedJobs []= $job;
$this->assert->areEqual(false, $job->requiresConfirmedEmail());
$this->assert->areEqual(false, $job->isConfirmedEmailRequired());
}
public function testCommentsEmailRequirements()
@ -66,10 +66,10 @@ class ApiEmailRequirementsTest extends AbstractFullApiTest
$this->testedJobs []= $job;
getConfig()->registration->needEmailForCommenting = false;
$this->assert->areEqual(false, $job->requiresConfirmedEmail());
$this->assert->areEqual(false, $job->isConfirmedEmailRequired());
getConfig()->registration->needEmailForCommenting = true;
$this->assert->areEqual(true, $job->requiresConfirmedEmail());
$this->assert->areEqual(true, $job->isConfirmedEmailRequired());
}
public function testPostingEmailRequirement()
@ -79,10 +79,10 @@ class ApiEmailRequirementsTest extends AbstractFullApiTest
$this->testedJobs []= $job;
getConfig()->registration->needEmailForUploading = false;
$this->assert->areEqual(false, $job->requiresConfirmedEmail());
$this->assert->areEqual(false, $job->isConfirmedEmailRequired());
getConfig()->registration->needEmailForUploading = true;
$this->assert->areEqual(true, $job->requiresConfirmedEmail());
$this->assert->areEqual(true, $job->isConfirmedEmailRequired());
}
public function testEnforcing()

View file

@ -33,7 +33,7 @@ class ApiPrivilegeTest extends AbstractFullApiTest
protected function testRegularPrivilege($job, $expectedPrivilege)
{
$this->testedJobs []= $job;
$this->assert->areEquivalent($expectedPrivilege, $job->requiresPrivilege());
$this->assert->areEquivalent($expectedPrivilege, $job->getRequiredPrivileges());
}
public function testDynamicPostPrivileges()
@ -80,12 +80,12 @@ class ApiPrivilegeTest extends AbstractFullApiTest
$expectedPrivilege->secondary = 'all';
$job->setArgument(JobArgs::ARG_POST_ID, $otherPost->getId());
$job->prepare();
$this->assert->areEquivalent($expectedPrivilege, $job->requiresPrivilege());
$this->assert->areEquivalent($expectedPrivilege, $job->getRequiredPrivileges());
$expectedPrivilege->secondary = 'own';
$job->setArgument(JobArgs::ARG_POST_ID, $ownPost->getId());
$job->prepare();
$this->assert->areEquivalent($expectedPrivilege, $job->requiresPrivilege());
$this->assert->areEquivalent($expectedPrivilege, $job->getRequiredPrivileges());
}
public function testDynamicPostRetrievalPrivileges()
@ -110,7 +110,7 @@ class ApiPrivilegeTest extends AbstractFullApiTest
$job->prepare();
$this->assert->areEquivalent([
new Privilege(Privilege::ViewPost, 'hidden'),
new Privilege(Privilege::ViewPost, 'safe')], $job->requiresPrivilege());
new Privilege(Privilege::ViewPost, 'safe')], $job->getRequiredPrivileges());
}
}
@ -118,7 +118,7 @@ class ApiPrivilegeTest extends AbstractFullApiTest
{
$job = new GetPostThumbJob();
$this->testedJobs []= $job;
$this->assert->areEquivalent(false, $job->requiresPrivilege());
$this->assert->areEquivalent(false, $job->getRequiredPrivileges());
}
public function testDynamicUserPrivileges()
@ -149,12 +149,12 @@ class ApiPrivilegeTest extends AbstractFullApiTest
$expectedPrivilege->secondary = 'own';
$job->setArgument(JobArgs::ARG_USER_NAME, $ownUser->getName());
$job->prepare();
$this->assert->areEquivalent($expectedPrivilege, $job->requiresPrivilege());
$this->assert->areEquivalent($expectedPrivilege, $job->getRequiredPrivileges());
$expectedPrivilege->secondary = 'all';
$job->setArgument(JobArgs::ARG_USER_NAME, $otherUser->getName());
$job->prepare();
$this->assert->areEquivalent($expectedPrivilege, $job->requiresPrivilege());
$this->assert->areEquivalent($expectedPrivilege, $job->getRequiredPrivileges());
}
public function testDynamicCommentPrivileges()
@ -175,12 +175,12 @@ class ApiPrivilegeTest extends AbstractFullApiTest
$expectedPrivilege->secondary = 'own';
$job->setArgument(JobArgs::ARG_COMMENT_ID, $ownComment->getId());
$job->prepare();
$this->assert->areEquivalent($expectedPrivilege, $job->requiresPrivilege());
$this->assert->areEquivalent($expectedPrivilege, $job->getRequiredPrivileges());
$expectedPrivilege->secondary = 'all';
$job->setArgument(JobArgs::ARG_COMMENT_ID, $otherComment->getId());
$job->prepare();
$this->assert->areEquivalent($expectedPrivilege, $job->requiresPrivilege());
$this->assert->areEquivalent($expectedPrivilege, $job->getRequiredPrivileges());
}
public function testPrivilegeEnforcing()