Commit 0b8d4ffc87fa03c56c0f37762ad8c9c000aa6220

Authored by Alex Savenko
Committed by Alex Savenko
1 parent 8baf4948

Add Roles.

app/library/App/Bootstrap/AclBootstrap.php
... ... @@ -5,6 +5,8 @@ namespace App\Bootstrap;
5 5 use App\BootstrapInterface;
6 6 use App\Constants\Services;
7 7 use Phalcon\Acl;
  8 +use Phalcon\Acl\Resource;
  9 +use Phalcon\Acl\Role;
8 10 use Phalcon\Config;
9 11 use Phalcon\DiInterface;
10 12 use PhalconRest\Api;
... ... @@ -17,17 +19,22 @@ class AclBootstrap implements BootstrapInterface
17 19 /** @var \PhalconApi\Acl\MountingEnabledAdapterInterface $acl */
18 20 $acl = $di->get(Services::ACL);
19 21  
20   - $unauthorizedRole = new Acl\Role(AclRoles::UNAUTHORIZED);
21   - $authorizedRole = new Acl\Role(AclRoles::AUTHORIZED);
  22 + $unauthorizedRole = new Role(AclRoles::UNAUTHORIZED);
  23 + $authorizedRole = new Role(AclRoles::AUTHORIZED);
22 24  
23 25 $acl->addRole($unauthorizedRole);
24 26 $acl->addRole($authorizedRole);
25 27  
26   - $acl->addRole(new Acl\Role(AclRoles::ADMINISTRATOR), $authorizedRole);
27   - $acl->addRole(new Acl\Role(AclRoles::MANAGER), $authorizedRole);
28   - $acl->addRole(new Acl\Role(AclRoles::USER), $authorizedRole);
29   - $acl->addRole(new Acl\Role(AclRoles::EDITOR), $authorizedRole);
30   - $acl->addRole(new Acl\Role(AclRoles::AUTHOR), $authorizedRole);
  28 + $administrator = new Role(AclRoles::ADMINISTRATOR);
  29 + $user = new Role(AclRoles::USER);
  30 + $editor = new Role(AclRoles::EDITOR);
  31 + $author = new Role(AclRoles::AUTHOR);
  32 +
  33 +
  34 + $acl->addRole($administrator, $authorizedRole);
  35 + $acl->addRole($user, $authorizedRole);
  36 + $acl->addRole($editor, $authorizedRole);
  37 + $acl->addRole($author, $authorizedRole);
31 38  
32 39 $acl->mountMany($api->getCollections());
33 40 }
... ...
app/library/App/Constants/AclRoles.php
... ... @@ -9,9 +9,55 @@ class AclRoles
9 9 const AUTHOR = 'Author';
10 10 const EDITOR = 'Editor';
11 11 const USER = 'User';
12   - const MANAGER = 'Manager';
13 12 const ADMINISTRATOR = 'Administrator';
14 13  
15   - const ALL_ROLES = [self::UNAUTHORIZED, self::AUTHORIZED, self::USER, self::MANAGER, self::ADMINISTRATOR];
16   - const ALL_REAL_ROLES = [self::AUTHOR, self::EDITOR, self::USER, self::MANAGER, self::ADMINISTRATOR];
  14 + const ALL_ROLES = [
  15 + self::UNAUTHORIZED,
  16 + self::AUTHORIZED,
  17 + self::AUTHOR,
  18 + self::EDITOR,
  19 + self::USER,
  20 + self::ADMINISTRATOR
  21 + ];
  22 +
  23 + const ALL_REAL_ROLES = [
  24 + self::AUTHOR,
  25 + self::EDITOR,
  26 + self::USER,
  27 + self::ADMINISTRATOR
  28 + ];
  29 +
  30 + /**
  31 + * Check if $role can remove user with role $role_to_remove
  32 + *
  33 + * @param $role
  34 + * @param $role_to_remove
  35 + * @return bool
  36 + */
  37 + static public function access_user_delete($role, $role_to_remove)
  38 + {
  39 + $is_accessible = true;
  40 + switch ($role)
  41 + {
  42 + case self::AUTHOR:
  43 + if (in_array($role_to_remove, [self::EDITOR, self::USER, self::ADMINISTRATOR]))
  44 + {
  45 + $is_accessible = false;
  46 + }
  47 + break;
  48 + case self::EDITOR:
  49 + if (in_array($role_to_remove, [self::USER, self::ADMINISTRATOR]))
  50 + {
  51 + $is_accessible = false;
  52 + }
  53 + break;
  54 + case self::USER:
  55 + if (in_array($role_to_remove, [self::ADMINISTRATOR]))
  56 + {
  57 + $is_accessible = false;
  58 + }
  59 + break;
  60 + }
  61 + return $is_accessible;
  62 + }
17 63 }
18 64 \ No newline at end of file
... ...
app/library/App/Controllers/ProjectController.php 0 โ†’ 100644
  1 +<?php
  2 +
  3 +namespace App\Controllers;
  4 +
  5 +
  6 +use App\Constants\AclRoles;
  7 +use App\Model\Project;
  8 +use App\Model\User;
  9 +use App\Model\UserProject;
  10 +use PhalconApi\Constants\ErrorCodes;
  11 +use PhalconApi\Exception;
  12 +use PhalconRest\Mvc\Controllers\CrudResourceController;
  13 +
  14 +class ProjectController extends CrudResourceController
  15 +{
  16 + /**
  17 + * ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ะฒัะต ะฟั€ะพัะบั‚ั‹ ะทะฐะปะพะณะธะฝะตะฝะพะณะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั
  18 + *
  19 + * @return mixed
  20 + * @throws Exception
  21 + */
  22 + public function allAction()
  23 + {
  24 + $user_id = $this->userService->getIdentity();
  25 + $projects = Project::find(["user_id = '$user_id'"]);
  26 + if (count($projects) == 0)
  27 + {
  28 + $projects = User::findFirst([$user_id])->projects;
  29 + if (count($projects) == 0)
  30 + {
  31 + throw new Exception(ErrorCodes::GENERAL_NOT_FOUND, 'Projects not found');
  32 + }
  33 + else
  34 + {
  35 + var_dump($projects);
  36 + return $this->createArrayResponse($projects, 'projects');
  37 + }
  38 + }
  39 + else
  40 + {
  41 + return $this->createArrayResponse($projects, 'projects');
  42 + }
  43 + }
  44 +
  45 + /**
  46 + * @param $data
  47 + * @param $isUpdate
  48 + * @return bool
  49 + * @throws Exception
  50 + */
  51 + public function postDataValid($data, $isUpdate)
  52 + {
  53 + if ($isUpdate)
  54 + {
  55 + if (isset($data['user_id']))
  56 + {
  57 + throw new Exception(ErrorCodes::ACCESS_DENIED, 'Find user_id value in post-data. Operation is not allowed.');
  58 + }
  59 + return true;
  60 + }
  61 + else
  62 + {
  63 + if (isset($data['user_id']))
  64 + {
  65 + throw new Exception(ErrorCodes::ACCESS_DENIED, 'Find user_id value in post-data. Operation is not allowed.');
  66 + }
  67 + return true;
  68 + }
  69 + }
  70 +
  71 + /**
  72 + *
  73 + * @param Project $item
  74 + */
  75 + protected function beforeCreate(Project $item)
  76 + {
  77 + $user_id = $this->userService->getIdentity();
  78 + $item->user_id = $user_id;
  79 + }
  80 +
  81 + /**
  82 + * @param Project $item
  83 + * @return bool|void
  84 + */
  85 + protected function afterCreate(Project $item)
  86 + {
  87 + $data = ['project_id' => $item->id, 'user_id' => $item->user_id];
  88 + $junction = new UserProject();
  89 + $junction->user_id = $item->user_id;
  90 + $junction->project_id = $item->id;
  91 + if (!$junction->save())
  92 + {
  93 + return $this->onCreateFailed($junction, $data);
  94 + }
  95 + return true;
  96 + }
  97 +
  98 + /**
  99 + * @param $id
  100 + * @throws Exception
  101 + */
  102 + protected function beforeHandleUpdate($id)
  103 + {
  104 + $user_id = $this->userService->getIdentity();
  105 +
  106 + if(!UserProject::findFirst(["user_id = '$user_id'"]) && $this->userService->getRole() !== AclRoles::ADMINISTRATOR)
  107 + {
  108 + throw new Exception(ErrorCodes::ACCESS_DENIED, 'Operation is not allowed');
  109 + }
  110 + }
  111 +
  112 + /**
  113 + * @param $id
  114 + * @throws Exception
  115 + */
  116 + protected function beforeHandleRemove($id)
  117 + {
  118 + $project = Project::findFirst($id)->id;
  119 +
  120 + if (empty($project))
  121 + {
  122 + throw new Exception(ErrorCodes::GENERAL_NOT_FOUND, 'Project with `id`='.$id.' not found');
  123 + }
  124 +
  125 + $user_id = $this->userService->getIdentity();
  126 +
  127 + $project = Project::findFirst(["user_id = '$user_id' AND id = '$id'"]);
  128 +
  129 + if (empty($project) && $this->userService->getRole() !== AclRoles::ADMINISTRATOR)
  130 + {
  131 + throw new Exception(ErrorCodes::ACCESS_DENIED, 'Operation is not allowed');
  132 + }
  133 + else
  134 + {
  135 + $project_links = UserProject::find(["project_id = '$id'"]);
  136 + foreach ($project_links as $project_link) {
  137 + $this->removeItem($project_link);
  138 + }
  139 + }
  140 + }
  141 +}
0 142 \ No newline at end of file
... ...
app/library/App/Controllers/UserController.php
... ... @@ -2,6 +2,14 @@
2 2  
3 3 namespace App\Controllers;
4 4  
  5 +use App\Auth\UsernameAccountType;
  6 +use App\Constants\AclRoles;
  7 +use App\Model\Project;
  8 +use App\Model\User;
  9 +use App\Model\UserProject;
  10 +use App\Transformers\UserTransformer;
  11 +use PhalconApi\Constants\ErrorCodes;
  12 +use PhalconApi\Exception;
5 13 use PhalconRest\Mvc\Controllers\CrudResourceController;
6 14  
7 15 class UserController extends CrudResourceController
... ... @@ -22,6 +30,48 @@ class UserController extends CrudResourceController
22 30 }
23 31  
24 32 /**
  33 + * ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ะฒัะตั… ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝะฝั‹ั… ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน c ั€ะพะปัŒัŽ AclRoles::EDITOR
  34 + *
  35 + * @return mixed
  36 + */
  37 + public function editorsAction()
  38 + {
  39 + $current_projects = $this->userService->getDetails()->projects;
  40 + $editors = [];
  41 + foreach ($current_projects as $project)
  42 + {
  43 + foreach ($project->users as $user) {
  44 + if ($user->role == AclRoles::EDITOR)
  45 + {
  46 + $editors[$project->id][] = $this->createItemResponse($user, new UserTransformer());
  47 + }
  48 + }
  49 + }
  50 + return $this->createResponse($editors);
  51 + }
  52 +
  53 + /**
  54 + * ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ะฒัะตั… ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝะฝั‹ั… ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน c ั€ะพะปัŒัŽ AclRoles::AUTHOR
  55 + *
  56 + * @return mixed
  57 + */
  58 + public function authorsAction()
  59 + {
  60 + $current_projects = $this->userService->getDetails()->projects;
  61 + $authors = [];
  62 + foreach ($current_projects as $project)
  63 + {
  64 + foreach ($project->users as $user) {
  65 + if ($user->role == AclRoles::AUTHOR)
  66 + {
  67 + $authors[$project->id][] = $this->createItemResponse($user, new UserTransformer());
  68 + }
  69 + }
  70 + }
  71 + return $this->createResponse($authors);
  72 + }
  73 +
  74 + /**
25 75 * ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ั‚ะตะบัƒั‰ะตะณะพ ะทะฐะปะพะณะธะฝะตะฝะฝะพะณะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั
26 76 *
27 77 * @return mixed
... ... @@ -32,6 +82,46 @@ class UserController extends CrudResourceController
32 82 }
33 83  
34 84 /**
  85 + * ะ˜ะทะผะตะฝะตะฝะธะต ะดะฐะฝะฝั‹ั… ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั
  86 + *
  87 + * @param $id
  88 + * @throws Exception
  89 + */
  90 + public function updateAction($id)
  91 + {
  92 + if ($this->userService->getRole() == AclRoles::ADMINISTRATOR || $id == $this->userService->getIdentity())
  93 + {
  94 + return $this->update($id);
  95 + }
  96 + else
  97 + {
  98 + throw new Exception(ErrorCodes::ACCESS_DENIED, 'Operation is not allowed');
  99 + }
  100 + }
  101 +
  102 + /**
  103 + * ะฃะดะฐะปะตะฝะธะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั
  104 + *
  105 + * @param $id
  106 + * @throws Exception
  107 + */
  108 + public function removeAction($id)
  109 + {
  110 + $user_role = $this->userService->getRole();
  111 + $user_id = $this->userService->getIdentity();
  112 + $role_to_delete = User::findFirst($id)->role;
  113 +
  114 + if (AclRoles::access_user_delete($user_role, $role_to_delete) || $user_id == $id)
  115 + {
  116 + return $this->remove($id);
  117 + }
  118 + else
  119 + {
  120 + throw new Exception(ErrorCodes::ACCESS_DENIED, 'Operation is not allowed');
  121 + }
  122 + }
  123 +
  124 + /**
35 125 * ะะฒั‚ะพั€ะธะทะฐั†ะธั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั ั‡ะตั€ะตะท BasicAuth ะธ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ั‚ะพะบะตะฝ ะดะพัั‚ัƒะฟะฐ
36 126 *
37 127 * @return mixed
... ... @@ -41,13 +131,13 @@ class UserController extends CrudResourceController
41 131 $username = $this->request->getUsername();
42 132 $password = $this->request->getPassword();
43 133  
44   - $session = $this->authManager->loginWithUsernamePassword(\App\Auth\UsernameAccountType::NAME, $username,
  134 + $session = $this->authManager->loginWithUsernamePassword(UsernameAccountType::NAME, $username,
45 135 $password);
46 136  
47   - $transformer = new \App\Transformers\UserTransformer;
  137 + $transformer = new UserTransformer;
48 138 $transformer->setModelClass('App\Model\User');
49 139  
50   - $user = $this->createItemResponse(\App\Model\User::findFirst($session->getIdentity()), $transformer);
  140 + $user = $this->createItemResponse(User::findFirst($session->getIdentity()), $transformer);
51 141  
52 142 $response = [
53 143 'token' => $session->getToken(),
... ... @@ -63,7 +153,8 @@ class UserController extends CrudResourceController
63 153 *
64 154 * @return mixed
65 155 */
66   - public function registerAction() {
  156 + public function registerAction()
  157 + {
67 158  
68 159 $this->beforeHandle();
69 160 $this->beforeHandleWrite();
... ... @@ -106,16 +197,72 @@ class UserController extends CrudResourceController
106 197 }
107 198  
108 199 /**
  200 + * ะŸั€ะธะณะปะฐัˆะตะฝะธะต ััƒั‰ะตัั‚ะฒัƒัŽั‰ะตะณะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั ะฒ ะฟั€ะพัะบั‚
  201 + *
  202 + * @throws Exception
  203 + */
  204 + public function inviteAction()
  205 + {
  206 + $user_id = $this->request->get('user_id');
  207 + $project_id = $this->request->get('project_id');
  208 +
  209 + if (empty($user_id) || empty($project_id))
  210 + {
  211 + throw new Exception(ErrorCodes::DATA_NOT_FOUND, 'Empty post-data');
  212 + }
  213 + elseif (!User::findFirst($user_id))
  214 + {
  215 + throw new Exception(ErrorCodes::GENERAL_NOT_FOUND, 'User with requested id not found');
  216 + }
  217 + elseif (!Project::findFirst($project_id))
  218 + {
  219 + throw new Exception(ErrorCodes::GENERAL_NOT_FOUND, 'Project with requested id not found');
  220 + }
  221 + elseif (UserProject::findFirst(["user_id = '$user_id' AND project_id = '$project_id'"]))
  222 + {
  223 + throw new Exception(ErrorCodes::POST_DATA_INVALID, 'User already invited');
  224 + }
  225 + else
  226 + {
  227 + $userProject = new UserProject();
  228 + $data = ['project_id' => $project_id, 'user_id' => $user_id];
  229 + $userProject->user_id = $user_id;
  230 + $userProject->project_id = $project_id;
  231 + if (!$userProject->save())
  232 + {
  233 + return $this->onCreateFailed($userProject, $data);
  234 + }
  235 + else
  236 + {
  237 + return $this->createResponse($data);
  238 + }
  239 + }
  240 + }
  241 +
  242 + /**
109 243 * ะŸะตั€ะตะพะฟั€ะตะดะตะปะตะฝะธะต ะฒั…ะพะดะฝั‹ั… ะดะฐะฝะฝั‹ั…
110 244 *
111 245 * @param $data
112 246 * @return array
  247 + * @throws Exception
113 248 */
114 249 protected function transformPostData($data)
115 250 {
116 251 $result = [];
117 252  
118   - foreach ($data as $key => $value) {
  253 + foreach ($data as $key => $value)
  254 + {
  255 + /** --- ะœะตะฝัั‚ัŒ ั€ะพะปะธ ะผะพะถะตั‚ ั‚ะพะปัŒะบะพ ะฐะดะผะธะฝ ---- **/
  256 + if ($this->userService->getRole() !== AclRoles::ADMINISTRATOR && $key == 'role')
  257 + {
  258 + $msg = 'You have not access for field `role`';
  259 + throw new Exception(
  260 + ErrorCodes::POST_DATA_INVALID,
  261 + $msg,
  262 + ['post data field' => $key, 'value' => $value]
  263 + );
  264 + }
  265 + /** -------------------------------------- **/
119 266 $result[$key] = $this->transformPostDataValue($key, $value, $data);
120 267 }
121 268  
... ... @@ -139,4 +286,17 @@ class UserController extends CrudResourceController
139 286 }
140 287 }
141 288  
  289 + /**
  290 + * ะกะพะฟัƒั‚ัั‚ะฒัƒัŽั‰ะตะต ัƒะดะฐะปะตะฝะธะต ะธะท ะฟะตั€ะตะปะธะฝะบะพะฒะพั‡ะฝะพะน ั‚ะฐะฑะปะธั†ั‹ ะฟั€ะพัะบั‚-ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒ
  291 + *
  292 + * @param $id
  293 + */
  294 + protected function beforeHandleRemove($id)
  295 + {
  296 + $junctions = UserProject::findFirst("user_id = '$id'");
  297 + if ($junctions)
  298 + {
  299 + $junctions->delete();
  300 + }
  301 + }
142 302 }
143 303 \ No newline at end of file
... ...
app/library/App/Model/Album.php deleted
1   -<?php
2   -
3   -namespace App\Model;
4   -
5   -class Album extends \App\Mvc\DateTrackingModel
6   -{
7   - public $id;
8   - public $title;
9   -
10   - public function getSource()
11   - {
12   - return 'album';
13   - }
14   -
15   - public function columnMap()
16   - {
17   - return parent::columnMap() + [
18   - 'id' => 'id',
19   - 'title' => 'title'
20   - ];
21   - }
22   -
23   - public function initialize() {
24   -
25   - $this->hasMany('id', Photo::class, 'albumId', [
26   - 'alias' => 'Photos',
27   - ]);
28   - }
29   -}
app/library/App/Model/Photo.php deleted
1   -<?php
2   -
3   -namespace App\Model;
4   -
5   -class Photo extends \App\Mvc\DateTrackingModel
6   -{
7   - public $id;
8   - public $title;
9   - public $albumId;
10   -
11   - public function getSource()
12   - {
13   - return 'photo';
14   - }
15   -
16   - public function columnMap()
17   - {
18   - return parent::columnMap() + [
19   - 'id' => 'id',
20   - 'title' => 'title',
21   - 'album_id' => 'albumId'
22   - ];
23   - }
24   -
25   - public function initialize() {
26   -
27   - $this->belongsTo('albumId', Album::class, 'id', [
28   - 'alias' => 'Album',
29   - ]);
30   - }
31   -}
app/library/App/Model/Project.php
... ... @@ -2,7 +2,11 @@
2 2  
3 3 namespace App\Model;
4 4  
5   -class Project extends \App\Mvc\DateTrackingModel
  5 +use App\Mvc\DateTrackingModel;
  6 +use PhalconApi\Constants\ErrorCodes;
  7 +use PhalconApi\Exception;
  8 +
  9 +class Project extends DateTrackingModel
6 10 {
7 11 public $id;
8 12 public $name;
... ... @@ -31,5 +35,94 @@ class Project extends \App\Mvc\DateTrackingModel
31 35 $this->belongsTo('user_id', User::class, 'id', [
32 36 'alias' => 'User',
33 37 ]);
  38 +
  39 + $this->hasManyToMany(
  40 + 'id',
  41 + UserProject::class,
  42 + 'project_id',
  43 + 'user_id',
  44 + User::class,
  45 + 'id',
  46 + array('alias' => 'users')
  47 + );
34 48 }
  49 +
  50 + /** ------- Getters and Setters ------- **/
  51 +
  52 + /** validation: non-empty, 4+ letters *
  53 + * @param $name
  54 + * @throws Exception
  55 + */
  56 + public function setName($name)
  57 + {
  58 + if (empty($name))
  59 + {
  60 + $msg = 'Post-data is invalid, trying to use empty value of `name`';
  61 + throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['name' => $name]);
  62 + }
  63 + elseif (strlen($name) < 4)
  64 + {
  65 + $msg = 'Post-data is invalid, value of `name` should be more than 4 letters';
  66 + throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['name' => $name]);
  67 + }
  68 +
  69 + $this->name = $name;
  70 + }
  71 +
  72 + /** validation: non-empty, integer *
  73 + * @param $ga_view_id
  74 + * @throws Exception
  75 + */
  76 + public function setGa_view_id($ga_view_id)
  77 + {
  78 + if (empty($ga_view_id))
  79 + {
  80 + $msg = 'Post-data is invalid, trying to use empty value of `ga_view_id`';
  81 + throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['ga_view_id' => $ga_view_id]);
  82 + }
  83 + elseif (!is_integer($ga_view_id))
  84 + {
  85 + $msg = 'Post-data is invalid, type of `ga_view_id` should be integer';
  86 + throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['ga_view_id' => $ga_view_id]);
  87 + }
  88 +
  89 + $this->ga_view_id = $ga_view_id;
  90 + }
  91 +
  92 + /** validation: non-empty, integer *
  93 + * @param $group
  94 + * @throws Exception
  95 + */
  96 + public function setGroup($group)
  97 + {
  98 + if (empty($group))
  99 + {
  100 + $msg = 'Post-data is invalid, trying to use empty value of `group`';
  101 + throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['group' => $group]);
  102 + }
  103 + elseif (!is_integer($group))
  104 + {
  105 + $msg = 'Post-data is invalid, type of `group` should be integer';
  106 + throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['group' => $group]);
  107 + }
  108 +
  109 + $this->group = $group;
  110 + }
  111 +
  112 + public function getName()
  113 + {
  114 + return $this->name;
  115 + }
  116 +
  117 + public function getGa_view_id()
  118 + {
  119 + return $this->ga_view_id;
  120 + }
  121 +
  122 + public function getGroup()
  123 + {
  124 + return $this->group;
  125 + }
  126 +
  127 + /** ----------------------------------- **/
35 128 }
... ...
app/library/App/Model/User.php
... ... @@ -34,19 +34,35 @@ class User extends DateTrackingModel
34 34  
35 35 public function initialize()
36 36 {
37   - $this->hasMany('id', Project::class, 'user_id', [
38   - 'alias' => 'Projects',
39   - ]);
  37 + $this->hasMany(
  38 + 'id',
  39 + Project::class,
  40 + 'user_id',
  41 + [
  42 + 'alias' => 'Projects',
  43 + ]
  44 + );
  45 +
  46 + $this->hasManyToMany(
  47 + 'id',
  48 + UserProject::class,
  49 + 'user_id',
  50 + 'project_id',
  51 + Project::class,
  52 + 'id',
  53 + array('alias' => 'projects')
  54 + );
40 55 }
41 56  
42   - public function getUsername()
43   - {
44   - return $this->username;
45   - }
  57 + /** ------- Getters and Setters ------- **/
  58 +
  59 + /** validation: unique, non-empty, 4+ letters *
  60 + * @param $username
  61 + * @throws Exception
  62 + */
  63 + public function setUsername($username)
  64 + {
46 65  
47   - public function setUsername($username)
48   - {
49   - /** validation: unique, non-empty, 4+ letters **/
50 66 $same_user = User::find(["username = '".$username."'"]);
51 67 if (isset($same_user[0]) && !empty($same_user[0]->username))
52 68 {
... ... @@ -56,45 +72,38 @@ class User extends DateTrackingModel
56 72 elseif (empty($username))
57 73 {
58 74 $msg = 'Post-data is invalid, trying to use empty value of `username`';
59   - throw new Exception(ErrorCodes::DATA_NOT_FOUND, $msg, ['username' => $username]);
  75 + throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['username' => $username]);
60 76 }
61 77 elseif (strlen($username) < 4)
62 78 {
63 79 $msg = 'Post-data is invalid, value of `username` should be more than 4 letters';
64 80 throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['username' => $username]);
65 81 }
66   - /** ---------------------------------------- **/
67 82  
68   - $this->username = $username;
69   - }
  83 + $this->username = $username;
  84 + }
70 85  
71   - public function getEmail()
72   - {
73   - return $this->email;
74   - }
75   -
76   - public function setEmail($email)
77   - {
78   - /** validation: FILTER_VALIDATE_EMAIL **/
  86 + /** validation: FILTER_VALIDATE_EMAIL *
  87 + * @param $email
  88 + * @throws Exception
  89 + */
  90 + public function setEmail($email)
  91 + {
79 92 if (!filter_var($email, FILTER_VALIDATE_EMAIL))
80 93 {
81 94 $msg = 'Post-data is invalid, bad email value';
82 95 throw new Exception(ErrorCodes::POST_DATA_INVALID, $msg, ['email' => $email]);
83 96 }
84   - /** ---------- */
85 97  
86   - $this->email = $email;
87   - }
  98 + $this->email = $email;
  99 + }
88 100  
89   - public function getRole()
90   - {
91   - $service = new Service();
92   - return $service->getRole();
93   - }
94   -
95   - public function setRole($role)
96   - {
97   - /** validation: constant value **/
  101 + /** validation: constant value *
  102 + * @param $role
  103 + * @throws Exception
  104 + */
  105 + public function setRole($role)
  106 + {
98 107 if (!in_array($role, AclRoles::ALL_REAL_ROLES))
99 108 {
100 109 $msg = 'Post-data is invalid, bad `role` value';
... ... @@ -104,9 +113,27 @@ class User extends DateTrackingModel
104 113 ['role' => $role, 'valid values' => AclRoles::ALL_REAL_ROLES]
105 114 );
106 115 }
107   - /** -------------------------- **/
108 116  
109   - $this->role = $role;
110   - }
  117 + $this->role = $role;
  118 + }
  119 +
  120 +
  121 + public function getUsername()
  122 + {
  123 + return $this->username;
  124 + }
  125 +
  126 + public function getEmail()
  127 + {
  128 + return $this->email;
  129 + }
  130 +
  131 + public function getRole()
  132 + {
  133 + $service = new Service();
  134 + return $service->getRole();
  135 + }
  136 +
  137 + /** ----------------------------------- **/
111 138  
112 139 }
... ...
app/library/App/Model/UserProject.php 0 โ†’ 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: Alex Savenko
  5 + * Date: 05.04.2017
  6 + * Time: 18:08
  7 + */
  8 +
  9 +namespace App\Model;
  10 +
  11 +
  12 +use Phalcon\Mvc\Model;
  13 +
  14 +class UserProject extends Model
  15 +{
  16 + public function getSource()
  17 + {
  18 + return 'user_project';
  19 + }
  20 +
  21 + public function initialize()
  22 + {
  23 + $this->belongsTo('project_id', Project::class, 'id',
  24 + array('alias' => 'project')
  25 + );
  26 + $this->belongsTo('user_id', User::class, 'id',
  27 + array('alias' => 'user')
  28 + );
  29 + }
  30 +}
0 31 \ No newline at end of file
... ...
app/library/App/Resources/AlbumResource.php deleted
1   -<?php
2   -
3   -namespace App\Resources;
4   -
5   -use PhalconRest\Api\ApiEndpoint;
6   -use PhalconRest\Api\ApiResource;
7   -use App\Model\Album;
8   -use App\Transformers\AlbumTransformer;
9   -use App\Constants\AclRoles;
10   -use PhalconRest\Mvc\Controllers\CrudResourceController;
11   -
12   -class AlbumResource extends ApiResource {
13   -
14   - public function initialize()
15   - {
16   - $this
17   - ->name('Album')
18   - ->model(Album::class)
19   - ->expectsJsonData()
20   - ->transformer(AlbumTransformer::class)
21   - ->itemKey('album')
22   - ->collectionKey('albums')
23   - ->deny(AclRoles::UNAUTHORIZED)
24   - ->handler(CrudResourceController::class)
25   -
26   - ->endpoint(ApiEndpoint::all())
27   - ->endpoint(ApiEndpoint::create())
28   - ->endpoint(ApiEndpoint::find())
29   - ->endpoint(ApiEndpoint::update())
30   - ->endpoint(ApiEndpoint::remove());
31   - }
32   -}
app/library/App/Resources/PhotoResource.php deleted
1   -<?php
2   -
3   -namespace App\Resources;
4   -
5   -use PhalconRest\Api\ApiEndpoint;
6   -use PhalconRest\Api\ApiResource;
7   -use App\Model\Photo;
8   -use App\Transformers\PhotoTransformer;
9   -use App\Constants\AclRoles;
10   -use PhalconRest\Mvc\Controllers\CrudResourceController;
11   -
12   -class PhotoResource extends ApiResource {
13   -
14   - public function initialize()
15   - {
16   - $this
17   - ->name('Photo')
18   - ->model(Photo::class)
19   - ->expectsJsonData()
20   - ->transformer(PhotoTransformer::class)
21   - ->itemKey('photo')
22   - ->collectionKey('photos')
23   - ->deny(AclRoles::UNAUTHORIZED)
24   - ->handler(CrudResourceController::class)
25   -
26   - ->endpoint(ApiEndpoint::all())
27   - ->endpoint(ApiEndpoint::create())
28   - ->endpoint(ApiEndpoint::find())
29   - ->endpoint(ApiEndpoint::update())
30   - ->endpoint(ApiEndpoint::remove());
31   - }
32   -}
app/library/App/Resources/ProjectResource.php
... ... @@ -8,12 +8,13 @@
8 8  
9 9 namespace App\Resources;
10 10  
  11 +use App\Controllers\ProjectController;
  12 +use PhalconApi\Constants\HttpMethods;
11 13 use PhalconRest\Api\ApiEndpoint;
12 14 use PhalconRest\Api\ApiResource;
13 15 use App\Model\Project;
14 16 use PhalconRest\Transformers\ModelTransformer;
15 17 use App\Constants\AclRoles;
16   -use PhalconRest\Mvc\Controllers\CrudResourceController;
17 18  
18 19 class ProjectResource extends ApiResource {
19 20  
... ... @@ -26,14 +27,60 @@ class ProjectResource extends ApiResource {
26 27 ->transformer(ModelTransformer::class)
27 28 ->itemKey('project')
28 29 ->collectionKey('projects')
29   - ->deny(AclRoles::UNAUTHORIZED)
30   - ->handler(CrudResourceController::class)
31   -
32   - ->endpoint(ApiEndpoint::all())
33   - ->endpoint(ApiEndpoint::create())
34   - ->endpoint(ApiEndpoint::find())
35   - ->endpoint(ApiEndpoint::update())
36   - ->endpoint(ApiEndpoint::remove());
  30 + ->deny(AclRoles::ALL_ROLES)
  31 + ->handler(ProjectController::class)
  32 +
  33 + /** -------------------- [GET] projects ----------------------------- **/
  34 + ->endpoint(ApiEndpoint::factory('/', HttpMethods::GET, 'allAction')
  35 + ->name(ApiEndpoint::ALL)
  36 + ->description('Returns all items')
  37 + ->allow(
  38 + AclRoles::ADMINISTRATOR,
  39 + AclRoles::USER,
  40 + AclRoles::EDITOR,
  41 + AclRoles::AUTHOR
  42 + )
  43 + )
  44 + /** ----------------------------------------------------------------- **/
  45 +
  46 + /** -------------------- [POST] projects ---------------------------- **/
  47 + ->endpoint(ApiEndpoint::factory('/', HttpMethods::POST, 'create')
  48 + ->name(ApiEndpoint::CREATE)
  49 + ->description('Creates a new item using the posted data')
  50 + ->allow(
  51 + AclRoles::ADMINISTRATOR,
  52 + AclRoles::USER
  53 + )
  54 + )
  55 + /** ----------------------------------------------------------------- **/
  56 +
  57 + /** -------------------- [GET] projects/{id} ------------------------ **/
  58 + ->endpoint(ApiEndpoint::find()
  59 + ->allow(AclRoles::ADMINISTRATOR)
  60 + )
  61 + /** ----------------------------------------------------------------- **/
  62 +
  63 + /** -------------------- [PUT] projects/{id} ------------------------ **/
  64 + ->endpoint(ApiEndpoint::factory('/{id}', HttpMethods::PUT, 'update')
  65 + ->name(ApiEndpoint::UPDATE)
  66 + ->description('Updates an existing item identified by {id}, using the posted data')
  67 + ->allow(
  68 + AclRoles::ADMINISTRATOR,
  69 + AclRoles::USER
  70 + )
  71 + )
  72 + /** ----------------------------------------------------------------- **/
  73 +
  74 + /** -------------------- [DELETE] projects/{id} --------------------- **/
  75 + ->endpoint(ApiEndpoint::factory('/{id}', HttpMethods::DELETE, 'remove')
  76 + ->name(ApiEndpoint::REMOVE)
  77 + ->description('Removes the item identified by {id}')
  78 + ->allow(
  79 + AclRoles::ADMINISTRATOR,
  80 + AclRoles::USER
  81 + )
  82 + );
  83 + /** ----------------------------------------------------------------- **/
37 84 }
38 85  
39 86 }
40 87 \ No newline at end of file
... ...
app/library/App/Resources/UserResource.php
... ... @@ -21,53 +21,132 @@ class UserResource extends ApiResource {
21 21 ->transformer(UserTransformer::class)
22 22 ->itemKey('user')
23 23 ->collectionKey('users')
24   - ->deny(AclRoles::UNAUTHORIZED, AclRoles::USER)
25 24 ->handler(UserController::class)
  25 + ->deny(AclRoles::ALL_ROLES)
26 26  
27 27 /** -------------------- [GET] users -------------------------------- **/
28 28 ->endpoint(ApiEndpoint::all()
29   - ->allow(AclRoles::USER)
30 29 ->name('all')
31 30 ->description('ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ะฒัะตั… ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝะฝั‹ั… ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน')
  31 + ->allow(
  32 + AclRoles::ADMINISTRATOR
  33 + )
  34 + )
  35 + /** ----------------------------------------------------------------- **/
  36 +
  37 + /** -------------------- [GET] users/editors ------------------------ **/
  38 + ->endpoint(ApiEndpoint::factory('/editors', HttpMethods::GET, 'editorsAction')
  39 + ->name('all editors')
  40 + ->description('ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ะฒัะตั… ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝะฝั‹ั… ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน c ั€ะพะปัŒัŽ "'.AclRoles::EDITOR.'" ะฟะพ ะบะฐะถะดะพะผัƒ ะฟั€ะพัะบั‚ัƒ')
  41 + ->allow(
  42 + AclRoles::ADMINISTRATOR,
  43 + AclRoles::USER
  44 + )
  45 + ->exampleResponse([
  46 + "68" => [
  47 + [
  48 + "id" => 4,
  49 + "username" => "Tim2",
  50 + "email" => "timTEST2@awd.awd",
  51 + "role" => "Editor",
  52 + "createdAt" => "2017-02-16 19:05:18",
  53 + "updatedAt" => "2017-03-21 14:31:48"
  54 + ],
  55 + [
  56 + "id" => 5,
  57 + "username" => "Tim3",
  58 + "email" => "timTEST3@awd.awd",
  59 + "role" => "Editor",
  60 + "createdAt" => "2017-02-16 19:05:18",
  61 + "updatedAt" => "2017-03-21 14:31:48"
  62 + ]
  63 + ]
  64 + ])
  65 + )
  66 + /** ----------------------------------------------------------------- **/
  67 +
  68 + /** -------------------- [GET] users/authors ------------------------ **/
  69 + ->endpoint(ApiEndpoint::factory('/authors', HttpMethods::GET, 'authorsAction')
  70 + ->name('all authors')
  71 + ->description('ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ะฒัะตั… ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝะฝั‹ั… ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน c ั€ะพะปัŒัŽ "'.AclRoles::AUTHOR.'" ะฟะพ ะบะฐะถะดะพะผัƒ ะฟั€ะพัะบั‚ัƒ')
  72 + ->allow(
  73 + AclRoles::ADMINISTRATOR,
  74 + AclRoles::USER,
  75 + AclRoles::EDITOR
  76 + )
  77 + ->exampleResponse([
  78 + "68" => [
  79 + [
  80 + "id" => 4,
  81 + "username" => "Tim2",
  82 + "email" => "timTEST2@awd.awd",
  83 + "role" => "Author",
  84 + "createdAt" => "2017-02-16 19:05:18",
  85 + "updatedAt" => "2017-03-21 14:31:48"
  86 + ],
  87 + [
  88 + "id" => 5,
  89 + "username" => "Tim3",
  90 + "email" => "timTEST3@awd.awd",
  91 + "role" => "Author",
  92 + "createdAt" => "2017-02-16 19:05:18",
  93 + "updatedAt" => "2017-03-21 14:31:48"
  94 + ]
  95 + ]
  96 + ])
32 97 )
33 98 /** ----------------------------------------------------------------- **/
34 99  
35 100 /** -------------------- [GET] users/me ----------------------------- **/
36 101 ->endpoint(ApiEndpoint::factory('/me', HttpMethods::GET, 'meAction')
37   - ->name('me')
38   - ->description('ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ั‚ะตะบัƒั‰ะตะณะพ ะทะฐะปะพะณะธะฝะตะฝะฝะพะณะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั')
39   - ->allow(AclRoles::USER)
40   - )
  102 + ->name('me')
  103 + ->description('ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ั‚ะตะบัƒั‰ะตะณะพ ะทะฐะปะพะณะธะฝะตะฝะฝะพะณะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั')
  104 + ->allow(
  105 + AclRoles::ADMINISTRATOR,
  106 + AclRoles::USER,
  107 + AclRoles::EDITOR,
  108 + AclRoles::AUTHOR
  109 + )
  110 + )
41 111 /** ----------------------------------------------------------------- **/
42 112  
43 113 /** -------------------- [PUT] users/{id} -------------------------- **/
44   - ->endpoint(ApiEndpoint::update()
45   - ->name('update')
46   - ->description('ะ˜ะทะผะตะฝะตะฝะธะต ะดะฐะฝะฝั‹ั… ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั')
47   - ->allow(AclRoles::ADMINISTRATOR)
48   - ->deny(AclRoles::MANAGER)
49   - ->exampleRequest([
50   - 'role' => 'Manager'
51   - ])
52   - ->exampleResponse([
53   - "result" => "OK",
54   - "user" => [
55   - "id" => 101,
56   - "username" => "qwerty",
57   - "email" => "1a23@awd.awd",
58   - "role" => "Manager",
59   - "createdAt" => "2017-02-16 19:05:18",
60   - "updatedAt" => "2017-03-21 14:31:48"
61   - ]
62   - ])
63   - )
  114 + ->endpoint(ApiEndpoint::factory('/{id}', HttpMethods::PUT, 'updateAction')
  115 + ->name('update')
  116 + ->description('ะ˜ะทะผะตะฝะตะฝะธะต ะดะฐะฝะฝั‹ั… ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั')
  117 + ->allow(
  118 + AclRoles::ADMINISTRATOR,
  119 + AclRoles::USER,
  120 + AclRoles::EDITOR,
  121 + AclRoles::AUTHOR
  122 + )
  123 + ->exampleRequest([
  124 + 'role' => 'User'
  125 + ])
  126 + ->exampleResponse([
  127 + "result" => "OK",
  128 + "user" => [
  129 + "id" => 101,
  130 + "username" => "qwerty",
  131 + "email" => "1a23@awd.awd",
  132 + "role" => "User",
  133 + "createdAt" => "2017-02-16 19:05:18",
  134 + "updatedAt" => "2017-03-21 14:31:48"
  135 + ]
  136 + ])
  137 + )
64 138 /** ----------------------------------------------------------------- **/
65 139  
66 140 /** -------------------- [DELETE] users/{id} ------------------------ **/
67   - ->endpoint(ApiEndpoint::remove()
  141 + ->endpoint(ApiEndpoint::factory('/{id}', HttpMethods::DELETE, 'removeAction')
68 142 ->name('remove')
69 143 ->description('ะฃะดะฐะปะตะฝะธะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั')
70   - ->allow(AclRoles::USER)
  144 + ->allow(
  145 + AclRoles::ADMINISTRATOR,
  146 + AclRoles::USER,
  147 + AclRoles::EDITOR,
  148 + AclRoles::AUTHOR
  149 + )
71 150 ->exampleResponse([
72 151 "result" => "OK"
73 152 ])
... ... @@ -79,7 +158,6 @@ class UserResource extends ApiResource {
79 158 ->name('authenticate')
80 159 ->description('ะะฒั‚ะพั€ะธะทะฐั†ะธั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั ั‡ะตั€ะตะท BasicAuth ะธ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ั‚ะพะบะตะฝ ะดะพัั‚ัƒะฟะฐ')
81 160 ->allow(AclRoles::UNAUTHORIZED)
82   - ->deny(AclRoles::AUTHORIZED)
83 161 ->exampleResponse([
84 162 'data' => [
85 163 'token' => 'co126bbm40wqp41i3bo7pj1gfsvt9lp6',
... ... @@ -99,12 +177,11 @@ class UserResource extends ApiResource {
99 177 )
100 178 /** ----------------------------------------------------------------- **/
101 179  
102   - /** -------------------- [POST] users -------------------------------- **/
  180 + /** -------------------- [POST] users ------------------------------- **/
103 181 ->endpoint(ApiEndpoint::factory('/', HttpMethods::POST, 'registerAction')
104 182 ->name('register')
105 183 ->description('ะ ะตะณะธัั‚ั€ะฐั†ะธั ะฝะพะฒะพะณะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั')
106 184 ->allow(AclRoles::UNAUTHORIZED)
107   - ->deny(AclRoles::AUTHORIZED)
108 185 ->exampleResponse([
109 186 "result" => "OK",
110 187 "user" => [
... ... @@ -118,6 +195,29 @@ class UserResource extends ApiResource {
118 195 ])
119 196 )
120 197 /** ----------------------------------------------------------------- **/
  198 +
  199 + /** -------------------- [POST] users/invite ------------------------ **/
  200 + ->endpoint(ApiEndpoint::factory('/invite', HttpMethods::POST, 'inviteAction')
  201 + ->name('invite')
  202 + ->description('ะŸั€ะธะณะปะฐัˆะตะฝะธะต ััƒั‰ะตัั‚ะฒัƒัŽั‰ะตะณะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั ะฒ ะฟั€ะพัะบั‚')
  203 + ->allow(
  204 + AclRoles::ADMINISTRATOR,
  205 + AclRoles::USER,
  206 + AclRoles::EDITOR
  207 + )
  208 + ->exampleResponse([
  209 + "result" => "OK",
  210 + "user" => [
  211 + "id" => "95",
  212 + "username" => "MyLogin",
  213 + "email" => "myGmail@gmail.com",
  214 + "role" => "User",
  215 + "createdAt" => "2017-02-16 17:57:52",
  216 + "updatedAt" => "2017-02-16 17:57:52"
  217 + ]
  218 + ])
  219 + )
  220 + /** ----------------------------------------------------------------- **/
121 221 ;
122 222 }
123 223 }
124 224 \ No newline at end of file
... ...
app/library/App/Transformers/AlbumTransformer.php deleted
1   -<?php
2   -
3   -namespace App\Transformers;
4   -
5   -use App\Model\Album;
6   -use PhalconRest\Transformers\Transformer;
7   -
8   -class AlbumTransformer extends Transformer
9   -{
10   - protected $availableIncludes = [
11   - 'photos'
12   - ];
13   -
14   - public function includePhotos($album)
15   - {
16   - return $this->collection($album->getPhotos(), new PhotoTransformer);
17   - }
18   -
19   - public function transform(Album $album)
20   - {
21   - return [
22   - 'id' => $this->int($album->id),
23   - 'title' => $album->title,
24   - 'updated_at' => $album->updatedAt,
25   - 'created_at' => $album->createdAt
26   - ];
27   - }
28   -}
app/library/App/Transformers/PhotoTransformer.php deleted
1   -<?php
2   -
3   -namespace App\Transformers;
4   -
5   -use App\Model\Photo;
6   -use PhalconRest\Transformers\ModelTransformer;
7   -
8   -class PhotoTransformer extends ModelTransformer
9   -{
10   - /**
11   - * Transforms are automatically handled
12   - * based on your model when you extend ModelTransformer
13   - * and assign the modelClass property
14   - */
15   - protected $modelClass = Photo::class;
16   -
17   - protected $availableIncludes = [
18   - 'album'
19   - ];
20   -
21   - public function includeAlbum($photo)
22   - {
23   - return $this->item($photo->getAlbum(), new AlbumTransformer());
24   - }
25   -
26   - /**
27   - * You can always transform manually by using
28   - * the following code (below):
29   - *
30   - public function transform(Photo $photo)
31   - {
32   - return [
33   - 'id' => $this->int($photo->id),
34   - 'title' => $photo->title,
35   - 'albumId' => $this->int($photo->albumId)
36   - ];
37   - }
38   - */
39   -}