Skip to content

Commit

Permalink
Identify user's role from hierarchy instead of just assuming it's fir…
Browse files Browse the repository at this point in the history
…st one from the list.
  • Loading branch information
Vlad Ghita committed Mar 17, 2022
1 parent 81bc8e5 commit 3921134
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 17 deletions.
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 3921134

Please sign in to comment.