/** * Copyright © ${project.inceptionYear} Instituto Superior Técnico * * This file is part of Fenix IST. * * Fenix IST is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Fenix IST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Fenix IST. If not, see <http://www.gnu.org/licenses/>. */ package pt.ist.fenix.service.services.externalServices; import java.util.List; import org.apache.commons.lang.StringUtils; import org.fenixedu.academic.domain.CompetenceCourse; import org.fenixedu.academic.domain.CurricularCourse; import org.fenixedu.academic.domain.Degree; import org.fenixedu.academic.domain.DegreeCurricularPlan; import org.fenixedu.academic.domain.Department; import org.fenixedu.academic.domain.Enrolment; import org.fenixedu.academic.domain.ExecutionCourse; import org.fenixedu.academic.domain.ExecutionSemester; import org.fenixedu.academic.domain.ExecutionYear; import org.fenixedu.academic.domain.Person; import org.fenixedu.academic.domain.accessControl.StudentGroup; import org.fenixedu.academic.domain.accessControl.TeacherGroup; import org.fenixedu.academic.domain.organizationalStructure.Unit; import org.fenixedu.academic.domain.organizationalStructure.UnitUtils; import org.fenixedu.academic.domain.person.RoleType; import org.fenixedu.academic.domain.student.Registration; import org.fenixedu.academic.service.services.exceptions.FenixServiceException; import org.fenixedu.academic.service.services.exceptions.NonExistingServiceException; import org.fenixedu.bennu.core.groups.Group; import pt.ist.fenixedu.contracts.domain.accessControl.ActiveEmployees; import pt.ist.fenixframework.Atomic; /** * * @author naat * */ public class GroupCheckService { private static final String PAIR_SEPARATOR = ";"; private static final String NAME_VALUE_SEPARATOR = "="; private enum QueryType { DEPARTMENT, DEGREE, CURRICULAR_COURSE, EXECUTION_COURSE, ROLE } private static class GroupCheckQuery { public String username; public String roleType; public QueryType queryType; public String unitFullPath; public String year; public Integer semester; } /** * Checks if the user belongs to the group specified in query * * Generic query format: * user=ISTnnnn;role=ROLE;type=TYPE;unit=IST.<TheUnit>{ * .<SubUnit>}[;year=<TheYear>][;semester=<TheSemester>] * * Available queries: * user=ISTnnnn;role=ROLE;type=DEPARTMENT;unit=IST.<DepartmentAcronym * >[;year=<TheYear>] * user=ISTnnnn;role=ROLE;type=DEGREE;unit=IST.<DegreeAcronym> (Uses the * active degree curricular plans) * user=ISTnnnn;role=ROLE;type=CURRICULAR_COURSE * ;unit=IST.<DegreeAcronym>.<CurricularCourseAcronym * >[;year=<TheYear>;semester=<TheSemester>] * user=ISTnnnn;role=ROLE;type=EXECUTION_COURSE * ;unit=IST.<DegreeAcronym>.<CurricularCourseAcronym * >[;year=<TheYear>;semester=<TheSemester>] * * Queries that will be available in future: * user=ISTnnnn;role=ROLE;type=SCIENTIFIC_AREA * ;unit=IST.<TheUnit>{.<SubUnit>}[;year=<TheYear>][;semester=<TheSemester>] * user * =ISTnnnn;role=ROLE;type=SECTION;unit=IST.<TheUnit>{.<SubUnit>}[;year=< * TheYear>][;semester=<TheSemester>] * */ @Atomic public static Boolean run(String query) throws FenixServiceException { GroupCheckQuery groupCheckQuery = parseQuery(query); Person person = Person.readPersonByUsername(groupCheckQuery.username); if (person == null) { return false; } if (groupCheckQuery.queryType == QueryType.DEPARTMENT) { return checkDepartmentGroup(person, groupCheckQuery); } else if (groupCheckQuery.queryType == QueryType.DEGREE) { return checkDegreeGroup(person, groupCheckQuery); } else if (groupCheckQuery.queryType == QueryType.CURRICULAR_COURSE) { return checkCurricularCourseGroup(person, groupCheckQuery); } else if (groupCheckQuery.queryType == QueryType.EXECUTION_COURSE) { return checkExecutionCourseGroup(person, groupCheckQuery); } else if (groupCheckQuery.queryType == QueryType.ROLE) { return checkRoleGroup(person, groupCheckQuery); } else { throw new NonExistingServiceException(); } } /** * Checks if person has role. * * Accepted roles: TEACHER and EMPLOYEE * * @throws NonExistingServiceException * * */ private static Boolean checkRoleGroup(Person person, GroupCheckQuery groupCheckQuery) throws NonExistingServiceException { switch (groupCheckQuery.roleType) { case "TEACHER": return RoleType.TEACHER.actualGroup().isMember(person.getUser()); case "EMPLOYEE": return new ActiveEmployees().isMember(person.getUser()); default: throw new NonExistingServiceException(); } } /** * Checks if person belongs to curricular course. The unit path format * should be: * IST{.<SubUnitAcronym>}.<DegreeAcronym>.<CurricularCourseAcronym> * * Accepted roles: STUDENT and TEACHER * * * @param person * @param groupCheckQuery * @return * @throws NonExistingServiceException * @throws ExcepcaoPersistencia */ private static Boolean checkExecutionCourseGroup(Person person, GroupCheckQuery groupCheckQuery) throws NonExistingServiceException { String[] unitAcronyms = groupCheckQuery.unitFullPath.split("\\."); if (!groupCheckQuery.roleType.equals("TEACHER") && !groupCheckQuery.roleType.equals("STUDENT")) { throw new NonExistingServiceException(); } Degree degree = getDegree(unitAcronyms); for (DegreeCurricularPlan degreeCurricularPlan : degree.getActiveDegreeCurricularPlans()) { ExecutionSemester executionSemester = getExecutionPeriod(groupCheckQuery.year, groupCheckQuery.semester); CurricularCourse curricularCourse = degreeCurricularPlan.getCurricularCourseByAcronym(unitAcronyms[4]); if (curricularCourse != null) { List<ExecutionCourse> executionCourses = curricularCourse.getExecutionCoursesByExecutionPeriod(executionSemester); for (ExecutionCourse executionCourse : executionCourses) { Group group; if (groupCheckQuery.roleType.equals("TEACHER")) { group = TeacherGroup.get(executionCourse); } else { group = StudentGroup.get(executionCourse); } if (group.isMember(person.getUser())) { return true; } } } } return false; } /** * Checks if person belongs to curricular course. The unit path format * should be: * IST{.<SubUnitAcronym>}.<DegreeAcronym>.<CurricularCourseAcronym> * * Accepted roles: STUDENT * * @param person * @param groupCheckQuery * @return * @throws NonExistingServiceException * @throws ExcepcaoPersistencia */ private static Boolean checkCurricularCourseGroup(Person person, GroupCheckQuery groupCheckQuery) throws NonExistingServiceException { final String[] unitAcronyms = groupCheckQuery.unitFullPath.split("\\."); if (!groupCheckQuery.roleType.equals("STUDENT")) { throw new NonExistingServiceException(); } for (final DegreeCurricularPlan degreeCurricularPlan : getDegree(unitAcronyms).getActiveDegreeCurricularPlans()) { final CurricularCourse curricularCourse = degreeCurricularPlan.getCurricularCourseByAcronym(unitAcronyms[4]); if (curricularCourse != null) { List<Enrolment> enrolments = curricularCourse.getEnrolmentsByExecutionPeriod(getExecutionPeriod(groupCheckQuery.year, groupCheckQuery.semester)); for (Enrolment enrolment : enrolments) { if (enrolment.getStudentCurricularPlan().getRegistration().getPerson().equals(person)) { return true; } } } } return false; } /** * Checks if person belongs to degree. The unit path format should be: * IST.<DegreeAcronym> * * Accepted roles: TEACHER and STUDENT * * @param person * @param groupCheckQuery * @return * @throws ExcepcaoPersistencia * @throws FenixServiceException */ private static Boolean checkDegreeGroup(Person person, GroupCheckQuery groupCheckQuery) throws NonExistingServiceException { String[] unitAcronyms = groupCheckQuery.unitFullPath.split("\\."); if (!groupCheckQuery.roleType.equals("TEACHER") && !groupCheckQuery.roleType.equals("STUDENT")) { throw new NonExistingServiceException(); } Degree degree = getDegree(unitAcronyms); Group group; if (groupCheckQuery.roleType.equals("STUDENT")) { group = StudentGroup.get(degree, null); } else { group = TeacherGroup.get(degree); } return group.isMember(person.getUser()); } private static Degree getDegree(String[] unitAcronyms) throws NonExistingServiceException { Unit unit = getUnit(unitAcronyms, 3); if (!unit.isDegreeUnit()) { throw new NonExistingServiceException(); } Degree degree = unit.getDegree(); return degree; } private static Department getDepartment(String[] unitAcronyms) throws NonExistingServiceException { final Unit unit = getUnit(unitAcronyms, 2); if (!unit.isDepartmentUnit()) { throw new NonExistingServiceException(); } return unit.getDepartment(); } private static Unit getUnit(String[] unitAcronyms, int maxIndex) throws NonExistingServiceException { Unit unit = UnitUtils.readInstitutionUnit(); if (unit == null || StringUtils.isEmpty(unit.getAcronym()) || !unit.getAcronym().equals(unitAcronyms[0])) { throw new NonExistingServiceException(); } for (int i = 1; i <= maxIndex; i++) { unit = unit.getChildUnitByAcronym(unitAcronyms[i]); if (unit == null) { throw new NonExistingServiceException(); } } return unit; } /** * Checks if person belongs to deparment on a specified execution year. The * unit path format should be: IST.<DepartmentAcronym> * * Accepted roles: STUDENT, TEACHER and EMPLOYEE * * @param person * @param groupCheckQuery * @return * @throws ExcepcaoPersistencia * @throws FenixServiceException */ private static Boolean checkDepartmentGroup(Person person, GroupCheckQuery groupCheckQuery) throws NonExistingServiceException { final String[] unitAcronyms = groupCheckQuery.unitFullPath.split("\\."); if (!groupCheckQuery.roleType.equals("TEACHER") && !groupCheckQuery.roleType.equals("STUDENT") && !groupCheckQuery.roleType.equals("EMPLOYEE")) { throw new NonExistingServiceException(); } if (groupCheckQuery.roleType.equals("TEACHER")) { return TeacherGroup.get(getDepartment(unitAcronyms), getExecutionYear(groupCheckQuery.year)).isMember( person.getUser()); } else if (groupCheckQuery.roleType.equals("EMPLOYEE")) { if (person != null && person.getEmployee() != null) { final Department lastDepartmentWorkingPlace = person.getEmployee().getLastDepartmentWorkingPlace( getExecutionYear(groupCheckQuery.year).getBeginDateYearMonthDay(), getExecutionYear(groupCheckQuery.year).getEndDateYearMonthDay()); return (lastDepartmentWorkingPlace != null && lastDepartmentWorkingPlace.equals(getDepartment(unitAcronyms))); } return false; } else { if (person != null && person.getStudent() != null) { for (final Registration registration : person.getStudent().getRegistrationsSet()) { for (final Enrolment enrolment : registration.getLastStudentCurricularPlan().getEnrolmentsByExecutionYear( getExecutionYear(groupCheckQuery.year))) { if (enrolment.getCurricularCourse().getCompetenceCourse() != null) { final CompetenceCourse competenceCourse = enrolment.getCurricularCourse().getCompetenceCourse(); if (competenceCourse.getDepartmentsSet().contains(getDepartment(unitAcronyms))) { return true; } if (competenceCourse.hasDepartmentUnit() && competenceCourse.getDepartmentUnit().getDepartment() == getDepartment(unitAcronyms)) { return true; } } } } } return false; } } private static ExecutionSemester getExecutionPeriod(String year, Integer semester) throws NonExistingServiceException { if (year != null && semester != null) { return ExecutionSemester.readBySemesterAndExecutionYear(semester, year); } else if (year == null && semester == null) { return ExecutionSemester.readActualExecutionSemester(); } else { throw new NonExistingServiceException(); } } private static ExecutionYear getExecutionYear(String year) { if (year != null) { return ExecutionYear.readExecutionYearByName(year); } else { return ExecutionYear.readCurrentExecutionYear(); } } private static GroupCheckQuery parseQuery(String query) { GroupCheckQuery groupCheckQuery = new GroupCheckQuery(); String[] nameValuePairs = query.split(PAIR_SEPARATOR); for (String nameValuePair : nameValuePairs) { String[] nameValueParts = nameValuePair.split(NAME_VALUE_SEPARATOR); String fieldName = nameValueParts[0]; String fieldValue = nameValueParts[1]; if (fieldName.equals("user")) { groupCheckQuery.username = fieldValue; } else if (fieldName.equals("role")) { groupCheckQuery.roleType = fieldValue; } else if (fieldName.equals("type")) { groupCheckQuery.queryType = QueryType.valueOf(fieldValue); } else if (fieldName.equals("unit")) { groupCheckQuery.unitFullPath = fieldValue; } else if (fieldName.equals("year")) { groupCheckQuery.year = fieldValue; } else if (fieldName.equals("semester")) { groupCheckQuery.semester = Integer.valueOf(fieldValue); } } return groupCheckQuery; } }