Better privilege checking for batch operations

This commit is contained in:
Marcin Kurczewski 2014-05-06 19:39:41 +02:00
parent cd437ca036
commit 410237d678
30 changed files with 314 additions and 85 deletions

View file

@ -73,7 +73,6 @@ passwordResetEmailBody = "Hello,{nl}{nl}You received this e-mail because someone
registerAccount=anonymous registerAccount=anonymous
;registerAccount=nobody ;registerAccount=nobody
uploadPost=registered
listPosts=anonymous listPosts=anonymous
listPosts.sketchy=registered listPosts.sketchy=registered
listPosts.unsafe=registered listPosts.unsafe=registered
@ -84,6 +83,16 @@ viewPost.unsafe=registered
viewPost.hidden=moderator viewPost.hidden=moderator
retrievePost=anonymous retrievePost=anonymous
favoritePost=registered favoritePost=registered
addPost=registered
addPostSafety=registered
addPostTags=registered
addPostThumb=power-user
addPostSource=registered
addPostRelations=power-user
addPostContent=registered
editPost=registered
editPostSafety.own=registered editPostSafety.own=registered
editPostSafety.all=moderator editPostSafety.all=moderator
editPostTags=registered editPostTags=registered
@ -92,6 +101,7 @@ editPostSource=moderator
editPostRelations.own=registered editPostRelations.own=registered
editPostRelations.all=moderator editPostRelations.all=moderator
editPostContent=moderator editPostContent=moderator
massTag.own=registered massTag.own=registered
massTag.all=power-user massTag.all=power-user
hidePost=moderator hidePost=moderator

View file

@ -86,7 +86,7 @@ class Access
public static function assert(Privilege $privilege, $user = null) public static function assert(Privilege $privilege, $user = null)
{ {
if (!self::check($privilege, $user)) if (!self::check($privilege, $user))
self::fail(); self::fail('Insufficient privileges (' . $privilege->toString() . ')');
} }
public static function assertEmailConfirmation($user = null) public static function assertEmailConfirmation($user = null)
@ -95,9 +95,9 @@ class Access
self::fail('Need e-mail address confirmation to continue'); self::fail('Need e-mail address confirmation to continue');
} }
public static function fail($message = 'Insufficient privileges') public static function fail($message)
{ {
throw new SimpleException($message); throw new AccessException($message);
} }
public static function getIdentity($user) public static function getIdentity($user)

4
src/AccessException.php Normal file
View file

@ -0,0 +1,4 @@
<?php
class AccessException extends SimpleException
{
}

View file

@ -1,6 +1,10 @@
<?php <?php
abstract class AbstractJob abstract class AbstractJob
{ {
const CONTEXT_NORMAL = 1;
const CONTEXT_BATCH_EDIT = 2;
const CONTEXT_BATCH_ADD = 3;
const COMMENT_ID = 'comment-id'; const COMMENT_ID = 'comment-id';
const LOG_ID = 'log-id'; const LOG_ID = 'log-id';
@ -21,6 +25,7 @@ abstract class AbstractJob
const STATE = 'state'; const STATE = 'state';
protected $arguments = []; protected $arguments = [];
protected $context = self::CONTEXT_NORMAL;
public function prepare() public function prepare()
{ {
@ -28,6 +33,11 @@ abstract class AbstractJob
public abstract function execute(); public abstract function execute();
public function isSatisfied()
{
return true;
}
public function requiresAuthentication() public function requiresAuthentication()
{ {
return false; return false;
@ -43,6 +53,16 @@ abstract class AbstractJob
return false; return false;
} }
public function getContext()
{
return $this->context;
}
public function setContext($context)
{
$this->context = $context;
}
public function getArgument($key) public function getArgument($key)
{ {
if (!$this->hasArgument($key)) if (!$this->hasArgument($key))

View file

@ -8,6 +8,10 @@ final class Api
return \Chibi\Database::transaction(function() use ($job, $jobArgs) return \Chibi\Database::transaction(function() use ($job, $jobArgs)
{ {
$job->setArguments($jobArgs); $job->setArguments($jobArgs);
if (!$job->isSatisfied())
throw new ApiJobUnsatisfiedException($job);
$job->prepare(); $job->prepare();
self::checkPrivileges($job); self::checkPrivileges($job);

View file

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

View file

@ -1,11 +0,0 @@
<?php
abstract class AbstractPostEditJob extends AbstractPostJob
{
protected $skipSaving = false;
public function skipSaving()
{
$this->skipSaving = true;
return $this;
}
}

View file

@ -1,11 +0,0 @@
<?php
abstract class AbstractUserEditJob extends AbstractUserJob
{
protected $skipSaving = false;
public function skipSaving()
{
$this->skipSaving = true;
return $this;
}
}

View file

@ -6,7 +6,6 @@ class AddPostJob extends AbstractJob
public function execute() public function execute()
{ {
$post = PostModel::spawn(); $post = PostModel::spawn();
Logger::bufferChanges();
//basic stuff //basic stuff
$anonymous = $this->getArgument(self::ANONYMOUS); $anonymous = $this->getArgument(self::ANONYMOUS);
@ -20,14 +19,16 @@ class AddPostJob extends AbstractJob
//warning: it uses internally the same privileges as post editing //warning: it uses internally the same privileges as post editing
$arguments = $this->getArguments(); $arguments = $this->getArguments();
$arguments[EditPostJob::POST_ENTITY] = $post; $arguments[EditPostJob::POST_ENTITY] = $post;
Api::run((new EditPostJob)->skipSaving(), $arguments);
Logger::bufferChanges();
$job = new EditPostJob();
$job->setContext(AbstractJob::CONTEXT_BATCH_ADD);
Api::run($job, $arguments);
Logger::setBuffer([]);
//save to db //save to db
PostModel::save($post); PostModel::save($post);
//clean edit log
Logger::setBuffer([]);
//log //log
Logger::log('{user} added {post} (tags: {tags}, safety: {safety}, source: {source})', [ Logger::log('{user} added {post} (tags: {tags}, safety: {safety}, source: {source})', [
'user' => ($anonymous and !getConfig()->misc->logAnonymousUploads) 'user' => ($anonymous and !getConfig()->misc->logAnonymousUploads)
@ -46,7 +47,7 @@ class AddPostJob extends AbstractJob
public function requiresPrivilege() public function requiresPrivilege()
{ {
return new Privilege(Privilege::UploadPost); return new Privilege(Privilege::AddPost);
} }
public function requiresConfirmedEmail() public function requiresConfirmedEmail()

View file

@ -20,7 +20,9 @@ class AddUserJob extends AbstractJob
Logger::bufferChanges(); Logger::bufferChanges();
Access::disablePrivilegeChecking(); Access::disablePrivilegeChecking();
Api::run((new EditUserJob)->skipSaving(), $arguments); $job = new EditUserJob();
$job->setContext(self::CONTEXT_BATCH_ADD);
Api::run($job, $arguments);
Access::enablePrivilegeChecking(); Access::enablePrivilegeChecking();
Logger::setBuffer([]); Logger::setBuffer([]);

View file

@ -1,9 +1,15 @@
<?php <?php
class EditPostContentJob extends AbstractPostEditJob class EditPostContentJob extends AbstractPostJob
{ {
const POST_CONTENT = 'post-content'; const POST_CONTENT = 'post-content';
const POST_CONTENT_URL = 'post-content-url'; const POST_CONTENT_URL = 'post-content-url';
public function isSatisfied()
{
return $this->hasArgument(self::POST_CONTENT)
or $this->hasArgument(self::POST_CONTENT_URL);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->post;
@ -19,7 +25,7 @@ class EditPostContentJob extends AbstractPostEditJob
$post->setContentFromPath($file->filePath, $file->fileName); $post->setContentFromPath($file->filePath, $file->fileName);
} }
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
PostModel::save($post); PostModel::save($post);
Logger::log('{user} changed contents of {post}', [ Logger::log('{user} changed contents of {post}', [
@ -32,7 +38,9 @@ class EditPostContentJob extends AbstractPostEditJob
public function requiresPrivilege() public function requiresPrivilege()
{ {
return new Privilege( return new Privilege(
Privilege::EditPostContent, $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostContent
: Privilege::EditPostContent,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->post->getUploader()));
} }
} }

View file

@ -1,5 +1,5 @@
<?php <?php
class EditPostJob extends AbstractPostEditJob class EditPostJob extends AbstractPostJob
{ {
public function execute() public function execute()
{ {
@ -19,8 +19,9 @@ class EditPostJob extends AbstractPostEditJob
foreach ($subJobs as $subJob) foreach ($subJobs as $subJob)
{ {
if ($this->skipSaving) $subJob->setContext($this->getContext() == self::CONTEXT_BATCH_ADD
$subJob->skipSaving(); ? self::CONTEXT_BATCH_ADD
: self::CONTEXT_BATCH_EDIT);
$args = $this->getArguments(); $args = $this->getArguments();
$args[self::POST_ENTITY] = $post; $args[self::POST_ENTITY] = $post;
@ -28,15 +29,24 @@ class EditPostJob extends AbstractPostEditJob
{ {
Api::run($subJob, $args); Api::run($subJob, $args);
} }
catch (ApiMissingArgumentException $e) catch (ApiJobUnsatisfiedException $e)
{ {
} }
} }
if (!$this->skipSaving) if ($this->getContext() == AbstractJob::CONTEXT_NORMAL)
PostModel::save($post); PostModel::save($post);
Logger::flush(); Logger::flush();
return $post; return $post;
} }
public function requiresPrivilege()
{
return new Privilege(
$this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPost
: Privilege::EditPost,
Access::getIdentity($this->post->getUploader()));
}
} }

View file

@ -1,8 +1,13 @@
<?php <?php
class EditPostRelationsJob extends AbstractPostEditJob class EditPostRelationsJob extends AbstractPostJob
{ {
const RELATED_POST_IDS = 'related-post-ids'; const RELATED_POST_IDS = 'related-post-ids';
public function isSatisfied()
{
return $this->hasArgument(self::RELATED_POST_IDS);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->post;
@ -12,7 +17,7 @@ class EditPostRelationsJob extends AbstractPostEditJob
$post->setRelationsFromText($relations); $post->setRelationsFromText($relations);
$newRelatedIds = array_map(function($post) { return $post->getId(); }, $post->getRelations()); $newRelatedIds = array_map(function($post) { return $post->getId(); }, $post->getRelations());
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
PostModel::save($post); PostModel::save($post);
foreach (array_diff($oldRelatedIds, $newRelatedIds) as $post2id) foreach (array_diff($oldRelatedIds, $newRelatedIds) as $post2id)
@ -37,7 +42,9 @@ class EditPostRelationsJob extends AbstractPostEditJob
public function requiresPrivilege() public function requiresPrivilege()
{ {
return new Privilege( return new Privilege(
Privilege::EditPostRelations, $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostRelations
: Privilege::EditPostRelations,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->post->getUploader()));
} }
} }

View file

@ -1,8 +1,13 @@
<?php <?php
class EditPostSafetyJob extends AbstractPostEditJob class EditPostSafetyJob extends AbstractPostJob
{ {
const SAFETY = 'safety'; const SAFETY = 'safety';
public function isSatisfied()
{
return $this->hasArgument(self::SAFETY);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->post;
@ -11,7 +16,7 @@ class EditPostSafetyJob extends AbstractPostEditJob
$oldSafety = $post->getSafety(); $oldSafety = $post->getSafety();
$post->setSafety($newSafety); $post->setSafety($newSafety);
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
PostModel::save($post); PostModel::save($post);
if ($oldSafety != $newSafety) if ($oldSafety != $newSafety)
@ -28,7 +33,9 @@ class EditPostSafetyJob extends AbstractPostEditJob
public function requiresPrivilege() public function requiresPrivilege()
{ {
return new Privilege( return new Privilege(
Privilege::EditPostSafety, $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostSafety
: Privilege::EditPostSafety,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->post->getUploader()));
} }
} }

View file

@ -1,8 +1,13 @@
<?php <?php
class EditPostSourceJob extends AbstractPostEditJob class EditPostSourceJob extends AbstractPostJob
{ {
const SOURCE = 'source'; const SOURCE = 'source';
public function isSatisfied()
{
return $this->hasArgument(self::SOURCE);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->post;
@ -11,7 +16,7 @@ class EditPostSourceJob extends AbstractPostEditJob
$oldSource = $post->source; $oldSource = $post->source;
$post->setSource($newSource); $post->setSource($newSource);
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
PostModel::save($post); PostModel::save($post);
if ($oldSource != $newSource) if ($oldSource != $newSource)
@ -28,7 +33,9 @@ class EditPostSourceJob extends AbstractPostEditJob
public function requiresPrivilege() public function requiresPrivilege()
{ {
return new Privilege( return new Privilege(
Privilege::EditPostSource, $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostSource
: Privilege::EditPostSource,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->post->getUploader()));
} }
} }

View file

@ -1,6 +1,11 @@
<?php <?php
class EditPostTagsJob extends AbstractPostEditJob class EditPostTagsJob extends AbstractPostJob
{ {
public function isSatisfied()
{
return $this->hasArgument(self::TAG_NAMES);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->post;
@ -10,7 +15,7 @@ class EditPostTagsJob extends AbstractPostEditJob
$post->setTagsFromText($tags); $post->setTagsFromText($tags);
$newTags = array_map(function($tag) { return $tag->getName(); }, $post->getTags()); $newTags = array_map(function($tag) { return $tag->getName(); }, $post->getTags());
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
{ {
PostModel::save($post); PostModel::save($post);
TagModel::removeUnused(); TagModel::removeUnused();
@ -38,7 +43,9 @@ class EditPostTagsJob extends AbstractPostEditJob
public function requiresPrivilege() public function requiresPrivilege()
{ {
return new Privilege( return new Privilege(
Privilege::EditPostTags, $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostTags
: Privilege::EditPostTags,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->post->getUploader()));
} }
} }

View file

@ -1,8 +1,13 @@
<?php <?php
class EditPostThumbJob extends AbstractPostEditJob class EditPostThumbJob extends AbstractPostJob
{ {
const THUMB_CONTENT = 'thumb-content'; const THUMB_CONTENT = 'thumb-content';
public function isSatisfied()
{
return $this->hasArgument(self::THUMB_CONTENT);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->post;
@ -10,7 +15,7 @@ class EditPostThumbJob extends AbstractPostEditJob
$post->setCustomThumbnailFromPath($file->filePath); $post->setCustomThumbnailFromPath($file->filePath);
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
PostModel::save($post); PostModel::save($post);
Logger::log('{user} changed thumb of {post}', [ Logger::log('{user} changed thumb of {post}', [
@ -23,7 +28,9 @@ class EditPostThumbJob extends AbstractPostEditJob
public function requiresPrivilege() public function requiresPrivilege()
{ {
return new Privilege( return new Privilege(
Privilege::EditPostThumb, $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostThumb
: Privilege::EditPostThumb,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->post->getUploader()));
} }
} }

View file

@ -1,8 +1,13 @@
<?php <?php
class EditUserAccessRankJob extends AbstractUserEditJob class EditUserAccessRankJob extends AbstractUserJob
{ {
const NEW_ACCESS_RANK = 'new-access-rank'; const NEW_ACCESS_RANK = 'new-access-rank';
public function isSatisfied()
{
return $this->hasArgument(self::NEW_ACCESS_RANK);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->user;
@ -14,7 +19,7 @@ class EditUserAccessRankJob extends AbstractUserEditJob
$user->setAccessRank($newAccessRank); $user->setAccessRank($newAccessRank);
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
UserModel::save($user); UserModel::save($user);
Logger::log('{user} changed {subject}\'s access rank to {rank}', [ Logger::log('{user} changed {subject}\'s access rank to {rank}', [

View file

@ -1,8 +1,13 @@
<?php <?php
class EditUserEmailJob extends AbstractUserEditJob class EditUserEmailJob extends AbstractUserJob
{ {
const NEW_EMAIL = 'new-email'; const NEW_EMAIL = 'new-email';
public function isSatisfied()
{
return $this->hasArgument(self::NEW_EMAIL);
}
public function execute() public function execute()
{ {
if (getConfig()->registration->needEmailForRegistering) if (getConfig()->registration->needEmailForRegistering)
@ -29,7 +34,7 @@ class EditUserEmailJob extends AbstractUserEditJob
$user->confirmEmail(); $user->confirmEmail();
} }
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
UserModel::save($user); UserModel::save($user);
Logger::log('{user} changed {subject}\'s e-mail to {mail}', [ Logger::log('{user} changed {subject}\'s e-mail to {mail}', [

View file

@ -1,5 +1,5 @@
<?php <?php
class EditUserJob extends AbstractUserEditJob class EditUserJob extends AbstractUserJob
{ {
protected $subJobs; protected $subJobs;
@ -25,7 +25,7 @@ class EditUserJob extends AbstractUserEditJob
Api::checkPrivileges($subJob); Api::checkPrivileges($subJob);
return true; return true;
} }
catch (SimpleException $e) catch (AccessException $e)
{ {
} }
} }
@ -40,8 +40,9 @@ class EditUserJob extends AbstractUserEditJob
foreach ($this->subJobs as $subJob) foreach ($this->subJobs as $subJob)
{ {
if ($this->skipSaving) $subJob->setContext($this->getContext() == self::CONTEXT_BATCH_ADD
$subJob->skipSaving(); ? self::CONTEXT_BATCH_ADD
: self::CONTEXT_BATCH_EDIT);
$args = $this->getArguments(); $args = $this->getArguments();
$args[self::USER_ENTITY] = $user; $args[self::USER_ENTITY] = $user;
@ -49,12 +50,12 @@ class EditUserJob extends AbstractUserEditJob
{ {
Api::run($subJob, $args); Api::run($subJob, $args);
} }
catch (ApiMissingArgumentException $e) catch (ApiJobUnsatisfiedException $e)
{ {
} }
} }
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
UserModel::save($user); UserModel::save($user);
Logger::flush(); Logger::flush();

View file

@ -1,8 +1,13 @@
<?php <?php
class EditUserNameJob extends AbstractUserEditJob class EditUserNameJob extends AbstractUserJob
{ {
const NEW_USER_NAME = 'new-user-name'; const NEW_USER_NAME = 'new-user-name';
public function isSatisfied()
{
return $this->hasArgument(self::NEW_USER_NAME);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->user;
@ -15,7 +20,7 @@ class EditUserNameJob extends AbstractUserEditJob
$user->setName($newName); $user->setName($newName);
UserModel::validateUserName($user); UserModel::validateUserName($user);
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
UserModel::save($user); UserModel::save($user);
Logger::log('{user} renamed {old} to {new}', [ Logger::log('{user} renamed {old} to {new}', [

View file

@ -1,8 +1,13 @@
<?php <?php
class EditUserPasswordJob extends AbstractUserEditJob class EditUserPasswordJob extends AbstractUserJob
{ {
const NEW_PASSWORD = 'new-password'; const NEW_PASSWORD = 'new-password';
public function isSatisfied()
{
return $this->hasArgument(self::NEW_PASSWORD);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->user;
@ -15,7 +20,7 @@ class EditUserPasswordJob extends AbstractUserEditJob
$user->passHash = $newPasswordHash; $user->passHash = $newPasswordHash;
if (!$this->skipSaving) if ($this->getContext() == self::CONTEXT_NORMAL)
UserModel::save($user); UserModel::save($user);
Logger::log('{user} changed {subject}\'s password', [ Logger::log('{user} changed {subject}\'s password', [

View file

@ -13,7 +13,7 @@ abstract class Enum
public function toDisplayString() public function toDisplayString()
{ {
return TextCaseConverter::convert($this->toString(), return TextCaseConverter::convert($this->toString(),
TextCaseConverter::SNAKE_CASE, TextCaseConverter::CAMEL_CASE,
TextCaseConverter::BLANK_CASE); TextCaseConverter::BLANK_CASE);
} }

View file

@ -2,21 +2,30 @@
class Privilege extends Enum class Privilege extends Enum
{ {
const ListPosts = 1; const ListPosts = 1;
const UploadPost = 2;
const ViewPost = 3; const ViewPost = 3;
const RetrievePost = 4; const RetrievePost = 4;
const FavoritePost = 5; const FavoritePost = 5;
const HidePost = 9;
const DeletePost = 10;
const FeaturePost = 25;
const ScorePost = 31;
const FlagPost = 34;
const EditPost = 45;
const EditPostSafety = 6; const EditPostSafety = 6;
const EditPostTags = 7; const EditPostTags = 7;
const EditPostThumb = 8; const EditPostThumb = 8;
const EditPostSource = 26; const EditPostSource = 26;
const EditPostRelations = 30; const EditPostRelations = 30;
const EditPostContent = 36; const EditPostContent = 36;
const HidePost = 9;
const DeletePost = 10; const AddPost = 2;
const FeaturePost = 25; const AddPostSafety = 39;
const ScorePost = 31; const AddPostTags = 40;
const FlagPost = 34; const AddPostThumb = 41;
const AddPostSource = 42;
const AddPostRelations = 43;
const AddPostContent = 44;
const RegisterAccount = 38; const RegisterAccount = 38;
const ListUsers = 11; const ListUsers = 11;

View file

@ -26,7 +26,7 @@
$activeController == 'post' and $activeAction != 'upload'); $activeController == 'post' and $activeAction != 'upload');
} }
if (Access::check(new Privilege(Privilege::UploadPost))) if (Access::check(new Privilege(Privilege::AddPost)))
{ {
$registerNavItem( $registerNavItem(
'Upload', 'Upload',

View file

@ -59,4 +59,9 @@ class AbstractTest
getConfig()->privileges->$privilege = 'nobody'; getConfig()->privileges->$privilege = 'nobody';
Access::init(); Access::init();
} }
protected function getPath($name)
{
return getConfig()->rootDir . DS . 'tests' . DS . 'TestFiles' . DS . $name;
}
} }

View file

@ -15,9 +15,8 @@ class ApiPrivilegeTest extends AbstractFullApiTest
$this->testRegularPrivilege(new ActivateUserEmailJob(), false); $this->testRegularPrivilege(new ActivateUserEmailJob(), false);
$this->testRegularPrivilege(new AddCommentJob(), new Privilege(Privilege::AddComment)); $this->testRegularPrivilege(new AddCommentJob(), new Privilege(Privilege::AddComment));
$this->testRegularPrivilege(new PreviewCommentJob(), new Privilege(Privilege::AddComment)); $this->testRegularPrivilege(new PreviewCommentJob(), new Privilege(Privilege::AddComment));
$this->testRegularPrivilege(new AddPostJob(), new Privilege(Privilege::UploadPost)); $this->testRegularPrivilege(new AddPostJob(), new Privilege(Privilege::AddPost));
$this->testRegularPrivilege(new AddUserJob(), new Privilege(Privilege::RegisterAccount)); $this->testRegularPrivilege(new AddUserJob(), new Privilege(Privilege::RegisterAccount));
$this->testRegularPrivilege(new EditPostJob(), false);
$this->testRegularPrivilege(new EditUserJob(), false); $this->testRegularPrivilege(new EditUserJob(), false);
$this->testRegularPrivilege(new GetLogJob(), new Privilege(Privilege::ViewLog)); $this->testRegularPrivilege(new GetLogJob(), new Privilege(Privilege::ViewLog));
$this->testRegularPrivilege(new ListCommentsJob(), new Privilege(Privilege::ListComments)); $this->testRegularPrivilege(new ListCommentsJob(), new Privilege(Privilege::ListComments));
@ -42,12 +41,27 @@ class ApiPrivilegeTest extends AbstractFullApiTest
$this->login($this->mockUser()); $this->login($this->mockUser());
$this->testDynamicPostPrivilege(new DeletePostJob(), new Privilege(Privilege::DeletePost)); $this->testDynamicPostPrivilege(new DeletePostJob(), new Privilege(Privilege::DeletePost));
$this->testDynamicPostPrivilege(new EditPostJob(), new Privilege(Privilege::EditPost));
$this->testDynamicPostPrivilege(new EditPostContentJob(), new Privilege(Privilege::EditPostContent)); $this->testDynamicPostPrivilege(new EditPostContentJob(), new Privilege(Privilege::EditPostContent));
$this->testDynamicPostPrivilege(new EditPostRelationsJob(), new Privilege(Privilege::EditPostRelations)); $this->testDynamicPostPrivilege(new EditPostRelationsJob(), new Privilege(Privilege::EditPostRelations));
$this->testDynamicPostPrivilege(new EditPostSafetyJob(), new Privilege(Privilege::EditPostSafety)); $this->testDynamicPostPrivilege(new EditPostSafetyJob(), new Privilege(Privilege::EditPostSafety));
$this->testDynamicPostPrivilege(new EditPostSourceJob(), new Privilege(Privilege::EditPostSource)); $this->testDynamicPostPrivilege(new EditPostSourceJob(), new Privilege(Privilege::EditPostSource));
$this->testDynamicPostPrivilege(new EditPostTagsJob(), new Privilege(Privilege::EditPostTags)); $this->testDynamicPostPrivilege(new EditPostTagsJob(), new Privilege(Privilege::EditPostTags));
$this->testDynamicPostPrivilege(new EditPostThumbJob(), new Privilege(Privilege::EditPostThumb)); $this->testDynamicPostPrivilege(new EditPostThumbJob(), new Privilege(Privilege::EditPostThumb));
$ctx = function($job)
{
$job->setContext(AbstractJob::CONTEXT_BATCH_ADD);
return $job;
};
$this->testDynamicPostPrivilege($ctx(new EditPostJob), new Privilege(Privilege::AddPost));
$this->testDynamicPostPrivilege($ctx(new EditPostContentJob), new Privilege(Privilege::AddPostContent));
$this->testDynamicPostPrivilege($ctx(new EditPostRelationsJob), new Privilege(Privilege::AddPostRelations));
$this->testDynamicPostPrivilege($ctx(new EditPostSafetyJob), new Privilege(Privilege::AddPostSafety));
$this->testDynamicPostPrivilege($ctx(new EditPostSourceJob), new Privilege(Privilege::AddPostSource));
$this->testDynamicPostPrivilege($ctx(new EditPostTagsJob), new Privilege(Privilege::AddPostTags));
$this->testDynamicPostPrivilege($ctx(new EditPostThumbJob), new Privilege(Privilege::AddPostThumb));
$this->testDynamicPostPrivilege(new FeaturePostJob(), new Privilege(Privilege::FeaturePost)); $this->testDynamicPostPrivilege(new FeaturePostJob(), new Privilege(Privilege::FeaturePost));
$this->testDynamicPostPrivilege(new FlagPostJob(), new Privilege(Privilege::FlagPost)); $this->testDynamicPostPrivilege(new FlagPostJob(), new Privilege(Privilege::FlagPost));
$this->testDynamicPostPrivilege(new ScorePostJob(), new Privilege(Privilege::ScorePost)); $this->testDynamicPostPrivilege(new ScorePostJob(), new Privilege(Privilege::ScorePost));

View file

@ -0,0 +1,55 @@
<?php
class AddPostJobTest extends AbstractTest
{
public function testSaving()
{
$this->prepare();
$this->grantAccess('addPost');
$this->grantAccess('addPostSafety');
$this->grantAccess('addPostTags');
$this->grantAccess('addPostSource');
$this->grantAccess('addPostContent');
$args =
[
AddPostJob::ANONYMOUS => false,
EditPostSafetyJob::SAFETY => PostSafety::Safe,
EditPostSourceJob::SOURCE => '',
EditPostContentJob::POST_CONTENT => new ApiFileInput($this->getPath('image.jpg'), 'test.jpg'),
];
$this->assert->doesNotThrow(function() use ($args)
{
Api::run(new AddPostJob(), $args);
});
}
public function testPrivilegeFail()
{
$this->prepare();
$this->grantAccess('addPost');
$this->grantAccess('addPostSafety');
$this->grantAccess('addPostTags');
$this->grantAccess('addPostContent');
$args =
[
AddPostJob::ANONYMOUS => false,
EditPostSafetyJob::SAFETY => PostSafety::Safe,
EditPostSourceJob::SOURCE => '',
EditPostContentJob::POST_CONTENT => new ApiFileInput($this->getPath('image.jpg'), 'test.jpg'),
];
$this->assert->throws(function() use ($args)
{
Api::run(new AddPostJob(), $args);
}, 'Insufficient privilege');
}
protected function prepare()
{
getConfig()->registration->needEmailForUploading = false;
}
}

View file

@ -162,9 +162,4 @@ class EditPostContentJobTest extends AbstractTest
return $post; return $post;
} }
protected function getPath($name)
{
return getConfig()->rootDir . DS . 'tests' . DS . 'TestFiles' . DS . $name;
}
} }

View file

@ -0,0 +1,50 @@
<?php
class EditPostJobTest extends AbstractTest
{
public function testSaving()
{
$this->grantAccess('editPost');
$this->grantAccess('editPostSafety');
$this->grantAccess('editPostTags');
$this->grantAccess('editPostSource');
$this->grantAccess('editPostContent');
$post = $this->mockPost(Auth::getCurrentUser());
$args =
[
EditPostJob::POST_ID => $post->getId(),
EditPostSafetyJob::SAFETY => PostSafety::Safe,
EditPostSourceJob::SOURCE => '',
EditPostContentJob::POST_CONTENT => new ApiFileInput($this->getPath('image.jpg'), 'test.jpg'),
];
$this->assert->doesNotThrow(function() use ($args)
{
Api::run(new EditPostJob(), $args);
});
}
public function testPrivilegeFail()
{
$this->grantAccess('editPost');
$this->grantAccess('editPostSafety');
$this->grantAccess('editPostTags');
$this->grantAccess('editPostContent');
$post = $this->mockPost(Auth::getCurrentUser());
$args =
[
EditPostJob::POST_ID => $post->getId(),
EditPostSafetyJob::SAFETY => PostSafety::Safe,
EditPostSourceJob::SOURCE => '',
EditPostContentJob::POST_CONTENT => new ApiFileInput($this->getPath('image.jpg'), 'test.jpg'),
];
$this->assert->throws(function() use ($args)
{
Api::run(new EditPostJob(), $args);
}, 'Insufficient privilege');
}
}