diff --git a/env.template b/env.template index eacf687..05538b6 100644 --- a/env.template +++ b/env.template @@ -36,13 +36,15 @@ export COMANAGE_API_SSH_KEY_AUTHENTICATOR_ID=123 ### COmanage COU IDs export COU_ID_FACILITY_OPERATORS=100 -export COU_ID_PROJECT_LEADS=101 -export COU_ID_PROJECTS=102 -export COU_ID_ACTIVE_USERS=103 -export COU_ID_APPROVAL_COMMITTEE=104 -export COU_ID_JUPYTERHUB=105 -export COU_ID_PORTAL_ADMINS=106 +export COU_ID_FACILITY_VIEWERS=101 +export COU_ID_PROJECT_LEADS=102 +export COU_ID_PROJECTS=103 +export COU_ID_ACTIVE_USERS=104 +export COU_ID_APPROVAL_COMMITTEE=105 +export COU_ID_JUPYTERHUB=106 +export COU_ID_PORTAL_ADMINS=107 export COU_NAME_FACILITY_OPERATORS=facility-operators +export COU_NAME_FACILITY_VIEWERS=facility-viewers export COU_NAME_PROJECT_LEADS=project-leads export COU_NAME_PROJECTS=projects export COU_NAME_ACTIVE_USERS=fabric-active-users @@ -74,7 +76,8 @@ export SSH_KEY_SECRET="xxxx-xxxx-xxxx-xxxx" export SSH_KEY_QTY_LIMIT=5 ### Python Path -export PYTHONPATH=$(pwd)/server:${PYTHONPATH} +export PYTHONPATH=./server:./venv/bin/python3:${PYTHONPATH} # local development +#export PYTHONPATH=/code/server:/code/.venv/bin/python3:${PYTHONPATH} # docker deployment ### Flask export FLASK_APP=swagger_server.__main__:app diff --git a/server/swagger_server/backup/utils/db_restore.py b/server/swagger_server/backup/utils/db_restore.py index e2239ae..9059baf 100644 --- a/server/swagger_server/backup/utils/db_restore.py +++ b/server/swagger_server/backup/utils/db_restore.py @@ -1,5 +1,5 @@ """ -v1.6.2 --> v1.7.0 - database tables +v1.7.0 --> v1.8.0 - database tables $ docker exec -u postgres api-database psql -c "\dt;" List of relations @@ -60,7 +60,7 @@ from swagger_server.response_code.core_api_utils import normalize_date_to_utc # API version of data to restore from -api_version = '1.6.1' +api_version = '1.7.0' # relative to the top level of the repository BACKUP_DATA_DIR = os.getcwd() + '/server/swagger_server/backup/data' diff --git a/server/swagger_server/database/models/people.py b/server/swagger_server/database/models/people.py index bc281b3..7e0b515 100644 --- a/server/swagger_server/database/models/people.py +++ b/server/swagger_server/database/models/people.py @@ -124,6 +124,9 @@ def is_portal_admin(self) -> bool: def is_facility_operator(self) -> bool: return os.getenv('COU_NAME_FACILITY_OPERATORS').casefold() in [r.name.casefold() for r in self.roles] + def is_facility_viewer(self) -> bool: + return os.getenv('COU_NAME_FACILITY_VIEWERS').casefold() in [r.name.casefold() for r in self.roles] + def is_project_creator(self, project_uuid: str = None) -> bool: return project_uuid + '-pc' in [r.name.casefold() for r in self.roles] diff --git a/server/swagger_server/response_code/people_controller.py b/server/swagger_server/response_code/people_controller.py index 40cbd59..8a6bada 100644 --- a/server/swagger_server/response_code/people_controller.py +++ b/server/swagger_server/response_code/people_controller.py @@ -95,7 +95,10 @@ def people_get(search: str = None, exact_match: bool = False, offset: int = None prefs = get_people_preferences(fab_person=FabricPeople.query.filter_by(uuid=item.uuid).one_or_none()) # set person attributes person = Person() - person.email = item.preferred_email if prefs.__getattribute__('show_email') else None + if api_user.is_facility_operator() or api_user.is_facility_viewer(): + person.email = item.preferred_email + else: + person.email = item.preferred_email if prefs.__getattribute__('show_email') else None person.name = item.display_name person.uuid = str(item.uuid) # add person to people results @@ -325,7 +328,7 @@ def people_uuid_get(uuid, as_self=None) -> PeopleDetails: # noqa: E501 people_one.user_org_affiliations = [a.affiliation for a in fab_person.user_org_affiliations] people_one.uuid = fab_person.uuid # set remaining attributes for uuid == self - if as_self and api_user.uuid == uuid: + if as_self and api_user.uuid == uuid or api_user.is_facility_operator() or api_user.is_facility_viewer(): people_one.bastion_login = fab_person.bastion_login people_one.cilogon_email = fab_person.oidc_claim_email people_one.cilogon_family_name = fab_person.oidc_claim_family_name diff --git a/server/swagger_server/response_code/projects_controller.py b/server/swagger_server/response_code/projects_controller.py index 28668b4..262bcfc 100644 --- a/server/swagger_server/response_code/projects_controller.py +++ b/server/swagger_server/response_code/projects_controller.py @@ -243,7 +243,8 @@ def projects_get(search=None, search_set=None, exact_match=None, offset=None, li FabricProjects.project_creators.any(FabricPeople.id == api_user.id) | FabricProjects.project_owners.any(FabricPeople.id == api_user.id) | FabricProjects.project_members.any(FabricPeople.id == api_user.id) | - api_user.is_facility_operator() + api_user.is_facility_operator() | + api_user.is_facility_viewer() ) else: is_public_check = ( @@ -374,7 +375,7 @@ def projects_get(search=None, search_set=None, exact_match=None, offset=None, li project.memberships = get_project_membership(fab_project=item, fab_person=fab_person) project.name = item.name project.project_type = item.project_type.name - if api_user.is_facility_operator(): + if api_user.is_facility_operator() or api_user.is_facility_viewer(): project.tags = get_project_tags(fab_project=item, fab_person=api_user) elif as_self and ( project.memberships.is_creator or project.memberships.is_member or project.memberships.is_owner): @@ -594,6 +595,7 @@ def projects_uuid_communities_patch(uuid: str, str(fab_project.expires_on))) # verify active project_creator, project_owner or facility-operator if not api_user.active or not api_user.is_facility_operator() and \ + not api_user.is_facility_viewer() and \ not api_user.is_project_creator(str(fab_project.uuid)) and \ not api_user.is_project_owner(str(fab_project.uuid)): return cors_403( @@ -916,7 +918,7 @@ def projects_uuid_get(uuid: str) -> ProjectsDetails: # noqa: E501 project_one.uuid = fab_project.uuid # set remaining attributes for project_creators, project_owners and project_members if project_one.memberships.is_creator or project_one.memberships.is_owner or project_one.memberships.is_member \ - or api_user.is_facility_operator(): + or api_user.is_facility_operator() or api_user.is_facility_viewer(): project_one.active = fab_project.active project_one.modified = str(fab_project.modified) project_one.preferences = {p.key: p.value for p in fab_project.preferences}