Skip to content

Commit

Permalink
feat(core): filter getMembersPage
Browse files Browse the repository at this point in the history
* getMembersPage now adhere to policy
* added filter `filter-getMembersPage_policy` policy
* added getPolicyByName to AuthzResolver
* added tests to accompany this change
* added support for VOADMIN and VOOBSERVER
  • Loading branch information
mattjoke committed Aug 9, 2023
1 parent ad72c8e commit 9d52d58
Show file tree
Hide file tree
Showing 13 changed files with 638 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,20 @@ public enum MembersOrderColumn {
NAME(
", users.first_name, users.last_name ",
"",
", users.last_name, users.first_name",
query -> "users.last_name " + getLangSql(query) + query.getOrder().getSqlValue() + ", " +
"users.first_name " + getLangSql(query) + query.getOrder().getSqlValue()
),

ID("", "", query -> "members.id " + query.getOrder().getSqlValue()),
STATUS("","", query -> "members.status " + query.getOrder().getSqlValue()),
GROUP_STATUS("", "", query -> "groups_members.source_group_status " + query.getOrder().getSqlValue()),
STATUS("",
"",
"",
query -> "members.status " + query.getOrder().getSqlValue()),
GROUP_STATUS("",
"",
", groups_members.group_id, groups_members.source_group_id, groups_members.membership_type, groups_members.source_group_status",
query -> "groups_members.source_group_status " + query.getOrder().getSqlValue()),

// 1. user preferred mail, 2. member mail
EMAIL(
Expand All @@ -33,6 +40,7 @@ public enum MembersOrderColumn {
"(select attr_value, user_id, attr_id from user_attr_values) as usrvals " +
"on members.user_id=usrvals.user_id and usrvals.attr_id=" +
"(select id from attr_names where attr_name='urn:perun:user:attribute-def:def:preferredMail') ",
", usrvals.attr_value, memvals.attr_value ",
query -> "usrvals.attr_value " + query.getOrder().getSqlValue() + ", " +
"memvals.attr_value " + query.getOrder().getSqlValue()
),
Expand All @@ -48,17 +56,27 @@ public enum MembersOrderColumn {
"(select attr_value, user_id, attr_id from user_attr_values) as usrvals " +
"on members.user_id=usrvals.user_id and usrvals.attr_id=" +
"(select id from attr_names where attr_name='urn:perun:user:attribute-def:def:organization') ",
", usrvals.attr_value, memvals.attr_value ",
query -> "memvals.attr_value " + query.getOrder().getSqlValue() + ", " +
"usrvals.attr_value " + query.getOrder().getSqlValue()
);

private final Function<MembersPageQuery, String> orderBySqlFunction;
private final String selectSql;
private final String joinSql;
private final String groupbySql;

MembersOrderColumn(String selectSql, String joinSql, String groupbySql, Function<MembersPageQuery, String> sqlFunction) {
this.selectSql = selectSql;
this.joinSql = joinSql;
this.groupbySql = groupbySql;
this.orderBySqlFunction = sqlFunction;
}

MembersOrderColumn(String selectSql, String joinSql, Function<MembersPageQuery, String> sqlFunction) {
this.selectSql = selectSql;
this.joinSql = joinSql;
this.groupbySql = "";
this.orderBySqlFunction = sqlFunction;
}

Expand All @@ -74,6 +92,10 @@ public String getSqlJoin() {
return this.joinSql;
}

public String getSqlGroupBy() {
return this.groupbySql;
}

private static String getLangSql(MembersPageQuery query) {
return "";
// TODO add support for other languages
Expand Down
11 changes: 11 additions & 0 deletions perun-base/src/main/resources/perun-roles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3630,6 +3630,17 @@ perun_policies:
include_policies:
- default_policy

filter-getMembersPage_policy:
policy_roles:
- GROUPADMIN:
- GROUPOBSERVER:
- GROUPMEMBERSHIPMANAGER:
- PERUNOBSERVER:
- VOADMIN:
- VOOBSERVER:
include_policies:
- default_policy

updateSponsorshipValidity_Member_User_LocalDate:
policy_roles:
- VOADMIN: Vo
Expand Down
33 changes: 33 additions & 0 deletions perun-base/src/test/resources/test-roles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,38 @@ perun_policies:
- PROXY:
include_policies: []

test_filter-getMembersPage_policy:
policy_roles:
- GROUPADMIN: Group
- GROUPOBSERVER: Group
- GROUPMEMBERSHIPMANAGER: Group
- PERUNOBSERVER:
- VOADMIN:
- VOOBSERVER:
include_policies:
- default_policy

test_filter-getMembersPage_policy-vo:
policy_roles:
- GROUPADMIN: Group
- GROUPOBSERVER: Group
- GROUPMEMBERSHIPMANAGER: Group
- PERUNOBSERVER:
- VOADMIN: Vo
- VOOBSERVER:
include_policies:
- default_policy

test_filter-getMembersPage_policy-voobserver:
policy_roles:
- GROUPADMIN: Group
- GROUPOBSERVER: Group
- GROUPMEMBERSHIPMANAGER: Group
- PERUNOBSERVER:
- VOADMIN:
- VOOBSERVER: Vo
include_policies:
- default_policy

perun_roles_management: {}
...
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import cz.metacentrum.perun.core.api.exceptions.PasswordCreationFailedException;
import cz.metacentrum.perun.core.api.exceptions.NotificationMemberMailNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.PasswordStrengthException;
import cz.metacentrum.perun.core.api.exceptions.PolicyNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.PrivilegeException;
import cz.metacentrum.perun.core.api.exceptions.ResourceNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.SponsorshipDoesNotExistException;
Expand Down Expand Up @@ -1521,7 +1522,23 @@ List<Map<String, String>> createSponsoredMembersFromCSV(PerunSession sess, Vo vo
* @throws GroupNotExistsException if there is no such query group
* @throws PrivilegeException insufficient permission
*/
Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames) throws VoNotExistsException, PrivilegeException, GroupNotExistsException;
Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames) throws VoNotExistsException, PrivilegeException, GroupNotExistsException, PolicyNotExistsException;

/**
* Get page of members from the given vo, with the given attributes, based on policy.
*
* @param sess session
* @param vo vo
* @param query query with page information
* @param attrNames attribute names
* @param policy policy to use
* @return page of requested rich members
* @throws VoNotExistsException if there is no such vo
* @throws GroupNotExistsException if there is no such query group
* @throws PrivilegeException insufficient permission
*/
Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames, String policy) throws VoNotExistsException, PrivilegeException, GroupNotExistsException, PolicyNotExistsException;


/**
* Update the sponsorship of given member for given sponsor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import cz.metacentrum.perun.core.api.exceptions.ParentGroupNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.PasswordCreationFailedException;
import cz.metacentrum.perun.core.api.exceptions.PasswordStrengthException;
import cz.metacentrum.perun.core.api.exceptions.PolicyNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.PrivilegeException;
import cz.metacentrum.perun.core.api.exceptions.SponsorshipDoesNotExistException;
import cz.metacentrum.perun.core.api.exceptions.UserExtSourceNotExistsException;
Expand Down Expand Up @@ -1797,7 +1798,19 @@ List<Map<String, String>> createSponsoredMembersFromCSV(PerunSession sess, Vo vo
* @param attrNames attribute names
* @return page of requested rich members
*/
Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames);
Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames) throws PolicyNotExistsException;

/**
* Get page of members from the given vo, with the given attributes, based on policy.
*
* @param sess session
* @param vo vo
* @param query query with page information
* @param attrNames attribute names
* @param policy policy to use
* @return page of requested rich members
*/
Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames, String policy) throws PolicyNotExistsException;

/**
* Update the sponsorship of given member for given sponsor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2288,6 +2288,16 @@ public static boolean isVoObserver(PerunSession sess) {
return sess.getPerunPrincipal().getRoles().hasRole(Role.VOOBSERVER);
}

/**
* Returns true if the perun principal inside the perun session is Perun Observer.
*
* @param sess perun session
* @return true if the perun principal is top group creator.
*/
public static boolean isPerunObserver(PerunSession sess) {
return sess.getPerunPrincipal().getRoles().hasRole(Role.PERUNOBSERVER);
}

/**
* Returns true if the perun principal inside the perun session is top group creator.
*
Expand All @@ -2308,6 +2318,16 @@ public static boolean isPerunAdmin(PerunSession sess) {
return sess.getPerunPrincipal().getRoles().hasRole(Role.PERUNADMIN);
}

/**
* Returns true if perun principal is Vo admin or Vo observer of specific Vo.
* @param sess - perun session
* @param vo -specific vo
* @return bolean
**/
public static boolean isVoAdminOrObserver(PerunSession sess, Vo vo) {
return authzResolverImpl.isVoAdminOrObserver(sess, vo);
}

/**
* Get all principal role names.
*
Expand Down Expand Up @@ -4472,4 +4492,14 @@ private static boolean checkAuthValidityForMFA(PerunSession sess) {
private static boolean sessionHasMfa(PerunSession sess) {
return sess.getPerunPrincipal().getAdditionalInformations().containsKey(ACR_MFA);
}

/**
* Return id of the role by its name.
*
* @param name - name of the role
* @return - id of the role
*/
public static int getRoleIdByName(String name) {
return authzResolverImpl.getRoleIdByName(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import cz.metacentrum.perun.core.api.exceptions.ParentGroupNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.PasswordCreationFailedException;
import cz.metacentrum.perun.core.api.exceptions.PasswordStrengthException;
import cz.metacentrum.perun.core.api.exceptions.PolicyNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.RelationExistsException;
import cz.metacentrum.perun.core.api.exceptions.RoleCannotBeManagedException;
import cz.metacentrum.perun.core.api.exceptions.RoleManagementRulesNotExistsException;
Expand Down Expand Up @@ -2992,8 +2993,8 @@ public List<Member> findMembers(PerunSession sess, Vo vo, String searchString, b
}

@Override
public Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames) {
Paginated<Member> paginatedMembers = membersManagerImpl.getMembersPage(sess, vo, query);
public Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames, String policy) throws PolicyNotExistsException {
Paginated<Member> paginatedMembers = membersManagerImpl.getMembersPage(sess, vo, query, policy);
List<RichMember> richMembers = convertMembersToRichMembers(sess, paginatedMembers.getData());

List<AttributeDefinition> attrDefs = new ArrayList<>();
Expand All @@ -3019,6 +3020,11 @@ public Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPag
paginatedMembers.getTotalCount());
}

@Override
public Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames) throws PolicyNotExistsException {
return getMembersPage(sess, vo, query, attrNames, null);
}

@Override
public void updateSponsorshipValidity(PerunSession sess, Member sponsoredMember, User sponsor,
LocalDate newValidity) throws SponsorshipDoesNotExistException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import cz.metacentrum.perun.core.api.exceptions.PasswordCreationFailedException;
import cz.metacentrum.perun.core.api.exceptions.NotificationMemberMailNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.PasswordStrengthException;
import cz.metacentrum.perun.core.api.exceptions.PolicyNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.PrivilegeException;
import cz.metacentrum.perun.core.api.exceptions.ResourceNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.SponsorshipDoesNotExistException;
Expand Down Expand Up @@ -1630,7 +1631,12 @@ public void removeSponsors(PerunSession sess, Member sponsoredMember, List<User>
}

@Override
public Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames) throws VoNotExistsException, PrivilegeException, GroupNotExistsException {
public Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames) throws VoNotExistsException, PrivilegeException, GroupNotExistsException, PolicyNotExistsException {
return getMembersPage(sess, vo, query, attrNames, null);
}

@Override
public Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPageQuery query, List<String> attrNames, String policy) throws VoNotExistsException, PrivilegeException, GroupNotExistsException, PolicyNotExistsException {
Utils.checkPerunSession(sess);
perunBl.getVosManagerBl().checkVoExists(sess, vo);

Expand All @@ -1649,7 +1655,7 @@ public Paginated<RichMember> getMembersPage(PerunSession sess, Vo vo, MembersPag
throw new IllegalArgumentException("Group status cannot be used to sort VO members.");
}

Paginated<RichMember> result = membersManagerBl.getMembersPage(sess, vo, query, attrNames);
Paginated<RichMember> result = membersManagerBl.getMembersPage(sess, vo, query, attrNames, policy);

if (query.getGroupId() == null) {
result.setData(getPerunBl().getMembersManagerBl().filterOnlyAllowedAttributes(sess, result.getData()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import cz.metacentrum.perun.core.api.Member;
import cz.metacentrum.perun.core.api.MemberGroupStatus;
import cz.metacentrum.perun.core.api.Pair;
import cz.metacentrum.perun.core.api.Perun;
import cz.metacentrum.perun.core.api.PerunPolicy;
import cz.metacentrum.perun.core.api.PerunSession;
import cz.metacentrum.perun.core.api.Resource;
Expand All @@ -27,6 +28,7 @@
import cz.metacentrum.perun.core.api.exceptions.RoleManagementRulesNotExistsException;
import cz.metacentrum.perun.core.api.exceptions.RoleNotSetException;
import cz.metacentrum.perun.core.api.exceptions.UserNotAdminException;
import cz.metacentrum.perun.core.blImpl.AuthzResolverBlImpl;
import cz.metacentrum.perun.core.implApi.AuthzResolverImplApi;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
Expand Down Expand Up @@ -1286,4 +1288,39 @@ private String prepareSelectQueryString(Map<String, Integer> mappingOfValues) {

return StringUtils.join(listOfConditions, " and ");
}

/**
* Returns role id based on its name
*
* @param name - name of the role
* @return role id
*/
@Override
public int getRoleIdByName(String name) {
try {
return jdbc.queryForInt("SELECT id FROM roles WHERE name=?", name.toLowerCase());
} catch (RuntimeException e) {
throw new InternalErrorException(e);
}
}

/**
* Returns true if the user in session is vo admin or vo observer of specific vo
*
* @param sess - session
* @param vo - vo
* @return
*/
@Override
public boolean isVoAdminOrObserver(PerunSession sess, Vo vo) {
try {
var query = jdbc.query("SELECT 1 FROM authz WHERE user_id=? AND vo_id=? AND (role_id=? OR role_id=?)",
(rs, i) -> true,
sess.getPerunPrincipal().getUserId(), vo.getId(), AuthzResolverBlImpl.getRoleIdByName(Role.VOADMIN), AuthzResolverBlImpl.getRoleIdByName(Role.VOOBSERVER));
return !query.isEmpty();
} catch (InternalErrorException e) {
log.error("Error during checking if user is vo admin of vo {}", vo, e);
}
return false;
}
}
Loading

0 comments on commit 9d52d58

Please sign in to comment.