Revamped the organisation approvals process & refactored some files
This commit is contained in:
@@ -50,22 +50,26 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function create(Request $request, Response $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\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'create_organisation')) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
// Get POST parameters: name, slug, icon, description
|
||||
$params = $request->getParsedBody();
|
||||
|
||||
// Load the request schema
|
||||
$schema = new RequestSchema('schema://requests/organisation/create.yaml');
|
||||
@@ -83,9 +87,6 @@ class OrganisationController extends SimpleController
|
||||
$error = true;
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
// Check if name or slug already exists
|
||||
if ($classMapper->getClassMapping('organisation')::findUnique($data['name'], 'name')) {
|
||||
$ms->addMessageTranslated('danger', 'ORGANISATION.NAME.IN_USE', $data);
|
||||
@@ -102,6 +103,7 @@ class OrganisationController extends SimpleController
|
||||
}
|
||||
|
||||
$data['flag_approved'] = 1;
|
||||
$data['registrant_id'] = $currentUser->id;
|
||||
|
||||
// All checks passed! log events/activities and create organisation
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
@@ -139,6 +141,13 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function getInfo(Request $request, Response $response, array $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;
|
||||
|
||||
|
||||
$organisation = $this->getOrganisationFromParams($args);
|
||||
|
||||
// If the organisation doesn't exist, return 404
|
||||
@@ -146,21 +155,6 @@ class OrganisationController extends SimpleController
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
// Join organisation's most recent activity
|
||||
$organisation = $classMapper->createInstance('organisation')
|
||||
->where('slug', $organisation->slug)
|
||||
->joinMemberCounts()
|
||||
->first();
|
||||
|
||||
/** @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_organisation', [
|
||||
'organisation' => $organisation,
|
||||
@@ -168,10 +162,11 @@ class OrganisationController extends SimpleController
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
// Join organisation's member counts
|
||||
$organisation = $organisation->joinMemberCounts()->first();
|
||||
|
||||
$result = $organisation->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);
|
||||
}
|
||||
|
||||
@@ -197,6 +192,19 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function update(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
// Get the organisation based on slug in URL
|
||||
$organisation = $this->getOrganisationFromParams($args);
|
||||
|
||||
@@ -207,9 +215,6 @@ class OrganisationController extends SimpleController
|
||||
// Get PUT parameters: (name, slug, icon, description)
|
||||
$params = $request->getParsedBody();
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
// Load the request schema
|
||||
$schema = new RequestSchema('schema://requests/organisation/edit-info.yaml');
|
||||
|
||||
@@ -232,12 +237,6 @@ class OrganisationController extends SimpleController
|
||||
$fieldNames[] = $name;
|
||||
}
|
||||
|
||||
/** @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 resource - check that currentUser has permission to edit submitted fields for this organisation
|
||||
if (!$authorizer->checkAccess($currentUser, 'update_organisation_field', [
|
||||
'organisation' => $organisation,
|
||||
@@ -246,14 +245,11 @@ class OrganisationController extends SimpleController
|
||||
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'] != $organisation->name &&
|
||||
$classMapper->getClassMapping('organisation')::where('name', $data['name'])->first()
|
||||
$classMapper->getClassMapping('organisation')::findUnique($data['name'], 'name')
|
||||
) {
|
||||
$ms->addMessageTranslated('danger', 'ORGANISATION.NAME.IN_USE', $data);
|
||||
$error = true;
|
||||
@@ -262,7 +258,7 @@ class OrganisationController extends SimpleController
|
||||
if (
|
||||
isset($data['slug']) &&
|
||||
$data['slug'] != $organisation->slug &&
|
||||
$classMapper->getClassMapping('organisation')::where('slug', $data['slug'])->first()
|
||||
$classMapper->getClassMapping('organisation')::findUnique($data['slug'], 'slug')
|
||||
) {
|
||||
$ms->addMessageTranslated('danger', 'ORGANISATION.SLUG.IN_USE', $data);
|
||||
$error = true;
|
||||
@@ -319,6 +315,24 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function merge(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'merge_organisations')) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
// Get POST parameters
|
||||
$params = $request->getParsedBody();
|
||||
|
||||
@@ -329,53 +343,26 @@ class OrganisationController extends SimpleController
|
||||
$transformer = new RequestDataTransformer($schema);
|
||||
$data = $transformer->transform($params);
|
||||
|
||||
// Validate, and throw exception on validation errors.
|
||||
// Validate, and return bad request 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);
|
||||
$ms->addValidationErrors($validator);
|
||||
return $response->withJson([], 400);
|
||||
}
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
// Get the organisations
|
||||
$source = $classMapper->getClassMapping('organisation')::where('slug', $data['source_slug'])->first();
|
||||
$target = $classMapper->getClassMapping('organisation')::where('slug', $data['target_slug'])->first();
|
||||
$source = $classMapper->getClassMapping('organisation')::findUnique($data['source_slug'], 'slug', false);
|
||||
$target = $classMapper->getClassMapping('organisation')::findUnique($data['target_slug'], 'slug', false);
|
||||
|
||||
// If a organisation doesn't exist, return 404
|
||||
if (!$source || !$target) {
|
||||
throw new BadRequestException();
|
||||
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, 'merge_organisations')) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
$sourceName = $source->name;
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($source, $sourceName, $target, $currentUser) {
|
||||
Capsule::transaction(function () use ($source, $target, $currentUser) {
|
||||
$sourceName = $source->name;
|
||||
|
||||
$this->ci->get('organisation.beforeMerge')($source, $target);
|
||||
|
||||
$source->beforeMerge($target, ['currentUser' => $currentUser]);
|
||||
@@ -390,9 +377,6 @@ class OrganisationController extends SimpleController
|
||||
]);
|
||||
});
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.MERGE_SUCCESSFUL', [
|
||||
'source' => $sourceName,
|
||||
'target' => $target->name,
|
||||
@@ -423,6 +407,16 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function delete(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\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
$organisation = $this->getOrganisationFromParams($args);
|
||||
|
||||
// If the organisation doesn't exist, return 404
|
||||
@@ -430,12 +424,6 @@ class OrganisationController extends SimpleController
|
||||
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,
|
||||
@@ -443,16 +431,11 @@ class OrganisationController extends SimpleController
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($organisation, $currentUser) {
|
||||
$organisationName = $organisation->name;
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($organisation, $organisationName, $currentUser) {
|
||||
// Delete the organisation (soft)
|
||||
$organisation->delete();
|
||||
unset($organisation);
|
||||
|
||||
@@ -463,9 +446,6 @@ class OrganisationController extends SimpleController
|
||||
]);
|
||||
});
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.DELETION_SUCCESSFUL', [
|
||||
'name' => $organisationName,
|
||||
]);
|
||||
@@ -495,6 +475,16 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function deletePermenent(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\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
$organisation = $this->getOrganisationFromParams($args, true);
|
||||
|
||||
// If the organisation doesn't exist, return 404
|
||||
@@ -502,12 +492,6 @@ class OrganisationController extends SimpleController
|
||||
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, 'permenent_delete_organisation', [
|
||||
'organisation' => $organisation,
|
||||
@@ -515,16 +499,11 @@ class OrganisationController extends SimpleController
|
||||
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) {
|
||||
// Delete the organisation (HARD)
|
||||
$organisation->delete(true);
|
||||
unset($organisation);
|
||||
|
||||
@@ -535,9 +514,6 @@ class OrganisationController extends SimpleController
|
||||
]);
|
||||
});
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.PERMENENT_DELETION_SUCCESSFUL', [
|
||||
'name' => $organisationName,
|
||||
]);
|
||||
@@ -565,6 +541,16 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function restore(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\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
$organisation = $this->getOrganisationFromParams($args, true);
|
||||
|
||||
// If the organisation doesn't exist, return 404
|
||||
@@ -572,12 +558,6 @@ class OrganisationController extends SimpleController
|
||||
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, 'restore_organisation', [
|
||||
'organisation' => $organisation,
|
||||
@@ -585,16 +565,10 @@ class OrganisationController extends SimpleController
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($organisation, $currentUser) {
|
||||
if (!$organisation->flag_approved) {
|
||||
$verification = $this->ci->repoOrganisationApproval->revert($organisation);
|
||||
$this->ci->repoOrganisationApproval->revert($organisation);
|
||||
}
|
||||
|
||||
$organisation->restore();
|
||||
@@ -606,9 +580,6 @@ class OrganisationController extends SimpleController
|
||||
]);
|
||||
});
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.RESTORE_SUCCESSFUL', [
|
||||
'name' => $organisation->name,
|
||||
]);
|
||||
@@ -633,22 +604,23 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
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\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @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;
|
||||
// GET parameters
|
||||
$params = $request->getQueryParams();
|
||||
|
||||
$params['ci'] = $this->ci;
|
||||
|
||||
@@ -682,22 +654,23 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function getListDeleted(Request $request, Response $response, $args)
|
||||
{
|
||||
// GET parameters
|
||||
$params = $request->getQueryParams();
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'uri_deleted_organisations')) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
// GET parameters
|
||||
$params = $request->getQueryParams();
|
||||
|
||||
$sprunje = $classMapper->createInstance('organisation_sprunje', $classMapper, $params);
|
||||
$sprunje->extendQuery(function ($query) use ($user) {
|
||||
@@ -722,6 +695,16 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function getModalConfirmDelete(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
|
||||
// GET parameters
|
||||
$params = $request->getQueryParams();
|
||||
|
||||
@@ -732,12 +715,6 @@ class OrganisationController extends SimpleController
|
||||
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,
|
||||
@@ -745,9 +722,6 @@ class OrganisationController extends SimpleController
|
||||
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' => [
|
||||
@@ -769,6 +743,16 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function getModalConfirmPermenentDelete(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
|
||||
// GET parameters
|
||||
$params = $request->getQueryParams();
|
||||
|
||||
@@ -779,12 +763,6 @@ class OrganisationController extends SimpleController
|
||||
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, 'permenent_delete_organisation', [
|
||||
'organisation' => $organisation,
|
||||
@@ -792,9 +770,6 @@ class OrganisationController extends SimpleController
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
return $this->ci->view->render($response, 'modals/confirm-permenent-delete-organisation.html.twig', [
|
||||
'organisation' => $organisation,
|
||||
'form' => [
|
||||
@@ -822,20 +797,21 @@ class OrganisationController extends SimpleController
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @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', []);
|
||||
|
||||
@@ -880,6 +856,16 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function getModalEdit(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;
|
||||
|
||||
|
||||
// GET parameters
|
||||
$params = $request->getQueryParams();
|
||||
|
||||
@@ -890,18 +876,6 @@ class OrganisationController extends SimpleController
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
/** @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\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
/** @var \UserFrosting\I18n\Translator $translator */
|
||||
$translator = $this->ci->translator;
|
||||
|
||||
// Access-controlled resource - check that currentUser has permission to edit basic fields "name", "slug", "description" for this organisation
|
||||
$fieldNames = ['name', 'slug', 'description'];
|
||||
if (!$authorizer->checkAccess($currentUser, 'update_organisation_field', [
|
||||
@@ -955,6 +929,19 @@ class OrganisationController extends SimpleController
|
||||
*/
|
||||
public function getModalMerge(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
/** @var \UserFrosting\I18n\Translator $translator */
|
||||
$translator = $this->ci->translator;
|
||||
|
||||
|
||||
// GET parameters
|
||||
$params = $request->getQueryParams();
|
||||
|
||||
@@ -965,18 +952,6 @@ class OrganisationController extends SimpleController
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
/** @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\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
/** @var \UserFrosting\I18n\Translator $translator */
|
||||
$translator = $this->ci->translator;
|
||||
|
||||
// Access-controlled resource - check that currentUser has permission to merge organisations.
|
||||
if (!$authorizer->checkAccess($currentUser, 'merge_organisations')) {
|
||||
throw new ForbiddenException();
|
||||
@@ -1020,7 +995,13 @@ class OrganisationController extends SimpleController
|
||||
* @throws ForbiddenException If user is not authorized to access page
|
||||
*/
|
||||
public function pageInfo(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;
|
||||
|
||||
|
||||
$organisation = $this->getOrganisationFromParams($args);
|
||||
|
||||
// If the organisation no longer exists, forward to main organisation listing page
|
||||
@@ -1028,12 +1009,6 @@ class OrganisationController extends SimpleController
|
||||
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, 'uri_organisation', [
|
||||
'organisation' => $organisation,
|
||||
|
||||
@@ -54,25 +54,29 @@ class OrganisationRegistrationController extends SimpleController
|
||||
*/
|
||||
public function register(Request $request, Response $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\Interfaces\UserInterface $currentUser */
|
||||
$currentUser = $this->ci->currentUser;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'register_organisation')) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
// Get POST parameters: name, slug, icon, description
|
||||
$params = $request->getParsedBody();
|
||||
|
||||
// Load the request schema
|
||||
$schema = new RequestSchema('schema://requests/organisation/create.yaml');
|
||||
@@ -90,9 +94,6 @@ class OrganisationRegistrationController extends SimpleController
|
||||
$error = true;
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
// Check if name or slug already exists
|
||||
if ($classMapper->getClassMapping('organisation')::findUnique($data['name'], 'name')) {
|
||||
$ms->addMessageTranslated('danger', 'ORGANISATION.NAME.IN_USE_REGISTER', $data);
|
||||
@@ -103,6 +104,7 @@ class OrganisationRegistrationController extends SimpleController
|
||||
return $response->withJson([], 400);
|
||||
}
|
||||
|
||||
// Generate a unique slug
|
||||
$slugIncrement = 0;
|
||||
$slugIncrementString = '';
|
||||
while ($classMapper->getClassMapping('organisation')::findUnique($data['slug'] . $slugIncrementString, 'slug')) {
|
||||
@@ -111,41 +113,45 @@ class OrganisationRegistrationController extends SimpleController
|
||||
}
|
||||
$data['slug'] .= $slugIncrementString;
|
||||
|
||||
// Prefill some default values
|
||||
$data['flag_approved'] = !$config['organisation.registration.require_approval'];
|
||||
$data['registrant_id'] = $currentUser->id;
|
||||
|
||||
// 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, $config) {
|
||||
Capsule::transaction(function () use ($classMapper, $data, $currentUser, $config) {
|
||||
// Create the organisation
|
||||
$organisation = $classMapper->createInstance('organisation', $data);
|
||||
|
||||
// Store new organisation to database
|
||||
$organisation->save();
|
||||
|
||||
// Attach the members
|
||||
$organisation->members()->attach($currentUser, ['flag_admin' => true]);
|
||||
// Attach the creating member
|
||||
$organisation->members()->attach($currentUser->id, [
|
||||
'flag_admin' => 1,
|
||||
'flag_approved' => 1,
|
||||
]);
|
||||
|
||||
// Save members
|
||||
$organisation->save();
|
||||
// If approval is required, generate a token & send an email
|
||||
if ($config['organisation.registration.require_approval']) {
|
||||
$timeout = $config['organisation.registration.timeout'];
|
||||
|
||||
// Try to generate a new approval request
|
||||
$approval = $this->ci->repoOrganisationApproval->create($organisation, $timeout);
|
||||
|
||||
$this->sendApprovalEmail($currentUser, $organisation, $approval->getToken(), $timeout);
|
||||
}
|
||||
|
||||
// Create activity record
|
||||
$this->ci->userActivityLogger->info("User {$currentUser->user_name} registered organisation {$organisation->name}.", [
|
||||
'type' => 'organisation_register',
|
||||
'user_id' => $currentUser->id,
|
||||
]);
|
||||
|
||||
if ($config['organisation.registration.require_approval']) {
|
||||
$timeout = $this->ci->config['organisation.registration.timeout'];
|
||||
|
||||
// Try to generate a new approval request
|
||||
$approval = $this->ci->repoOrganisationApproval->create($organisation, $currentUser, $timeout);
|
||||
|
||||
$this->sendApprovalEmail($currentUser, $organisation, $approval->getToken());
|
||||
}
|
||||
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.REGISTRATION.SUCCESSFUL', $data);
|
||||
});
|
||||
|
||||
// Generate a success message
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.REGISTRATION.SUCCESSFUL', $data);
|
||||
|
||||
return $response->withJson([], 200);
|
||||
}
|
||||
|
||||
@@ -156,7 +162,7 @@ class OrganisationRegistrationController extends SimpleController
|
||||
* Before doing so, checks that:
|
||||
* 1. The user has permission to cancel this organisation registration request;
|
||||
* 2. The submitted data is valid.
|
||||
* This route requires authentication (and should generally be limited to admins or the root user).
|
||||
* This route requires authentication. (NOTE: This route is only available to the organisation registrant!)
|
||||
*
|
||||
* Request type: DELETE
|
||||
*
|
||||
@@ -170,6 +176,17 @@ class OrganisationRegistrationController extends SimpleController
|
||||
*/
|
||||
public function cancel(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\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
// Get the organisation from the uri
|
||||
$organisation = $this->getOrganisationFromParams($args);
|
||||
|
||||
// If the organisation doesn't exist, return 404
|
||||
@@ -177,12 +194,6 @@ class OrganisationRegistrationController extends SimpleController
|
||||
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, 'register_organisation', [
|
||||
'organisation' => $organisation,
|
||||
@@ -190,20 +201,16 @@ class OrganisationRegistrationController extends SimpleController
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
if (!$authorizer->runCallback($currentUser, 'is_organisation_admin', $currentUser->id, $organisation->id)) {
|
||||
// Check the user is registrant of this organisation
|
||||
if ($organisation->registrant_id == $currentUser->id) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($organisation, $currentUser) {
|
||||
$organisationName = $organisation->name;
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($organisation, $organisationName, $currentUser) {
|
||||
// Delete the organisation
|
||||
$organisation->delete(true);
|
||||
unset($organisation);
|
||||
|
||||
@@ -214,9 +221,7 @@ class OrganisationRegistrationController extends SimpleController
|
||||
]);
|
||||
});
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
// Generate a response
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.REGISTRATION.CANCEL_SUCCESSFUL', [
|
||||
'name' => $organisationName,
|
||||
]);
|
||||
@@ -243,21 +248,22 @@ class OrganisationRegistrationController extends SimpleController
|
||||
*/
|
||||
public function approve(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
/** @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\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'approve_organisation')) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
// Get the organisation from the uri
|
||||
$organisation = $this->getOrganisationFromParams($args);
|
||||
|
||||
// If the organisation doesn't exist, return 404
|
||||
@@ -265,22 +271,30 @@ class OrganisationRegistrationController extends SimpleController
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'approve_organisation')) {
|
||||
throw new ForbiddenException();
|
||||
$approval = $this->ci->repoOrganisationApproval->exists($organisation);
|
||||
if (!$approval) {
|
||||
$ms->addMessageTranslated('danger', 'ORGANISATION.REGISTRATION.TOKEN_NOT_FOUND');
|
||||
return $response->withJson([], 400);
|
||||
}
|
||||
|
||||
$verification = $this->ci->repoOrganisationApproval->completeWithoutToken($organisation, $currentUser, ['approved' => true]);
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($organisation, $currentUser) {
|
||||
$this->ci->repoOrganisationApproval->completeForOwner($organisation, [
|
||||
'approver_id' => $currentUser->id,
|
||||
'approved' => true
|
||||
]);
|
||||
|
||||
$requester = $classMapper->getClassMapping('user')::find($verification->requester_id);
|
||||
|
||||
$this->sendApprovedEmail($organisation, $requester);
|
||||
// Send a notification email to the registrant
|
||||
$this->sendApprovedEmail($organisation);
|
||||
|
||||
// Record the event in the activity log
|
||||
$this->ci->userActivityLogger->info("User {$currentUser->user_name} approved the registration request for organisation {$organisation->name}.", [
|
||||
'type' => 'organisation_approved',
|
||||
'user_id' => $currentUser->id,
|
||||
]);
|
||||
});
|
||||
|
||||
// Generate a response
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.REGISTRATION.APPROVED', [
|
||||
'name' => $organisation->name
|
||||
]);
|
||||
@@ -307,21 +321,19 @@ class OrganisationRegistrationController extends SimpleController
|
||||
*/
|
||||
public function approveToken(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
/** @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\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'approve_organisation')) {
|
||||
throw new ForbiddenException();
|
||||
@@ -342,39 +354,50 @@ class OrganisationRegistrationController extends SimpleController
|
||||
if (!$validator->validate($data)) {
|
||||
$ms->addValidationErrors($validator);
|
||||
|
||||
return $response->withRedirect($this->ci->router->pathFor('dashboard'));
|
||||
return $response->withRedirect($this->ci->router->pathFor('uri_organisations'));
|
||||
}
|
||||
|
||||
$verification = $this->ci->repoOrganisationApproval->complete($data['token'], $currentUser, ['approved' => true]);
|
||||
$token = $data['token'];
|
||||
|
||||
if (!$verification) {
|
||||
$organisation = $classMapper->getClassMapping('organisation')::query()
|
||||
->where('id', $this->ci->repoOrganisationApproval->findOwner($token))
|
||||
->first();
|
||||
if (!$organisation) {
|
||||
$ms->addMessageTranslated('danger', 'ORGANISATION.REGISTRATION.TOKEN_NOT_FOUND');
|
||||
return $response->withRedirect($this->ci->router->pathFor('dashboard'));
|
||||
return $response->withRedirect($this->ci->router->pathFor('uri_organisations'));
|
||||
}
|
||||
|
||||
$organisation = $classMapper->getClassMapping('organisation')::find($verification->organisation_id);
|
||||
$requester = $classMapper->getClassMapping('user')::find($verification->requester_id);
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($currentUser, $token, $organisation) {
|
||||
$this->ci->repoOrganisationApproval->complete($token, [
|
||||
'approver_id' => $currentUser->id,
|
||||
'approved' => true
|
||||
]);
|
||||
|
||||
$this->sendApprovedEmail($organisation, $requester);
|
||||
// Send a notification email to the registrant
|
||||
$this->sendApprovedEmail($organisation);
|
||||
|
||||
// Record the event in the activity log
|
||||
$this->ci->userActivityLogger->info("User {$currentUser->user_name} approved the registration request for organisation {$organisation->name}.", [
|
||||
'type' => 'organisation_approved',
|
||||
'user_id' => $currentUser->id,
|
||||
]);
|
||||
});
|
||||
|
||||
// Generate the response
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.REGISTRATION.APPROVED', [
|
||||
'name' => $organisation->name
|
||||
]);
|
||||
|
||||
// Forward to login page
|
||||
return $response->withRedirect($this->ci->router->pathFor('dashboard'));
|
||||
// Forward to organisations page
|
||||
return $response->withRedirect($this->ci->router->pathFor('uri_organisations'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Denies an organisation registration request.
|
||||
*
|
||||
* Processes the request from the email verification link that was emailed to the organisation administrators, checking that:
|
||||
* 1. The token provided matches an organisation in the database;
|
||||
* Processes the request from the organisation page, checking that:
|
||||
* 1. The organisation exists;
|
||||
* 2. The organisation is not already approved;
|
||||
* This route requires authorization.
|
||||
*
|
||||
@@ -389,21 +412,22 @@ class OrganisationRegistrationController extends SimpleController
|
||||
*/
|
||||
public function deny(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
/** @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\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'approve_organisation')) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
// Get the organisation from the uri
|
||||
$organisation = $this->getOrganisationFromParams($args);
|
||||
|
||||
// If the organisation doesn't exist, return 404
|
||||
@@ -411,24 +435,30 @@ class OrganisationRegistrationController extends SimpleController
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'approve_organisation')) {
|
||||
throw new ForbiddenException();
|
||||
$approval = $this->ci->repoOrganisationApproval->exists($organisation);
|
||||
if (!$approval) {
|
||||
$ms->addMessageTranslated('danger', 'ORGANISATION.REGISTRATION.TOKEN_NOT_FOUND');
|
||||
return $response->withJson([], 400);
|
||||
}
|
||||
|
||||
$verification = $this->ci->repoOrganisationApproval->completeWithoutToken($organisation, $currentUser, ['approved' => false]);
|
||||
|
||||
$requester = $classMapper->getClassMapping('user')::find($verification->requester_id);
|
||||
|
||||
$this->sendDeniedEmail($organisation, $requester);
|
||||
|
||||
$organisation->delete();
|
||||
|
||||
$this->ci->userActivityLogger->info("User {$currentUser->user_name} denied the registration request for organisation {$organisation->name}.", [
|
||||
'type' => 'organisation_approval',
|
||||
'user_id' => $currentUser->id,
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($organisation, $currentUser) {
|
||||
$this->ci->repoOrganisationApproval->completeForOwner($organisation, [
|
||||
'approver_id' => $currentUser->id,
|
||||
'approved' => false
|
||||
]);
|
||||
|
||||
// Send a notification email to the registrant
|
||||
$this->sendDeniedEmail($organisation);
|
||||
|
||||
// Record the event in the activity log
|
||||
$this->ci->userActivityLogger->info("User {$currentUser->user_name} denied the registration request for organisation {$organisation->name}.", [
|
||||
'type' => 'organisation_approved',
|
||||
'user_id' => $currentUser->id,
|
||||
]);
|
||||
});
|
||||
|
||||
// Generate a response
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.REGISTRATION.DENIED', [
|
||||
'name' => $organisation->name
|
||||
]);
|
||||
@@ -455,23 +485,18 @@ class OrganisationRegistrationController extends SimpleController
|
||||
*/
|
||||
public function denyToken(Request $request, Response $response, $args)
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||
$config = $this->ci->config;
|
||||
|
||||
/** @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\Sprinkle\Core\Alert\AlertStream $ms */
|
||||
$ms = $this->ci->alerts;
|
||||
|
||||
$dashboardPage = $this->ci->router->pathFor('dashboard');
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->checkAccess($currentUser, 'approve_organisation')) {
|
||||
@@ -493,33 +518,43 @@ class OrganisationRegistrationController extends SimpleController
|
||||
if (!$validator->validate($data)) {
|
||||
$ms->addValidationErrors($validator);
|
||||
|
||||
return $response->withRedirect($dashboardPage);
|
||||
return $response->withRedirect($this->ci->router->pathFor('uri_organisations'));
|
||||
}
|
||||
|
||||
$verification = $this->ci->repoOrganisationApproval->complete($data['token'], $currentUser, ['approved' => false]);
|
||||
$token = $data['token'];
|
||||
|
||||
if ($verification === false) {
|
||||
$organisation = $classMapper->getClassMapping('organisation')::query()
|
||||
->where('id', $this->ci->repoOrganisationApproval->findOwner($token))
|
||||
->first();
|
||||
if (!$organisation) {
|
||||
$ms->addMessageTranslated('danger', 'ORGANISATION.REGISTRATION.TOKEN_NOT_FOUND');
|
||||
|
||||
return $response->withRedirect($dashboardPage);
|
||||
return $response->withRedirect($this->ci->router->pathFor('uri_organisations'));
|
||||
}
|
||||
|
||||
$organisation = $classMapper->getClassMapping('organisation')::find($verification->organisation_id);
|
||||
$requester = $classMapper->getClassMapping('user')::find($verification->requester_id);
|
||||
|
||||
$this->sendDeniedEmail($organisation, $requester);
|
||||
|
||||
$this->ci->userActivityLogger->info("User {$currentUser->user_name} denied the registration request for organisation {$organisation->name}.", [
|
||||
'type' => 'organisation_approval',
|
||||
'user_id' => $currentUser->id,
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($currentUser, $token, $organisation) {
|
||||
$this->ci->repoOrganisationApproval->complete($token, [
|
||||
'approver_id' => $currentUser->id,
|
||||
'approved' => false
|
||||
]);
|
||||
|
||||
// Send a notification email to the registrant
|
||||
$this->sendDeniedEmail($organisation);
|
||||
|
||||
// Record the event in the activity log
|
||||
$this->ci->userActivityLogger->info("User {$currentUser->user_name} denied the registration request for organisation {$organisation->name}.", [
|
||||
'type' => 'organisation_approved',
|
||||
'user_id' => $currentUser->id,
|
||||
]);
|
||||
});
|
||||
|
||||
// Generate the response
|
||||
$ms->addMessageTranslated('success', 'ORGANISATION.REGISTRATION.DENIED', [
|
||||
'name' => $organisation->name
|
||||
]);
|
||||
|
||||
// Forward to login page
|
||||
return $response->withRedirect($dashboardPage);
|
||||
// Forward to organisations page
|
||||
return $response->withRedirect($this->ci->router->pathFor('uri_organisations'));
|
||||
}
|
||||
|
||||
|
||||
@@ -542,20 +577,21 @@ class OrganisationRegistrationController extends SimpleController
|
||||
/** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
|
||||
$authorizer = $this->ci->authorizer;
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
/** @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, 'register_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', []);
|
||||
|
||||
@@ -569,6 +605,7 @@ class OrganisationRegistrationController extends SimpleController
|
||||
$schema = new RequestSchema('schema://requests/organisation/create.yaml');
|
||||
$validator = new JqueryValidationAdapter($schema, $this->ci->translator);
|
||||
|
||||
// Generate the response
|
||||
return $this->ci->view->render($response, 'modals/organisation.html.twig', [
|
||||
'organisation' => $organisation,
|
||||
'form' => [
|
||||
@@ -596,6 +633,12 @@ class OrganisationRegistrationController extends SimpleController
|
||||
*/
|
||||
public function getModalConfirmCancel(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;
|
||||
|
||||
// GET parameters
|
||||
$params = $request->getQueryParams();
|
||||
|
||||
@@ -606,12 +649,6 @@ class OrganisationRegistrationController extends SimpleController
|
||||
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, 'register_organisation', [
|
||||
'organisation' => $organisation,
|
||||
@@ -619,14 +656,12 @@ class OrganisationRegistrationController extends SimpleController
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
// Access-controlled page
|
||||
if (!$authorizer->runCallback($currentUser, 'is_organisation_admin', $currentUser->id, $organisation->id)) {
|
||||
// Check the user is registrant of this organisation
|
||||
if ($organisation->registrant_id == $currentUser->id) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = $this->ci->classMapper;
|
||||
|
||||
// Generate the response
|
||||
return $this->ci->view->render($response, 'modals/confirm-cancel-organisation-registration.html.twig', [
|
||||
'organisation' => $organisation,
|
||||
'form' => [
|
||||
@@ -642,10 +677,8 @@ class OrganisationRegistrationController extends SimpleController
|
||||
* @param UserInterface $requester The user to send the confirmation of registration to
|
||||
* @param UserInterface $organisation The organisation to send the email for
|
||||
*/
|
||||
protected function sendApprovalEmail(UserInterface $requester, OrganisationInterface $organisation, $token)
|
||||
protected function sendApprovalEmail(UserInterface $requester, OrganisationInterface $organisation, $token, $timeout)
|
||||
{
|
||||
$timeout = $this->ci->config['organisation.registration.timeout'];
|
||||
|
||||
// Create and send approval email
|
||||
$message = new TwigMailMessage($this->ci->view, 'mail/organisation-approval-request.html.twig');
|
||||
|
||||
@@ -657,18 +690,19 @@ class OrganisationRegistrationController extends SimpleController
|
||||
'approval_expiration' => ($timeout > 0 ? floor($timeout / 86400) . ' days' : false),
|
||||
]);
|
||||
|
||||
// Find the organisations admins or, if there are none, the site admin.
|
||||
$role = $this->ci->classMapper->getClassMapping('role')::where('slug', 'organisations-admin')->with('users')->first();
|
||||
if ($role->users()->count() == 0) {
|
||||
$role = $this->ci->classMapper->getClassMapping('role')::where('slug', 'site-admin')->with('users')->first();
|
||||
}
|
||||
|
||||
// Generate a list of recipients and send the email addressed to each.
|
||||
$recipients = $role->users()->get();
|
||||
|
||||
foreach($recipients as $recipient) {
|
||||
$message->addEmailRecipient(new EmailRecipient($recipient->email, $recipient->full_name));
|
||||
$message->addParams([ 'recipient' => $recipient ]);
|
||||
$this->ci->mailer->send($message);
|
||||
$message->addParams([ 'recipient' => null ]);
|
||||
$message->clearRecipients();
|
||||
}
|
||||
}
|
||||
@@ -679,8 +713,10 @@ class OrganisationRegistrationController extends SimpleController
|
||||
* @param UserInterface $requester The user to send the approved notice to
|
||||
* @param UserInterface $organisation The organisation to send the email for
|
||||
*/
|
||||
protected function sendApprovedEmail(OrganisationInterface $organisation, UserInterface $requester)
|
||||
protected function sendApprovedEmail(OrganisationInterface $organisation)
|
||||
{
|
||||
$requester = $organisation->registrant()->first();
|
||||
|
||||
$message = new TwigMailMessage($this->ci->view, 'mail/organisation-approval-approved.html.twig');
|
||||
|
||||
$message->from($this->ci->config['address_book.admin'])
|
||||
@@ -699,8 +735,13 @@ class OrganisationRegistrationController extends SimpleController
|
||||
* @param UserInterface $requester The user to send the denial notice to
|
||||
* @param UserInterface $organisation The organisation to send the email for
|
||||
*/
|
||||
protected function sendDeniedEmail(OrganisationInterface $organisation, UserInterface $requester)
|
||||
protected function sendDeniedEmail(OrganisationInterface $organisation)
|
||||
{
|
||||
$requester = $organisation->registrant()->first();
|
||||
|
||||
$this->ci->debugLogger->debug('organisation', [$organisation]);
|
||||
$this->ci->debugLogger->debug('requester', [$requester]);
|
||||
|
||||
$message = new TwigMailMessage($this->ci->view, 'mail/organisation-approval-denied.html.twig');
|
||||
|
||||
$message->from($this->ci->config['address_book.admin'])
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AVSDev UF Organisations (https://avsdev.uk)
|
||||
*
|
||||
* @link https://git.avsdev.uk/avsdev/sprinkle-organisations
|
||||
* @license https://git.avsdev.uk/avsdev/sprinkle-organisations/blob/master/LICENSE.md (LGPL-3.0 License)
|
||||
*/
|
||||
|
||||
namespace UserFrosting\Sprinkle\Organisations\Database\Migrations\v003;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Capsule\Manager as DB;
|
||||
use UserFrosting\Sprinkle\Core\Database\Migration;
|
||||
|
||||
/**
|
||||
* Organisations approvals table migration
|
||||
* Drops the requester_id (moved to organisations as registrant_id) and organisation_id in favor of an owner_id.
|
||||
* Version 1.0.0.
|
||||
*
|
||||
* @author Craig Williams (https://avsdev.uk)
|
||||
*/
|
||||
class UpdateOrganisationApprovalsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $dependencies = [
|
||||
'\UserFrosting\Sprinkle\Organisations\Database\Migrations\v002\UpdateOrganisationApprovalsTable',
|
||||
];
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if ($this->schema->hasTable('organisation_approvals')) {
|
||||
DB::table('organisation_approvals')->delete();
|
||||
$this->schema->table('organisation_approvals', function (Blueprint $table) {
|
||||
$table->dropForeign(['requester_id']);
|
||||
$table->dropForeign(['organisation_id']);
|
||||
$table->dropIndex(['requester_id']);
|
||||
$table->dropColumn(['requester_id']);
|
||||
$table->dropColumn(['organisation_id']);
|
||||
|
||||
$table->integer('owner_id')->unsigned();
|
||||
$table->index('owner_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
DB::table('organisation_approvals')->delete();
|
||||
$this->schema->table('organisation_approvals', function (Blueprint $table) {
|
||||
$table->dropIndex(['owner_id']);
|
||||
$table->dropColumn('owner_id')->unsigned();
|
||||
|
||||
$table->integer('requester_id')->unsigned();
|
||||
$table->integer('organisation_id')->unsigned();
|
||||
$table->index('requester_id');
|
||||
$table->foreign('requester_id')->references('id')->on('users');
|
||||
$table->foreign('organisation_id')->references('id')->on('organisations');
|
||||
});
|
||||
}
|
||||
}
|
||||
55
src/Database/Migrations/v003/UpdateOrganisationsTable.php
Normal file
55
src/Database/Migrations/v003/UpdateOrganisationsTable.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AVSDev UF Organisations (https://avsdev.uk)
|
||||
*
|
||||
* @link https://git.avsdev.uk/avsdev/sprinkle-organisations
|
||||
* @license https://git.avsdev.uk/avsdev/sprinkle-organisations/blob/master/LICENSE.md (LGPL-3.0 License)
|
||||
*/
|
||||
|
||||
namespace UserFrosting\Sprinkle\Organisations\Database\Migrations\v003;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use UserFrosting\Sprinkle\Organisations\Database\Models\Organisation;
|
||||
use UserFrosting\Sprinkle\Core\Database\Migration;
|
||||
use UserFrosting\Sprinkle\Core\Facades\Seeder;
|
||||
|
||||
/**
|
||||
* Organisations table migration
|
||||
* Adds a `registrant_id` column to the `organisations` table
|
||||
* Version 1.0.0.
|
||||
*
|
||||
* @author Craig Williams (https://avsdev.uk)
|
||||
*/
|
||||
class UpdateOrganisationsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $dependencies = [
|
||||
'\UserFrosting\Sprinkle\Account\Database\Migrations\v400\UsersTable',
|
||||
'\UserFrosting\Sprinkle\Organisations\Database\Migrations\v002\UpdateOrganisationsTable',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if ($this->schema->hasTable('organisations')) {
|
||||
$this->schema->table('organisations', function (Blueprint $table) {
|
||||
$table->integer('registrant_id')->unsigned()->nullable();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$this->schema->table('organisations', function (Blueprint $table) {
|
||||
$table->dropColumn('registrant_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AVSDev UF Organisations (https://avsdev.uk)
|
||||
*
|
||||
* @link https://git.avsdev.uk/avsdev/sprinkle-organisations
|
||||
* @license https://git.avsdev.uk/avsdev/sprinkle-organisations/blob/master/LICENSE.md (LGPL-3.0 License)
|
||||
*/
|
||||
|
||||
namespace UserFrosting\Sprinkle\Organisations\Database\Models;
|
||||
|
||||
use Illuminate\Database\Capsule\Manager as DB;
|
||||
use UserFrosting\Sprinkle\Core\Database\Models\Model;
|
||||
|
||||
/**
|
||||
* Base organisation approval class.
|
||||
*
|
||||
* Represents a pending approval request which is tied to a user/organisation pair (membership, registration etc)
|
||||
*
|
||||
* @author Craig Williams (https://avsdev.uk)
|
||||
*
|
||||
* @property int $requester_id
|
||||
* @property int $organisation_id
|
||||
* @property hash $token
|
||||
* @property bool $completed
|
||||
* @property datetime $expires_at
|
||||
* @property datetime $completed_at
|
||||
* @property int $approver_id
|
||||
*/
|
||||
|
||||
class BaseOrganisationApproval extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'requester_id',
|
||||
'organisation_id',
|
||||
'hash',
|
||||
'completed',
|
||||
'expires_at',
|
||||
'completed_at',
|
||||
'approver_id,'
|
||||
];
|
||||
|
||||
/**
|
||||
* @var bool Enable timestamps for Verifications.
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
/**
|
||||
* @var string Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted.
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setToken($value)
|
||||
{
|
||||
$this->token = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user associated with this request of this approval.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function requester()
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = static::$ci->classMapper;
|
||||
|
||||
return $this->belongsTo($classMapper->getClassMapping('user'), 'requester_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the organisation associated with this approval request.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\belongsTo
|
||||
*/
|
||||
public function organisation()
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = static::$ci->classMapper;
|
||||
|
||||
return $this->belongsTo($classMapper->getClassMapping('organisation'), 'organisation_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user associated with this approval or denial of this request.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\belongsTo
|
||||
*/
|
||||
public function approver()
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = static::$ci->classMapper;
|
||||
|
||||
return $this->belongsTo($classMapper->getClassMapping('user'), 'approver_id');
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Capsule\Manager as DB;
|
||||
use UserFrosting\Sprinkle\Core\Database\Models\Model;
|
||||
use UserFrosting\Sprinkle\Organisations\Database\Models\Interfaces\OrganisationInterface;
|
||||
use UserFrosting\Sprinkle\Organisations\Repository\Interfaces\TokenOwnerInterface;
|
||||
|
||||
/**
|
||||
* Organisation Class.
|
||||
@@ -28,7 +29,7 @@ use UserFrosting\Sprinkle\Organisations\Database\Models\Interfaces\OrganisationI
|
||||
* @property timestamp $updated_at
|
||||
* @property timestamp $deleted_at
|
||||
*/
|
||||
class Organisation extends Model implements OrganisationInterface
|
||||
class Organisation extends Model implements OrganisationInterface, TokenOwnerInterface
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
@@ -46,6 +47,7 @@ class Organisation extends Model implements OrganisationInterface
|
||||
'slug',
|
||||
'name',
|
||||
'description',
|
||||
'registrant_id',
|
||||
'flag_approved',
|
||||
'deleted_at',
|
||||
];
|
||||
@@ -82,6 +84,25 @@ class Organisation extends Model implements OrganisationInterface
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
/**
|
||||
* Get the mapping id, as per TokenOwnerInterface
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the user who registered this organisation
|
||||
*/
|
||||
public function registrant()
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = static::$ci->classMapper;
|
||||
|
||||
return $this->hasOne($classMapper->getClassMapping('user'), 'id', 'registrant_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of members within this organisation.
|
||||
@@ -93,8 +114,7 @@ class Organisation extends Model implements OrganisationInterface
|
||||
|
||||
return $this
|
||||
->belongsToMany($classMapper->getClassMapping('user'), 'organisation_members', 'organisation_id', 'user_id')
|
||||
->where('flag_admin', false)
|
||||
->withTimestamps();
|
||||
->where('flag_admin', false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,8 +127,7 @@ class Organisation extends Model implements OrganisationInterface
|
||||
|
||||
return $this
|
||||
->belongsToMany($classMapper->getClassMapping('user'), 'organisation_members', 'organisation_id', 'user_id')
|
||||
->where('flag_admin', true)
|
||||
->withTimestamps();
|
||||
->where('flag_admin', true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +146,7 @@ class Organisation extends Model implements OrganisationInterface
|
||||
static::$ci->get('organisation.beforeDelete')($this);
|
||||
|
||||
// Remove all organisation tokens
|
||||
$classMapper->getClassMapping('organisation_approval')::where('organisation_id', $this->id)->delete();
|
||||
$classMapper->getClassMapping('organisation_approval')::where('owner_id', $this->id)->delete();
|
||||
|
||||
// Remove all member associations
|
||||
$this->members()->detach();
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
namespace UserFrosting\Sprinkle\Organisations\Database\Models;
|
||||
|
||||
use Illuminate\Database\Capsule\Manager as DB;
|
||||
use UserFrosting\Sprinkle\Organisations\Database\Models\BaseOrganisationApproval;
|
||||
use UserFrosting\Sprinkle\Core\Database\Models\Model;
|
||||
|
||||
/**
|
||||
* Organisation Approval Class.
|
||||
@@ -18,12 +17,111 @@ use UserFrosting\Sprinkle\Organisations\Database\Models\BaseOrganisationApproval
|
||||
* Represents a pending organisation approval request.
|
||||
*
|
||||
* @author Craig Williams (https://avsdev.uk)
|
||||
*
|
||||
* @property int $owner_id
|
||||
* @property hash $token
|
||||
* @property bool $completed
|
||||
* @property datetime $expires_at
|
||||
* @property datetime $completed_at
|
||||
* @property int $approver_id
|
||||
*/
|
||||
|
||||
class OrganisationApproval extends BaseOrganisationApproval
|
||||
class OrganisationApproval extends Model
|
||||
{
|
||||
/**
|
||||
* @var string The name of the table for the current model.
|
||||
*/
|
||||
protected $table = 'organisation_approvals';
|
||||
|
||||
/**
|
||||
* Fields that should be mass-assignable when creating a new Organisation.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
'owner_id',
|
||||
'hash',
|
||||
'completed',
|
||||
'expires_at',
|
||||
'completed_at',
|
||||
'approver_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var bool Enable timestamps for Verifications.
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
|
||||
/**
|
||||
* @var string Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted.
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setToken($value)
|
||||
{
|
||||
$this->token = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the owner.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function owner()
|
||||
{
|
||||
return $this->organisation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the organisation of this approval.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function organisation()
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = static::$ci->classMapper;
|
||||
|
||||
return $this->belongsTo($classMapper->getClassMapping('organisation'), 'owner_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the requester of this approval.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function requester()
|
||||
{
|
||||
return $this->organisation->registrant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user associated with this approval or denial of this request.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\belongsTo
|
||||
*/
|
||||
public function approver()
|
||||
{
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = static::$ci->classMapper;
|
||||
|
||||
return $this->belongsTo($classMapper->getClassMapping('user'), 'approver_id');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ class User extends UFUser
|
||||
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||
$classMapper = static::$ci->classMapper;
|
||||
|
||||
return $this->belongsToMany($classMapper->getClassMapping('organisation'), 'organisation_members', 'user_id', 'organisation_id')->orderBy('organisations.name', 'asc')->withPivot('flag_admin');
|
||||
return $this->belongsToMany(
|
||||
$classMapper->getClassMapping('organisation'), 'organisation_members', 'user_id', 'organisation_id'
|
||||
)
|
||||
->orderBy('organisations.name', 'asc')
|
||||
->withPivot('flag_admin');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +57,16 @@ class User extends UFUser
|
||||
$classMapper = static::$ci->classMapper;
|
||||
|
||||
if ($hardDelete) {
|
||||
// TODO: remove user from organisations?
|
||||
$classMapper->getClassMapping('organisation')::query()
|
||||
->where('registrant_id', $this->id)
|
||||
->update(['registrant_id' => null]);
|
||||
|
||||
$classMapper->getClassMapping('organisation_approval')::query()
|
||||
->where('approver_id', $this->id)
|
||||
->update(['approver_id' => null]);
|
||||
|
||||
$this->organisations()->detach();
|
||||
$this->refresh();
|
||||
}
|
||||
|
||||
return parent::delete();
|
||||
|
||||
@@ -9,12 +9,6 @@
|
||||
|
||||
namespace UserFrosting\Sprinkle\Organisations\Repository;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Capsule\Manager as Capsule;
|
||||
use UserFrosting\Sprinkle\Organisations\Database\Models\Interfaces\OrganisationInterface;
|
||||
use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface;
|
||||
use UserFrosting\Sprinkle\Account\Repository\TokenRepository;
|
||||
use UserFrosting\Sprinkle\Core\Database\Models\Model;
|
||||
use UserFrosting\Sprinkle\Core\Util\ClassMapper;
|
||||
|
||||
/**
|
||||
@@ -22,215 +16,38 @@ use UserFrosting\Sprinkle\Core\Util\ClassMapper;
|
||||
*
|
||||
* @author Craig Williams (https://avsdev.uk)
|
||||
*/
|
||||
class OrganisationApprovalRepository extends TokenRepository
|
||||
class OrganisationApprovalRepository extends BasicTokenRepository
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $modelIdentifier = 'organisation_approval';
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function complete($token, UserInterface $approver, $params = [])
|
||||
protected function updateTokenOwner($owner_id, $model, $args)
|
||||
{
|
||||
// Hash the token for the stored version
|
||||
$hash = hash($this->algorithm, $token);
|
||||
$organisation = $this->classMapper->getClassMapping('organisation')::findUnique($owner_id, 'id', false);
|
||||
|
||||
// Find an unexpired, incomplete token for the specified hash
|
||||
$model = $this->classMapper->getClassMapping($this->modelIdentifier)::query()
|
||||
->where('hash', $hash)
|
||||
->where('completed', false)
|
||||
->where(function($query) {
|
||||
return $query->where('expires_at', '>', Carbon::now())->orWhereNull('expires_at');
|
||||
})
|
||||
->first();
|
||||
|
||||
if ($model === null) {
|
||||
if (!$organisation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fetch user for this token
|
||||
$organisation = $this->classMapper->getClassMapping('organisation')::find($model->organisation_id);
|
||||
$requester = $this->classMapper->getClassMapping('user')::find($model->requester_id);
|
||||
|
||||
if (!$organisation || !$requester) {
|
||||
return false;
|
||||
// If specified, recored the approver. This assumes the model has an approver_id field which it may not...
|
||||
if ($args['approver_id']) {
|
||||
$model->approver_id = $args['approver_id'];
|
||||
}
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($model, $organisation, $requester, $approver, $params) {
|
||||
$this->updateOrganisation($organisation, $requester, $approver, $params);
|
||||
|
||||
$model->fill([
|
||||
'completed' => true,
|
||||
'completed_at' => Carbon::now(),
|
||||
]);
|
||||
|
||||
$model->approver_id = $approver->id;
|
||||
|
||||
$model->save();
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes a token request without requiring the token (admin overrride)
|
||||
*/
|
||||
public function completeWithoutToken(OrganisationInterface $organisation, UserInterface $approver, $params = [])
|
||||
{
|
||||
$model = $this->classMapper->getClassMapping($this->modelIdentifier)::query()
|
||||
->where('organisation_id', $organisation->id)
|
||||
->where('completed', false)
|
||||
->first();
|
||||
|
||||
if ($model === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fetch user for this token
|
||||
$requester = $this->classMapper->getClassMapping('user')::find($model->requester_id);
|
||||
|
||||
if (!$requester) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($model, $organisation, $requester, $approver, $params) {
|
||||
$this->updateOrganisation($organisation, $requester, $approver, $params);
|
||||
|
||||
$model->fill([
|
||||
'completed' => true,
|
||||
'completed_at' => Carbon::now(),
|
||||
]);
|
||||
|
||||
$model->approver_id = $approver->id;
|
||||
|
||||
$model->save();
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts a token request without requiring the token (admin overrride)
|
||||
*/
|
||||
public function revert(OrganisationInterface $organisation)
|
||||
{
|
||||
$model = $this->classMapper->getClassMapping($this->modelIdentifier)::query()
|
||||
->where('organisation_id', $organisation->id)
|
||||
->where('completed', true)
|
||||
->first();
|
||||
|
||||
if ($model === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Begin transaction - DB will be rolled back if an exception occurs
|
||||
Capsule::transaction(function () use ($model) {
|
||||
$model->fill([
|
||||
'completed' => false,
|
||||
'completed_at' => null,
|
||||
'approver_id' => null,
|
||||
]);
|
||||
|
||||
$model->save();
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function create(OrganisationInterface $organisation, UserInterface $requester, $timeout)
|
||||
{
|
||||
// Remove any previous tokens for this organisation
|
||||
$this->removeExisting($organisation);
|
||||
|
||||
// Compute expiration time
|
||||
$expiresAt = Carbon::now()->addSeconds($timeout);
|
||||
|
||||
$model = $this->classMapper->createInstance($this->modelIdentifier);
|
||||
|
||||
// Generate a random token
|
||||
$model->setToken($this->generateRandomToken());
|
||||
|
||||
// Hash the password reset token for the stored version
|
||||
$hash = hash($this->algorithm, $model->getToken());
|
||||
|
||||
$model->fill([
|
||||
'organisation_id' => $organisation->id,
|
||||
'requester_id' => $requester->id,
|
||||
'hash' => $hash,
|
||||
'completed' => false,
|
||||
'expires_at' => ($timeout >= 0 ? $expiresAt : null),
|
||||
]);
|
||||
|
||||
$model->save();
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists(OrganisationInterface $organisation, UserInterface $requester = null, $token = null)
|
||||
{
|
||||
$model = $this->classMapper->getClassMapping($this->modelIdentifier)::query()
|
||||
->where('organisation_id', $organisation->id)
|
||||
->where('completed', false)
|
||||
->where(function($query) {
|
||||
return $query->where('expires_at', '>', Carbon::now())->orWhereNull('expires_at');
|
||||
});
|
||||
|
||||
if ($token) {
|
||||
// get token hash
|
||||
$hash = hash($this->algorithm, $token);
|
||||
$model->where('hash', $hash);
|
||||
}
|
||||
|
||||
if ($requester) {
|
||||
$model->where('requester_id', $requester->id);
|
||||
}
|
||||
|
||||
return $model->first() ?: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function removeExisting(OrganisationInterface $organisation, UserInterface $requester = null)
|
||||
{
|
||||
$model = $this->classMapper->getClassMapping($this->modelIdentifier)::query()
|
||||
->where('organisation_id', $organisation->id);
|
||||
|
||||
if ($requester) {
|
||||
$model->where('requester_id', $requester->id);
|
||||
}
|
||||
|
||||
return $model->delete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function updateOrganisation(OrganisationInterface $organisation, UserInterface $requester, UserInterface $approver, $args)
|
||||
{
|
||||
if ($args['approved']) {
|
||||
// Mark the organisation as approved
|
||||
$organisation->flag_approved = 1;
|
||||
$organisation->save();
|
||||
}
|
||||
} else {
|
||||
// Soft delete the organisation
|
||||
$organisation->delete(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden
|
||||
*/
|
||||
protected function updateUser(UserInterface $user, $args)
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ class ServicesProvider
|
||||
*/
|
||||
$container['organisation.beforeDelete'] = function ($c) {
|
||||
/*
|
||||
* This method is invoked when an organisation is about to be merged
|
||||
* This method is invoked when an organisation is about to be deleted
|
||||
*
|
||||
* Returns a callback that handles re-owning any organisation objects.
|
||||
* Throwing exceptions is allowed but not recommended. This method is triggered within a Capsule context.
|
||||
@@ -168,7 +168,7 @@ class ServicesProvider
|
||||
};
|
||||
|
||||
/*
|
||||
* Repository for approval requests.
|
||||
* Repository for organisation registration approval requests.
|
||||
*
|
||||
* @return \UserFrosting\Sprinkle\Organisations\Repository\OrganisationApprovalRepository
|
||||
*/
|
||||
@@ -176,7 +176,7 @@ class ServicesProvider
|
||||
$classMapper = $c->classMapper;
|
||||
$config = $c->config;
|
||||
|
||||
$repo = new OrganisationApprovalRepository($classMapper, $config['verification.algorithm']);
|
||||
$repo = new OrganisationApprovalRepository($classMapper, $config['verification.algorithm'], $c['tokenLogger'], $config['debug.tokens']);
|
||||
|
||||
return $repo;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user