Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions api/v1/invitations/InvitationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public function getGroupRoutes(): void

Route::post('add/{type}', $this->add(...))
->name('invitation.add');

Route::put('{invitationId}/populate', $this->populate(...))
->name('invitation.populate')
->whereNumber('invitationId');
Expand Down Expand Up @@ -272,9 +272,9 @@ public function add(Request $illuminateRequest): JsonResponse
'inviteeEmail.prohibited' => __('invitation.api.error.initialization.noUserIdAndEmailTogether'),
'userId.prohibited' => __('invitation.api.error.initialization.noUserIdAndEmailTogether')
];

$validator = ValidatorFactory::make(
$payload,
$payload,
$rules,
$messages
);
Expand Down Expand Up @@ -345,11 +345,13 @@ public function getMany(Request $illuminateRequest): JsonResponse
->when($context, fn($query) => $query->byContextId($context->getId()))
->stillActive();

$itemsMax = $query->clone()->count();

// Delegate to the specific handler for additional logic
$specificData = $this->selectedHandler->getMany($illuminateRequest, $query);

return response()->json([
'itemsMax' => $query->count(),
'itemsMax' => $itemsMax,
'items' => $specificData,
], Response::HTTP_OK);
}
Expand Down
4 changes: 3 additions & 1 deletion classes/security/authorization/UserRolesRequiredPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ public function effect(): int

$userGroups = UserGroup::withUserIds([$user->getId()])
->withContextIds($context ? [$context->getId(), Application::SITE_CONTEXT_ID] : [Application::SITE_CONTEXT_ID])
->whereHas('userUserGroups', function ($query) use ($user) {
$query->withUserId($user->getId())->withActive();
})
->get()
->all();

$roleIds = array_map(fn ($userGroup) => $userGroup->roleId, $userGroups);
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES, $roleIds);
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_USER_GROUP, $userGroups);
Expand Down
33 changes: 16 additions & 17 deletions classes/user/maps/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ protected function mapByProperties(array $props, User $user, array $auxiliaryDat
case 'canLoginAs':
$output[$prop] = $this->getPropertyCanLoginAs($user);
break;

case 'canMergeUsers':
$output[$prop] = $this->getPropertyCanMergeUsers($user);
break;
Expand Down Expand Up @@ -175,22 +174,22 @@ protected function mapByProperties(array $props, User $user, array $auxiliaryDat

$output[$prop] = [];
foreach ($userGroups as $userGroup) {
$output[$prop][] = [
'id' => (int) $userGroup->id,
'name' => $userGroup->getLocalizedData('name'),
'abbrev' => $userGroup->getLocalizedData('abbrev'),
'roleId' => (int) $userGroup->roleId,
'showTitle' => (bool) $userGroup->showTitle,
'permitSelfRegistration' => (bool) $userGroup->permitSelfRegistration,
'permitMetadataEdit' => (bool) $userGroup->permitMetadataEdit,
'recommendOnly' => (bool) $userGroup->recommendOnly,
'dateStart' => UserUserGroup::withUserId($user->getId())
->withUserGroupIds([$userGroup->id])
->pluck('date_start')->first(),
'dateEnd' => UserUserGroup::withUserId($user->getId())
->withUserGroupIds([$userGroup->id])
->pluck('date_end')->first(),
];
$userUserGroup = UserUserGroup::withUserId($user->getId())
->withUserGroupIds([$userGroup->id])->get()->toArray();
foreach ($userUserGroup as $userUserGroupItem) {
$output[$prop][] = [
'id' => (int) $userGroup->id,
'name' => $userGroup->getLocalizedData('name'),
'abbrev' => $userGroup->getLocalizedData('abbrev'),
'roleId' => (int) $userGroup->roleId,
'showTitle' => (bool) $userGroup->showTitle,
'permitSelfRegistration' => (bool) $userGroup->permitSelfRegistration,
'permitMetadataEdit' => (bool) $userGroup->permitMetadataEdit,
'recommendOnly' => (bool) $userGroup->recommendOnly,
'dateStart' => $userUserGroupItem['dateStart'],
'dateEnd' => $userUserGroupItem['dateEnd'],
];
}
}
}
break;
Expand Down
31 changes: 7 additions & 24 deletions controllers/grid/settings/user/UserGridHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,6 @@ public function initialize($request, $args = null)
// Basic grid configuration.
$this->setTitle('grid.user.currentUsers');

// Grid actions.
$router = $request->getRouter();

$this->addAction(
new LinkAction(
'addUser',
new AjaxModal(
$router->url($request, null, null, 'addUser', null, null),
__('grid.user.add'),
null,
true
),
__('grid.user.add'),
'add_user'
)
);

//
// Grid columns.
//
Expand Down Expand Up @@ -171,7 +154,7 @@ public function getTemplateVarsFromRow($row): array
->withActive();
})
->get();

$roles = $userGroups->map(fn (UserGroup $userGroup) => $userGroup->getLocalizedData('name'))->join(__('common.commaListSeparator'));
return ['label' => $roles];
}
Expand Down Expand Up @@ -550,18 +533,18 @@ public function removeUser($args, $request)
if (!$request->checkCSRF()) {
return new JSONMessage(false);
}

$context = $request->getContext();
$user = $request->getUser();

// Identify the user Id.
$userId = $request->getUserVar('rowId');

if ($userId !== null && Validation::getAdministrationLevel($userId, $user->getId(), $context->getId()) === Validation::ADMINISTRATION_PROHIBITED) {
// We don't have administrative rights over this user.
return new JSONMessage(false, __('grid.user.cannotAdminister'));
}

// Check if this user has any active user group assignments for this context.
$activeUserGroupCount = UserGroup::query()
->withContextIds($context->getId())
Expand All @@ -570,7 +553,7 @@ public function removeUser($args, $request)
->withActive();
})
->count();

if (!$activeUserGroupCount) {
return new JSONMessage(false, __('grid.user.userNoRoles'));
} else {
Expand All @@ -582,7 +565,7 @@ public function removeUser($args, $request)
$query->withContextIds($context->getId());
})
->update(['date_end' => now()]);

return \PKP\db\DAO::getDataChangedEvent($userId);
}
}
Expand Down
18 changes: 0 additions & 18 deletions controllers/grid/users/author/AuthorGridRow.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,6 @@ public function initialize($request, $template = null)
'delete'
)
);

$author = Repo::author()->get((int) $rowId, $this->getPublication()->getId());

if ($author && !Repo::user()->getByEmail($author->getEmail(), true)) {
$this->addAction(
new LinkAction(
'addUser',
new AjaxModal(
$router->url($request, null, null, 'addUser', null, $actionArgs),
__('grid.user.add'),
null,
true
),
__('grid.user.add'),
'add_user'
)
);
}
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion locale/en/user.po
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ msgid "orcid.field.unverified.shouldRequest"
msgstr "This ORCID has not been verified. Please remove this unverified ORCID and request verification from the user/author directly."

msgid "user.removeRole.message"
msgstr "Are you sure want remove this role permanently?"
msgstr "Are you sure you want to permanently remove this role? This action will revoke the user's access to all information and permissions associated with this role."

msgid "user.futureRole.notification.message"
msgstr "Your role is scheduled to begin on {$roleStartDate}"
Expand All @@ -874,3 +874,6 @@ msgstr "Enable {$fullName}"

msgid "user.bioStatement"
msgstr "Bio Statement"

msgid "user.removeRole.roleRemainMessage"
msgstr "You cannot remove the role. At least one role must be assigned to the user."
64 changes: 48 additions & 16 deletions pages/invitation/InvitationHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@
namespace PKP\pages\invitation;

use APP\core\Application;
use APP\core\PageRouter;
use APP\core\Request;
use APP\facades\Repo;
use APP\handler\Handler;
use APP\template\TemplateManager;
use PKP\context\Context;
use PKP\core\PKPApplication;
use PKP\core\PKPRequest;
use PKP\facades\Locale;
use PKP\i18n\LocaleMetadata;
use PKP\invitation\core\enums\InvitationAction;
use PKP\invitation\core\Invitation;
use PKP\invitation\stepTypes\SendInvitationStep;
use PKP\user\User;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\authorization\PolicySet;
use PKP\security\authorization\RoleBasedHandlerOperationPolicy;
use PKP\security\Role;
use PKP\userGroup\relationships\UserUserGroup;

class InvitationHandler extends Handler
Expand All @@ -38,6 +41,34 @@ class InvitationHandler extends Handler
public const REPLY_OP_ACCEPT = 'accept';
public const REPLY_OP_DECLINE = 'decline';

/**
* @see PKPHandler::authorize()
*
* @param PKPRequest $request
* @param array $args
* @param array $roleAssignments
*/
public function authorize($request, &$args, $roleAssignments)
{
/** @var PageRouter */
$router = $request->getRouter();
$op = $router->getRequestedOp($request);
$rolePolicy = new PolicySet(PolicySet::COMBINING_PERMIT_OVERRIDES);
$rolePolicy->addPolicy(
new RoleBasedHandlerOperationPolicy(
$request,
[Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER],
['invite', 'editUser']
)
);
$this->addPolicy($rolePolicy);

if (in_array($op, ['accept', 'decline'])) {
return true;
}
return parent::authorize($request, $args, $roleAssignments);
}

/**
* Accept invitation handler
*/
Expand Down Expand Up @@ -155,8 +186,8 @@ public function invite(array $args, Request $request): void
$invitationModel = $invitation->invitationModel->toArray();

$invitationMode = 'edit';
$payload['email']=$invitationModel['email'];
$invitationData = $this->generateInvitationPayload($invitationModel['userId'],$payload,$request->getContext())['invitationPayload'];
$payload['email'] = $invitationModel['email'];
$invitationData = $this->generateInvitationPayload($invitationModel['userId'], $payload, $request->getContext());
$user = $invitationData['user'];
$invitationPayload = $invitationData['invitationPayload'];
}
Expand Down Expand Up @@ -206,7 +237,8 @@ public function invite(array $args, Request $request): void
'pageTitleDescription' => $invitation ?
__(
'invitation.wizard.viewPageTitleDescription',
['name' => $invitationPayload['givenName'][Locale::getLocale()]]
['name' => $invitationPayload['givenName'][Locale::getLocale()] ?
$invitationPayload['givenName'][Locale::getLocale()] : $invitationPayload['inviteeEmail']]
)
: __('invitation.wizard.pageTitleDescription'),
]);
Expand All @@ -228,9 +260,9 @@ public function invite(array $args, Request $request): void
public function editUser($args, $request): void
{
$invitation = null;
if(!empty($args)) {
if (!empty($args)) {
$invitationMode = 'editUser';
$invitationData = $this->generateInvitationPayload($args[0],[],$request->getContext());
$invitationData = $this->generateInvitationPayload($args[0], [], $request->getContext());
$user = $invitationData['user'];
$invitationPayload = $invitationData['invitationPayload'];
$templateMgr = TemplateManager::getManager($request);
Expand All @@ -257,7 +289,7 @@ public function editUser($args, $request): void
];
$steps = new SendInvitationStep();
$templateMgr->setState([
'steps' => $steps->getSteps($invitation, $context,$user),
'steps' => $steps->getSteps($invitation, $context, $user),
'emailTemplatesApiUrl' => $request
->getDispatcher()
->url(
Expand Down Expand Up @@ -295,7 +327,7 @@ public function editUser($args, $request): void
* @param Context $context
* @param int $id
*/
private function getUserUserGroups(int $id , Context $context): array
private function getUserUserGroups(int $id, Context $context): array
{
$userGroups = [];
$userUserGroups = UserUserGroup::query()
Expand Down Expand Up @@ -325,11 +357,11 @@ private function getUserUserGroups(int $id , Context $context): array
private function generateInvitationPayload($userId, array $payload, Context $context): array
{
$user = null;
if($userId){
$user = Repo::user()->get($userId,true);
if ($userId) {
$user = Repo::user()->get($userId, true);
}

$invitationPayload =[];
$invitationPayload = [];
$invitationPayload['userId'] = $user ? $user->getId() : $userId;
$invitationPayload['inviteeEmail'] = $user ? $user->getEmail() : $payload['email'];
$invitationPayload['orcid'] = $user ? $user->getData('orcid') : $payload['orcid'];
Expand All @@ -341,12 +373,12 @@ private function generateInvitationPayload($userId, array $payload, Context $con
$invitationPayload['phone'] = $user?->getPhone();
$invitationPayload['mailingAddress'] = $user?->getMailingAddress();
$invitationPayload['signature'] = $user?->getSignature(null);
$invitationPayload['locales'] = $user? $this->getWorkingLanguages($context,$user->getLocales()) : null;
$invitationPayload['locales'] = $user ? $this->getWorkingLanguages($context, $user->getLocales()) : null;
$invitationPayload['reviewInterests'] = $user?->getInterestString();
$invitationPayload['homePageUrl'] = $user?->getUrl();
$invitationPayload['disabled'] = $user?->getData('disabled');
$invitationPayload['userGroupsToAdd'] = !$payload['userGroupsToAdd'] ? [] : $payload['userGroupsToAdd'];
$invitationPayload['currentUserGroups'] = !$userId ? [] : $this->getUserUserGroups($userId,$context);
$invitationPayload['currentUserGroups'] = !$userId ? [] : $this->getUserUserGroups($userId, $context);
$invitationPayload['userGroupsToRemove'] = [];
$invitationPayload['emailComposer'] = [
'emailBody' => '',
Expand All @@ -364,7 +396,7 @@ private function generateInvitationPayload($userId, array $payload, Context $con
* @param $userLocales
* @return string
*/
private function getWorkingLanguages(Context $context,$userLocales): string
private function getWorkingLanguages(Context $context, $userLocales): string
{
$locales = $context->getSupportedLocaleNames();
return join(__('common.commaListSeparator'), array_map(fn($key) => $locales[$key], $userLocales));
Expand Down