blob: aaa6d9e9eb681f7f8e9f84d3d06c9dcab7430c6b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.causeway.extensions.secman.applib.role.seed;
import javax.inject.Inject;
import org.apache.causeway.applib.CausewayModuleApplib;
import org.apache.causeway.applib.services.appfeat.ApplicationFeatureId;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.core.config.CausewayConfiguration.Extensions.Secman;
import org.apache.causeway.core.config.environment.CausewaySystemEnvironment;
import org.apache.causeway.core.security.CausewayModuleCoreSecurity;
import org.apache.causeway.core.security.authentication.logout.LogoutMenu;
import org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionMode;
import org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionRule;
import org.apache.causeway.extensions.secman.applib.role.dom.ApplicationRole;
import org.apache.causeway.extensions.secman.applib.role.fixtures.AbstractRoleAndPermissionsFixtureScript;
import org.apache.causeway.extensions.secman.applib.user.dom.ApplicationUser;
import org.apache.causeway.extensions.secman.applib.user.menu.MeService;
import org.apache.causeway.testing.fixtures.applib.CausewayModuleTestingFixturesApplib;
import lombok.val;
/**
* Sets up a role for regular users of the security module.
*
* <p>
* These permissions are intended to be sufficient for most regular users
* to have access to the 'safe' features provided by the core framework
* (in particular, everything under the {@link CausewayModuleApplib#NAMESPACE causeway.applib}
* namespace.
* </p>
*
* <p>
* That said, it does <i>not</i> include the ability to impersonate other users
* (for this, grant the
* {@link CausewaySudoImpersonateRoleAndPermissions}
* role), and also does <i>not</i> include the ability to access the
* configuration properties (for this, grant the
* {@link CausewaySudoImpersonateRoleAndPermissions}
* role).
* </p>
*
* <p>
* The permissions also provide the ability to lookup their user account using
* the {@link MeService}, and for viewing and maintaining their user details.
* </p>
*
* @see CausewaySudoImpersonateRoleAndPermissions
* @see CausewayConfigurationRoleAndPermissions
*
* @since 2.0 {@index}
*/
public class CausewayExtSecmanRegularUserRoleAndPermissions extends AbstractRoleAndPermissionsFixtureScript {
@Inject private CausewaySystemEnvironment env;
/**
* Prevent a regular user from viewing any of these actions.
*
* <p>
* This is a constant because {@link CausewayExtSecmanAdminRoleAndPermissions} can explicitly revert the change and make the
* access visible (in case a user has both admin and regular user roles).
* </p>
*/
static final Can<ApplicationFeatureId> NOT_VISIBLE_ACTIONS = Can.of(
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "effectiveMemberPermissions"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "filterEffectiveMemberPermissions"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "resetPassword"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "lock"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "unlock"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "addRole"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "removeRoles"),
ApplicationFeatureId.newMember(ApplicationRole.LOGICAL_TYPE_NAME, "addUser"),
ApplicationFeatureId.newMember(ApplicationRole.LOGICAL_TYPE_NAME, "removeUsers"),
ApplicationFeatureId.newMember(ApplicationRole.LOGICAL_TYPE_NAME, "addPermission"),
ApplicationFeatureId.newMember(ApplicationRole.LOGICAL_TYPE_NAME, "removePermissions"),
ApplicationFeatureId.newMember(ApplicationRole.LOGICAL_TYPE_NAME, "delete")
);
/**
* Prevent a regular user from changing any of types
*
* <p>
* This is a constant so that {@link CausewayExtSecmanAdminRoleAndPermissions} can explicit allows changes to this type
* (in case a user has both admin and regular user roles).
* </p>
*/
static final Can<ApplicationFeatureId> NOT_ENABLED_TYPES = Can.of(
ApplicationFeatureId.newType(ApplicationRole.LOGICAL_TYPE_NAME)
);
public CausewayExtSecmanRegularUserRoleAndPermissions(final Secman config) {
super(config.getSeed().getRegularUser().getRoleName(), "Regular user of the security module");
}
@Override
protected void execute(final ExecutionContext executionContext) {
val allowChanging = Can.of(
// everything under "causeway.applib" is granted.
// this includes prototype actions for metamodel and translations
ApplicationFeatureId.newNamespace(CausewayModuleApplib.NAMESPACE),
// we also provide default access to run fixtures (prototype action only)
ApplicationFeatureId.newNamespace(CausewayModuleTestingFixturesApplib.NAMESPACE),
// we also provide default access to logout action (!)
ApplicationFeatureId.newNamespace(CausewayModuleCoreSecurity.NAMESPACE),
// also the ability to logout (!)
ApplicationFeatureId.newType(LogoutMenu.LOGICAL_TYPE_NAME),
// remaining permissions give access to the user to maintain their details
ApplicationFeatureId.newType(MeService.LOGICAL_TYPE_NAME),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "updateName"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "updatePassword"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "updateEmailAddress"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "updatePhoneNumber"),
ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "updateFaxNumber"),
// optionally allow access to documentation menu and pages, based on module presence
env.getIocContainer().containsBean("org.apache.causeway.extensions.docgen.help.CausewayModuleExtDocgenHelp")
? ApplicationFeatureId.newNamespace(CausewayExtDocgenRoleAndPermissions.NAMESPACE)
: null,
// optionally allow access to layout menu and pages, based on module presence
env.getIocContainer().containsBean("org.apache.causeway.extensions.layoutloaders.github.CausewayModuleExtLayoutLoadersGithub")
? ApplicationFeatureId.newNamespace(CausewayExtLayoutLoadersRoleAndPermissions.NAMESPACE)
: null
);
val allowViewing = Can.of(
// we also allow the user to see the roles they are in
// (but nothing more than that)
ApplicationFeatureId.newType(ApplicationUser.LOGICAL_TYPE_NAME),
ApplicationFeatureId.newMember(ApplicationRole.LOGICAL_TYPE_NAME, "name"),
ApplicationFeatureId.newMember(ApplicationRole.LOGICAL_TYPE_NAME, "description")
);
newPermissions(
ApplicationPermissionRule.ALLOW,
ApplicationPermissionMode.VIEWING,
allowViewing);
newPermissions(
ApplicationPermissionRule.ALLOW,
ApplicationPermissionMode.CHANGING,
allowChanging);
newPermissions(
ApplicationPermissionRule.VETO,
ApplicationPermissionMode.VIEWING,
NOT_VISIBLE_ACTIONS);
newPermissions(
ApplicationPermissionRule.VETO,
ApplicationPermissionMode.CHANGING,
NOT_ENABLED_TYPES);
}
}