aboutsummaryrefslogtreecommitdiffhomepage
path: root/main/app/sprinkles/admin/src
diff options
context:
space:
mode:
authorMarvin Borner2018-06-08 20:03:25 +0200
committerMarvin Borner2018-06-08 20:03:25 +0200
commit92b7dd3335a6572debeacfb5faa82c63a5e67888 (patch)
tree7ebbca22595d542ec5e2912a24a0400ac8f6b113 /main/app/sprinkles/admin/src
parent22a1bb27f94ea33042b0bdd35bef1a5cfa96cc0d (diff)
Some minor fixes
Diffstat (limited to 'main/app/sprinkles/admin/src')
-rw-r--r--main/app/sprinkles/admin/src/Admin.php42
-rw-r--r--main/app/sprinkles/admin/src/Controller/ActivityController.php168
-rw-r--r--main/app/sprinkles/admin/src/Controller/AdminController.php296
-rw-r--r--main/app/sprinkles/admin/src/Controller/GroupController.php1426
-rw-r--r--main/app/sprinkles/admin/src/Controller/PermissionController.php404
-rw-r--r--main/app/sprinkles/admin/src/Controller/PostController.php382
-rw-r--r--main/app/sprinkles/admin/src/Controller/RoleController.php1830
-rw-r--r--main/app/sprinkles/admin/src/Controller/SearchController.php112
-rw-r--r--main/app/sprinkles/admin/src/Controller/UserController.php3032
-rw-r--r--main/app/sprinkles/admin/src/Controller/WormholeController.php292
-rw-r--r--main/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php168
-rw-r--r--main/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php156
-rw-r--r--main/app/sprinkles/admin/src/Sprunje/GroupSprunje.php84
-rw-r--r--main/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php180
-rw-r--r--main/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php96
-rw-r--r--main/app/sprinkles/admin/src/Sprunje/RoleSprunje.php132
-rw-r--r--main/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php96
-rw-r--r--main/app/sprinkles/admin/src/Sprunje/UserSprunje.php356
18 files changed, 4626 insertions, 4626 deletions
diff --git a/main/app/sprinkles/admin/src/Admin.php b/main/app/sprinkles/admin/src/Admin.php
index 3aa21f6..efe9816 100644
--- a/main/app/sprinkles/admin/src/Admin.php
+++ b/main/app/sprinkles/admin/src/Admin.php
@@ -1,21 +1,21 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin;
-
-use UserFrosting\System\Sprinkle\Sprinkle;
-
-/**
- * Bootstrapper class for the 'admin' sprinkle.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class Admin extends Sprinkle
-{
-
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin;
+
+use UserFrosting\System\Sprinkle\Sprinkle;
+
+/**
+ * Bootstrapper class for the 'admin' sprinkle.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class Admin extends Sprinkle
+{
+
+}
diff --git a/main/app/sprinkles/admin/src/Controller/ActivityController.php b/main/app/sprinkles/admin/src/Controller/ActivityController.php
index 09675d2..0d43fd8 100644
--- a/main/app/sprinkles/admin/src/Controller/ActivityController.php
+++ b/main/app/sprinkles/admin/src/Controller/ActivityController.php
@@ -1,84 +1,84 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use Slim\Exception\NotFoundException;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Controller class for activity-related requests.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ActivityController extends SimpleController
-{
- /**
- * Returns a list of Activities
- *
- * Generates a list of activities, optionally paginated, sorted and/or filtered.
- * This page requires authentication.
- * Request type: GET
- */
- public function getList($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_activities')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $sprunje = $classMapper->createInstance('activity_sprunje', $classMapper, $params);
- $sprunje->extendQuery(function ($query) {
- return $query->with('user');
- });
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- /**
- * Renders the activity listing page.
- *
- * This page renders a table of user activities.
- * This page requires authentication.
- * Request type: GET
- */
- public function pageList($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_activities')) {
- throw new ForbiddenException();
- }
-
- return $this->ci->view->render($response, 'pages/activities.html.twig');
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Slim\Exception\NotFoundException;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Controller class for activity-related requests.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ActivityController extends SimpleController
+{
+ /**
+ * Returns a list of Activities
+ *
+ * Generates a list of activities, optionally paginated, sorted and/or filtered.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getList($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_activities')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $sprunje = $classMapper->createInstance('activity_sprunje', $classMapper, $params);
+ $sprunje->extendQuery(function ($query) {
+ return $query->with('user');
+ });
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ /**
+ * Renders the activity listing page.
+ *
+ * This page renders a table of user activities.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function pageList($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_activities')) {
+ throw new ForbiddenException();
+ }
+
+ return $this->ci->view->render($response, 'pages/activities.html.twig');
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Controller/AdminController.php b/main/app/sprinkles/admin/src/Controller/AdminController.php
index 91342de..7e4e2f0 100644
--- a/main/app/sprinkles/admin/src/Controller/AdminController.php
+++ b/main/app/sprinkles/admin/src/Controller/AdminController.php
@@ -1,148 +1,148 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use Carbon\Carbon;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Sprinkle\Account\Database\Models\Group;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-use UserFrosting\Sprinkle\Account\Database\Models\Role;
-use UserFrosting\Sprinkle\Core\Database\Models\Version;
-use UserFrosting\Sprinkle\Core\Util\EnvironmentInfo;
-use UserFrosting\Support\Exception\ForbiddenException;
-
-/**
- * AdminController Class
- *
- * Controller class for /dashboard URL. Handles admin-related activities
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AdminController extends SimpleController
-{
-
- /**
- * Renders the admin panel dashboard
- *
- */
- public function pageDashboard($request, $response, $args) {
- //** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_dashboard')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Probably a better way to do this
- $users = $classMapper->staticMethod('user', 'orderBy', 'created_at', 'desc')
- ->take(8)
- ->get();
-
- // Transform the `create_at` date in "x days ago" type of string
- $users->transform(function ($item, $key) {
- $item->registered = Carbon::parse($item->created_at)->diffForHumans();
- return $item;
- });
-
- /** @var Config $config */
- $config = $this->ci->config;
-
- /** @var Config $config */
- $cache = $this->ci->cache;
-
- // Get each sprinkle db version
- $sprinkles = $this->ci->sprinkleManager->getSprinkleNames();
-
- return $this->ci->view->render($response, 'pages/dashboard.html.twig', [
- 'counter' => [
- 'users' => $classMapper->staticMethod('user', 'count'),
- 'roles' => $classMapper->staticMethod('role', 'count'),
- 'groups' => $classMapper->staticMethod('group', 'count')
- ],
- 'info' => [
- 'version' => [
- 'UF' => \UserFrosting\VERSION,
- 'php' => phpversion(),
- 'database' => EnvironmentInfo::database()
- ],
- 'database' => [
- 'name' => $config['db.default.database']
- ],
- 'environment' => $this->ci->environment,
- 'path' => [
- 'project' => \UserFrosting\ROOT_DIR
- ]
- ],
- 'sprinkles' => $sprinkles,
- 'users' => $users
- ]);
- }
-
- /**
- * Clear the site cache.
- *
- * This route requires authentication.
- * Request type: POST
- */
- public function clearCache($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'clear_cache')) {
- throw new ForbiddenException();
- }
-
- // Flush cache
- $this->ci->cache->flush();
-
- /** @var MessageStream $ms */
- $ms = $this->ci->alerts;
-
- $ms->addMessageTranslated('success', 'CACHE.CLEARED');
-
- return $response->withStatus(200);
- }
-
- /**
- * Renders the modal form to confirm cache deletion.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- */
- public function getModalConfirmClearCache($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'clear_cache')) {
- throw new ForbiddenException();
- }
-
- return $this->ci->view->render($response, 'modals/confirm-clear-cache.html.twig', [
- 'form' => [
- 'action' => 'api/dashboard/clear-cache',
- ]
- ]);
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use Carbon\Carbon;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Sprinkle\Account\Database\Models\Group;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\Account\Database\Models\Role;
+use UserFrosting\Sprinkle\Core\Database\Models\Version;
+use UserFrosting\Sprinkle\Core\Util\EnvironmentInfo;
+use UserFrosting\Support\Exception\ForbiddenException;
+
+/**
+ * AdminController Class
+ *
+ * Controller class for /dashboard URL. Handles admin-related activities
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AdminController extends SimpleController
+{
+
+ /**
+ * Renders the admin panel dashboard
+ *
+ */
+ public function pageDashboard($request, $response, $args) {
+ //** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_dashboard')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Probably a better way to do this
+ $users = $classMapper->staticMethod('user', 'orderBy', 'created_at', 'desc')
+ ->take(8)
+ ->get();
+
+ // Transform the `create_at` date in "x days ago" type of string
+ $users->transform(function ($item, $key) {
+ $item->registered = Carbon::parse($item->created_at)->diffForHumans();
+ return $item;
+ });
+
+ /** @var Config $config */
+ $config = $this->ci->config;
+
+ /** @var Config $config */
+ $cache = $this->ci->cache;
+
+ // Get each sprinkle db version
+ $sprinkles = $this->ci->sprinkleManager->getSprinkleNames();
+
+ return $this->ci->view->render($response, 'pages/dashboard.html.twig', [
+ 'counter' => [
+ 'users' => $classMapper->staticMethod('user', 'count'),
+ 'roles' => $classMapper->staticMethod('role', 'count'),
+ 'groups' => $classMapper->staticMethod('group', 'count')
+ ],
+ 'info' => [
+ 'version' => [
+ 'UF' => \UserFrosting\VERSION,
+ 'php' => phpversion(),
+ 'database' => EnvironmentInfo::database()
+ ],
+ 'database' => [
+ 'name' => $config['db.default.database']
+ ],
+ 'environment' => $this->ci->environment,
+ 'path' => [
+ 'project' => \UserFrosting\ROOT_DIR
+ ]
+ ],
+ 'sprinkles' => $sprinkles,
+ 'users' => $users
+ ]);
+ }
+
+ /**
+ * Clear the site cache.
+ *
+ * This route requires authentication.
+ * Request type: POST
+ */
+ public function clearCache($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'clear_cache')) {
+ throw new ForbiddenException();
+ }
+
+ // Flush cache
+ $this->ci->cache->flush();
+
+ /** @var MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ $ms->addMessageTranslated('success', 'CACHE.CLEARED');
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Renders the modal form to confirm cache deletion.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getModalConfirmClearCache($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'clear_cache')) {
+ throw new ForbiddenException();
+ }
+
+ return $this->ci->view->render($response, 'modals/confirm-clear-cache.html.twig', [
+ 'form' => [
+ 'action' => 'api/dashboard/clear-cache',
+ ]
+ ]);
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Controller/GroupController.php b/main/app/sprinkles/admin/src/Controller/GroupController.php
index 720f12d..17659ec 100644
--- a/main/app/sprinkles/admin/src/Controller/GroupController.php
+++ b/main/app/sprinkles/admin/src/Controller/GroupController.php
@@ -1,713 +1,713 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use Carbon\Carbon;
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use Slim\Exception\NotFoundException;
-use UserFrosting\Fortress\RequestDataTransformer;
-use UserFrosting\Fortress\RequestSchema;
-use UserFrosting\Fortress\ServerSideValidator;
-use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
-use UserFrosting\Sprinkle\Account\Database\Models\Group;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Controller class for group-related requests, including listing groups, CRUD for groups, etc.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class GroupController extends SimpleController
-{
- /**
- * Processes the request to create a new group.
- *
- * Processes the request from the group creation form, checking that:
- * 1. The group name and slug are not already in use;
- * 2. The user has permission to create a new group;
- * 3. The submitted data is valid.
- * This route requires authentication (and should generally be limited to admins or the root user).
- * Request type: POST
- * @see getModalCreateGroup
- */
- public function create($request, $response, $args) {
- // Get POST parameters: name, slug, icon, description
- $params = $request->getParsedBody();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'create_group')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/group/create.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate request data
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check if name or slug already exists
- if ($classMapper->staticMethod('group', 'where', 'name', $data['name'])->first()) {
- $ms->addMessageTranslated('danger', 'GROUP.NAME.IN_USE', $data);
- $error = TRUE;
- }
-
- if ($classMapper->staticMethod('group', 'where', 'slug', $data['slug'])->first()) {
- $ms->addMessageTranslated('danger', 'GROUP.SLUG.IN_USE', $data);
- $error = TRUE;
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // All checks passed! log events/activities and create group
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) {
- // Create the group
- $group = $classMapper->createInstance('group', $data);
-
- // Store new group to database
- $group->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} created group {$group->name}.", [
- 'type' => 'group_create',
- 'user_id' => $currentUser->id
- ]);
-
- $ms->addMessageTranslated('success', 'GROUP.CREATION_SUCCESSFUL', $data);
- });
-
- return $response->withStatus(200);
- }
-
- /**
- * Processes the request to delete an existing group.
- *
- * Deletes the specified group.
- * Before doing so, checks that:
- * 1. The user has permission to delete this group;
- * 2. The group is not currently set as the default for new users;
- * 3. The group is empty (does not have any users);
- * 4. The submitted data is valid.
- * This route requires authentication (and should generally be limited to admins or the root user).
- * Request type: DELETE
- */
- public function delete($request, $response, $args) {
- $group = $this->getGroupFromParams($args);
-
- // If the group doesn't exist, return 404
- if (!$group) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'delete_group', [
- 'group' => $group
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Check that we are not deleting the default group
- // Need to use loose comparison for now, because some DBs return `id` as a string
- if ($group->slug == $config['site.registration.user_defaults.group']) {
- $e = new BadRequestException();
- $e->addUserMessage('GROUP.DELETE_DEFAULT', $group->toArray());
- throw $e;
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check if there are any users in this group
- $countGroupUsers = $classMapper->staticMethod('user', 'where', 'group_id', $group->id)->count();
- if ($countGroupUsers > 0) {
- $e = new BadRequestException();
- $e->addUserMessage('GROUP.NOT_EMPTY', $group->toArray());
- throw $e;
- }
-
- $groupName = $group->name;
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($group, $groupName, $currentUser) {
- $group->delete();
- unset($group);
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted group {$groupName}.", [
- 'type' => 'group_delete',
- 'user_id' => $currentUser->id
- ]);
- });
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- $ms->addMessageTranslated('success', 'GROUP.DELETION_SUCCESSFUL', [
- 'name' => $groupName
- ]);
-
- return $response->withStatus(200);
- }
-
- /**
- * Returns info for a single group.
- *
- * This page requires authentication.
- * Request type: GET
- */
- public function getInfo($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_groups')) {
- throw new ForbiddenException();
- }
-
- $slug = $args['slug'];
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $group = $classMapper->staticMethod('group', 'where', 'slug', $slug)->first();
-
- // If the group doesn't exist, return 404
- if (!$group) {
- throw new NotFoundException($request, $response);
- }
-
- // Get group
- $result = $group->toArray();
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $response->withJson($result, 200, JSON_PRETTY_PRINT);
- }
-
- /**
- * Returns a list of Groups
- *
- * Generates a list of groups, optionally paginated, sorted and/or filtered.
- * This page requires authentication.
- * Request type: GET
- */
- public function getList($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_groups')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $sprunje = $classMapper->createInstance('group_sprunje', $classMapper, $params);
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- public function getModalConfirmDelete($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $group = $this->getGroupFromParams($params);
-
- // If the group no longer exists, forward to main group listing page
- if (!$group) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'delete_group', [
- 'group' => $group
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check if there are any users in this group
- $countGroupUsers = $classMapper->staticMethod('user', 'where', 'group_id', $group->id)->count();
- if ($countGroupUsers > 0) {
- $e = new BadRequestException();
- $e->addUserMessage('GROUP.NOT_EMPTY', $group->toArray());
- throw $e;
- }
-
- return $this->ci->view->render($response, 'modals/confirm-delete-group.html.twig', [
- 'group' => $group,
- 'form' => [
- 'action' => "api/groups/g/{$group->slug}",
- ]
- ]);
- }
-
- /**
- * Renders the modal form for creating a new group.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- */
- public function getModalCreate($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- /** @var UserFrosting\I18n\MessageTranslator $translator */
- $translator = $this->ci->translator;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'create_group')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Create a dummy group to prepopulate fields
- $group = $classMapper->createInstance('group', []);
-
- $group->icon = 'fa fa-user';
-
- $fieldNames = ['name', 'slug', 'icon', 'description'];
- $fields = [
- 'hidden' => [],
- 'disabled' => []
- ];
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/group/create.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'modals/group.html.twig', [
- 'group' => $group,
- 'form' => [
- 'action' => 'api/groups',
- 'method' => 'POST',
- 'fields' => $fields,
- 'submit_text' => $translator->translate('CREATE')
- ],
- 'page' => [
- 'validators' => $validator->rules('json', FALSE)
- ]
- ]);
- }
-
- /**
- * Renders the modal form for editing an existing group.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- */
- public function getModalEdit($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $group = $this->getGroupFromParams($params);
-
- // If the group doesn't exist, return 404
- if (!$group) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- /** @var UserFrosting\I18n\MessageTranslator $translator */
- $translator = $this->ci->translator;
-
- // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "slug", "icon", "description" for this group
- $fieldNames = ['name', 'slug', 'icon', 'description'];
- if (!$authorizer->checkAccess($currentUser, 'update_group_field', [
- 'group' => $group,
- 'fields' => $fieldNames
- ])) {
- throw new ForbiddenException();
- }
-
- // Generate form
- $fields = [
- 'hidden' => [],
- 'disabled' => []
- ];
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/group/edit-info.yaml');
- $validator = new JqueryValidationAdapter($schema, $translator);
-
- return $this->ci->view->render($response, 'modals/group.html.twig', [
- 'group' => $group,
- 'form' => [
- 'action' => "api/groups/g/{$group->slug}",
- 'method' => 'PUT',
- 'fields' => $fields,
- 'submit_text' => $translator->translate('UPDATE')
- ],
- 'page' => [
- 'validators' => $validator->rules('json', FALSE)
- ]
- ]);
- }
-
- public function getUsers($request, $response, $args) {
- $group = $this->getGroupFromParams($args);
-
- // If the group no longer exists, forward to main group listing page
- if (!$group) {
- throw new NotFoundException($request, $response);
- }
-
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'view_group_field', [
- 'group' => $group,
- 'property' => 'users'
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params);
- $sprunje->extendQuery(function ($query) use ($group) {
- return $query->where('group_id', $group->id);
- });
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- /**
- * Renders a page displaying a group's information, in read-only mode.
- *
- * This checks that the currently logged-in user has permission to view the requested group's info.
- * It checks each field individually, showing only those that you have permission to view.
- * This will also try to show buttons for deleting, and editing the group.
- * This page requires authentication.
- * Request type: GET
- */
- public function pageInfo($request, $response, $args) {
- $group = $this->getGroupFromParams($args);
-
- // If the group no longer exists, forward to main group listing page
- if (!$group) {
- $redirectPage = $this->ci->router->pathFor('uri_groups');
- return $response->withRedirect($redirectPage, 404);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_group', [
- 'group' => $group
- ])) {
- throw new ForbiddenException();
- }
-
- // Determine fields that currentUser is authorized to view
- $fieldNames = ['name', 'slug', 'icon', 'description'];
-
- // Generate form
- $fields = [
- 'hidden' => []
- ];
-
- foreach ($fieldNames as $field) {
- if (!$authorizer->checkAccess($currentUser, 'view_group_field', [
- 'group' => $group,
- 'property' => $field
- ])) {
- $fields['hidden'][] = $field;
- }
- }
-
- // Determine buttons to display
- $editButtons = [
- 'hidden' => []
- ];
-
- if (!$authorizer->checkAccess($currentUser, 'update_group_field', [
- 'group' => $group,
- 'fields' => ['name', 'slug', 'icon', 'description']
- ])) {
- $editButtons['hidden'][] = 'edit';
- }
-
- if (!$authorizer->checkAccess($currentUser, 'delete_group', [
- 'group' => $group
- ])) {
- $editButtons['hidden'][] = 'delete';
- }
-
- return $this->ci->view->render($response, 'pages/group.html.twig', [
- 'group' => $group,
- 'fields' => $fields,
- 'tools' => $editButtons
- ]);
- }
-
- /**
- * Renders the group listing page.
- *
- * This page renders a table of groups, with dropdown menus for admin actions for each group.
- * Actions typically include: edit group, delete group.
- * This page requires authentication.
- * Request type: GET
- */
- public function pageList($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_groups')) {
- throw new ForbiddenException();
- }
-
- return $this->ci->view->render($response, 'pages/groups.html.twig');
- }
-
- /**
- * Processes the request to update an existing group's details.
- *
- * Processes the request from the group update form, checking that:
- * 1. The group name/slug are not already in use;
- * 2. The user has the necessary permissions to update the posted field(s);
- * 3. The submitted data is valid.
- * This route requires authentication (and should generally be limited to admins or the root user).
- * Request type: PUT
- * @see getModalGroupEdit
- */
- public function updateInfo($request, $response, $args) {
- // Get the group based on slug in URL
- $group = $this->getGroupFromParams($args);
-
- if (!$group) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Get PUT parameters: (name, slug, icon, description)
- $params = $request->getParsedBody();
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/group/edit-info.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate request data
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- // Determine targeted fields
- $fieldNames = [];
- foreach ($data as $name => $value) {
- $fieldNames[] = $name;
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit submitted fields for this group
- if (!$authorizer->checkAccess($currentUser, 'update_group_field', [
- 'group' => $group,
- 'fields' => array_values(array_unique($fieldNames))
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check if name or slug already exists
- if (
- isset($data['name']) &&
- $data['name'] != $group->name &&
- $classMapper->staticMethod('group', 'where', 'name', $data['name'])->first()
- ) {
- $ms->addMessageTranslated('danger', 'GROUP.NAME.IN_USE', $data);
- $error = TRUE;
- }
-
- if (
- isset($data['slug']) &&
- $data['slug'] != $group->slug &&
- $classMapper->staticMethod('group', 'where', 'slug', $data['slug'])->first()
- ) {
- $ms->addMessageTranslated('danger', 'GROUP.SLUG.IN_USE', $data);
- $error = TRUE;
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($data, $group, $currentUser) {
- // Update the group and generate success messages
- foreach ($data as $name => $value) {
- if ($value != $group->$name) {
- $group->$name = $value;
- }
- }
-
- $group->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated details for group {$group->name}.", [
- 'type' => 'group_update_info',
- 'user_id' => $currentUser->id
- ]);
- });
-
- $ms->addMessageTranslated('success', 'GROUP.UPDATE', [
- 'name' => $group->name
- ]);
-
- return $response->withStatus(200);
- }
-
- protected function getGroupFromParams($params) {
- // Load the request schema
- $schema = new RequestSchema('schema://requests/group/get-by-slug.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and throw exception on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $e = new BadRequestException();
- foreach ($validator->errors() as $idx => $field) {
- foreach ($field as $eidx => $error) {
- $e->addUserMessage($error);
- }
- }
- throw $e;
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Get the group
- $group = $classMapper->staticMethod('group', 'where', 'slug', $data['slug'])
- ->first();
-
- return $group;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use Carbon\Carbon;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Slim\Exception\NotFoundException;
+use UserFrosting\Fortress\RequestDataTransformer;
+use UserFrosting\Fortress\RequestSchema;
+use UserFrosting\Fortress\ServerSideValidator;
+use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
+use UserFrosting\Sprinkle\Account\Database\Models\Group;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Controller class for group-related requests, including listing groups, CRUD for groups, etc.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class GroupController extends SimpleController
+{
+ /**
+ * Processes the request to create a new group.
+ *
+ * Processes the request from the group creation form, checking that:
+ * 1. The group name and slug are not already in use;
+ * 2. The user has permission to create a new group;
+ * 3. The submitted data is valid.
+ * This route requires authentication (and should generally be limited to admins or the root user).
+ * Request type: POST
+ * @see getModalCreateGroup
+ */
+ public function create($request, $response, $args) {
+ // Get POST parameters: name, slug, icon, description
+ $params = $request->getParsedBody();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'create_group')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/group/create.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate request data
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check if name or slug already exists
+ if ($classMapper->staticMethod('group', 'where', 'name', $data['name'])->first()) {
+ $ms->addMessageTranslated('danger', 'GROUP.NAME.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($classMapper->staticMethod('group', 'where', 'slug', $data['slug'])->first()) {
+ $ms->addMessageTranslated('danger', 'GROUP.SLUG.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // All checks passed! log events/activities and create group
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) {
+ // Create the group
+ $group = $classMapper->createInstance('group', $data);
+
+ // Store new group to database
+ $group->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} created group {$group->name}.", [
+ 'type' => 'group_create',
+ 'user_id' => $currentUser->id
+ ]);
+
+ $ms->addMessageTranslated('success', 'GROUP.CREATION_SUCCESSFUL', $data);
+ });
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes the request to delete an existing group.
+ *
+ * Deletes the specified group.
+ * Before doing so, checks that:
+ * 1. The user has permission to delete this group;
+ * 2. The group is not currently set as the default for new users;
+ * 3. The group is empty (does not have any users);
+ * 4. The submitted data is valid.
+ * This route requires authentication (and should generally be limited to admins or the root user).
+ * Request type: DELETE
+ */
+ public function delete($request, $response, $args) {
+ $group = $this->getGroupFromParams($args);
+
+ // If the group doesn't exist, return 404
+ if (!$group) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'delete_group', [
+ 'group' => $group
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Check that we are not deleting the default group
+ // Need to use loose comparison for now, because some DBs return `id` as a string
+ if ($group->slug == $config['site.registration.user_defaults.group']) {
+ $e = new BadRequestException();
+ $e->addUserMessage('GROUP.DELETE_DEFAULT', $group->toArray());
+ throw $e;
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check if there are any users in this group
+ $countGroupUsers = $classMapper->staticMethod('user', 'where', 'group_id', $group->id)->count();
+ if ($countGroupUsers > 0) {
+ $e = new BadRequestException();
+ $e->addUserMessage('GROUP.NOT_EMPTY', $group->toArray());
+ throw $e;
+ }
+
+ $groupName = $group->name;
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($group, $groupName, $currentUser) {
+ $group->delete();
+ unset($group);
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted group {$groupName}.", [
+ 'type' => 'group_delete',
+ 'user_id' => $currentUser->id
+ ]);
+ });
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ $ms->addMessageTranslated('success', 'GROUP.DELETION_SUCCESSFUL', [
+ 'name' => $groupName
+ ]);
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Returns info for a single group.
+ *
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getInfo($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_groups')) {
+ throw new ForbiddenException();
+ }
+
+ $slug = $args['slug'];
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $group = $classMapper->staticMethod('group', 'where', 'slug', $slug)->first();
+
+ // If the group doesn't exist, return 404
+ if (!$group) {
+ throw new NotFoundException($request, $response);
+ }
+
+ // Get group
+ $result = $group->toArray();
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $response->withJson($result, 200, JSON_PRETTY_PRINT);
+ }
+
+ /**
+ * Returns a list of Groups
+ *
+ * Generates a list of groups, optionally paginated, sorted and/or filtered.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getList($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_groups')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $sprunje = $classMapper->createInstance('group_sprunje', $classMapper, $params);
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ public function getModalConfirmDelete($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $group = $this->getGroupFromParams($params);
+
+ // If the group no longer exists, forward to main group listing page
+ if (!$group) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'delete_group', [
+ 'group' => $group
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check if there are any users in this group
+ $countGroupUsers = $classMapper->staticMethod('user', 'where', 'group_id', $group->id)->count();
+ if ($countGroupUsers > 0) {
+ $e = new BadRequestException();
+ $e->addUserMessage('GROUP.NOT_EMPTY', $group->toArray());
+ throw $e;
+ }
+
+ return $this->ci->view->render($response, 'modals/confirm-delete-group.html.twig', [
+ 'group' => $group,
+ 'form' => [
+ 'action' => "api/groups/g/{$group->slug}",
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for creating a new group.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getModalCreate($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ /** @var UserFrosting\I18n\MessageTranslator $translator */
+ $translator = $this->ci->translator;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'create_group')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Create a dummy group to prepopulate fields
+ $group = $classMapper->createInstance('group', []);
+
+ $group->icon = 'fa fa-user';
+
+ $fieldNames = ['name', 'slug', 'icon', 'description'];
+ $fields = [
+ 'hidden' => [],
+ 'disabled' => []
+ ];
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/group/create.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'modals/group.html.twig', [
+ 'group' => $group,
+ 'form' => [
+ 'action' => 'api/groups',
+ 'method' => 'POST',
+ 'fields' => $fields,
+ 'submit_text' => $translator->translate('CREATE')
+ ],
+ 'page' => [
+ 'validators' => $validator->rules('json', FALSE)
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for editing an existing group.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getModalEdit($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $group = $this->getGroupFromParams($params);
+
+ // If the group doesn't exist, return 404
+ if (!$group) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ /** @var UserFrosting\I18n\MessageTranslator $translator */
+ $translator = $this->ci->translator;
+
+ // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "slug", "icon", "description" for this group
+ $fieldNames = ['name', 'slug', 'icon', 'description'];
+ if (!$authorizer->checkAccess($currentUser, 'update_group_field', [
+ 'group' => $group,
+ 'fields' => $fieldNames
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ // Generate form
+ $fields = [
+ 'hidden' => [],
+ 'disabled' => []
+ ];
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/group/edit-info.yaml');
+ $validator = new JqueryValidationAdapter($schema, $translator);
+
+ return $this->ci->view->render($response, 'modals/group.html.twig', [
+ 'group' => $group,
+ 'form' => [
+ 'action' => "api/groups/g/{$group->slug}",
+ 'method' => 'PUT',
+ 'fields' => $fields,
+ 'submit_text' => $translator->translate('UPDATE')
+ ],
+ 'page' => [
+ 'validators' => $validator->rules('json', FALSE)
+ ]
+ ]);
+ }
+
+ public function getUsers($request, $response, $args) {
+ $group = $this->getGroupFromParams($args);
+
+ // If the group no longer exists, forward to main group listing page
+ if (!$group) {
+ throw new NotFoundException($request, $response);
+ }
+
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'view_group_field', [
+ 'group' => $group,
+ 'property' => 'users'
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params);
+ $sprunje->extendQuery(function ($query) use ($group) {
+ return $query->where('group_id', $group->id);
+ });
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ /**
+ * Renders a page displaying a group's information, in read-only mode.
+ *
+ * This checks that the currently logged-in user has permission to view the requested group's info.
+ * It checks each field individually, showing only those that you have permission to view.
+ * This will also try to show buttons for deleting, and editing the group.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function pageInfo($request, $response, $args) {
+ $group = $this->getGroupFromParams($args);
+
+ // If the group no longer exists, forward to main group listing page
+ if (!$group) {
+ $redirectPage = $this->ci->router->pathFor('uri_groups');
+ return $response->withRedirect($redirectPage, 404);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_group', [
+ 'group' => $group
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ // Determine fields that currentUser is authorized to view
+ $fieldNames = ['name', 'slug', 'icon', 'description'];
+
+ // Generate form
+ $fields = [
+ 'hidden' => []
+ ];
+
+ foreach ($fieldNames as $field) {
+ if (!$authorizer->checkAccess($currentUser, 'view_group_field', [
+ 'group' => $group,
+ 'property' => $field
+ ])) {
+ $fields['hidden'][] = $field;
+ }
+ }
+
+ // Determine buttons to display
+ $editButtons = [
+ 'hidden' => []
+ ];
+
+ if (!$authorizer->checkAccess($currentUser, 'update_group_field', [
+ 'group' => $group,
+ 'fields' => ['name', 'slug', 'icon', 'description']
+ ])) {
+ $editButtons['hidden'][] = 'edit';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'delete_group', [
+ 'group' => $group
+ ])) {
+ $editButtons['hidden'][] = 'delete';
+ }
+
+ return $this->ci->view->render($response, 'pages/group.html.twig', [
+ 'group' => $group,
+ 'fields' => $fields,
+ 'tools' => $editButtons
+ ]);
+ }
+
+ /**
+ * Renders the group listing page.
+ *
+ * This page renders a table of groups, with dropdown menus for admin actions for each group.
+ * Actions typically include: edit group, delete group.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function pageList($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_groups')) {
+ throw new ForbiddenException();
+ }
+
+ return $this->ci->view->render($response, 'pages/groups.html.twig');
+ }
+
+ /**
+ * Processes the request to update an existing group's details.
+ *
+ * Processes the request from the group update form, checking that:
+ * 1. The group name/slug are not already in use;
+ * 2. The user has the necessary permissions to update the posted field(s);
+ * 3. The submitted data is valid.
+ * This route requires authentication (and should generally be limited to admins or the root user).
+ * Request type: PUT
+ * @see getModalGroupEdit
+ */
+ public function updateInfo($request, $response, $args) {
+ // Get the group based on slug in URL
+ $group = $this->getGroupFromParams($args);
+
+ if (!$group) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Get PUT parameters: (name, slug, icon, description)
+ $params = $request->getParsedBody();
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/group/edit-info.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate request data
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ // Determine targeted fields
+ $fieldNames = [];
+ foreach ($data as $name => $value) {
+ $fieldNames[] = $name;
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit submitted fields for this group
+ if (!$authorizer->checkAccess($currentUser, 'update_group_field', [
+ 'group' => $group,
+ 'fields' => array_values(array_unique($fieldNames))
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check if name or slug already exists
+ if (
+ isset($data['name']) &&
+ $data['name'] != $group->name &&
+ $classMapper->staticMethod('group', 'where', 'name', $data['name'])->first()
+ ) {
+ $ms->addMessageTranslated('danger', 'GROUP.NAME.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if (
+ isset($data['slug']) &&
+ $data['slug'] != $group->slug &&
+ $classMapper->staticMethod('group', 'where', 'slug', $data['slug'])->first()
+ ) {
+ $ms->addMessageTranslated('danger', 'GROUP.SLUG.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($data, $group, $currentUser) {
+ // Update the group and generate success messages
+ foreach ($data as $name => $value) {
+ if ($value != $group->$name) {
+ $group->$name = $value;
+ }
+ }
+
+ $group->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated details for group {$group->name}.", [
+ 'type' => 'group_update_info',
+ 'user_id' => $currentUser->id
+ ]);
+ });
+
+ $ms->addMessageTranslated('success', 'GROUP.UPDATE', [
+ 'name' => $group->name
+ ]);
+
+ return $response->withStatus(200);
+ }
+
+ protected function getGroupFromParams($params) {
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/group/get-by-slug.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and throw exception on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $e = new BadRequestException();
+ foreach ($validator->errors() as $idx => $field) {
+ foreach ($field as $eidx => $error) {
+ $e->addUserMessage($error);
+ }
+ }
+ throw $e;
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Get the group
+ $group = $classMapper->staticMethod('group', 'where', 'slug', $data['slug'])
+ ->first();
+
+ return $group;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Controller/PermissionController.php b/main/app/sprinkles/admin/src/Controller/PermissionController.php
index e8e542f..133cfe3 100644
--- a/main/app/sprinkles/admin/src/Controller/PermissionController.php
+++ b/main/app/sprinkles/admin/src/Controller/PermissionController.php
@@ -1,202 +1,202 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use Carbon\Carbon;
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use Slim\Exception\NotFoundException;
-use UserFrosting\Fortress\RequestDataTransformer;
-use UserFrosting\Fortress\RequestSchema;
-use UserFrosting\Fortress\ServerSideValidator;
-use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
-use UserFrosting\Sprinkle\Account\Database\Models\Permission;
-use UserFrosting\Sprinkle\Account\Database\Models\Role;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Controller class for permission-related requests, including listing permissions, CRUD for permissions, etc.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class PermissionController extends SimpleController
-{
- /**
- * Returns info for a single permission.
- *
- * This page requires authentication.
- * Request type: GET
- */
- public function getInfo($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
- throw new ForbiddenException();
- }
-
- $permissionId = $args['id'];
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $permission = $classMapper->staticMethod('permission', 'find', $permissionId);
-
- // If the permission doesn't exist, return 404
- if (!$permission) {
- throw new NotFoundException($request, $response);
- }
-
- // Get permission
- $result = $permission->load('users')->toArray();
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $response->withJson($result, 200, JSON_PRETTY_PRINT);
- }
-
- /**
- * Returns a list of Permissions
- *
- * Generates a list of permissions, optionally paginated, sorted and/or filtered.
- * This page requires authentication.
- * Request type: GET
- */
- public function getList($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $sprunje = $classMapper->createInstance('permission_sprunje', $classMapper, $params);
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- /**
- * Returns a list of Users for a specified Permission.
- *
- * Generates a list of users, optionally paginated, sorted and/or filtered.
- * This page requires authentication.
- * Request type: GET
- */
- public function getUsers($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $params['permission_id'] = $args['id'];
-
- $sprunje = $classMapper->createInstance('permission_user_sprunje', $classMapper, $params);
-
- $response = $sprunje->toResponse($response);
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $response;
- }
-
- /**
- * Renders a page displaying a permission's information, in read-only mode.
- *
- * This checks that the currently logged-in user has permission to view permissions.
- * Note that permissions cannot be modified through the interface. This is because
- * permissions are highly coupled to the code and should only be modified by developers.
- * This page requires authentication.
- * Request type: GET
- */
- public function pageInfo($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
- throw new ForbiddenException();
- }
-
- $permissionId = $args['id'];
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $permission = $classMapper->staticMethod('permission', 'find', $permissionId);
-
- // If the permission doesn't exist, return 404
- if (!$permission) {
- throw new NotFoundException($request, $response);
- }
-
- return $this->ci->view->render($response, 'pages/permission.html.twig', [
- 'permission' => $permission
- ]);
- }
-
- /**
- * Renders the permission listing page.
- *
- * This page renders a table of permissions, with dropdown menus for admin actions for each permission.
- * Actions typically include: edit permission, delete permission.
- * This page requires authentication.
- * Request type: GET
- */
- public function pageList($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
- throw new ForbiddenException();
- }
-
- return $this->ci->view->render($response, 'pages/permissions.html.twig');
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use Carbon\Carbon;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Slim\Exception\NotFoundException;
+use UserFrosting\Fortress\RequestDataTransformer;
+use UserFrosting\Fortress\RequestSchema;
+use UserFrosting\Fortress\ServerSideValidator;
+use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
+use UserFrosting\Sprinkle\Account\Database\Models\Permission;
+use UserFrosting\Sprinkle\Account\Database\Models\Role;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Controller class for permission-related requests, including listing permissions, CRUD for permissions, etc.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class PermissionController extends SimpleController
+{
+ /**
+ * Returns info for a single permission.
+ *
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getInfo($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
+ throw new ForbiddenException();
+ }
+
+ $permissionId = $args['id'];
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $permission = $classMapper->staticMethod('permission', 'find', $permissionId);
+
+ // If the permission doesn't exist, return 404
+ if (!$permission) {
+ throw new NotFoundException($request, $response);
+ }
+
+ // Get permission
+ $result = $permission->load('users')->toArray();
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $response->withJson($result, 200, JSON_PRETTY_PRINT);
+ }
+
+ /**
+ * Returns a list of Permissions
+ *
+ * Generates a list of permissions, optionally paginated, sorted and/or filtered.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getList($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $sprunje = $classMapper->createInstance('permission_sprunje', $classMapper, $params);
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ /**
+ * Returns a list of Users for a specified Permission.
+ *
+ * Generates a list of users, optionally paginated, sorted and/or filtered.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getUsers($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $params['permission_id'] = $args['id'];
+
+ $sprunje = $classMapper->createInstance('permission_user_sprunje', $classMapper, $params);
+
+ $response = $sprunje->toResponse($response);
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $response;
+ }
+
+ /**
+ * Renders a page displaying a permission's information, in read-only mode.
+ *
+ * This checks that the currently logged-in user has permission to view permissions.
+ * Note that permissions cannot be modified through the interface. This is because
+ * permissions are highly coupled to the code and should only be modified by developers.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function pageInfo($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
+ throw new ForbiddenException();
+ }
+
+ $permissionId = $args['id'];
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $permission = $classMapper->staticMethod('permission', 'find', $permissionId);
+
+ // If the permission doesn't exist, return 404
+ if (!$permission) {
+ throw new NotFoundException($request, $response);
+ }
+
+ return $this->ci->view->render($response, 'pages/permission.html.twig', [
+ 'permission' => $permission
+ ]);
+ }
+
+ /**
+ * Renders the permission listing page.
+ *
+ * This page renders a table of permissions, with dropdown menus for admin actions for each permission.
+ * Actions typically include: edit permission, delete permission.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function pageList($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_permissions')) {
+ throw new ForbiddenException();
+ }
+
+ return $this->ci->view->render($response, 'pages/permissions.html.twig');
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Controller/PostController.php b/main/app/sprinkles/admin/src/Controller/PostController.php
index a310237..cab87cd 100644
--- a/main/app/sprinkles/admin/src/Controller/PostController.php
+++ b/main/app/sprinkles/admin/src/Controller/PostController.php
@@ -1,191 +1,191 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use function GuzzleHttp\Psr7\str;
-use UserFrosting\Fortress\RequestDataTransformer;
-use UserFrosting\Fortress\RequestSchema;
-use UserFrosting\Fortress\ServerSideValidator;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\NotFoundException;
-use Slim\Http\Request;
-use Slim\Http\Response;
-use Slim\Http\UploadedFile;
-use Illuminate\Database\Capsule\Manager as DB;
-
-/**
- * Controller class for user-related requests, including listing users, CRUD for users, etc.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class PostController extends SimpleController
-{
-
- /**
- * Gets the feed of the requested user (for non-administrators only own feed allowed)
- *
- * @param Request $request
- * @param Response $response
- * @param $args
- * @throws BadRequestException
- * @throws NotFoundException
- */
- public function getFeed(Request $request, Response $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException();
- }
-
- // Get friends first // TODO: Make friend select query more efficient
- $UsersFriends = DB::select("SELECT id FROM (SELECT user_id AS id FROM user_follow WHERE followed_by_id = $user->id UNION ALL SELECT followed_by_id FROM user_follow WHERE user_id = $user->id) t GROUP BY id HAVING COUNT(id) > 1");
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
- $ImagesFromFriends = "";
- $config = $this->ci->config;
- foreach ($UsersFriends as $UsersFriendId) { // NOT THAT EFFICIENT... (get images from all friends in an array)
- $UsersFriendInformation = $classMapper->createInstance('user')// raw select doesnt work with instance
- ->where('id', $UsersFriendId->id)
- ->get();
-
- $ImagesFromFriends = DB::table('image_posts')
- ->where('UserID', '=', $UsersFriendInformation[0]->id) // IMAGES FROM FRIENDS
- ->orWhere('UserId', '=', $user->id) // IMAGES FROM THE USER HIMSELF
- ->select('PostID as image_id', 'UserID as user_id')
- ->get();
-
- foreach ($ImagesFromFriends as $ImageFromFriend) {
- $ImageFromFriend->image_url = $config["site.uri.public"] . "/image/" . $ImageFromFriend->image_id;
- if ($ImageFromFriend->user_id == $user->id) { // UPLOADED FROM HIMSELF
- $ImageFromFriend->full_name = $user->full_name; // ADD USERNAME TO IMAGE ID
- $ImageFromFriend->avatar = $user->avatar;
- } else { // UPLOADED FROM ANOTHER USER
- $ImageFromFriend->full_name = $UsersFriendInformation[0]->full_name; // ADD USERNAME TO IMAGE ID
- $ImageFromFriend->avatar = $UsersFriendInformation[0]->avatar;
- }
- }
- }
-
- return $response->withJson($ImagesFromFriends, 200, JSON_PRETTY_PRINT);
- }
-
- /**
- * Shows the requested image
- *
- * @param Request $request
- * @param Response $response
- * @param $args
- * @return Response
- * @throws ForbiddenException
- * @throws NotFoundException
- */
- public function showImage(Request $request, Response $response, $args) {
- // check if user is authorized
- $authorizer = $this->ci->authorizer;
- $currentUser = $this->ci->currentUser;
- if (!$authorizer->checkAccess($currentUser, 'view_image')) {
- throw new ForbiddenException();
- }
- $postID = $args['post_id'];
-
- // get filename from database
- $FileRequestedImage = DB::table('image_posts')
- ->where('PostID', '=', $postID)
- ->value('File');
-
- if ($FileRequestedImage) {
- $FileType = pathinfo($FileRequestedImage, PATHINFO_EXTENSION);
-
- // echo image
- $response->write(file_get_contents(__DIR__ . '/../../../../../uploads/' . $FileRequestedImage));
- return $response->withHeader('Content-type', 'image/' . $FileType);
- } else {
- throw new NotFoundException();
- }
- }
-
- /**
- * posts a image
- *
- * @param Request $request
- * @param Response $response
- * @return Response
- * @throws ForbiddenException
- */
- public function postImage(Request $request, Response $response) {
- // check if user is authorized
- $authorizer = $this->ci->authorizer;
- $currentUser = $this->ci->currentUser;
- if (!$authorizer->checkAccess($currentUser, 'post_image')) {
- throw new ForbiddenException();
- }
-
- $uploadedFiles = $request->getUploadedFiles();
- $uploadedFile = $uploadedFiles['image'];
-
- if (!strpos($uploadedFile->getClientMediaType(), "mage")) {
- return $response->withStatus(415);
- } else if ($uploadedFile->getError() === 1) {
- return $response->withStatus(406);
- } else if ($uploadedFile->getSize() > 10485760) {
- return $response->withStatus(413);
- } else { // Upload is accepted
- // Move file to upload directory
- $extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
- $basename = bin2hex(random_bytes(8));
- $filename = sprintf('%s.%0.8s', $basename, $extension);
- $uploadedFile->moveTo(__DIR__ . '/../../../../../uploads' . DIRECTORY_SEPARATOR . $filename);
-
- // Store in Database
- DB::table('image_posts')
- ->insert(['UserID' => $currentUser->id, 'File' => $filename]);
-
- return $response->write('Uploaded successfully! <br/>');
- }
- }
-
- /**
- * @param $params
- * @return mixed
- * @throws BadRequestException
- */
- protected function getUserFromParams($params) {
- // Load the request schema
- $schema = new RequestSchema('schema://requests/user/get-by-username.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and throw exception on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $e = new BadRequestException();
- foreach ($validator->errors() as $idx => $field) {
- foreach ($field as $eidx => $error) {
- $e->addUserMessage($error);
- }
- }
- throw $e;
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Get the user to delete
- $user = $classMapper->staticMethod('user', 'where', 'user_name', $data['user_name'])
- ->first();
-
- return $user;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use function GuzzleHttp\Psr7\str;
+use UserFrosting\Fortress\RequestDataTransformer;
+use UserFrosting\Fortress\RequestSchema;
+use UserFrosting\Fortress\ServerSideValidator;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\NotFoundException;
+use Slim\Http\Request;
+use Slim\Http\Response;
+use Slim\Http\UploadedFile;
+use Illuminate\Database\Capsule\Manager as DB;
+
+/**
+ * Controller class for user-related requests, including listing users, CRUD for users, etc.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class PostController extends SimpleController
+{
+
+ /**
+ * Gets the feed of the requested user (for non-administrators only own feed allowed)
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param $args
+ * @throws BadRequestException
+ * @throws NotFoundException
+ */
+ public function getFeed(Request $request, Response $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException();
+ }
+
+ // Get friends first // TODO: Make friend select query more efficient
+ $UsersFriends = DB::select("SELECT id FROM (SELECT user_id AS id FROM user_follow WHERE followed_by_id = $user->id UNION ALL SELECT followed_by_id FROM user_follow WHERE user_id = $user->id) t GROUP BY id HAVING COUNT(id) > 1");
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+ $ImagesFromFriends = "";
+ $config = $this->ci->config;
+ foreach ($UsersFriends as $UsersFriendId) { // NOT THAT EFFICIENT... (get images from all friends in an array)
+ $UsersFriendInformation = $classMapper->createInstance('user')// raw select doesnt work with instance
+ ->where('id', $UsersFriendId->id)
+ ->get();
+
+ $ImagesFromFriends = DB::table('image_posts')
+ ->where('UserID', '=', $UsersFriendInformation[0]->id) // IMAGES FROM FRIENDS
+ ->orWhere('UserId', '=', $user->id) // IMAGES FROM THE USER HIMSELF
+ ->select('PostID as image_id', 'UserID as user_id')
+ ->get();
+
+ foreach ($ImagesFromFriends as $ImageFromFriend) {
+ $ImageFromFriend->image_url = $config["site.uri.public"] . "/image/" . $ImageFromFriend->image_id;
+ if ($ImageFromFriend->user_id == $user->id) { // UPLOADED FROM HIMSELF
+ $ImageFromFriend->full_name = $user->full_name; // ADD USERNAME TO IMAGE ID
+ $ImageFromFriend->avatar = $user->avatar;
+ } else { // UPLOADED FROM ANOTHER USER
+ $ImageFromFriend->full_name = $UsersFriendInformation[0]->full_name; // ADD USERNAME TO IMAGE ID
+ $ImageFromFriend->avatar = $UsersFriendInformation[0]->avatar;
+ }
+ }
+ }
+
+ return $response->withJson($ImagesFromFriends, 200, JSON_PRETTY_PRINT);
+ }
+
+ /**
+ * Shows the requested image
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param $args
+ * @return Response
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ */
+ public function showImage(Request $request, Response $response, $args) {
+ // check if user is authorized
+ $authorizer = $this->ci->authorizer;
+ $currentUser = $this->ci->currentUser;
+ if (!$authorizer->checkAccess($currentUser, 'view_image')) {
+ throw new ForbiddenException();
+ }
+ $postID = $args['post_id'];
+
+ // get filename from database
+ $FileRequestedImage = DB::table('image_posts')
+ ->where('PostID', '=', $postID)
+ ->value('File');
+
+ if ($FileRequestedImage) {
+ $FileType = pathinfo($FileRequestedImage, PATHINFO_EXTENSION);
+
+ // echo image
+ $response->write(file_get_contents(__DIR__ . '/../../../../../uploads/' . $FileRequestedImage));
+ return $response->withHeader('Content-type', 'image/' . $FileType);
+ } else {
+ throw new NotFoundException();
+ }
+ }
+
+ /**
+ * posts a image
+ *
+ * @param Request $request
+ * @param Response $response
+ * @return Response
+ * @throws ForbiddenException
+ */
+ public function postImage(Request $request, Response $response) {
+ // check if user is authorized
+ $authorizer = $this->ci->authorizer;
+ $currentUser = $this->ci->currentUser;
+ if (!$authorizer->checkAccess($currentUser, 'post_image')) {
+ throw new ForbiddenException();
+ }
+
+ $uploadedFiles = $request->getUploadedFiles();
+ $uploadedFile = $uploadedFiles['image'];
+
+ if (!strpos($uploadedFile->getClientMediaType(), "mage")) {
+ return $response->withStatus(415);
+ } else if ($uploadedFile->getError() === 1) {
+ return $response->withStatus(406);
+ } else if ($uploadedFile->getSize() > 10485760) {
+ return $response->withStatus(413);
+ } else { // Upload is accepted
+ // Move file to upload directory
+ $extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
+ $basename = bin2hex(random_bytes(8));
+ $filename = sprintf('%s.%0.8s', $basename, $extension);
+ $uploadedFile->moveTo(__DIR__ . '/../../../../../uploads' . DIRECTORY_SEPARATOR . $filename);
+
+ // Store in Database
+ DB::table('image_posts')
+ ->insert(['UserID' => $currentUser->id, 'File' => $filename]);
+
+ return $response->write('Uploaded successfully! <br/>');
+ }
+ }
+
+ /**
+ * @param $params
+ * @return mixed
+ * @throws BadRequestException
+ */
+ protected function getUserFromParams($params) {
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/user/get-by-username.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and throw exception on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $e = new BadRequestException();
+ foreach ($validator->errors() as $idx => $field) {
+ foreach ($field as $eidx => $error) {
+ $e->addUserMessage($error);
+ }
+ }
+ throw $e;
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Get the user to delete
+ $user = $classMapper->staticMethod('user', 'where', 'user_name', $data['user_name'])
+ ->first();
+
+ return $user;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Controller/RoleController.php b/main/app/sprinkles/admin/src/Controller/RoleController.php
index 80ac6a0..af1d53c 100644
--- a/main/app/sprinkles/admin/src/Controller/RoleController.php
+++ b/main/app/sprinkles/admin/src/Controller/RoleController.php
@@ -1,915 +1,915 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use Carbon\Carbon;
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use Slim\Exception\NotFoundException;
-use UserFrosting\Fortress\RequestDataTransformer;
-use UserFrosting\Fortress\RequestSchema;
-use UserFrosting\Fortress\ServerSideValidator;
-use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
-use UserFrosting\Sprinkle\Account\Database\Models\Role;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Controller class for role-related requests, including listing roles, CRUD for roles, etc.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class RoleController extends SimpleController
-{
- /**
- * Processes the request to create a new role.
- *
- * Processes the request from the role creation form, checking that:
- * 1. The role name and slug are not already in use;
- * 2. The user has permission to create a new role;
- * 3. The submitted data is valid.
- * This route requires authentication (and should generally be limited to admins or the root user).
- * Request type: POST
- * @see getModalCreateRole
- */
- public function create($request, $response, $args) {
- // Get POST parameters: name, slug, description
- $params = $request->getParsedBody();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'create_role')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/role/create.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate request data
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check if name or slug already exists
- if ($classMapper->staticMethod('role', 'where', 'name', $data['name'])->first()) {
- $ms->addMessageTranslated('danger', 'ROLE.NAME_IN_USE', $data);
- $error = TRUE;
- }
-
- if ($classMapper->staticMethod('role', 'where', 'slug', $data['slug'])->first()) {
- $ms->addMessageTranslated('danger', 'SLUG_IN_USE', $data);
- $error = TRUE;
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // All checks passed! log events/activities and create role
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) {
- // Create the role
- $role = $classMapper->createInstance('role', $data);
-
- // Store new role to database
- $role->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} created role {$role->name}.", [
- 'type' => 'role_create',
- 'user_id' => $currentUser->id
- ]);
-
- $ms->addMessageTranslated('success', 'ROLE.CREATION_SUCCESSFUL', $data);
- });
-
- return $response->withStatus(200);
- }
-
- /**
- * Processes the request to delete an existing role.
- *
- * Deletes the specified role.
- * Before doing so, checks that:
- * 1. The user has permission to delete this role;
- * 2. The role is not a default for new users;
- * 3. The role does not have any associated users;
- * 4. The submitted data is valid.
- * This route requires authentication (and should generally be limited to admins or the root user).
- * Request type: DELETE
- */
- public function delete($request, $response, $args) {
- $role = $this->getRoleFromParams($args);
-
- // If the role doesn't exist, return 404
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'delete_role', [
- 'role' => $role
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check that we are not deleting a default role
- $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs');
-
- // Need to use loose comparison for now, because some DBs return `id` as a string
- if (in_array($role->slug, $defaultRoleSlugs)) {
- $e = new BadRequestException();
- $e->addUserMessage('ROLE.DELETE_DEFAULT');
- throw $e;
- }
-
- // Check if there are any users associated with this role
- $countUsers = $role->users()->count();
- if ($countUsers > 0) {
- $e = new BadRequestException();
- $e->addUserMessage('ROLE.HAS_USERS');
- throw $e;
- }
-
- $roleName = $role->name;
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($role, $roleName, $currentUser) {
- $role->delete();
- unset($role);
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted role {$roleName}.", [
- 'type' => 'role_delete',
- 'user_id' => $currentUser->id
- ]);
- });
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- $ms->addMessageTranslated('success', 'ROLE.DELETION_SUCCESSFUL', [
- 'name' => $roleName
- ]);
-
- return $response->withStatus(200);
- }
-
- /**
- * Returns info for a single role, along with associated permissions.
- *
- * This page requires authentication.
- * Request type: GET
- */
- public function getInfo($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_roles')) {
- throw new ForbiddenException();
- }
-
- $slug = $args['slug'];
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $role = $classMapper->staticMethod('role', 'where', 'slug', $slug)->first();
-
- // If the role doesn't exist, return 404
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- // Get role
- $result = $role->load('permissions')->toArray();
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $response->withJson($result, 200, JSON_PRETTY_PRINT);
- }
-
- /**
- * Returns a list of Roles
- *
- * Generates a list of roles, optionally paginated, sorted and/or filtered.
- * This page requires authentication.
- * Request type: GET
- */
- public function getList($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_roles')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $sprunje = $classMapper->createInstance('role_sprunje', $classMapper, $params);
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- public function getModalConfirmDelete($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $role = $this->getRoleFromParams($params);
-
- // If the role no longer exists, forward to main role listing page
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'delete_role', [
- 'role' => $role
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check that we are not deleting a default role
- $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs');
-
- // Need to use loose comparison for now, because some DBs return `id` as a string
- if (in_array($role->slug, $defaultRoleSlugs)) {
- $e = new BadRequestException();
- $e->addUserMessage('ROLE.DELETE_DEFAULT', $role->toArray());
- throw $e;
- }
-
- // Check if there are any users associated with this role
- $countUsers = $role->users()->count();
- if ($countUsers > 0) {
- $e = new BadRequestException();
- $e->addUserMessage('ROLE.HAS_USERS', $role->toArray());
- throw $e;
- }
-
- return $this->ci->view->render($response, 'modals/confirm-delete-role.html.twig', [
- 'role' => $role,
- 'form' => [
- 'action' => "api/roles/r/{$role->slug}",
- ]
- ]);
- }
-
- /**
- * Renders the modal form for creating a new role.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- */
- public function getModalCreate($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- /** @var UserFrosting\I18n\MessageTranslator $translator */
- $translator = $this->ci->translator;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'create_role')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Create a dummy role to prepopulate fields
- $role = $classMapper->createInstance('role', []);
-
- $fieldNames = ['name', 'slug', 'description'];
- $fields = [
- 'hidden' => [],
- 'disabled' => []
- ];
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/role/create.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'modals/role.html.twig', [
- 'role' => $role,
- 'form' => [
- 'action' => 'api/roles',
- 'method' => 'POST',
- 'fields' => $fields,
- 'submit_text' => $translator->translate('CREATE')
- ],
- 'page' => [
- 'validators' => $validator->rules('json', FALSE)
- ]
- ]);
- }
-
- /**
- * Renders the modal form for editing an existing role.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- */
- public function getModalEdit($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $role = $this->getRoleFromParams($params);
-
- // If the role doesn't exist, return 404
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- /** @var UserFrosting\I18n\MessageTranslator $translator */
- $translator = $this->ci->translator;
-
- // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "slug", "description" for this role
- $fieldNames = ['name', 'slug', 'description'];
- if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
- 'role' => $role,
- 'fields' => $fieldNames
- ])) {
- throw new ForbiddenException();
- }
-
- // Generate form
- $fields = [
- 'hidden' => [],
- 'disabled' => []
- ];
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/role/edit-info.yaml');
- $validator = new JqueryValidationAdapter($schema, $translator);
-
- return $this->ci->view->render($response, 'modals/role.html.twig', [
- 'role' => $role,
- 'form' => [
- 'action' => "api/roles/r/{$role->slug}",
- 'method' => 'PUT',
- 'fields' => $fields,
- 'submit_text' => $translator->translate('UPDATE')
- ],
- 'page' => [
- 'validators' => $validator->rules('json', FALSE)
- ]
- ]);
- }
-
- /**
- * Renders the modal form for editing a role's permissions.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- */
- public function getModalEditPermissions($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $role = $this->getRoleFromParams($params);
-
- // If the role doesn't exist, return 404
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit "permissions" field for this role
- if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
- 'role' => $role,
- 'fields' => ['permissions']
- ])) {
- throw new ForbiddenException();
- }
-
- return $this->ci->view->render($response, 'modals/role-manage-permissions.html.twig', [
- 'role' => $role
- ]);
- }
-
- /**
- * Returns a list of Permissions for a specified Role.
- *
- * Generates a list of permissions, optionally paginated, sorted and/or filtered.
- * This page requires authentication.
- * Request type: GET
- */
- public function getPermissions($request, $response, $args) {
- $role = $this->getRoleFromParams($args);
-
- // If the role no longer exists, forward to main role listing page
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'view_role_field', [
- 'role' => $role,
- 'property' => 'permissions'
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $sprunje = $classMapper->createInstance('permission_sprunje', $classMapper, $params);
- $sprunje->extendQuery(function ($query) use ($role) {
- return $query->forRole($role->id);
- });
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- /**
- * Returns users associated with a single role.
- *
- * This page requires authentication.
- * Request type: GET
- */
- public function getUsers($request, $response, $args) {
- $role = $this->getRoleFromParams($args);
-
- // If the role doesn't exist, return 404
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'view_role_field', [
- 'role' => $role,
- 'property' => 'users'
- ])) {
- throw new ForbiddenException();
- }
-
- $sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params);
- $sprunje->extendQuery(function ($query) use ($role) {
- return $query->forRole($role->id);
- });
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- /**
- * Renders a page displaying a role's information, in read-only mode.
- *
- * This checks that the currently logged-in user has permission to view the requested role's info.
- * It checks each field individually, showing only those that you have permission to view.
- * This will also try to show buttons for deleting and editing the role.
- * This page requires authentication.
- * Request type: GET
- */
- public function pageInfo($request, $response, $args) {
- $role = $this->getRoleFromParams($args);
-
- // If the role no longer exists, forward to main role listing page
- if (!$role) {
- $redirectPage = $this->ci->router->pathFor('uri_roles');
- return $response->withRedirect($redirectPage, 404);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_role', [
- 'role' => $role
- ])) {
- throw new ForbiddenException();
- }
-
- // Determine fields that currentUser is authorized to view
- $fieldNames = ['name', 'slug', 'description'];
-
- // Generate form
- $fields = [
- 'hidden' => []
- ];
-
- foreach ($fieldNames as $field) {
- if (!$authorizer->checkAccess($currentUser, 'view_role_field', [
- 'role' => $role,
- 'property' => $field
- ])) {
- $fields['hidden'][] = $field;
- }
- }
-
- // Determine buttons to display
- $editButtons = [
- 'hidden' => []
- ];
-
- if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
- 'role' => $role,
- 'fields' => ['name', 'slug', 'description']
- ])) {
- $editButtons['hidden'][] = 'edit';
- }
-
- if (!$authorizer->checkAccess($currentUser, 'delete_role', [
- 'role' => $role
- ])) {
- $editButtons['hidden'][] = 'delete';
- }
-
- return $this->ci->view->render($response, 'pages/role.html.twig', [
- 'role' => $role,
- 'fields' => $fields,
- 'tools' => $editButtons
- ]);
- }
-
- /**
- * Renders the role listing page.
- *
- * This page renders a table of roles, with dropdown menus for admin actions for each role.
- * Actions typically include: edit role, delete role.
- * This page requires authentication.
- * Request type: GET
- */
- public function pageList($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_roles')) {
- throw new ForbiddenException();
- }
-
- return $this->ci->view->render($response, 'pages/roles.html.twig');
- }
-
- /**
- * Processes the request to update an existing role's details.
- *
- * Processes the request from the role update form, checking that:
- * 1. The role name/slug are not already in use;
- * 2. The user has the necessary permissions to update the posted field(s);
- * 3. The submitted data is valid.
- * This route requires authentication (and should generally be limited to admins or the root user).
- * Request type: PUT
- * @see getModalRoleEdit
- */
- public function updateInfo($request, $response, $args) {
- // Get the role based on slug in the URL
- $role = $this->getRoleFromParams($args);
-
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Get PUT parameters: (name, slug, description)
- $params = $request->getParsedBody();
-
- /** @var UserFrosting\I18n\MessageTranslator $translator */
- $ms = $this->ci->alerts;
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/role/edit-info.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate request data
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- // Determine targeted fields
- $fieldNames = [];
- foreach ($data as $name => $value) {
- $fieldNames[] = $name;
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit submitted fields for this role
- if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
- 'role' => $role,
- 'fields' => array_values(array_unique($fieldNames))
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check if name or slug already exists
- if (
- isset($data['name']) &&
- $data['name'] != $role->name &&
- $classMapper->staticMethod('role', 'where', 'name', $data['name'])->first()
- ) {
- $ms->addMessageTranslated('danger', 'ROLE.NAME_IN_USE', $data);
- $error = TRUE;
- }
-
- if (
- isset($data['slug']) &&
- $data['slug'] != $role->slug &&
- $classMapper->staticMethod('role', 'where', 'slug', $data['slug'])->first()
- ) {
- $ms->addMessageTranslated('danger', 'SLUG_IN_USE', $data);
- $error = TRUE;
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($data, $role, $currentUser) {
- // Update the role and generate success messages
- foreach ($data as $name => $value) {
- if ($value != $role->$name) {
- $role->$name = $value;
- }
- }
-
- $role->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated details for role {$role->name}.", [
- 'type' => 'role_update_info',
- 'user_id' => $currentUser->id
- ]);
- });
-
- $ms->addMessageTranslated('success', 'ROLE.UPDATED', [
- 'name' => $role->name
- ]);
-
- return $response->withStatus(200);
- }
-
- /**
- * Processes the request to update a specific field for an existing role, including permissions.
- *
- * Processes the request from the role update form, checking that:
- * 1. The logged-in user has the necessary permissions to update the putted field(s);
- * 2. The submitted data is valid.
- * This route requires authentication.
- * Request type: PUT
- */
- public function updateField($request, $response, $args) {
- // Get the username from the URL
- $role = $this->getRoleFromParams($args);
-
- if (!$role) {
- throw new NotFoundException($request, $response);
- }
-
- // Get key->value pair from URL and request body
- $fieldName = $args['field'];
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit the specified field for this user
- if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
- 'role' => $role,
- 'fields' => [$fieldName]
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Get PUT parameters: value
- $put = $request->getParsedBody();
-
- if (!isset($put['value'])) {
- throw new BadRequestException();
- }
-
- $params = [
- $fieldName => $put['value']
- ];
-
- // Validate key -> value pair
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/role/edit-field.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and throw exception on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $e = new BadRequestException();
- foreach ($validator->errors() as $idx => $field) {
- foreach ($field as $eidx => $error) {
- $e->addUserMessage($error);
- }
- }
- throw $e;
- }
-
- // Get validated and transformed value
- $fieldValue = $data[$fieldName];
-
- /** @var UserFrosting\I18n\MessageTranslator $translator */
- $ms = $this->ci->alerts;
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($fieldName, $fieldValue, $role, $currentUser) {
- if ($fieldName == 'permissions') {
- $newPermissions = collect($fieldValue)->pluck('permission_id')->all();
- $role->permissions()->sync($newPermissions);
- } else {
- $role->$fieldName = $fieldValue;
- $role->save();
- }
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated property '$fieldName' for role {$role->name}.", [
- 'type' => 'role_update_field',
- 'user_id' => $currentUser->id
- ]);
- });
-
- // Add success messages
- if ($fieldName == 'permissions') {
- $ms->addMessageTranslated('success', 'ROLE.PERMISSIONS_UPDATED', [
- 'name' => $role->name
- ]);
- } else {
- $ms->addMessageTranslated('success', 'ROLE.UPDATED', [
- 'name' => $role->name
- ]);
- }
-
- return $response->withStatus(200);
- }
-
- protected function getRoleFromParams($params) {
- // Load the request schema
- $schema = new RequestSchema('schema://requests/role/get-by-slug.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and throw exception on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- // encapsulate the communication of error messages from ServerSideValidator to the BadRequestException
- $e = new BadRequestException();
- foreach ($validator->errors() as $idx => $field) {
- foreach ($field as $eidx => $error) {
- $e->addUserMessage($error);
- }
- }
- throw $e;
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Get the role
- $role = $classMapper->staticMethod('role', 'where', 'slug', $data['slug'])
- ->first();
-
- return $role;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use Carbon\Carbon;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Slim\Exception\NotFoundException;
+use UserFrosting\Fortress\RequestDataTransformer;
+use UserFrosting\Fortress\RequestSchema;
+use UserFrosting\Fortress\ServerSideValidator;
+use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
+use UserFrosting\Sprinkle\Account\Database\Models\Role;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Controller class for role-related requests, including listing roles, CRUD for roles, etc.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class RoleController extends SimpleController
+{
+ /**
+ * Processes the request to create a new role.
+ *
+ * Processes the request from the role creation form, checking that:
+ * 1. The role name and slug are not already in use;
+ * 2. The user has permission to create a new role;
+ * 3. The submitted data is valid.
+ * This route requires authentication (and should generally be limited to admins or the root user).
+ * Request type: POST
+ * @see getModalCreateRole
+ */
+ public function create($request, $response, $args) {
+ // Get POST parameters: name, slug, description
+ $params = $request->getParsedBody();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'create_role')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/role/create.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate request data
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check if name or slug already exists
+ if ($classMapper->staticMethod('role', 'where', 'name', $data['name'])->first()) {
+ $ms->addMessageTranslated('danger', 'ROLE.NAME_IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($classMapper->staticMethod('role', 'where', 'slug', $data['slug'])->first()) {
+ $ms->addMessageTranslated('danger', 'SLUG_IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // All checks passed! log events/activities and create role
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) {
+ // Create the role
+ $role = $classMapper->createInstance('role', $data);
+
+ // Store new role to database
+ $role->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} created role {$role->name}.", [
+ 'type' => 'role_create',
+ 'user_id' => $currentUser->id
+ ]);
+
+ $ms->addMessageTranslated('success', 'ROLE.CREATION_SUCCESSFUL', $data);
+ });
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes the request to delete an existing role.
+ *
+ * Deletes the specified role.
+ * Before doing so, checks that:
+ * 1. The user has permission to delete this role;
+ * 2. The role is not a default for new users;
+ * 3. The role does not have any associated users;
+ * 4. The submitted data is valid.
+ * This route requires authentication (and should generally be limited to admins or the root user).
+ * Request type: DELETE
+ */
+ public function delete($request, $response, $args) {
+ $role = $this->getRoleFromParams($args);
+
+ // If the role doesn't exist, return 404
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'delete_role', [
+ 'role' => $role
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check that we are not deleting a default role
+ $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs');
+
+ // Need to use loose comparison for now, because some DBs return `id` as a string
+ if (in_array($role->slug, $defaultRoleSlugs)) {
+ $e = new BadRequestException();
+ $e->addUserMessage('ROLE.DELETE_DEFAULT');
+ throw $e;
+ }
+
+ // Check if there are any users associated with this role
+ $countUsers = $role->users()->count();
+ if ($countUsers > 0) {
+ $e = new BadRequestException();
+ $e->addUserMessage('ROLE.HAS_USERS');
+ throw $e;
+ }
+
+ $roleName = $role->name;
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($role, $roleName, $currentUser) {
+ $role->delete();
+ unset($role);
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted role {$roleName}.", [
+ 'type' => 'role_delete',
+ 'user_id' => $currentUser->id
+ ]);
+ });
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ $ms->addMessageTranslated('success', 'ROLE.DELETION_SUCCESSFUL', [
+ 'name' => $roleName
+ ]);
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Returns info for a single role, along with associated permissions.
+ *
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getInfo($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_roles')) {
+ throw new ForbiddenException();
+ }
+
+ $slug = $args['slug'];
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $role = $classMapper->staticMethod('role', 'where', 'slug', $slug)->first();
+
+ // If the role doesn't exist, return 404
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ // Get role
+ $result = $role->load('permissions')->toArray();
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $response->withJson($result, 200, JSON_PRETTY_PRINT);
+ }
+
+ /**
+ * Returns a list of Roles
+ *
+ * Generates a list of roles, optionally paginated, sorted and/or filtered.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getList($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_roles')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $sprunje = $classMapper->createInstance('role_sprunje', $classMapper, $params);
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ public function getModalConfirmDelete($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $role = $this->getRoleFromParams($params);
+
+ // If the role no longer exists, forward to main role listing page
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'delete_role', [
+ 'role' => $role
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check that we are not deleting a default role
+ $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs');
+
+ // Need to use loose comparison for now, because some DBs return `id` as a string
+ if (in_array($role->slug, $defaultRoleSlugs)) {
+ $e = new BadRequestException();
+ $e->addUserMessage('ROLE.DELETE_DEFAULT', $role->toArray());
+ throw $e;
+ }
+
+ // Check if there are any users associated with this role
+ $countUsers = $role->users()->count();
+ if ($countUsers > 0) {
+ $e = new BadRequestException();
+ $e->addUserMessage('ROLE.HAS_USERS', $role->toArray());
+ throw $e;
+ }
+
+ return $this->ci->view->render($response, 'modals/confirm-delete-role.html.twig', [
+ 'role' => $role,
+ 'form' => [
+ 'action' => "api/roles/r/{$role->slug}",
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for creating a new role.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getModalCreate($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ /** @var UserFrosting\I18n\MessageTranslator $translator */
+ $translator = $this->ci->translator;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'create_role')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Create a dummy role to prepopulate fields
+ $role = $classMapper->createInstance('role', []);
+
+ $fieldNames = ['name', 'slug', 'description'];
+ $fields = [
+ 'hidden' => [],
+ 'disabled' => []
+ ];
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/role/create.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'modals/role.html.twig', [
+ 'role' => $role,
+ 'form' => [
+ 'action' => 'api/roles',
+ 'method' => 'POST',
+ 'fields' => $fields,
+ 'submit_text' => $translator->translate('CREATE')
+ ],
+ 'page' => [
+ 'validators' => $validator->rules('json', FALSE)
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for editing an existing role.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getModalEdit($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $role = $this->getRoleFromParams($params);
+
+ // If the role doesn't exist, return 404
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ /** @var UserFrosting\I18n\MessageTranslator $translator */
+ $translator = $this->ci->translator;
+
+ // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "slug", "description" for this role
+ $fieldNames = ['name', 'slug', 'description'];
+ if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
+ 'role' => $role,
+ 'fields' => $fieldNames
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ // Generate form
+ $fields = [
+ 'hidden' => [],
+ 'disabled' => []
+ ];
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/role/edit-info.yaml');
+ $validator = new JqueryValidationAdapter($schema, $translator);
+
+ return $this->ci->view->render($response, 'modals/role.html.twig', [
+ 'role' => $role,
+ 'form' => [
+ 'action' => "api/roles/r/{$role->slug}",
+ 'method' => 'PUT',
+ 'fields' => $fields,
+ 'submit_text' => $translator->translate('UPDATE')
+ ],
+ 'page' => [
+ 'validators' => $validator->rules('json', FALSE)
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for editing a role's permissions.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getModalEditPermissions($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $role = $this->getRoleFromParams($params);
+
+ // If the role doesn't exist, return 404
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit "permissions" field for this role
+ if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
+ 'role' => $role,
+ 'fields' => ['permissions']
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ return $this->ci->view->render($response, 'modals/role-manage-permissions.html.twig', [
+ 'role' => $role
+ ]);
+ }
+
+ /**
+ * Returns a list of Permissions for a specified Role.
+ *
+ * Generates a list of permissions, optionally paginated, sorted and/or filtered.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getPermissions($request, $response, $args) {
+ $role = $this->getRoleFromParams($args);
+
+ // If the role no longer exists, forward to main role listing page
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'view_role_field', [
+ 'role' => $role,
+ 'property' => 'permissions'
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $sprunje = $classMapper->createInstance('permission_sprunje', $classMapper, $params);
+ $sprunje->extendQuery(function ($query) use ($role) {
+ return $query->forRole($role->id);
+ });
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ /**
+ * Returns users associated with a single role.
+ *
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function getUsers($request, $response, $args) {
+ $role = $this->getRoleFromParams($args);
+
+ // If the role doesn't exist, return 404
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'view_role_field', [
+ 'role' => $role,
+ 'property' => 'users'
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ $sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params);
+ $sprunje->extendQuery(function ($query) use ($role) {
+ return $query->forRole($role->id);
+ });
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ /**
+ * Renders a page displaying a role's information, in read-only mode.
+ *
+ * This checks that the currently logged-in user has permission to view the requested role's info.
+ * It checks each field individually, showing only those that you have permission to view.
+ * This will also try to show buttons for deleting and editing the role.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function pageInfo($request, $response, $args) {
+ $role = $this->getRoleFromParams($args);
+
+ // If the role no longer exists, forward to main role listing page
+ if (!$role) {
+ $redirectPage = $this->ci->router->pathFor('uri_roles');
+ return $response->withRedirect($redirectPage, 404);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_role', [
+ 'role' => $role
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ // Determine fields that currentUser is authorized to view
+ $fieldNames = ['name', 'slug', 'description'];
+
+ // Generate form
+ $fields = [
+ 'hidden' => []
+ ];
+
+ foreach ($fieldNames as $field) {
+ if (!$authorizer->checkAccess($currentUser, 'view_role_field', [
+ 'role' => $role,
+ 'property' => $field
+ ])) {
+ $fields['hidden'][] = $field;
+ }
+ }
+
+ // Determine buttons to display
+ $editButtons = [
+ 'hidden' => []
+ ];
+
+ if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
+ 'role' => $role,
+ 'fields' => ['name', 'slug', 'description']
+ ])) {
+ $editButtons['hidden'][] = 'edit';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'delete_role', [
+ 'role' => $role
+ ])) {
+ $editButtons['hidden'][] = 'delete';
+ }
+
+ return $this->ci->view->render($response, 'pages/role.html.twig', [
+ 'role' => $role,
+ 'fields' => $fields,
+ 'tools' => $editButtons
+ ]);
+ }
+
+ /**
+ * Renders the role listing page.
+ *
+ * This page renders a table of roles, with dropdown menus for admin actions for each role.
+ * Actions typically include: edit role, delete role.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function pageList($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_roles')) {
+ throw new ForbiddenException();
+ }
+
+ return $this->ci->view->render($response, 'pages/roles.html.twig');
+ }
+
+ /**
+ * Processes the request to update an existing role's details.
+ *
+ * Processes the request from the role update form, checking that:
+ * 1. The role name/slug are not already in use;
+ * 2. The user has the necessary permissions to update the posted field(s);
+ * 3. The submitted data is valid.
+ * This route requires authentication (and should generally be limited to admins or the root user).
+ * Request type: PUT
+ * @see getModalRoleEdit
+ */
+ public function updateInfo($request, $response, $args) {
+ // Get the role based on slug in the URL
+ $role = $this->getRoleFromParams($args);
+
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Get PUT parameters: (name, slug, description)
+ $params = $request->getParsedBody();
+
+ /** @var UserFrosting\I18n\MessageTranslator $translator */
+ $ms = $this->ci->alerts;
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/role/edit-info.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate request data
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ // Determine targeted fields
+ $fieldNames = [];
+ foreach ($data as $name => $value) {
+ $fieldNames[] = $name;
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit submitted fields for this role
+ if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
+ 'role' => $role,
+ 'fields' => array_values(array_unique($fieldNames))
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check if name or slug already exists
+ if (
+ isset($data['name']) &&
+ $data['name'] != $role->name &&
+ $classMapper->staticMethod('role', 'where', 'name', $data['name'])->first()
+ ) {
+ $ms->addMessageTranslated('danger', 'ROLE.NAME_IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if (
+ isset($data['slug']) &&
+ $data['slug'] != $role->slug &&
+ $classMapper->staticMethod('role', 'where', 'slug', $data['slug'])->first()
+ ) {
+ $ms->addMessageTranslated('danger', 'SLUG_IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($data, $role, $currentUser) {
+ // Update the role and generate success messages
+ foreach ($data as $name => $value) {
+ if ($value != $role->$name) {
+ $role->$name = $value;
+ }
+ }
+
+ $role->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated details for role {$role->name}.", [
+ 'type' => 'role_update_info',
+ 'user_id' => $currentUser->id
+ ]);
+ });
+
+ $ms->addMessageTranslated('success', 'ROLE.UPDATED', [
+ 'name' => $role->name
+ ]);
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes the request to update a specific field for an existing role, including permissions.
+ *
+ * Processes the request from the role update form, checking that:
+ * 1. The logged-in user has the necessary permissions to update the putted field(s);
+ * 2. The submitted data is valid.
+ * This route requires authentication.
+ * Request type: PUT
+ */
+ public function updateField($request, $response, $args) {
+ // Get the username from the URL
+ $role = $this->getRoleFromParams($args);
+
+ if (!$role) {
+ throw new NotFoundException($request, $response);
+ }
+
+ // Get key->value pair from URL and request body
+ $fieldName = $args['field'];
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit the specified field for this user
+ if (!$authorizer->checkAccess($currentUser, 'update_role_field', [
+ 'role' => $role,
+ 'fields' => [$fieldName]
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Get PUT parameters: value
+ $put = $request->getParsedBody();
+
+ if (!isset($put['value'])) {
+ throw new BadRequestException();
+ }
+
+ $params = [
+ $fieldName => $put['value']
+ ];
+
+ // Validate key -> value pair
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/role/edit-field.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and throw exception on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $e = new BadRequestException();
+ foreach ($validator->errors() as $idx => $field) {
+ foreach ($field as $eidx => $error) {
+ $e->addUserMessage($error);
+ }
+ }
+ throw $e;
+ }
+
+ // Get validated and transformed value
+ $fieldValue = $data[$fieldName];
+
+ /** @var UserFrosting\I18n\MessageTranslator $translator */
+ $ms = $this->ci->alerts;
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($fieldName, $fieldValue, $role, $currentUser) {
+ if ($fieldName == 'permissions') {
+ $newPermissions = collect($fieldValue)->pluck('permission_id')->all();
+ $role->permissions()->sync($newPermissions);
+ } else {
+ $role->$fieldName = $fieldValue;
+ $role->save();
+ }
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated property '$fieldName' for role {$role->name}.", [
+ 'type' => 'role_update_field',
+ 'user_id' => $currentUser->id
+ ]);
+ });
+
+ // Add success messages
+ if ($fieldName == 'permissions') {
+ $ms->addMessageTranslated('success', 'ROLE.PERMISSIONS_UPDATED', [
+ 'name' => $role->name
+ ]);
+ } else {
+ $ms->addMessageTranslated('success', 'ROLE.UPDATED', [
+ 'name' => $role->name
+ ]);
+ }
+
+ return $response->withStatus(200);
+ }
+
+ protected function getRoleFromParams($params) {
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/role/get-by-slug.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and throw exception on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ // encapsulate the communication of error messages from ServerSideValidator to the BadRequestException
+ $e = new BadRequestException();
+ foreach ($validator->errors() as $idx => $field) {
+ foreach ($field as $eidx => $error) {
+ $e->addUserMessage($error);
+ }
+ }
+ throw $e;
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Get the role
+ $role = $classMapper->staticMethod('role', 'where', 'slug', $data['slug'])
+ ->first();
+
+ return $role;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Controller/SearchController.php b/main/app/sprinkles/admin/src/Controller/SearchController.php
index 2398a56..612b886 100644
--- a/main/app/sprinkles/admin/src/Controller/SearchController.php
+++ b/main/app/sprinkles/admin/src/Controller/SearchController.php
@@ -1,56 +1,56 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use function GuzzleHttp\Psr7\str;
-use UserFrosting\Fortress\RequestDataTransformer;
-use UserFrosting\Fortress\RequestSchema;
-use UserFrosting\Fortress\ServerSideValidator;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\NotFoundException;
-use Slim\Http\Request;
-use Slim\Http\Response;
-use Illuminate\Database\Capsule\Manager as DB;
-
-/**
- * Controller class for user-related requests, including listing users, CRUD for users, etc.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class SearchController extends SimpleController
-{
-
- /**
- * Searches a user by name, username and email // TODO: Maybe not allowed to search everyone?
- *
- * @param Request $request
- * @param Response $response
- * @param $args
- * @return Response
- * @throws NotFoundException
- */
- public function ByUsername(Request $request, Response $response, $args) {
- $classMapper = $this->ci->classMapper;
- $users = $classMapper->createInstance('user')
- ->where("first_name", "like", "%" . $args["search_term"] . "%")
- ->orWhere("last_name", "like", "%" . $args["search_term"] . "%")
- ->orWhere(DB::raw("CONCAT(`first_name`, ' ', `last_name`)"), 'LIKE', "%" . $args["search_term"] . "%")
- ->orWhere("user_name", "like", "%" . $args["search_term"] . "%")
- ->get();
-
- foreach ($users as $number => $user) {
- $users[$number]["avatar"] = $user->avatar;
- }
-
- if (count($users) === 0) throw new NotFoundException();
- return $response->withJson($users, 200, JSON_PRETTY_PRINT);
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use function GuzzleHttp\Psr7\str;
+use UserFrosting\Fortress\RequestDataTransformer;
+use UserFrosting\Fortress\RequestSchema;
+use UserFrosting\Fortress\ServerSideValidator;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\NotFoundException;
+use Slim\Http\Request;
+use Slim\Http\Response;
+use Illuminate\Database\Capsule\Manager as DB;
+
+/**
+ * Controller class for user-related requests, including listing users, CRUD for users, etc.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class SearchController extends SimpleController
+{
+
+ /**
+ * Searches a user by name, username and email // TODO: Maybe not allowed to search everyone?
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param $args
+ * @return Response
+ * @throws NotFoundException
+ */
+ public function ByUsername(Request $request, Response $response, $args) {
+ $classMapper = $this->ci->classMapper;
+ $users = $classMapper->createInstance('user')
+ ->where("first_name", "like", "%" . $args["search_term"] . "%")
+ ->orWhere("last_name", "like", "%" . $args["search_term"] . "%")
+ ->orWhere(DB::raw("CONCAT(`first_name`, ' ', `last_name`)"), 'LIKE', "%" . $args["search_term"] . "%")
+ ->orWhere("user_name", "like", "%" . $args["search_term"] . "%")
+ ->get();
+
+ foreach ($users as $number => $user) {
+ $users[$number]["avatar"] = $user->avatar;
+ }
+
+ if (count($users) === 0) throw new NotFoundException();
+ return $response->withJson($users, 200, JSON_PRETTY_PRINT);
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Controller/UserController.php b/main/app/sprinkles/admin/src/Controller/UserController.php
index 45f9919..d66f2f1 100644
--- a/main/app/sprinkles/admin/src/Controller/UserController.php
+++ b/main/app/sprinkles/admin/src/Controller/UserController.php
@@ -1,1516 +1,1516 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use Carbon\Carbon;
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use Slim\Exception\NotFoundException;
-use UserFrosting\Fortress\RequestDataTransformer;
-use UserFrosting\Fortress\RequestSchema;
-use UserFrosting\Fortress\ServerSideValidator;
-use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
-use UserFrosting\Sprinkle\Account\Database\Models\Group;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-use UserFrosting\Sprinkle\Account\Facades\Password;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Sprinkle\Core\Mail\EmailRecipient;
-use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Controller class for user-related requests, including listing users, CRUD for users, etc.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class UserController extends SimpleController
-{
- /**
- * Processes the request to create a new user (from the admin controls).
- *
- * Processes the request from the user creation form, checking that:
- * 1. The username and email are not already in use;
- * 2. The logged-in user has the necessary permissions to update the posted field(s);
- * 3. The submitted data is valid.
- * This route requires authentication.
- * Request type: POST
- * @see getModalCreate
- * @throws ForbiddenException
- * @throws BadRequestException
- * @throws ForbiddenException
- */
- public function create($request, $response, $args) {
- // Get POST parameters: user_name, first_name, last_name, email, locale, (group)
- $params = $request->getParsedBody();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'create_user')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/user/create.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate request data
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check if username or email already exists
- if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) {
- $ms->addMessageTranslated('danger', 'USERNAME.IN_USE', $data);
- $error = TRUE;
- }
-
- if ($classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) {
- $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data);
- $error = TRUE;
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // If currentUser does not have permission to set the group, but they try to set it to something other than their own group,
- // throw an exception.
- if (!$authorizer->checkAccess($currentUser, 'create_user_field', [
- 'fields' => ['group']
- ])) {
- if (isset($data['group_id']) && $data['group_id'] != $currentUser->group_id) {
- throw new ForbiddenException();
- }
- }
-
- // In any case, set the group id if not otherwise set
- if (!isset($data['group_id'])) {
- $data['group_id'] = $currentUser->group_id;
- }
-
- $data['flag_verified'] = 1;
- // Set password as empty on initial creation. We will then send email so new user can set it themselves via a verification token
- $data['password'] = '';
-
- // All checks passed! log events/activities, create user, and send verification email (if required)
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) {
- // Create the user
- $user = $classMapper->createInstance('user', $data);
-
- // Store new user to database
- $user->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} created a new account for {$user->user_name}.", [
- 'type' => 'account_create',
- 'user_id' => $currentUser->id
- ]);
-
- // Load default roles
- $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs');
- $defaultRoles = $classMapper->staticMethod('role', 'whereIn', 'slug', $defaultRoleSlugs)->get();
- $defaultRoleIds = $defaultRoles->pluck('id')->all();
-
- // Attach default roles
- $user->roles()->attach($defaultRoleIds);
-
- // Try to generate a new password request
- $passwordRequest = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.create']);
-
- // Create and send welcome email with password set link
- $message = new TwigMailMessage($this->ci->view, 'mail/password-create.html.twig');
-
- $message->from($config['address_book.admin'])
- ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
- ->addParams([
- 'user' => $user,
- 'create_password_expiration' => $config['password_reset.timeouts.create'] / 3600 . ' hours',
- 'token' => $passwordRequest->getToken()
- ]);
-
- $this->ci->mailer->send($message);
-
- $ms->addMessageTranslated('success', 'USER.CREATED', $data);
- });
-
- return $response->withStatus(200);
- }
-
- /**
- * Processes the request to send a user a password reset email.
- *
- * Processes the request from the user update form, checking that:
- * 1. The target user's new email address, if specified, is not already in use;
- * 2. The logged-in user has the necessary permissions to update the posted field(s);
- * 3. We're not trying to disable the master account;
- * 4. The submitted data is valid.
- * This route requires authentication.
- * Request type: POST
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function createPasswordReset($request, $response, $args) {
- // Get the username from the URL
- $user = $this->getUserFromParams($args);
-
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit "password" for this user
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['password']
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($user, $config) {
-
- // Create a password reset and shoot off an email
- $passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']);
-
- // Create and send welcome email with password set link
- $message = new TwigMailMessage($this->ci->view, 'mail/password-reset.html.twig');
-
- $message->from($config['address_book.admin'])
- ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
- ->addParams([
- 'user' => $user,
- 'token' => $passwordReset->getToken(),
- 'request_date' => Carbon::now()->format('Y-m-d H:i:s')
- ]);
-
- $this->ci->mailer->send($message);
- });
-
- $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', [
- 'email' => $user->email
- ]);
- return $response->withStatus(200);
- }
-
-
- /**
- * Sets the users public key
- * Request type: POST
- * @throws NotFoundException
- * @throws BadRequestException
- * @throws ForbiddenException
- */
- public function setPublicKey($request, $response, $args) {
- $requestedUser = $this->getUserFromParams($args);
-
- if (!$requestedUser) {
- throw new NotFoundException($request, $response);
- }
-
- $PublicKey = $request->getParsedBody()["PublicKey"];
-
- if ($this->ci->currentUser->id === $requestedUser->id && (Capsule::table('public_keys')
- ->where('user_id', "=", $requestedUser->id)
- ->exists()) === FALSE) {
- Capsule::table('public_keys')
- ->insert(['user_id' => $requestedUser->id, 'key' => substr(substr($PublicKey, 100), 0, -40)]);
- return $response->withStatus(200);
- } else if ($this->ci->currentUser->id === $requestedUser->id) {
- Capsule::table('public_keys')
- ->where('user_id', $requestedUser->id)
- ->update(['key' => substr(substr($PublicKey, 100), 0, -40)]);
- return $response->withStatus(200);
- } else {
- throw new ForbiddenException();
- }
- }
-
- /**
- * Processes the request to delete an existing user.
- *
- * Deletes the specified user, removing any existing associations.
- * Before doing so, checks that:
- * 1. You are not trying to delete the master account;
- * 2. You have permission to delete the target user's account.
- * This route requires authentication (and should generally be limited to admins or the root user).
- * Request type: DELETE
- * @throws BadRequestException
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function delete($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'delete_user', [
- 'user' => $user
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Check that we are not deleting the master account
- // Need to use loose comparison for now, because some DBs return `id` as a string
- if ($user->id == $config['reserved_user_ids.master']) {
- $e = new BadRequestException();
- $e->addUserMessage('DELETE_MASTER');
- throw $e;
- }
-
- $userName = $user->user_name;
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($user, $userName, $currentUser) {
- $user->delete();
- unset($user);
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted the account for {$userName}.", [
- 'type' => 'account_delete',
- 'user_id' => $currentUser->id
- ]);
- });
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- $ms->addMessageTranslated('success', 'DELETION_SUCCESSFUL', [
- 'user_name' => $userName
- ]);
-
- return $response->withStatus(200);
- }
-
- /**
- * Returns activity history for a single user.
- *
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getActivities($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
- 'user' => $user,
- 'property' => 'activities'
- ])) {
- throw new ForbiddenException();
- }
-
- $sprunje = $classMapper->createInstance('activity_sprunje', $classMapper, $params);
-
- $sprunje->extendQuery(function ($query) use ($user) {
- return $query->where('user_id', $user->id);
- });
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- /**
- * Returns info for a single user.
- *
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getInfo($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Join user's most recent activity
- $user = $classMapper->createInstance('user')
- ->where('user_name', $user->user_name)
- ->joinLastActivity()
- ->with('lastActivity', 'group')
- ->first();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_user', [
- 'user' => $user
- ])) {
- throw new ForbiddenException();
- }
-
- $result = $user->toArray();
- $result["avatar"] = $user->avatar;
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $response->withJson($result, 200, JSON_PRETTY_PRINT);
- }
-
- /**
- * Returns a list of Users
- *
- * Generates a list of users, optionally paginated, sorted and/or filtered.
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- */
- public function getList($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_users')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params);
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- /**
- * Renders the modal form to confirm user deletion.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- * @throws BadRequestException
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getModalConfirmDelete($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $user = $this->getUserFromParams($params);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'delete_user', [
- 'user' => $user
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Check that we are not deleting the master account
- // Need to use loose comparison for now, because some DBs return `id` as a string
- if ($user->id == $config['reserved_user_ids.master']) {
- $e = new BadRequestException();
- $e->addUserMessage('DELETE_MASTER');
- throw $e;
- }
-
- return $this->ci->view->render($response, 'modals/confirm-delete-user.html.twig', [
- 'user' => $user,
- 'form' => [
- 'action' => "api/users/u/{$user->user_name}",
- ]
- ]);
- }
-
- /**
- * Renders the modal form for creating a new user.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
- * If the currently logged-in user has permission to modify user group membership, then the group toggle will be displayed.
- * Otherwise, the user will be added to the default group and receive the default roles automatically.
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- */
- public function getModalCreate($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- /** @var UserFrosting\I18n\MessageTranslator $translator */
- $translator = $this->ci->translator;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'create_user')) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Determine form fields to hide/disable
- $fields = [
- 'hidden' => ['theme'],
- 'disabled' => []
- ];
-
- // Get a list of all locales
- $locales = $config->getDefined('site.locales.available');
-
- // Determine if currentUser has permission to modify the group. If so, show the 'group' dropdown.
- // Otherwise, set to the currentUser's group and disable the dropdown.
- if ($authorizer->checkAccess($currentUser, 'create_user_field', [
- 'fields' => ['group']
- ])) {
- // Get a list of all groups
- $groups = $classMapper->staticMethod('group', 'all');
- } else {
- // Get the current user's group
- $groups = $currentUser->group()->get();
- $fields['disabled'][] = 'group';
- }
-
- // Create a dummy user to prepopulate fields
- $data = [
- 'group_id' => $currentUser->group_id,
- 'locale' => $config['site.registration.user_defaults.locale'],
- 'theme' => ''
- ];
-
- $user = $classMapper->createInstance('user', $data);
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/user/create.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'modals/user.html.twig', [
- 'user' => $user,
- 'groups' => $groups,
- 'locales' => $locales,
- 'form' => [
- 'action' => 'api/users',
- 'method' => 'POST',
- 'fields' => $fields,
- 'submit_text' => $translator->translate('CREATE')
- ],
- 'page' => [
- 'validators' => $validator->rules('json', FALSE)
- ]
- ]);
- }
-
- /**
- * Renders the modal form for editing an existing user.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getModalEdit($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $user = $this->getUserFromParams($params);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Get the user to edit
- $user = $classMapper->staticMethod('user', 'where', 'user_name', $user->user_name)
- ->with('group')
- ->first();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "email", "locale" for this user
- $fieldNames = ['name', 'email', 'locale'];
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => $fieldNames
- ])) {
- throw new ForbiddenException();
- }
-
- // Get a list of all groups
- $groups = $classMapper->staticMethod('group', 'all');
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Get a list of all locales
- $locales = $config->getDefined('site.locales.available');
-
- // Generate form
- $fields = [
- 'hidden' => ['theme'],
- 'disabled' => ['user_name']
- ];
-
- // Disable group field if currentUser doesn't have permission to modify group
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['group']
- ])) {
- $fields['disabled'][] = 'group';
- }
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/user/edit-info.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- $translator = $this->ci->translator;
-
- return $this->ci->view->render($response, 'modals/user.html.twig', [
- 'user' => $user,
- 'groups' => $groups,
- 'locales' => $locales,
- 'form' => [
- 'action' => "api/users/u/{$user->user_name}",
- 'method' => 'PUT',
- 'fields' => $fields,
- 'submit_text' => $translator->translate('UPDATE')
- ],
- 'page' => [
- 'validators' => $validator->rules('json', FALSE)
- ]
- ]);
- }
-
- /**
- * Renders the modal form for editing a user's password.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getModalEditPassword($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $user = $this->getUserFromParams($params);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit "password" field for this user
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['password']
- ])) {
- throw new ForbiddenException();
- }
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/user/edit-password.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'modals/user-set-password.html.twig', [
- 'user' => $user,
- 'page' => [
- 'validators' => $validator->rules('json', FALSE)
- ]
- ]);
- }
-
- /**
- * Renders the modal form for editing a user's roles.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages.
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getModalEditRoles($request, $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- $user = $this->getUserFromParams($params);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit "roles" field for this user
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['roles']
- ])) {
- throw new ForbiddenException();
- }
-
- return $this->ci->view->render($response, 'modals/user-manage-roles.html.twig', [
- 'user' => $user
- ]);
- }
-
- /**
- * Returns a list of effective Permissions for a specified User.
- *
- * Generates a list of permissions, optionally paginated, sorted and/or filtered.
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getPermissions($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
- 'user' => $user,
- 'property' => 'permissions'
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $params['user_id'] = $user->id;
- $sprunje = $classMapper->createInstance('user_permission_sprunje', $classMapper, $params);
-
- $response = $sprunje->toResponse($response);
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $response;
- }
-
- /**
- * Returns roles associated with a single user.
- *
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getRoles($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
- 'user' => $user,
- 'property' => 'roles'
- ])) {
- throw new ForbiddenException();
- }
-
- $sprunje = $classMapper->createInstance('role_sprunje', $classMapper, $params);
- $sprunje->extendQuery(function ($query) use ($user) {
- return $query->forUser($user->id);
- });
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $sprunje->toResponse($response);
- }
-
- /**
- * Renders a page displaying a user's information, in read-only mode.
- *
- * This checks that the currently logged-in user has permission to view the requested user's info.
- * It checks each field individually, showing only those that you have permission to view.
- * This will also try to show buttons for activating, disabling/enabling, deleting, and editing the user.
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- * @throws BadRequestException
- */
- public function pageInfo($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user no longer exists, forward to main user listing page
- if (!$user) {
- $usersPage = $this->ci->router->pathFor('uri_users');
- return $response->withRedirect($usersPage, 404);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_user', [
- 'user' => $user
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Get a list of all locales
- $locales = $config->getDefined('site.locales.available');
-
- // Determine fields that currentUser is authorized to view
- $fieldNames = ['user_name', 'name', 'email', 'locale', 'group', 'roles'];
-
- // Generate form
- $fields = [
- // Always hide these
- 'hidden' => ['theme']
- ];
-
- // Determine which fields should be hidden
- foreach ($fieldNames as $field) {
- if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
- 'user' => $user,
- 'property' => $field
- ])) {
- $fields['hidden'][] = $field;
- }
- }
-
- // Determine buttons to display
- $editButtons = [
- 'hidden' => []
- ];
-
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['name', 'email', 'locale']
- ])) {
- $editButtons['hidden'][] = 'edit';
- }
-
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['flag_enabled']
- ])) {
- $editButtons['hidden'][] = 'enable';
- }
-
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['flag_verified']
- ])) {
- $editButtons['hidden'][] = 'activate';
- }
-
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['password']
- ])) {
- $editButtons['hidden'][] = 'password';
- }
-
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => ['roles']
- ])) {
- $editButtons['hidden'][] = 'roles';
- }
-
- if (!$authorizer->checkAccess($currentUser, 'delete_user', [
- 'user' => $user
- ])) {
- $editButtons['hidden'][] = 'delete';
- }
-
- // Determine widgets to display
- $widgets = [
- 'hidden' => []
- ];
-
- if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
- 'user' => $user,
- 'property' => 'permissions'
- ])) {
- $widgets['hidden'][] = 'permissions';
- }
-
- if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
- 'user' => $user,
- 'property' => 'activities'
- ])) {
- $widgets['hidden'][] = 'activities';
- }
-
- return $this->ci->view->render($response, 'pages/user.html.twig', [
- 'user' => $user,
- 'locales' => $locales,
- 'fields' => $fields,
- 'tools' => $editButtons,
- 'widgets' => $widgets
- ]);
- }
-
- /**
- * Renders the user listing page.
- *
- * This page renders a table of users, with dropdown menus for admin actions for each user.
- * Actions typically include: edit user details, activate user, enable/disable user, delete user.
- * This page requires authentication.
- * Request type: GET
- * @throws ForbiddenException
- */
- public function pageList($request, $response, $args) {
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_users')) {
- throw new ForbiddenException();
- }
-
- return $this->ci->view->render($response, 'pages/users.html.twig');
- }
-
- /**
- * Gets the users public key
- * Request type: GET
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getPublicKey($request, $response, $args) {
- $requestedUser = $this->getUserFromParams($args);
-
- if (!$requestedUser) {
- throw new NotFoundException($request, $response);
- }
-
- if ((Capsule::table('public_keys')
- ->where('user_id', "=", $requestedUser->id)
- ->exists())) {
-
- $RawPublicKey = Capsule::table('public_keys')
- ->where('user_id', "=", $requestedUser->id)
- ->value('key');
- $PublicKey = "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: OpenPGP.js v3.0.9\nComment: https://openpgpjs.org\n\n" . $RawPublicKey . "\n-----END PGP PUBLIC KEY BLOCK-----";
-
- $ContentType = explode(',', $request->getHeaderLine('Accept'))[0];
- switch ($ContentType) {
- case 'application/json':
- $response->write(json_encode(array('user_id' => $requestedUser->id, 'PublicKey' => $PublicKey)));
- break;
- case 'text/html':
- $response->write("<pre>" . $PublicKey);
- break;
- default:
- $response->write($PublicKey);
- }
- return $response->withStatus(200);
- } else {
- throw new NotFoundException($request, $response);
- }
- }
-
- /**
- * Gets the users which are following the requested user
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getFollowers($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_user', [
- 'user' => $user
- ])) {
- throw new ForbiddenException();
- }
-
- $UsersFollowers = Capsule::table('user_follow')
- ->where('user_id', "=", $user->id)
- ->join("users", "users.id", "=", "user_follow.followed_by_id")
- ->select("user_follow.followed_by_id as id", "users.user_name as username")
- ->get();
-
- $result = $UsersFollowers->toArray();
-
- return $response->withJson($result, 200, JSON_PRETTY_PRINT);
- }
-
- /**
- * Get users which the user follows
- * Request type: GET
- * @throws ForbiddenException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function getFollows($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (($user->id == $currentUser->id) || (!$authorizer->checkAccess($currentUser, 'uri_user', [
- 'user' => $user
- ]))) {
- throw new ForbiddenException();
- }
-
- $UsersFollows = Capsule::table('user_follow')
- ->where('followed_by_id', "=", $user->id)
- ->join("users", "users.id", "=", "user_follow.user_id")
- ->select("user_follow.user_id as id", "users.user_name as username")
- ->get();
-
- $result = $UsersFollows->toArray();
-
- return $response->withJson($result, 200, JSON_PRETTY_PRINT);
- }
-
- /**
- * Get users which the user follows and which are following the user
- * Request type: GET
- * @throws NotFoundException
- * @throws ForbiddenException
- * @throws BadRequestException
- */
- public function getFriends($request, $response, $args) {
- $user = $this->getUserFromParams($args);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_user', [
- 'user' => $user
- ])) {
- throw new ForbiddenException();
- }
-
- $UsersFriends = Capsule::select("SELECT id FROM (SELECT user_id AS id FROM user_follow WHERE followed_by_id = $user->id UNION ALL SELECT followed_by_id FROM user_follow WHERE user_id = $user->id) t GROUP BY id HAVING COUNT(id) > 1");
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- foreach ($UsersFriends as $Key => $UsersFriendId) { // NOT THAT EFFICIENT...
- $UsersFriendInformation = $classMapper->createInstance('user')// raw select doesnt work with instance
- ->where('id', $UsersFriendId->id)
- ->get();
-
- $UsersFriends[$Key]->id = $UsersFriendInformation[0]->id;
- $UsersFriends[$Key]->username = $UsersFriendInformation[0]->user_name;
- $UsersFriends[$Key]->avatar = $UsersFriendInformation[0]->avatar;
- $UsersFriends[$Key]->full_name = $UsersFriendInformation[0]->full_name;
- }
-
- $result = $UsersFriends;
-
- if (sizeof($result) > 0) { // USER HAS FRIENDS
- return $response->withJson($result, 200, JSON_PRETTY_PRINT);
- } else {
- throw new NotFoundException($request, $response);
- }
- }
-
-
- /**
- * Processes the request to update an existing user's basic details (first_name, last_name, email, locale, group_id)
- *
- * Processes the request from the user update form, checking that:
- * 1. The target user's new email address, if specified, is not already in use;
- * 2. The logged-in user has the necessary permissions to update the putted field(s);
- * 3. The submitted data is valid.
- * This route requires authentication.
- * Request type: PUT
- * @throws NotFoundException
- * @throws ForbiddenException
- * @throws BadRequestException
- * @throws BadRequestException
- */
- public function updateInfo($request, $response, $args) {
- // Get the username from the URL
- $user = $this->getUserFromParams($args);
-
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Get PUT parameters
- $params = $request->getParsedBody();
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/user/edit-info.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate request data
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- // Determine targeted fields
- $fieldNames = [];
- foreach ($data as $name => $value) {
- if ($name == 'first_name' || $name == 'last_name') {
- $fieldNames[] = 'name';
- } else if ($name == 'group_id') {
- $fieldNames[] = 'group';
- } else {
- $fieldNames[] = $name;
- }
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit submitted fields for this user
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => array_values(array_unique($fieldNames))
- ])) {
- throw new ForbiddenException();
- }
-
- // Only the master account can edit the master account!
- if (
- ($user->id == $config['reserved_user_ids.master']) &&
- ($currentUser->id != $config['reserved_user_ids.master'])
- ) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Check if email already exists
- if (
- isset($data['email']) &&
- $data['email'] != $user->email &&
- $classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')
- ) {
- $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data);
- $error = TRUE;
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($data, $user, $currentUser) {
- // Update the user and generate success messages
- foreach ($data as $name => $value) {
- if ($value != $user->$name) {
- $user->$name = $value;
- }
- }
-
- $user->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated basic account info for user {$user->user_name}.", [
- 'type' => 'account_update_info',
- 'user_id' => $currentUser->id
- ]);
- });
-
- $ms->addMessageTranslated('success', 'DETAILS_UPDATED', [
- 'user_name' => $user->user_name
- ]);
- return $response->withStatus(200);
- }
-
- /**
- * Processes the request to update a specific field for an existing user.
- *
- * Supports editing all user fields, including password, enabled/disabled status and verification status.
- * Processes the request from the user update form, checking that:
- * 1. The logged-in user has the necessary permissions to update the putted field(s);
- * 2. We're not trying to disable the master account;
- * 3. The submitted data is valid.
- * This route requires authentication.
- * Request type: PUT
- * @throws ForbiddenException
- * @throws BadRequestException
- * @throws BadRequestException
- * @throws BadRequestException
- * @throws BadRequestException
- * @throws BadRequestException
- * @throws NotFoundException
- * @throws BadRequestException
- */
- public function updateField($request, $response, $args) {
- // Get the username from the URL
- $user = $this->getUserFromParams($args);
-
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- // Get key->value pair from URL and request body
- $fieldName = $args['field'];
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
- $authorizer = $this->ci->authorizer;
-
- /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled resource - check that currentUser has permission to edit the specified field for this user
- if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
- 'user' => $user,
- 'fields' => [$fieldName]
- ])) {
- throw new ForbiddenException();
- }
-
- /** @var UserFrosting\Config\Config $config */
- $config = $this->ci->config;
-
- // Only the master account can edit the master account!
- if (
- ($user->id == $config['reserved_user_ids.master']) &&
- ($currentUser->id != $config['reserved_user_ids.master'])
- ) {
- throw new ForbiddenException();
- }
-
- // Get PUT parameters: value
- $put = $request->getParsedBody();
-
- if (!isset($put['value'])) {
- throw new BadRequestException();
- }
-
- // Create and validate key -> value pair
- $params = [
- $fieldName => $put['value']
- ];
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/user/edit-field.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and throw exception on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- // encapsulate the communication of error messages from ServerSideValidator to the BadRequestException
- $e = new BadRequestException();
- foreach ($validator->errors() as $idx => $field) {
- foreach ($field as $eidx => $error) {
- $e->addUserMessage($error);
- }
- }
- throw $e;
- }
-
- // Get validated and transformed value
- $fieldValue = $data[$fieldName];
-
- /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
- $ms = $this->ci->alerts;
-
- // Special checks and transformations for certain fields
- if ($fieldName == 'flag_enabled') {
- // Check that we are not disabling the master account
- if (
- ($user->id == $config['reserved_user_ids.master']) &&
- ($fieldValue == '0')
- ) {
- $e = new BadRequestException();
- $e->addUserMessage('DISABLE_MASTER');
- throw $e;
- } else if (
- ($user->id == $currentUser->id) &&
- ($fieldValue == '0')
- ) {
- $e = new BadRequestException();
- $e->addUserMessage('DISABLE_SELF');
- throw $e;
- }
- } else if ($fieldName == 'password') {
- $fieldValue = Password::hash($fieldValue);
- }
-
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($fieldName, $fieldValue, $user, $currentUser) {
- if ($fieldName == 'roles') {
- $newRoles = collect($fieldValue)->pluck('role_id')->all();
- $user->roles()->sync($newRoles);
- } else {
- $user->$fieldName = $fieldValue;
- $user->save();
- }
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated property '$fieldName' for user {$user->user_name}.", [
- 'type' => 'account_update_field',
- 'user_id' => $currentUser->id
- ]);
- });
-
- // Add success messages
- if ($fieldName == 'flag_enabled') {
- if ($fieldValue == '1') {
- $ms->addMessageTranslated('success', 'ENABLE_SUCCESSFUL', [
- 'user_name' => $user->user_name
- ]);
- } else {
- $ms->addMessageTranslated('success', 'DISABLE_SUCCESSFUL', [
- 'user_name' => $user->user_name
- ]);
- }
- } else if ($fieldName == 'flag_verified') {
- $ms->addMessageTranslated('success', 'MANUALLY_ACTIVATED', [
- 'user_name' => $user->user_name
- ]);
- } else {
- $ms->addMessageTranslated('success', 'DETAILS_UPDATED', [
- 'user_name' => $user->user_name
- ]);
- }
-
- return $response->withStatus(200);
- }
-
- protected function getUserFromParams($params) {
- // Load the request schema
- $schema = new RequestSchema('schema://requests/user/get-by-username.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and throw exception on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $e = new BadRequestException();
- foreach ($validator->errors() as $idx => $field) {
- foreach ($field as $eidx => $error) {
- $e->addUserMessage($error);
- }
- }
- throw $e;
- }
-
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- // Get the user to delete
- $user = $classMapper->staticMethod('user', 'where', 'user_name', $data['user_name'])
- ->first();
-
- return $user;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use Carbon\Carbon;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Slim\Exception\NotFoundException;
+use UserFrosting\Fortress\RequestDataTransformer;
+use UserFrosting\Fortress\RequestSchema;
+use UserFrosting\Fortress\ServerSideValidator;
+use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
+use UserFrosting\Sprinkle\Account\Database\Models\Group;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\Account\Facades\Password;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Sprinkle\Core\Mail\EmailRecipient;
+use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Controller class for user-related requests, including listing users, CRUD for users, etc.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class UserController extends SimpleController
+{
+ /**
+ * Processes the request to create a new user (from the admin controls).
+ *
+ * Processes the request from the user creation form, checking that:
+ * 1. The username and email are not already in use;
+ * 2. The logged-in user has the necessary permissions to update the posted field(s);
+ * 3. The submitted data is valid.
+ * This route requires authentication.
+ * Request type: POST
+ * @see getModalCreate
+ * @throws ForbiddenException
+ * @throws BadRequestException
+ * @throws ForbiddenException
+ */
+ public function create($request, $response, $args) {
+ // Get POST parameters: user_name, first_name, last_name, email, locale, (group)
+ $params = $request->getParsedBody();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'create_user')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/user/create.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate request data
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check if username or email already exists
+ if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) {
+ $ms->addMessageTranslated('danger', 'USERNAME.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) {
+ $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // If currentUser does not have permission to set the group, but they try to set it to something other than their own group,
+ // throw an exception.
+ if (!$authorizer->checkAccess($currentUser, 'create_user_field', [
+ 'fields' => ['group']
+ ])) {
+ if (isset($data['group_id']) && $data['group_id'] != $currentUser->group_id) {
+ throw new ForbiddenException();
+ }
+ }
+
+ // In any case, set the group id if not otherwise set
+ if (!isset($data['group_id'])) {
+ $data['group_id'] = $currentUser->group_id;
+ }
+
+ $data['flag_verified'] = 1;
+ // Set password as empty on initial creation. We will then send email so new user can set it themselves via a verification token
+ $data['password'] = '';
+
+ // All checks passed! log events/activities, create user, and send verification email (if required)
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) {
+ // Create the user
+ $user = $classMapper->createInstance('user', $data);
+
+ // Store new user to database
+ $user->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} created a new account for {$user->user_name}.", [
+ 'type' => 'account_create',
+ 'user_id' => $currentUser->id
+ ]);
+
+ // Load default roles
+ $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs');
+ $defaultRoles = $classMapper->staticMethod('role', 'whereIn', 'slug', $defaultRoleSlugs)->get();
+ $defaultRoleIds = $defaultRoles->pluck('id')->all();
+
+ // Attach default roles
+ $user->roles()->attach($defaultRoleIds);
+
+ // Try to generate a new password request
+ $passwordRequest = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.create']);
+
+ // Create and send welcome email with password set link
+ $message = new TwigMailMessage($this->ci->view, 'mail/password-create.html.twig');
+
+ $message->from($config['address_book.admin'])
+ ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
+ ->addParams([
+ 'user' => $user,
+ 'create_password_expiration' => $config['password_reset.timeouts.create'] / 3600 . ' hours',
+ 'token' => $passwordRequest->getToken()
+ ]);
+
+ $this->ci->mailer->send($message);
+
+ $ms->addMessageTranslated('success', 'USER.CREATED', $data);
+ });
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes the request to send a user a password reset email.
+ *
+ * Processes the request from the user update form, checking that:
+ * 1. The target user's new email address, if specified, is not already in use;
+ * 2. The logged-in user has the necessary permissions to update the posted field(s);
+ * 3. We're not trying to disable the master account;
+ * 4. The submitted data is valid.
+ * This route requires authentication.
+ * Request type: POST
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function createPasswordReset($request, $response, $args) {
+ // Get the username from the URL
+ $user = $this->getUserFromParams($args);
+
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit "password" for this user
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['password']
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($user, $config) {
+
+ // Create a password reset and shoot off an email
+ $passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']);
+
+ // Create and send welcome email with password set link
+ $message = new TwigMailMessage($this->ci->view, 'mail/password-reset.html.twig');
+
+ $message->from($config['address_book.admin'])
+ ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
+ ->addParams([
+ 'user' => $user,
+ 'token' => $passwordReset->getToken(),
+ 'request_date' => Carbon::now()->format('Y-m-d H:i:s')
+ ]);
+
+ $this->ci->mailer->send($message);
+ });
+
+ $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', [
+ 'email' => $user->email
+ ]);
+ return $response->withStatus(200);
+ }
+
+
+ /**
+ * Sets the users public key
+ * Request type: POST
+ * @throws NotFoundException
+ * @throws BadRequestException
+ * @throws ForbiddenException
+ */
+ public function setPublicKey($request, $response, $args) {
+ $requestedUser = $this->getUserFromParams($args);
+
+ if (!$requestedUser) {
+ throw new NotFoundException($request, $response);
+ }
+
+ $PublicKey = $request->getParsedBody()["PublicKey"];
+
+ if ($this->ci->currentUser->id === $requestedUser->id && (Capsule::table('public_keys')
+ ->where('user_id', "=", $requestedUser->id)
+ ->exists()) === FALSE) {
+ Capsule::table('public_keys')
+ ->insert(['user_id' => $requestedUser->id, 'key' => substr(substr($PublicKey, 100), 0, -40)]);
+ return $response->withStatus(200);
+ } else if ($this->ci->currentUser->id === $requestedUser->id) {
+ Capsule::table('public_keys')
+ ->where('user_id', $requestedUser->id)
+ ->update(['key' => substr(substr($PublicKey, 100), 0, -40)]);
+ return $response->withStatus(200);
+ } else {
+ throw new ForbiddenException();
+ }
+ }
+
+ /**
+ * Processes the request to delete an existing user.
+ *
+ * Deletes the specified user, removing any existing associations.
+ * Before doing so, checks that:
+ * 1. You are not trying to delete the master account;
+ * 2. You have permission to delete the target user's account.
+ * This route requires authentication (and should generally be limited to admins or the root user).
+ * Request type: DELETE
+ * @throws BadRequestException
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function delete($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'delete_user', [
+ 'user' => $user
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Check that we are not deleting the master account
+ // Need to use loose comparison for now, because some DBs return `id` as a string
+ if ($user->id == $config['reserved_user_ids.master']) {
+ $e = new BadRequestException();
+ $e->addUserMessage('DELETE_MASTER');
+ throw $e;
+ }
+
+ $userName = $user->user_name;
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($user, $userName, $currentUser) {
+ $user->delete();
+ unset($user);
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted the account for {$userName}.", [
+ 'type' => 'account_delete',
+ 'user_id' => $currentUser->id
+ ]);
+ });
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ $ms->addMessageTranslated('success', 'DELETION_SUCCESSFUL', [
+ 'user_name' => $userName
+ ]);
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Returns activity history for a single user.
+ *
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getActivities($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
+ 'user' => $user,
+ 'property' => 'activities'
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ $sprunje = $classMapper->createInstance('activity_sprunje', $classMapper, $params);
+
+ $sprunje->extendQuery(function ($query) use ($user) {
+ return $query->where('user_id', $user->id);
+ });
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ /**
+ * Returns info for a single user.
+ *
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getInfo($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Join user's most recent activity
+ $user = $classMapper->createInstance('user')
+ ->where('user_name', $user->user_name)
+ ->joinLastActivity()
+ ->with('lastActivity', 'group')
+ ->first();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_user', [
+ 'user' => $user
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ $result = $user->toArray();
+ $result["avatar"] = $user->avatar;
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $response->withJson($result, 200, JSON_PRETTY_PRINT);
+ }
+
+ /**
+ * Returns a list of Users
+ *
+ * Generates a list of users, optionally paginated, sorted and/or filtered.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ */
+ public function getList($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_users')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params);
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ /**
+ * Renders the modal form to confirm user deletion.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws BadRequestException
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getModalConfirmDelete($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $user = $this->getUserFromParams($params);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'delete_user', [
+ 'user' => $user
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Check that we are not deleting the master account
+ // Need to use loose comparison for now, because some DBs return `id` as a string
+ if ($user->id == $config['reserved_user_ids.master']) {
+ $e = new BadRequestException();
+ $e->addUserMessage('DELETE_MASTER');
+ throw $e;
+ }
+
+ return $this->ci->view->render($response, 'modals/confirm-delete-user.html.twig', [
+ 'user' => $user,
+ 'form' => [
+ 'action' => "api/users/u/{$user->user_name}",
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for creating a new user.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
+ * If the currently logged-in user has permission to modify user group membership, then the group toggle will be displayed.
+ * Otherwise, the user will be added to the default group and receive the default roles automatically.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ */
+ public function getModalCreate($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ /** @var UserFrosting\I18n\MessageTranslator $translator */
+ $translator = $this->ci->translator;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'create_user')) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Determine form fields to hide/disable
+ $fields = [
+ 'hidden' => ['theme'],
+ 'disabled' => []
+ ];
+
+ // Get a list of all locales
+ $locales = $config->getDefined('site.locales.available');
+
+ // Determine if currentUser has permission to modify the group. If so, show the 'group' dropdown.
+ // Otherwise, set to the currentUser's group and disable the dropdown.
+ if ($authorizer->checkAccess($currentUser, 'create_user_field', [
+ 'fields' => ['group']
+ ])) {
+ // Get a list of all groups
+ $groups = $classMapper->staticMethod('group', 'all');
+ } else {
+ // Get the current user's group
+ $groups = $currentUser->group()->get();
+ $fields['disabled'][] = 'group';
+ }
+
+ // Create a dummy user to prepopulate fields
+ $data = [
+ 'group_id' => $currentUser->group_id,
+ 'locale' => $config['site.registration.user_defaults.locale'],
+ 'theme' => ''
+ ];
+
+ $user = $classMapper->createInstance('user', $data);
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/user/create.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'modals/user.html.twig', [
+ 'user' => $user,
+ 'groups' => $groups,
+ 'locales' => $locales,
+ 'form' => [
+ 'action' => 'api/users',
+ 'method' => 'POST',
+ 'fields' => $fields,
+ 'submit_text' => $translator->translate('CREATE')
+ ],
+ 'page' => [
+ 'validators' => $validator->rules('json', FALSE)
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for editing an existing user.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getModalEdit($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $user = $this->getUserFromParams($params);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Get the user to edit
+ $user = $classMapper->staticMethod('user', 'where', 'user_name', $user->user_name)
+ ->with('group')
+ ->first();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "email", "locale" for this user
+ $fieldNames = ['name', 'email', 'locale'];
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => $fieldNames
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ // Get a list of all groups
+ $groups = $classMapper->staticMethod('group', 'all');
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Get a list of all locales
+ $locales = $config->getDefined('site.locales.available');
+
+ // Generate form
+ $fields = [
+ 'hidden' => ['theme'],
+ 'disabled' => ['user_name']
+ ];
+
+ // Disable group field if currentUser doesn't have permission to modify group
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['group']
+ ])) {
+ $fields['disabled'][] = 'group';
+ }
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/user/edit-info.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ $translator = $this->ci->translator;
+
+ return $this->ci->view->render($response, 'modals/user.html.twig', [
+ 'user' => $user,
+ 'groups' => $groups,
+ 'locales' => $locales,
+ 'form' => [
+ 'action' => "api/users/u/{$user->user_name}",
+ 'method' => 'PUT',
+ 'fields' => $fields,
+ 'submit_text' => $translator->translate('UPDATE')
+ ],
+ 'page' => [
+ 'validators' => $validator->rules('json', FALSE)
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for editing a user's password.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getModalEditPassword($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $user = $this->getUserFromParams($params);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit "password" field for this user
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['password']
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/user/edit-password.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'modals/user-set-password.html.twig', [
+ 'user' => $user,
+ 'page' => [
+ 'validators' => $validator->rules('json', FALSE)
+ ]
+ ]);
+ }
+
+ /**
+ * Renders the modal form for editing a user's roles.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getModalEditRoles($request, $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ $user = $this->getUserFromParams($params);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit "roles" field for this user
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['roles']
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ return $this->ci->view->render($response, 'modals/user-manage-roles.html.twig', [
+ 'user' => $user
+ ]);
+ }
+
+ /**
+ * Returns a list of effective Permissions for a specified User.
+ *
+ * Generates a list of permissions, optionally paginated, sorted and/or filtered.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getPermissions($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
+ 'user' => $user,
+ 'property' => 'permissions'
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $params['user_id'] = $user->id;
+ $sprunje = $classMapper->createInstance('user_permission_sprunje', $classMapper, $params);
+
+ $response = $sprunje->toResponse($response);
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $response;
+ }
+
+ /**
+ * Returns roles associated with a single user.
+ *
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getRoles($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
+ 'user' => $user,
+ 'property' => 'roles'
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ $sprunje = $classMapper->createInstance('role_sprunje', $classMapper, $params);
+ $sprunje->extendQuery(function ($query) use ($user) {
+ return $query->forUser($user->id);
+ });
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $sprunje->toResponse($response);
+ }
+
+ /**
+ * Renders a page displaying a user's information, in read-only mode.
+ *
+ * This checks that the currently logged-in user has permission to view the requested user's info.
+ * It checks each field individually, showing only those that you have permission to view.
+ * This will also try to show buttons for activating, disabling/enabling, deleting, and editing the user.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws BadRequestException
+ */
+ public function pageInfo($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user no longer exists, forward to main user listing page
+ if (!$user) {
+ $usersPage = $this->ci->router->pathFor('uri_users');
+ return $response->withRedirect($usersPage, 404);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_user', [
+ 'user' => $user
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Get a list of all locales
+ $locales = $config->getDefined('site.locales.available');
+
+ // Determine fields that currentUser is authorized to view
+ $fieldNames = ['user_name', 'name', 'email', 'locale', 'group', 'roles'];
+
+ // Generate form
+ $fields = [
+ // Always hide these
+ 'hidden' => ['theme']
+ ];
+
+ // Determine which fields should be hidden
+ foreach ($fieldNames as $field) {
+ if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
+ 'user' => $user,
+ 'property' => $field
+ ])) {
+ $fields['hidden'][] = $field;
+ }
+ }
+
+ // Determine buttons to display
+ $editButtons = [
+ 'hidden' => []
+ ];
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['name', 'email', 'locale']
+ ])) {
+ $editButtons['hidden'][] = 'edit';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['flag_enabled']
+ ])) {
+ $editButtons['hidden'][] = 'enable';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['flag_verified']
+ ])) {
+ $editButtons['hidden'][] = 'activate';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['password']
+ ])) {
+ $editButtons['hidden'][] = 'password';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['roles']
+ ])) {
+ $editButtons['hidden'][] = 'roles';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'delete_user', [
+ 'user' => $user
+ ])) {
+ $editButtons['hidden'][] = 'delete';
+ }
+
+ // Determine widgets to display
+ $widgets = [
+ 'hidden' => []
+ ];
+
+ if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
+ 'user' => $user,
+ 'property' => 'permissions'
+ ])) {
+ $widgets['hidden'][] = 'permissions';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
+ 'user' => $user,
+ 'property' => 'activities'
+ ])) {
+ $widgets['hidden'][] = 'activities';
+ }
+
+ return $this->ci->view->render($response, 'pages/user.html.twig', [
+ 'user' => $user,
+ 'locales' => $locales,
+ 'fields' => $fields,
+ 'tools' => $editButtons,
+ 'widgets' => $widgets
+ ]);
+ }
+
+ /**
+ * Renders the user listing page.
+ *
+ * This page renders a table of users, with dropdown menus for admin actions for each user.
+ * Actions typically include: edit user details, activate user, enable/disable user, delete user.
+ * This page requires authentication.
+ * Request type: GET
+ * @throws ForbiddenException
+ */
+ public function pageList($request, $response, $args) {
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_users')) {
+ throw new ForbiddenException();
+ }
+
+ return $this->ci->view->render($response, 'pages/users.html.twig');
+ }
+
+ /**
+ * Gets the users public key
+ * Request type: GET
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getPublicKey($request, $response, $args) {
+ $requestedUser = $this->getUserFromParams($args);
+
+ if (!$requestedUser) {
+ throw new NotFoundException($request, $response);
+ }
+
+ if ((Capsule::table('public_keys')
+ ->where('user_id', "=", $requestedUser->id)
+ ->exists())) {
+
+ $RawPublicKey = Capsule::table('public_keys')
+ ->where('user_id', "=", $requestedUser->id)
+ ->value('key');
+ $PublicKey = "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: OpenPGP.js v3.0.9\nComment: https://openpgpjs.org\n\n" . $RawPublicKey . "\n-----END PGP PUBLIC KEY BLOCK-----";
+
+ $ContentType = explode(',', $request->getHeaderLine('Accept'))[0];
+ switch ($ContentType) {
+ case 'application/json':
+ $response->write(json_encode(array('user_id' => $requestedUser->id, 'PublicKey' => $PublicKey)));
+ break;
+ case 'text/html':
+ $response->write("<pre>" . $PublicKey);
+ break;
+ default:
+ $response->write($PublicKey);
+ }
+ return $response->withStatus(200);
+ } else {
+ throw new NotFoundException($request, $response);
+ }
+ }
+
+ /**
+ * Gets the users which are following the requested user
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getFollowers($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_user', [
+ 'user' => $user
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ $UsersFollowers = Capsule::table('user_follow')
+ ->where('user_id', "=", $user->id)
+ ->join("users", "users.id", "=", "user_follow.followed_by_id")
+ ->select("user_follow.followed_by_id as id", "users.user_name as username")
+ ->get();
+
+ $result = $UsersFollowers->toArray();
+
+ return $response->withJson($result, 200, JSON_PRETTY_PRINT);
+ }
+
+ /**
+ * Get users which the user follows
+ * Request type: GET
+ * @throws ForbiddenException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function getFollows($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (($user->id == $currentUser->id) || (!$authorizer->checkAccess($currentUser, 'uri_user', [
+ 'user' => $user
+ ]))) {
+ throw new ForbiddenException();
+ }
+
+ $UsersFollows = Capsule::table('user_follow')
+ ->where('followed_by_id', "=", $user->id)
+ ->join("users", "users.id", "=", "user_follow.user_id")
+ ->select("user_follow.user_id as id", "users.user_name as username")
+ ->get();
+
+ $result = $UsersFollows->toArray();
+
+ return $response->withJson($result, 200, JSON_PRETTY_PRINT);
+ }
+
+ /**
+ * Get users which the user follows and which are following the user
+ * Request type: GET
+ * @throws NotFoundException
+ * @throws ForbiddenException
+ * @throws BadRequestException
+ */
+ public function getFriends($request, $response, $args) {
+ $user = $this->getUserFromParams($args);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_user', [
+ 'user' => $user
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ $UsersFriends = Capsule::select("SELECT id FROM (SELECT user_id AS id FROM user_follow WHERE followed_by_id = $user->id UNION ALL SELECT followed_by_id FROM user_follow WHERE user_id = $user->id) t GROUP BY id HAVING COUNT(id) > 1");
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ foreach ($UsersFriends as $Key => $UsersFriendId) { // NOT THAT EFFICIENT...
+ $UsersFriendInformation = $classMapper->createInstance('user')// raw select doesnt work with instance
+ ->where('id', $UsersFriendId->id)
+ ->get();
+
+ $UsersFriends[$Key]->id = $UsersFriendInformation[0]->id;
+ $UsersFriends[$Key]->username = $UsersFriendInformation[0]->user_name;
+ $UsersFriends[$Key]->avatar = $UsersFriendInformation[0]->avatar;
+ $UsersFriends[$Key]->full_name = $UsersFriendInformation[0]->full_name;
+ }
+
+ $result = $UsersFriends;
+
+ if (sizeof($result) > 0) { // USER HAS FRIENDS
+ return $response->withJson($result, 200, JSON_PRETTY_PRINT);
+ } else {
+ throw new NotFoundException($request, $response);
+ }
+ }
+
+
+ /**
+ * Processes the request to update an existing user's basic details (first_name, last_name, email, locale, group_id)
+ *
+ * Processes the request from the user update form, checking that:
+ * 1. The target user's new email address, if specified, is not already in use;
+ * 2. The logged-in user has the necessary permissions to update the putted field(s);
+ * 3. The submitted data is valid.
+ * This route requires authentication.
+ * Request type: PUT
+ * @throws NotFoundException
+ * @throws ForbiddenException
+ * @throws BadRequestException
+ * @throws BadRequestException
+ */
+ public function updateInfo($request, $response, $args) {
+ // Get the username from the URL
+ $user = $this->getUserFromParams($args);
+
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Get PUT parameters
+ $params = $request->getParsedBody();
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/user/edit-info.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate request data
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ // Determine targeted fields
+ $fieldNames = [];
+ foreach ($data as $name => $value) {
+ if ($name == 'first_name' || $name == 'last_name') {
+ $fieldNames[] = 'name';
+ } else if ($name == 'group_id') {
+ $fieldNames[] = 'group';
+ } else {
+ $fieldNames[] = $name;
+ }
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit submitted fields for this user
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => array_values(array_unique($fieldNames))
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ // Only the master account can edit the master account!
+ if (
+ ($user->id == $config['reserved_user_ids.master']) &&
+ ($currentUser->id != $config['reserved_user_ids.master'])
+ ) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Check if email already exists
+ if (
+ isset($data['email']) &&
+ $data['email'] != $user->email &&
+ $classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')
+ ) {
+ $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($data, $user, $currentUser) {
+ // Update the user and generate success messages
+ foreach ($data as $name => $value) {
+ if ($value != $user->$name) {
+ $user->$name = $value;
+ }
+ }
+
+ $user->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated basic account info for user {$user->user_name}.", [
+ 'type' => 'account_update_info',
+ 'user_id' => $currentUser->id
+ ]);
+ });
+
+ $ms->addMessageTranslated('success', 'DETAILS_UPDATED', [
+ 'user_name' => $user->user_name
+ ]);
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes the request to update a specific field for an existing user.
+ *
+ * Supports editing all user fields, including password, enabled/disabled status and verification status.
+ * Processes the request from the user update form, checking that:
+ * 1. The logged-in user has the necessary permissions to update the putted field(s);
+ * 2. We're not trying to disable the master account;
+ * 3. The submitted data is valid.
+ * This route requires authentication.
+ * Request type: PUT
+ * @throws ForbiddenException
+ * @throws BadRequestException
+ * @throws BadRequestException
+ * @throws BadRequestException
+ * @throws BadRequestException
+ * @throws BadRequestException
+ * @throws NotFoundException
+ * @throws BadRequestException
+ */
+ public function updateField($request, $response, $args) {
+ // Get the username from the URL
+ $user = $this->getUserFromParams($args);
+
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ // Get key->value pair from URL and request body
+ $fieldName = $args['field'];
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled resource - check that currentUser has permission to edit the specified field for this user
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => [$fieldName]
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Only the master account can edit the master account!
+ if (
+ ($user->id == $config['reserved_user_ids.master']) &&
+ ($currentUser->id != $config['reserved_user_ids.master'])
+ ) {
+ throw new ForbiddenException();
+ }
+
+ // Get PUT parameters: value
+ $put = $request->getParsedBody();
+
+ if (!isset($put['value'])) {
+ throw new BadRequestException();
+ }
+
+ // Create and validate key -> value pair
+ $params = [
+ $fieldName => $put['value']
+ ];
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/user/edit-field.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and throw exception on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ // encapsulate the communication of error messages from ServerSideValidator to the BadRequestException
+ $e = new BadRequestException();
+ foreach ($validator->errors() as $idx => $field) {
+ foreach ($field as $eidx => $error) {
+ $e->addUserMessage($error);
+ }
+ }
+ throw $e;
+ }
+
+ // Get validated and transformed value
+ $fieldValue = $data[$fieldName];
+
+ /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */
+ $ms = $this->ci->alerts;
+
+ // Special checks and transformations for certain fields
+ if ($fieldName == 'flag_enabled') {
+ // Check that we are not disabling the master account
+ if (
+ ($user->id == $config['reserved_user_ids.master']) &&
+ ($fieldValue == '0')
+ ) {
+ $e = new BadRequestException();
+ $e->addUserMessage('DISABLE_MASTER');
+ throw $e;
+ } else if (
+ ($user->id == $currentUser->id) &&
+ ($fieldValue == '0')
+ ) {
+ $e = new BadRequestException();
+ $e->addUserMessage('DISABLE_SELF');
+ throw $e;
+ }
+ } else if ($fieldName == 'password') {
+ $fieldValue = Password::hash($fieldValue);
+ }
+
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($fieldName, $fieldValue, $user, $currentUser) {
+ if ($fieldName == 'roles') {
+ $newRoles = collect($fieldValue)->pluck('role_id')->all();
+ $user->roles()->sync($newRoles);
+ } else {
+ $user->$fieldName = $fieldValue;
+ $user->save();
+ }
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated property '$fieldName' for user {$user->user_name}.", [
+ 'type' => 'account_update_field',
+ 'user_id' => $currentUser->id
+ ]);
+ });
+
+ // Add success messages
+ if ($fieldName == 'flag_enabled') {
+ if ($fieldValue == '1') {
+ $ms->addMessageTranslated('success', 'ENABLE_SUCCESSFUL', [
+ 'user_name' => $user->user_name
+ ]);
+ } else {
+ $ms->addMessageTranslated('success', 'DISABLE_SUCCESSFUL', [
+ 'user_name' => $user->user_name
+ ]);
+ }
+ } else if ($fieldName == 'flag_verified') {
+ $ms->addMessageTranslated('success', 'MANUALLY_ACTIVATED', [
+ 'user_name' => $user->user_name
+ ]);
+ } else {
+ $ms->addMessageTranslated('success', 'DETAILS_UPDATED', [
+ 'user_name' => $user->user_name
+ ]);
+ }
+
+ return $response->withStatus(200);
+ }
+
+ protected function getUserFromParams($params) {
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/user/get-by-username.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and throw exception on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $e = new BadRequestException();
+ foreach ($validator->errors() as $idx => $field) {
+ foreach ($field as $eidx => $error) {
+ $e->addUserMessage($error);
+ }
+ }
+ throw $e;
+ }
+
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ // Get the user to delete
+ $user = $classMapper->staticMethod('user', 'where', 'user_name', $data['user_name'])
+ ->first();
+
+ return $user;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Controller/WormholeController.php b/main/app/sprinkles/admin/src/Controller/WormholeController.php
index ec33f3e..e25f890 100644
--- a/main/app/sprinkles/admin/src/Controller/WormholeController.php
+++ b/main/app/sprinkles/admin/src/Controller/WormholeController.php
@@ -1,147 +1,147 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Controller;
-
-use UserFrosting\Fortress\RequestDataTransformer;
-use UserFrosting\Fortress\RequestSchema;
-use UserFrosting\Fortress\ServerSideValidator;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\NotFoundException;
-use Slim\Http\Request;
-use Slim\Http\Response;
-use Slim\Http\UploadedFile;
-use Illuminate\Database\Capsule\Manager as DB;
-use UserFrosting\Sprinkle\Account\Authenticate\Authenticator;
-use Illuminate\Filesystem\Filesystem;
-use Illuminate\Session\FileSessionHandler;
-
-/**
- * Controller class for user-related requests, including listing users, CRUD for users, etc.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class WormholeController extends SimpleController
-{
- /**
- * @param Request $request
- * @param Response $response
- * @param $args
- * @return Response
- * @throws NotFoundException
- */
- public function verify(Request $request, Response $response, $args) {
- if ($this->verifyAccessToken($args)) {
- $user_id = $args['user_id'];
- $session_id = $args['session_id'];
- $session_file = file_get_contents("../app/sessions/" . $session_id);
- $session_user_id = unserialize(substr($session_file, strpos($session_file, "account|") + 8))["current_user_id"];
- if ($session_user_id == $user_id) {
- return $response->withStatus(200);
- } else {
- throw new NotFoundException();
- }
- }
- }
-
- /**
- * @param $request
- * @param Response $response
- * @param $args
- * @return Response
- * @throws BadRequestException
- * @throws NotFoundException
- */
- public function newMessage($request, Response $response, $args) {
- if ($this->verifyAccessToken($args)) {
- $sender_id = $args['sender_id'];
- $receiver_id = $args['receiver_id'];
- $message = $request->getParsedBody()["message"];
- if (($sender_id != $receiver_id) && $message) {
- $MessageId = DB::table('chat_messages')
- ->insertGetId(['sender_id' => $sender_id, 'receiver_id' => $receiver_id, 'message' => $message], 'message_id');
- $response->write($MessageId);
- return $response->withStatus(200);
- } else {
- throw new BadRequestException();
- }
- }
- }
-
- /**
- * @param Request $request
- * @param Response $response
- * @param $args
- * @return Response
- * @throws NotFoundException
- */
- public function getInfo(Request $request, Response $response, $args) {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- if ($this->verifyAccessToken($args)) {
- $user = $classMapper->staticMethod('user', 'where', 'id', $args['user_id'])
- ->first();
- if (!$user) {
- throw new NotFoundException($request, $response);
- }
-
- $UsersFollower = DB::table('user_follow')
- ->where('user_id', $user->id)
- ->join("users", "users.id", "=", "user_follow.followed_by_id")
- ->select("user_follow.followed_by_id as id", "users.user_name as username")
- ->get();
-
- $UsersFollows = DB::table('user_follow')
- ->where('followed_by_id', $user->id)
- ->join("users", "users.id", "=", "user_follow.user_id")
- ->select("user_follow.user_id as id", "users.user_name as username")
- ->get();
-
- $UsersFriends = DB::select("SELECT id FROM (SELECT user_id AS id FROM user_follow WHERE followed_by_id = $user->id UNION ALL SELECT followed_by_id FROM user_follow WHERE user_id = $user->id) t GROUP BY id HAVING COUNT(id) > 1");
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
- foreach ($UsersFriends as $Key => $UsersFriendId) { // NOT THAT EFFICIENT...
- $UsersFriendInformation = $classMapper->createInstance('user')// select doesnt work with instance
- ->where('id', $UsersFriendId->id)
- ->get();
- $UsersFriends[$Key]->id = $UsersFriendInformation[0]->id;
- $UsersFriends[$Key]->username = $UsersFriendInformation[0]->user_name;
- $UsersFriends[$Key]->avatar = $UsersFriendInformation[0]->avatar;
- $UsersFriends[$Key]->full_name = $UsersFriendInformation[0]->full_name;
- }
-
- $result = $user->toArray();
- $result["avatar"] = $user->avatar;
- $result["followers"] = $UsersFollower;
- $result["follows"] = $UsersFollows;
- $result["friends"] = $UsersFriends;
- return $response->withJson($result, 200, JSON_PRETTY_PRINT);
- }
- }
-
- /**
- * @param $args
- * @return bool
- * @throws NotFoundException
- */
- private function verifyAccessToken($args) {
- $currentUser = $this->ci->currentUser; // FOR DATABASE QUERY
- $access_token = $args['access_token'];
- if (DB::table('access_token')
- ->where('id', 1)
- ->where('token', '=', $access_token)
- ->exists()) {
- return TRUE;
- } else {
- throw new NotFoundException(); // IT'S A FORBIDDEN
- }
- }
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Controller;
+
+use UserFrosting\Fortress\RequestDataTransformer;
+use UserFrosting\Fortress\RequestSchema;
+use UserFrosting\Fortress\ServerSideValidator;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\NotFoundException;
+use Slim\Http\Request;
+use Slim\Http\Response;
+use Slim\Http\UploadedFile;
+use Illuminate\Database\Capsule\Manager as DB;
+use UserFrosting\Sprinkle\Account\Authenticate\Authenticator;
+use Illuminate\Filesystem\Filesystem;
+use Illuminate\Session\FileSessionHandler;
+
+/**
+ * Controller class for user-related requests, including listing users, CRUD for users, etc.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class WormholeController extends SimpleController
+{
+ /**
+ * @param Request $request
+ * @param Response $response
+ * @param $args
+ * @return Response
+ * @throws NotFoundException
+ */
+ public function verify(Request $request, Response $response, $args) {
+ if ($this->verifyAccessToken($args)) {
+ $user_id = $args['user_id'];
+ $session_id = $args['session_id'];
+ $session_file = file_get_contents("../app/sessions/" . $session_id);
+ $session_user_id = unserialize(substr($session_file, strpos($session_file, "account|") + 8))["current_user_id"];
+ if ($session_user_id == $user_id) {
+ return $response->withStatus(200);
+ } else {
+ throw new NotFoundException();
+ }
+ }
+ }
+
+ /**
+ * @param $request
+ * @param Response $response
+ * @param $args
+ * @return Response
+ * @throws BadRequestException
+ * @throws NotFoundException
+ */
+ public function newMessage($request, Response $response, $args) {
+ if ($this->verifyAccessToken($args)) {
+ $sender_id = $args['sender_id'];
+ $receiver_id = $args['receiver_id'];
+ $message = $request->getParsedBody()["message"];
+ if (($sender_id != $receiver_id) && $message) {
+ $MessageId = DB::table('chat_messages')
+ ->insertGetId(['sender_id' => $sender_id, 'receiver_id' => $receiver_id, 'message' => $message], 'message_id');
+ $response->write($MessageId);
+ return $response->withStatus(200);
+ } else {
+ throw new BadRequestException();
+ }
+ }
+ }
+
+ /**
+ * @param Request $request
+ * @param Response $response
+ * @param $args
+ * @return Response
+ * @throws NotFoundException
+ */
+ public function getInfo(Request $request, Response $response, $args) {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ if ($this->verifyAccessToken($args)) {
+ $user = $classMapper->staticMethod('user', 'where', 'id', $args['user_id'])
+ ->first();
+ if (!$user) {
+ throw new NotFoundException($request, $response);
+ }
+
+ $UsersFollower = DB::table('user_follow')
+ ->where('user_id', $user->id)
+ ->join("users", "users.id", "=", "user_follow.followed_by_id")
+ ->select("user_follow.followed_by_id as id", "users.user_name as username")
+ ->get();
+
+ $UsersFollows = DB::table('user_follow')
+ ->where('followed_by_id', $user->id)
+ ->join("users", "users.id", "=", "user_follow.user_id")
+ ->select("user_follow.user_id as id", "users.user_name as username")
+ ->get();
+
+ $UsersFriends = DB::select("SELECT id FROM (SELECT user_id AS id FROM user_follow WHERE followed_by_id = $user->id UNION ALL SELECT followed_by_id FROM user_follow WHERE user_id = $user->id) t GROUP BY id HAVING COUNT(id) > 1");
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+ foreach ($UsersFriends as $Key => $UsersFriendId) { // NOT THAT EFFICIENT...
+ $UsersFriendInformation = $classMapper->createInstance('user')// select doesnt work with instance
+ ->where('id', $UsersFriendId->id)
+ ->get();
+ $UsersFriends[$Key]->id = $UsersFriendInformation[0]->id;
+ $UsersFriends[$Key]->username = $UsersFriendInformation[0]->user_name;
+ $UsersFriends[$Key]->avatar = $UsersFriendInformation[0]->avatar;
+ $UsersFriends[$Key]->full_name = $UsersFriendInformation[0]->full_name;
+ }
+
+ $result = $user->toArray();
+ $result["avatar"] = $user->avatar;
+ $result["followers"] = $UsersFollower;
+ $result["follows"] = $UsersFollows;
+ $result["friends"] = $UsersFriends;
+ return $response->withJson($result, 200, JSON_PRETTY_PRINT);
+ }
+ }
+
+ /**
+ * @param $args
+ * @return bool
+ * @throws NotFoundException
+ */
+ private function verifyAccessToken($args) {
+ $currentUser = $this->ci->currentUser; // FOR DATABASE QUERY
+ $access_token = $args['access_token'];
+ if (DB::table('access_token')
+ ->where('id', 1)
+ ->where('token', '=', $access_token)
+ ->exists()) {
+ return TRUE;
+ } else {
+ throw new NotFoundException(); // IT'S A FORBIDDEN
+ }
+ }
} \ No newline at end of file
diff --git a/main/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php b/main/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php
index cb4530e..395f1f6 100644
--- a/main/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php
+++ b/main/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php
@@ -1,84 +1,84 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\ServicesProvider;
-
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use UserFrosting\Sprinkle\Account\Authenticate\Authenticator;
-use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-
-/**
- * Registers services for the admin sprinkle.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ServicesProvider
-{
- /**
- * Register UserFrosting's admin services.
- *
- * @param Container $container A DI container implementing ArrayAccess and container-interop.
- */
- public function register($container) {
- /**
- * Extend the 'classMapper' service to register sprunje classes.
- *
- * Mappings added: 'activity_sprunje', 'group_sprunje', 'permission_sprunje', 'role_sprunje', 'user_sprunje'
- */
- $container->extend('classMapper', function ($classMapper, $c) {
- $classMapper->setClassMapping('activity_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\ActivitySprunje');
- $classMapper->setClassMapping('group_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\GroupSprunje');
- $classMapper->setClassMapping('permission_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\PermissionSprunje');
- $classMapper->setClassMapping('permission_user_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\PermissionUserSprunje');
- $classMapper->setClassMapping('role_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\RoleSprunje');
- $classMapper->setClassMapping('user_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\UserSprunje');
- $classMapper->setClassMapping('user_permission_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\UserPermissionSprunje');
- return $classMapper;
- });
-
- /**
- * Returns a callback that handles setting the `UF-Redirect` header after a successful login.
- *
- * Overrides the service definition in the account Sprinkle.
- */
- $container['redirect.onLogin'] = function ($c) {
- /**
- * This method is invoked when a user completes the login process.
- *
- * Returns a callback that handles setting the `UF-Redirect` header after a successful login.
- * @param \Psr\Http\Message\ServerRequestInterface $request
- * @param \Psr\Http\Message\ResponseInterface $response
- * @param array $args
- * @return \Psr\Http\Message\ResponseInterface
- */
- return function (Request $request, Response $response, array $args) use ($c) {
- // Backwards compatibility for the deprecated determineRedirectOnLogin service
- if ($c->has('determineRedirectOnLogin')) {
- $determineRedirectOnLogin = $c->determineRedirectOnLogin;
-
- return $determineRedirectOnLogin($response)->withStatus(200);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $c->authorizer;
-
- $currentUser = $c->authenticator->user();
-
- if ($authorizer->checkAccess($currentUser, 'uri_dashboard')) {
- return $response->withHeader('UF-Redirect', $c->router->pathFor('dashboard'));
- } else if ($authorizer->checkAccess($currentUser, 'uri_account_settings')) {
- return $response->withHeader('UF-Redirect', $c->router->pathFor('settings'));
- } else {
- return $response->withHeader('UF-Redirect', $c->router->pathFor('index'));
- }
- };
- };
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\ServicesProvider;
+
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use UserFrosting\Sprinkle\Account\Authenticate\Authenticator;
+use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+
+/**
+ * Registers services for the admin sprinkle.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ServicesProvider
+{
+ /**
+ * Register UserFrosting's admin services.
+ *
+ * @param Container $container A DI container implementing ArrayAccess and container-interop.
+ */
+ public function register($container) {
+ /**
+ * Extend the 'classMapper' service to register sprunje classes.
+ *
+ * Mappings added: 'activity_sprunje', 'group_sprunje', 'permission_sprunje', 'role_sprunje', 'user_sprunje'
+ */
+ $container->extend('classMapper', function ($classMapper, $c) {
+ $classMapper->setClassMapping('activity_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\ActivitySprunje');
+ $classMapper->setClassMapping('group_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\GroupSprunje');
+ $classMapper->setClassMapping('permission_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\PermissionSprunje');
+ $classMapper->setClassMapping('permission_user_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\PermissionUserSprunje');
+ $classMapper->setClassMapping('role_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\RoleSprunje');
+ $classMapper->setClassMapping('user_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\UserSprunje');
+ $classMapper->setClassMapping('user_permission_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\UserPermissionSprunje');
+ return $classMapper;
+ });
+
+ /**
+ * Returns a callback that handles setting the `UF-Redirect` header after a successful login.
+ *
+ * Overrides the service definition in the account Sprinkle.
+ */
+ $container['redirect.onLogin'] = function ($c) {
+ /**
+ * This method is invoked when a user completes the login process.
+ *
+ * Returns a callback that handles setting the `UF-Redirect` header after a successful login.
+ * @param \Psr\Http\Message\ServerRequestInterface $request
+ * @param \Psr\Http\Message\ResponseInterface $response
+ * @param array $args
+ * @return \Psr\Http\Message\ResponseInterface
+ */
+ return function (Request $request, Response $response, array $args) use ($c) {
+ // Backwards compatibility for the deprecated determineRedirectOnLogin service
+ if ($c->has('determineRedirectOnLogin')) {
+ $determineRedirectOnLogin = $c->determineRedirectOnLogin;
+
+ return $determineRedirectOnLogin($response)->withStatus(200);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $c->authorizer;
+
+ $currentUser = $c->authenticator->user();
+
+ if ($authorizer->checkAccess($currentUser, 'uri_dashboard')) {
+ return $response->withHeader('UF-Redirect', $c->router->pathFor('dashboard'));
+ } else if ($authorizer->checkAccess($currentUser, 'uri_account_settings')) {
+ return $response->withHeader('UF-Redirect', $c->router->pathFor('settings'));
+ } else {
+ return $response->withHeader('UF-Redirect', $c->router->pathFor('index'));
+ }
+ };
+ };
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php b/main/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php
index 3af04f0..70a3562 100644
--- a/main/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php
+++ b/main/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php
@@ -1,78 +1,78 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Sprunje;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
-
-/**
- * ActivitySprunje
- *
- * Implements Sprunje for the activities API.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ActivitySprunje extends Sprunje
-{
- protected $sortable = [
- 'occurred_at',
- 'user',
- 'description'
- ];
-
- protected $filterable = [
- 'occurred_at',
- 'user',
- 'description'
- ];
-
- protected $name = 'activities';
-
- /**
- * Set the initial query used by your Sprunje.
- */
- protected function baseQuery() {
- $query = $this->classMapper->createInstance('activity');
-
- return $query->joinUser();
- }
-
- /**
- * Filter LIKE the user info.
- *
- * @param Builder $query
- * @param mixed $value
- * @return $this
- */
- protected function filterUser($query, $value) {
- // Split value on separator for OR queries
- $values = explode($this->orSeparator, $value);
- $query->where(function ($query) use ($values) {
- foreach ($values as $value) {
- $query->orLike('users.first_name', $value)
- ->orLike('users.last_name', $value)
- ->orLike('users.email', $value);
- }
- });
- return $this;
- }
-
- /**
- * Sort based on user last name.
- *
- * @param Builder $query
- * @param string $direction
- * @return $this
- */
- protected function sortUser($query, $direction) {
- $query->orderBy('users.last_name', $direction);
- return $this;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Sprunje;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
+
+/**
+ * ActivitySprunje
+ *
+ * Implements Sprunje for the activities API.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ActivitySprunje extends Sprunje
+{
+ protected $sortable = [
+ 'occurred_at',
+ 'user',
+ 'description'
+ ];
+
+ protected $filterable = [
+ 'occurred_at',
+ 'user',
+ 'description'
+ ];
+
+ protected $name = 'activities';
+
+ /**
+ * Set the initial query used by your Sprunje.
+ */
+ protected function baseQuery() {
+ $query = $this->classMapper->createInstance('activity');
+
+ return $query->joinUser();
+ }
+
+ /**
+ * Filter LIKE the user info.
+ *
+ * @param Builder $query
+ * @param mixed $value
+ * @return $this
+ */
+ protected function filterUser($query, $value) {
+ // Split value on separator for OR queries
+ $values = explode($this->orSeparator, $value);
+ $query->where(function ($query) use ($values) {
+ foreach ($values as $value) {
+ $query->orLike('users.first_name', $value)
+ ->orLike('users.last_name', $value)
+ ->orLike('users.email', $value);
+ }
+ });
+ return $this;
+ }
+
+ /**
+ * Sort based on user last name.
+ *
+ * @param Builder $query
+ * @param string $direction
+ * @return $this
+ */
+ protected function sortUser($query, $direction) {
+ $query->orderBy('users.last_name', $direction);
+ return $this;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Sprunje/GroupSprunje.php b/main/app/sprinkles/admin/src/Sprunje/GroupSprunje.php
index 849673b..514c6bb 100644
--- a/main/app/sprinkles/admin/src/Sprunje/GroupSprunje.php
+++ b/main/app/sprinkles/admin/src/Sprunje/GroupSprunje.php
@@ -1,42 +1,42 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Sprunje;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
-
-/**
- * GroupSprunje
- *
- * Implements Sprunje for the groups API.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class GroupSprunje extends Sprunje
-{
- protected $name = 'groups';
-
- protected $sortable = [
- 'name',
- 'description'
- ];
-
- protected $filterable = [
- 'name',
- 'description'
- ];
-
- /**
- * {@inheritDoc}
- */
- protected function baseQuery() {
- return $this->classMapper->createInstance('group')->newQuery();
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Sprunje;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
+
+/**
+ * GroupSprunje
+ *
+ * Implements Sprunje for the groups API.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class GroupSprunje extends Sprunje
+{
+ protected $name = 'groups';
+
+ protected $sortable = [
+ 'name',
+ 'description'
+ ];
+
+ protected $filterable = [
+ 'name',
+ 'description'
+ ];
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function baseQuery() {
+ return $this->classMapper->createInstance('group')->newQuery();
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php b/main/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php
index 0a38ee9..1df288e 100644
--- a/main/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php
+++ b/main/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php
@@ -1,90 +1,90 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Sprunje;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
-
-/**
- * PermissionSprunje
- *
- * Implements Sprunje for the permissions API.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class PermissionSprunje extends Sprunje
-{
- protected $name = 'permissions';
-
- protected $sortable = [
- 'name',
- 'properties'
- ];
-
- protected $filterable = [
- 'name',
- 'properties',
- 'info'
- ];
-
- protected $excludeForAll = [
- 'info'
- ];
-
- /**
- * {@inheritDoc}
- */
- protected function baseQuery() {
- return $this->classMapper->createInstance('permission')->newQuery();
- }
-
- /**
- * Filter LIKE the slug, conditions, or description.
- *
- * @param Builder $query
- * @param mixed $value
- * @return $this
- */
- protected function filterInfo($query, $value) {
- return $this->filterProperties($query, $value);
- }
-
- /**
- * Filter LIKE the slug, conditions, or description.
- *
- * @param Builder $query
- * @param mixed $value
- * @return $this
- */
- protected function filterProperties($query, $value) {
- // Split value on separator for OR queries
- $values = explode($this->orSeparator, $value);
- $query->where(function ($query) use ($values) {
- foreach ($values as $value) {
- $query->orLike('slug', $value)
- ->orLike('conditions', $value)
- ->orLike('description', $value);
- }
- });
- return $this;
- }
-
- /**
- * Sort based on slug.
- *
- * @param Builder $query
- * @param string $direction
- * @return $this
- */
- protected function sortProperties($query, $direction) {
- $query->orderBy('slug', $direction);
- return $this;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Sprunje;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
+
+/**
+ * PermissionSprunje
+ *
+ * Implements Sprunje for the permissions API.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class PermissionSprunje extends Sprunje
+{
+ protected $name = 'permissions';
+
+ protected $sortable = [
+ 'name',
+ 'properties'
+ ];
+
+ protected $filterable = [
+ 'name',
+ 'properties',
+ 'info'
+ ];
+
+ protected $excludeForAll = [
+ 'info'
+ ];
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function baseQuery() {
+ return $this->classMapper->createInstance('permission')->newQuery();
+ }
+
+ /**
+ * Filter LIKE the slug, conditions, or description.
+ *
+ * @param Builder $query
+ * @param mixed $value
+ * @return $this
+ */
+ protected function filterInfo($query, $value) {
+ return $this->filterProperties($query, $value);
+ }
+
+ /**
+ * Filter LIKE the slug, conditions, or description.
+ *
+ * @param Builder $query
+ * @param mixed $value
+ * @return $this
+ */
+ protected function filterProperties($query, $value) {
+ // Split value on separator for OR queries
+ $values = explode($this->orSeparator, $value);
+ $query->where(function ($query) use ($values) {
+ foreach ($values as $value) {
+ $query->orLike('slug', $value)
+ ->orLike('conditions', $value)
+ ->orLike('description', $value);
+ }
+ });
+ return $this;
+ }
+
+ /**
+ * Sort based on slug.
+ *
+ * @param Builder $query
+ * @param string $direction
+ * @return $this
+ */
+ protected function sortProperties($query, $direction) {
+ $query->orderBy('slug', $direction);
+ return $this;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php b/main/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php
index 3c7b4ea..eba23c3 100644
--- a/main/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php
+++ b/main/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php
@@ -1,48 +1,48 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Sprunje;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\NotFoundException;
-
-/**
- * PermissionUserSprunje
- *
- * Implements Sprunje for retrieving a list of users for a specified permission.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class PermissionUserSprunje extends UserSprunje
-{
- protected $name = 'permission_users';
-
- /**
- * {@inheritDoc}
- */
- protected function baseQuery() {
- // Requires a permission id
- if (!isset($this->options['permission_id'])) {
- throw new BadRequestException();
- }
-
- $permission = $this->classMapper->staticMethod('permission', 'find', $this->options['permission_id']);
-
- // If the permission doesn't exist, return 404
- if (!$permission) {
- throw new NotFoundException;
- }
-
- // Get permission users
- $query = $permission->users()->withVia('roles_via');
-
- return $query;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Sprunje;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\NotFoundException;
+
+/**
+ * PermissionUserSprunje
+ *
+ * Implements Sprunje for retrieving a list of users for a specified permission.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class PermissionUserSprunje extends UserSprunje
+{
+ protected $name = 'permission_users';
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function baseQuery() {
+ // Requires a permission id
+ if (!isset($this->options['permission_id'])) {
+ throw new BadRequestException();
+ }
+
+ $permission = $this->classMapper->staticMethod('permission', 'find', $this->options['permission_id']);
+
+ // If the permission doesn't exist, return 404
+ if (!$permission) {
+ throw new NotFoundException;
+ }
+
+ // Get permission users
+ $query = $permission->users()->withVia('roles_via');
+
+ return $query;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Sprunje/RoleSprunje.php b/main/app/sprinkles/admin/src/Sprunje/RoleSprunje.php
index 624a1ba..59c5240 100644
--- a/main/app/sprinkles/admin/src/Sprunje/RoleSprunje.php
+++ b/main/app/sprinkles/admin/src/Sprunje/RoleSprunje.php
@@ -1,66 +1,66 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Sprunje;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
-
-/**
- * RoleSprunje
- *
- * Implements Sprunje for the roles API.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class RoleSprunje extends Sprunje
-{
- protected $name = 'roles';
-
- protected $sortable = [
- 'name',
- 'description'
- ];
-
- protected $filterable = [
- 'name',
- 'description',
- 'info'
- ];
-
- protected $excludeForAll = [
- 'info'
- ];
-
- /**
- * {@inheritDoc}
- */
- protected function baseQuery() {
- return $this->classMapper->createInstance('role')->newQuery();
- }
-
- /**
- * Filter LIKE name OR description.
- *
- * @param Builder $query
- * @param mixed $value
- * @return $this
- */
- protected function filterInfo($query, $value) {
- // Split value on separator for OR queries
- $values = explode($this->orSeparator, $value);
- $query->where(function ($query) use ($values) {
- foreach ($values as $value) {
- $query->orLike('name', $value)
- ->orLike('description', $value);
- }
- });
- return $this;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Sprunje;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
+
+/**
+ * RoleSprunje
+ *
+ * Implements Sprunje for the roles API.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class RoleSprunje extends Sprunje
+{
+ protected $name = 'roles';
+
+ protected $sortable = [
+ 'name',
+ 'description'
+ ];
+
+ protected $filterable = [
+ 'name',
+ 'description',
+ 'info'
+ ];
+
+ protected $excludeForAll = [
+ 'info'
+ ];
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function baseQuery() {
+ return $this->classMapper->createInstance('role')->newQuery();
+ }
+
+ /**
+ * Filter LIKE name OR description.
+ *
+ * @param Builder $query
+ * @param mixed $value
+ * @return $this
+ */
+ protected function filterInfo($query, $value) {
+ // Split value on separator for OR queries
+ $values = explode($this->orSeparator, $value);
+ $query->where(function ($query) use ($values) {
+ foreach ($values as $value) {
+ $query->orLike('name', $value)
+ ->orLike('description', $value);
+ }
+ });
+ return $this;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php b/main/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php
index f3c1734..3f4b58f 100644
--- a/main/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php
+++ b/main/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php
@@ -1,48 +1,48 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Sprunje;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\NotFoundException;
-
-/**
- * UserPermissionSprunje
- *
- * Implements Sprunje for retrieving a list of permissions for a specified user.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class UserPermissionSprunje extends PermissionSprunje
-{
- protected $name = 'user_permissions';
-
- /**
- * {@inheritDoc}
- */
- protected function baseQuery() {
- // Requires a user id
- if (!isset($this->options['user_id'])) {
- throw new BadRequestException();
- }
-
- $user = $this->classMapper->staticMethod('user', 'find', $this->options['user_id']);
-
- // If the user doesn't exist, return 404
- if (!$user) {
- throw new NotFoundException;
- }
-
- // Get user permissions
- $query = $user->permissions()->withVia('roles_via');
-
- return $query;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Sprunje;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\NotFoundException;
+
+/**
+ * UserPermissionSprunje
+ *
+ * Implements Sprunje for retrieving a list of permissions for a specified user.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class UserPermissionSprunje extends PermissionSprunje
+{
+ protected $name = 'user_permissions';
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function baseQuery() {
+ // Requires a user id
+ if (!isset($this->options['user_id'])) {
+ throw new BadRequestException();
+ }
+
+ $user = $this->classMapper->staticMethod('user', 'find', $this->options['user_id']);
+
+ // If the user doesn't exist, return 404
+ if (!$user) {
+ throw new NotFoundException;
+ }
+
+ // Get user permissions
+ $query = $user->permissions()->withVia('roles_via');
+
+ return $query;
+ }
+}
diff --git a/main/app/sprinkles/admin/src/Sprunje/UserSprunje.php b/main/app/sprinkles/admin/src/Sprunje/UserSprunje.php
index 0837912..a90eca3 100644
--- a/main/app/sprinkles/admin/src/Sprunje/UserSprunje.php
+++ b/main/app/sprinkles/admin/src/Sprunje/UserSprunje.php
@@ -1,178 +1,178 @@
-<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Admin\Sprunje;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Sprinkle\Core\Facades\Translator;
-use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
-
-/**
- * UserSprunje
- *
- * Implements Sprunje for the users API.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class UserSprunje extends Sprunje
-{
- protected $name = 'users';
-
- protected $listable = [
- 'status'
- ];
-
- protected $sortable = [
- 'name',
- 'last_activity',
- 'status'
- ];
-
- protected $filterable = [
- 'name',
- 'last_activity',
- 'status'
- ];
-
- protected $excludeForAll = [
- 'last_activity'
- ];
-
- /**
- * {@inheritDoc}
- */
- protected function baseQuery() {
- $query = $this->classMapper->createInstance('user');
-
- // Join user's most recent activity
- return $query->joinLastActivity()->with('lastActivity');
- }
-
- /**
- * Filter LIKE the last activity description.
- *
- * @param Builder $query
- * @param mixed $value
- * @return $this
- */
- protected function filterLastActivity($query, $value) {
- // Split value on separator for OR queries
- $values = explode($this->orSeparator, $value);
- $query->where(function ($query) use ($values) {
- foreach ($values as $value) {
- $query->orLike('activities.description', $value);
- }
- });
- return $this;
- }
-
- /**
- * Filter LIKE the first name, last name, or email.
- *
- * @param Builder $query
- * @param mixed $value
- * @return $this
- */
- protected function filterName($query, $value) {
- // Split value on separator for OR queries
- $values = explode($this->orSeparator, $value);
- $query->where(function ($query) use ($values) {
- foreach ($values as $value) {
- $query->orLike('first_name', $value)
- ->orLike('last_name', $value)
- ->orLike('email', $value);
- }
- });
- return $this;
- }
-
- /**
- * Filter by status (active, disabled, unactivated)
- *
- * @param Builder $query
- * @param mixed $value
- * @return $this
- */
- protected function filterStatus($query, $value) {
- // Split value on separator for OR queries
- $values = explode($this->orSeparator, $value);
- $query->where(function ($query) use ($values) {
- foreach ($values as $value) {
- if ($value == 'disabled') {
- $query->orWhere('flag_enabled', 0);
- } else if ($value == 'unactivated') {
- $query->orWhere('flag_verified', 0);
- } else if ($value == 'active') {
- $query->orWhere(function ($query) {
- $query->where('flag_enabled', 1)->where('flag_verified', 1);
- });
- }
- }
- });
- return $this;
- }
-
- /**
- * Return a list of possible user statuses.
- *
- * @return array
- */
- protected function listStatus() {
- return [
- [
- 'value' => 'active',
- 'text' => Translator::translate('ACTIVE')
- ],
- [
- 'value' => 'unactivated',
- 'text' => Translator::translate('UNACTIVATED')
- ],
- [
- 'value' => 'disabled',
- 'text' => Translator::translate('DISABLED')
- ]
- ];
- }
-
- /**
- * Sort based on last activity time.
- *
- * @param Builder $query
- * @param string $direction
- * @return $this
- */
- protected function sortLastActivity($query, $direction) {
- $query->orderBy('activities.occurred_at', $direction);
- return $this;
- }
-
- /**
- * Sort based on last name.
- *
- * @param Builder $query
- * @param string $direction
- * @return $this
- */
- protected function sortName($query, $direction) {
- $query->orderBy('last_name', $direction);
- return $this;
- }
-
- /**
- * Sort active, unactivated, disabled
- *
- * @param Builder $query
- * @param string $direction
- * @return $this
- */
- protected function sortStatus($query, $direction) {
- $query->orderBy('flag_enabled', $direction)->orderBy('flag_verified', $direction);
- return $this;
- }
-}
+<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Admin\Sprunje;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Sprinkle\Core\Facades\Translator;
+use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
+
+/**
+ * UserSprunje
+ *
+ * Implements Sprunje for the users API.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class UserSprunje extends Sprunje
+{
+ protected $name = 'users';
+
+ protected $listable = [
+ 'status'
+ ];
+
+ protected $sortable = [
+ 'name',
+ 'last_activity',
+ 'status'
+ ];
+
+ protected $filterable = [
+ 'name',
+ 'last_activity',
+ 'status'
+ ];
+
+ protected $excludeForAll = [
+ 'last_activity'
+ ];
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function baseQuery() {
+ $query = $this->classMapper->createInstance('user');
+
+ // Join user's most recent activity
+ return $query->joinLastActivity()->with('lastActivity');
+ }
+
+ /**
+ * Filter LIKE the last activity description.
+ *
+ * @param Builder $query
+ * @param mixed $value
+ * @return $this
+ */
+ protected function filterLastActivity($query, $value) {
+ // Split value on separator for OR queries
+ $values = explode($this->orSeparator, $value);
+ $query->where(function ($query) use ($values) {
+ foreach ($values as $value) {
+ $query->orLike('activities.description', $value);
+ }
+ });
+ return $this;
+ }
+
+ /**
+ * Filter LIKE the first name, last name, or email.
+ *
+ * @param Builder $query
+ * @param mixed $value
+ * @return $this
+ */
+ protected function filterName($query, $value) {
+ // Split value on separator for OR queries
+ $values = explode($this->orSeparator, $value);
+ $query->where(function ($query) use ($values) {
+ foreach ($values as $value) {
+ $query->orLike('first_name', $value)
+ ->orLike('last_name', $value)
+ ->orLike('email', $value);
+ }
+ });
+ return $this;
+ }
+
+ /**
+ * Filter by status (active, disabled, unactivated)
+ *
+ * @param Builder $query
+ * @param mixed $value
+ * @return $this
+ */
+ protected function filterStatus($query, $value) {
+ // Split value on separator for OR queries
+ $values = explode($this->orSeparator, $value);
+ $query->where(function ($query) use ($values) {
+ foreach ($values as $value) {
+ if ($value == 'disabled') {
+ $query->orWhere('flag_enabled', 0);
+ } else if ($value == 'unactivated') {
+ $query->orWhere('flag_verified', 0);
+ } else if ($value == 'active') {
+ $query->orWhere(function ($query) {
+ $query->where('flag_enabled', 1)->where('flag_verified', 1);
+ });
+ }
+ }
+ });
+ return $this;
+ }
+
+ /**
+ * Return a list of possible user statuses.
+ *
+ * @return array
+ */
+ protected function listStatus() {
+ return [
+ [
+ 'value' => 'active',
+ 'text' => Translator::translate('ACTIVE')
+ ],
+ [
+ 'value' => 'unactivated',
+ 'text' => Translator::translate('UNACTIVATED')
+ ],
+ [
+ 'value' => 'disabled',
+ 'text' => Translator::translate('DISABLED')
+ ]
+ ];
+ }
+
+ /**
+ * Sort based on last activity time.
+ *
+ * @param Builder $query
+ * @param string $direction
+ * @return $this
+ */
+ protected function sortLastActivity($query, $direction) {
+ $query->orderBy('activities.occurred_at', $direction);
+ return $this;
+ }
+
+ /**
+ * Sort based on last name.
+ *
+ * @param Builder $query
+ * @param string $direction
+ * @return $this
+ */
+ protected function sortName($query, $direction) {
+ $query->orderBy('last_name', $direction);
+ return $this;
+ }
+
+ /**
+ * Sort active, unactivated, disabled
+ *
+ * @param Builder $query
+ * @param string $direction
+ * @return $this
+ */
+ protected function sortStatus($query, $direction) {
+ $query->orderBy('flag_enabled', $direction)->orderBy('flag_verified', $direction);
+ return $this;
+ }
+}