Allow users to see their own organisation pages

This commit is contained in:
2022-02-08 16:13:43 +00:00
parent 2d701760c3
commit b3c51527a0
9 changed files with 275 additions and 6 deletions

View File

@@ -74,10 +74,7 @@ class OrganisationMembersController extends SimpleController
$sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params);
$sprunje->extendQuery(function ($query) use ($classMapper, $organisation) {
return $query
->join('organisation_members', function($join) use($organisation) {
$join->on('organisation_members.user_id', '=', 'users.id')->where('organisation_id', $organisation->id);
});
return $query->where('organisation_id', $organisation->id);
});
// Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.

View File

@@ -0,0 +1,76 @@
<?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 Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletes;
use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface;
use UserFrosting\Sprinkle\Account\Database\Models\User as UFUser;
use UserFrosting\Sprinkle\Account\Facades\Password;
use UserFrosting\Sprinkle\Core\Database\Models\Model;
use UserFrosting\Sprinkle\Core\Facades\Debug;
/**
* User Class.
*
* Extends the UF User object by adding organisation membership
*
* @author Craig Williams (https://avsdev.uk)
*/
class User extends UFUser
{
/**
* Get all organisations this user is a member of.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function organisations()
{
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
$classMapper = static::$ci->classMapper;
return $this->belongsToMany($classMapper->getClassMapping('organisation'), 'organisation_members', 'user_id', 'organisation_id');
}
/**
* Delete this member from the database, along with any links to organisations.
*
* @param bool $hardDelete Set to true to completely remove the member and all associated objects.
*
* @return bool true if the deletion was successful, false otherwise.
*/
public function delete($hardDelete = false)
{
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
$classMapper = static::$ci->classMapper;
if ($hardDelete) {
// TODO: remove user from organisations?
}
return parent::delete();
}
/**
* Joins the user's organisations directly, so we can do things like sort, search, paginate, etc.
*
* @param Builder $query
*
* @return Builder
*/
public function scopeJoinOrganisations($query)
{
$query = $query->leftJoin('organisation_members', 'organisation_members.user_id', '=', 'users.id');
$query = $query->leftJoin('organisations', 'organisations.id', '=', 'organisation_members.organisation_id');
return $query;
}
}

View File

@@ -27,6 +27,7 @@ class OrganisationPermissions extends BaseSeed
public function run()
{
// We require the default roles
Seeder::execute('DefaultPermissions');
Seeder::execute('DefaultRoles');
Seeder::execute('OrganisationRoles');
@@ -56,6 +57,12 @@ class OrganisationPermissions extends BaseSeed
'conditions' => "in(property,['name','slug','description','members'])",
'description' => 'View certain properties of any organisation.',
]),
'view_organisation_field_own' => new Permission([
'slug' => 'view_organisation_field',
'name' => 'View own organisation',
'conditions' => "is_organisation_member(self.id,organisation.id) & in(property,['name','slug','description','members'])",
'description' => 'View certain properties of own organisation.',
]),
'update_organisation_field' => new Permission([
'slug' => 'update_organisation_field',
'name' => 'Edit organisation',
@@ -80,6 +87,12 @@ class OrganisationPermissions extends BaseSeed
'conditions' => 'always()',
'description' => 'View the organisation page of any organisation.',
]),
'uri_organisation_own' => new Permission([
'slug' => 'uri_organisation',
'name' => 'View own organisation',
'conditions' => 'is_organisation_member(self.id,organisation.id)',
'description' => 'View the organisation page of an organisation you are a member of.',
]),
'uri_organisations' => new Permission([
'slug' => 'uri_organisations',
'name' => 'Organisation management page',
@@ -144,6 +157,13 @@ class OrganisationPermissions extends BaseSeed
$permissions['uri_organisation']->id,
]);
}
$roleUser = Role::where('slug', 'user')->first();
if ($roleUser) {
$roleUser->permissions()->syncWithoutDetaching([
$permissions['uri_organisation_own']->id,
$permissions['view_organisation_field_own']->id,
]);
}
}
}

View File

@@ -9,6 +9,7 @@
namespace UserFrosting\Sprinkle\Organisations\ServicesProvider;
use Illuminate\Database\Capsule\Manager as Capsule;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
@@ -38,10 +39,49 @@ class ServicesProvider
$container->extend('classMapper', function ($classMapper, $c) {
$classMapper->setClassMapping('organisation', 'UserFrosting\Sprinkle\Organisations\Database\Models\Organisation');
$classMapper->setClassMapping('organisation_sprunje', 'UserFrosting\Sprinkle\Organisations\Sprunje\OrganisationSprunje');
$classMapper->setClassMapping('user', 'UserFrosting\Sprinkle\Organisations\Database\Models\User');
$classMapper->setClassMapping('user_sprunje', 'UserFrosting\Sprinkle\Organisations\Sprunje\UserSprunje');
return $classMapper;
});
/*
* Extend the 'authorizer' service to add extra access condition callbacks.
*
* @return \UserFrosting\Sprinkle\Core\Util\ClassMapper
*/
$container->extend('authorizer', function ($authorizer, $c) {
/*
* Check if all $user is a member of $organisation.
*
* @param int $user_id the id of the requesting user (normally currentUser->id).
* @param int $organisation_id the id of the target organisation.
* @return bool true if $user is a member of $organisation.
*/
$authorizer->addCallback('is_organisation_member', function ($user_id, $organisation_id) {
return Capsule::table('organisation_members')
->where('user_id', $user_id)
->where('organisation_id', $organisation_id)
->count() > 0;
});
/*
* Check if all $user is an administrator of $organisation.
*
* @param int $user_id the id of the requesting user (normally currentUser->id).
* @param int $organisation_id the id of the target organisation.
* @return bool true if $user is an administrator of $organisation.
*/
$authorizer->addCallback('is_organisation_admin', function ($user_id, $organisation_id) {
return Capsule::table('organisation_members')
->where('user_id', $user_id)
->where('organisation_id', $organisation_id)
->where('flag_admin', true)
->count() > 0;
});
return $authorizer;
});
/*
* Returns a callback that handles merging any organisation objects.
@@ -79,6 +119,5 @@ class ServicesProvider
};
};
}
}

View File

@@ -0,0 +1,85 @@
<?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\Sprunje;
use Illuminate\Database\Schema\Builder;
use UserFrosting\Sprinkle\Core\Facades\Translator;
use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
use UserFrosting\Sprinkle\Admin\Sprunje\UserSprunje as UFUserSprunje;
/**
* UserSprunje.
*
* Extends Sprunje for the users API.
*
* @author Craig Williams (https://avsdev.uk)
*/
class UserSprunje extends UFUserSprunje
{
protected $filterable = [
'name',
'organisations',
'last_activity',
'status',
];
protected $sortable = [
'name',
'organisations',
'last_activity',
'status',
];
/**
* {@inheritdoc}
*/
protected function baseQuery()
{
$query = parent::baseQuery();
// Join user's organisations
return $query->joinOrganisations()->with('organisations');
}
/**
* Sort based on organisations names.
*
* @param Builder $query
* @param mixed $value
*
* @return self
*/
protected function sortOrganisations($query, $direction)
{
$query->orderBy('organisations.name', $direction);
return $this;
}
/**
* Filter LIKE the last activity description.
*
* @param Builder $query
* @param mixed $value
*
* @return self
*/
protected function filterOrganisations($query, $value)
{
// Split value on separator for OR queries
$values = explode($this->orSeparator, $value);
$query->where(function ($query) use ($values) {
foreach ($values as $value) {
$query->orLike('organisations.name', $value);
}
});
return $this;
}
}