getParsedBody(); /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page if (!$authorizer->checkAccess($currentUser, 'create_organisation')) { throw new ForbiddenException(); } /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // Load the request schema $schema = new RequestSchema('schema://requests/organisation/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->getClassMapping('organisation')::where('name', $data['name'])->first()) { $ms->addMessageTranslated('danger', 'ORGANISATION.NAME.IN_USE', $data); $error = true; } if ($classMapper->getClassMapping('organisation')::where('slug', $data['slug'])->first()) { $ms->addMessageTranslated('danger', 'ORGANISATION.SLUG.IN_USE', $data); $error = true; } if ($error) { return $response->withJson([], 400); } /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // All checks passed! log events/activities and create organisation // Begin transaction - DB will be rolled back if an exception occurs Capsule::transaction(function () use ($classMapper, $data, $ms, $currentUser) { // Create the organisation $organisation = $classMapper->createInstance('organisation', $data); // Store new organisation to database $organisation->save(); // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} created organisation {$organisation->name}.", [ 'type' => 'organisation_create', 'user_id' => $currentUser->id, ]); $ms->addMessageTranslated('success', 'ORGANISATION.CREATION_SUCCESSFUL', $data); }); return $response->withJson([], 200); } /** * Processes the request to delete an existing organisation. * * Deletes the specified organisation. * Organisations with members will retain the membership information. * Before doing so, checks that: * 1. The user has permission to delete this organisation; * 2. The submitted data is valid. * This route requires authentication (and should generally be limited to admins or the root user). * * Request type: DELETE * * @param Request $request * @param Response $response * @param array $args * * @throws NotFoundException If organisation is not found * @throws ForbiddenException If user is not authorized to access page * @throws BadRequestException */ public function delete(Request $request, Response $response, $args) { $organisation = $this->getOrganisationFromParams($args); // If the organisation doesn't exist, return 404 if (!$organisation) { throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page if (!$authorizer->checkAccess($currentUser, 'delete_organisation', [ 'organisation' => $organisation, ])) { throw new ForbiddenException(); } /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $organisationName = $organisation->name; // Begin transaction - DB will be rolled back if an exception occurs Capsule::transaction(function () use ($organisation, $organisationName, $currentUser) { $organisation->delete(); unset($organisation); // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted organisation {$organisationName}.", [ 'type' => 'organisation_delete', 'user_id' => $currentUser->id, ]); }); /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; $ms->addMessageTranslated('success', 'ORGANISATION.DELETION_SUCCESSFUL', [ 'name' => $organisationName, ]); return $response->withJson([], 200); } /** * Returns a list of Organisations. * * Generates a list of organisations, optionally paginated, sorted and/or filtered. * This page requires authentication. * * Request type: GET * * @param Request $request * @param Response $response * @param array $args * * @throws ForbiddenException If user is not authorized to access page */ public function getList(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page if (!$authorizer->checkAccess($currentUser, 'uri_organisations')) { throw new ForbiddenException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $sprunje = $classMapper->createInstance('organisation_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); } /** * Get deletion confirmation modal. * * @param Request $request * @param Response $response * @param array $args * * @throws NotFoundException If organisation is not found * @throws ForbiddenException If user is not authorized to access page * @throws BadRequestException */ public function getModalConfirmDelete(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); $organisation = $this->getOrganisationFromParams($params); // If the organisation no longer exists, forward to main organisation listing page if (!$organisation) { throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page if (!$authorizer->checkAccess($currentUser, 'delete_organisation', [ 'organisation' => $organisation, ])) { throw new ForbiddenException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; return $this->ci->view->render($response, 'modals/confirm-delete-organisation.html.twig', [ 'organisation' => $organisation, 'form' => [ 'action' => "api/organisations/o/{$organisation->slug}", ], ]); } /** * Renders the modal form for creating a new organisation. * * 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 * * @param Request $request * @param Response $response * @param array $args * * @throws ForbiddenException If user is not authorized to access page */ public function getModalCreate(Request $request, Response $response, $args) { /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; /** @var \UserFrosting\I18n\Translator $translator */ $translator = $this->ci->translator; // Access-controlled page if (!$authorizer->checkAccess($currentUser, 'create_organisation')) { throw new ForbiddenException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Create a dummy organisation to prepopulate fields $organisation = $classMapper->createInstance('organisation', []); $fieldNames = ['name', 'slug', 'description']; $fields = [ 'hidden' => [], 'disabled' => [], ]; // Load validation rules $schema = new RequestSchema('schema://requests/organisation/create.yaml'); $validator = new JqueryValidationAdapter($schema, $this->ci->translator); return $this->ci->view->render($response, 'modals/organisation.html.twig', [ 'organisation' => $organisation, 'form' => [ 'action' => 'api/organisations', 'method' => 'POST', 'fields' => $fields, 'submit_text' => $translator->translate('CREATE'), ], 'page' => [ 'validators' => $validator->rules('json', false), ], ]); } /** * Renders the organisation listing page. * * This page renders a table of organisations, with dropdown menus for admin actions for each organisation. * Actions typically include: edit organisation, delete organisation. * This page requires authentication. * * Request type: GET * * @param Request $request * @param Response $response * @param array $args * * @throws ForbiddenException If user is not authorized to access page */ public function pageList(Request $request, Response $response, $args) { /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page if (!$authorizer->checkAccess($currentUser, 'uri_organisations')) { throw new ForbiddenException(); } return $this->ci->view->render($response, 'pages/organisations.html.twig'); } /** * Get organisation from params. * * @param array $params * * @throws BadRequestException * * @return Organisation */ protected function getOrganisationFromParams($params) { // Load the request schema $schema = new RequestSchema('schema://requests/organisation/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)) { // TODO: 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 organisation $organisation = $classMapper->getClassMapping('organisation')::where('slug', $data['slug']) ->first(); return $organisation; } }