Skip to content

Commit

Permalink
Merge pull request #24 from vlad-ghita/pull-2
Browse files Browse the repository at this point in the history
Improve active role identification
  • Loading branch information
bobdenotter authored Mar 18, 2022
2 parents f202489 + 3921134 commit 7ceed7a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ composer require bolt/users

## Basic usage

To limit a a ContentType to a specific group of users, say `ROLE_MEMBER`, do the following:
To limit a ContentType to a specific group of users, say `ROLE_MEMBER`, do the following:

1. Define your user group in `config/extensions/bolt-usersextension.yaml`:

Expand Down
22 changes: 21 additions & 1 deletion src/Controller/AccessAwareController.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,28 @@ public function applyIsAuthenticatedGuard(): void

public function applyEditProfileGuard(): void
{
if (! $this->getExtension()->getExtConfig('allow_profile_edit', $this->getUser()->getRoles()[0], false)) {
if (! $this->getExtension()->getExtConfig('allow_profile_edit', $this->findGrantedUserRole(), false)) {
throw new AccessDeniedHttpException();
}
}

/**
* Walks through defined groups and returns first one matching users' roles.
* Supports role hierarchies.
*
* Eg: if ROLE_ADMIN inherits from ROLE_MEMBER, groups contains ROLE_MEMBER and user's role is ROLE_ADMIN, then ROLE_MEMBER is returned.
*/
public function findGrantedUserRole(): string
{
$groups = $this->getExtension()->getConfig()->get('groups', []);

foreach ($groups as $role => $roleConfig)
if ($this->isGranted(new Expression(sprintf("'%s' in role_names", $role)))) {
return $role;
}

// no user role was found in groups
throw new AccessDeniedHttpException();
}

}
45 changes: 29 additions & 16 deletions src/Controller/FrontendUsersProfileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Bolt\UsersExtension\ExtensionConfigTrait;
use Bolt\UsersExtension\Utils\ExtensionTemplateChooser;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
Expand Down Expand Up @@ -69,10 +70,10 @@ public function view(): Response
if ($user instanceof User && $this->isGranted('ROLE_ADMIN')) {
return $this->redirectToRoute('bolt_user_edit', ['id' => $user->getId()]);
}

if ($user !== null /* Ensure there is an active user logged on*/ ) {
$contentTypeSlug = $this->getExtension()->getExtConfig('contenttype', $user->getRoles()[0]);
$contentTypeSlug = $this->findContentTypeSlug();

/** @var ContentType $contentType */
$contentType = $this->getBoltConfig()->getContentType($contentTypeSlug);
$this->applyAllowForGroupsGuard($contentType);
Expand All @@ -93,12 +94,12 @@ public function view(): Response
public function edit(ContentType $contentType, Request $request): Response
{
$user = $this->getUser();

if ($user !== null /* Ensure there is an active user logged on*/ ) {

$this->applyIsAuthenticatedGuard();

$contentTypeSlug = $this->getExtension()->getExtConfig('contenttype', $this->getUser()->getRoles()[0]);
$contentTypeSlug = $this->findContentTypeSlug();

/** @var ContentType $contentType */
$contentType = $this->getBoltConfig()->getContentType($contentTypeSlug);
Expand All @@ -112,7 +113,7 @@ public function edit(ContentType $contentType, Request $request): Response
return $this->redirectToRoute('extension_frontend_user_profile');
}

$templates = $this->templateChooser->forProfileEdit($this->getUser()->getRoles()[0]);
$templates = $this->templateChooser->forProfileEdit($this->findGrantedUserRole());

$parameters = [
'record' => $content,
Expand All @@ -133,24 +134,24 @@ private function getUserRecord(ContentType $contentType): Content
{
/** @var User $user */
$user = $this->getUser();

// Access user record, if available
$contentTypeSlug = $this->getExtension()->getExtConfig('contenttype', $user->getRoles()[0]);
$contentTypeSlug = $this->findContentTypeSlug();
$contentType = $this->getBoltConfig()->getContentType($contentTypeSlug);

$content = $this->contentRepository->findBy([
'author' => $user,
'contentType' => $contentType->getSlug(),
]);

// If user record unavailable, create it
if (empty($content)) {
return $this->new($contentType);
}
}
elseif (is_iterable($content)) {
$content = end($content);
}

return $content;
}

Expand All @@ -159,9 +160,9 @@ private function new(ContentType $contentType): Content
{
/** @var User $user */
$user = $this->getUser();
$contentTypeSlug = $this->getExtension()->getExtConfig('contenttype', $user->getRoles()[0]);
$contentTypeSlug = $this->findContentTypeSlug();
$contentType = $this->getBoltConfig()->getContentType($contentTypeSlug);

$content = new Content($contentType);
$content->setAuthor($user);
$content->setCreatedAt(new \DateTime());
Expand All @@ -172,7 +173,7 @@ private function new(ContentType $contentType): Content
$content->setFieldValue('displayName', $user->getDisplayName()); // Hidden field for record title
$content->setFieldValue('username', $user->getUsername()); // Hidden field with copy of username
$content->setFieldValue('slug', $user->getUsername()); // Make slugs unique to users

// Initialise ALL extra fields as defined in the contenttype with empty strings.
// This ensures they are displayed on the /profile/edit route without backend intervention
foreach($contentType->get('fields') as $name => $field){
Expand All @@ -181,7 +182,7 @@ private function new(ContentType $contentType): Content
$content->setFieldValue($name, '');
}
}

$this->contentFillListener->fillContent($content);

// Persist in DB
Expand All @@ -196,4 +197,16 @@ private function saveContent(Content $content): void
$this->em->flush();
}

private function findContentTypeSlug(): ?string
{
$role = $this->findGrantedUserRole();

$contentTypeSlug = $this->getExtension()->getExtConfig('contenttype', $role);

if ($contentTypeSlug === null)
throw new \Exception("Must define a contenttype.");

return $contentTypeSlug;
}

}

0 comments on commit 7ceed7a

Please sign in to comment.