def test_it_should_be_impossible_to_create_restriction_with_end_time_happening_before_start_time(tables): start_time = datetime.utcnow() + timedelta(hours=5) end_time = datetime.utcnow() + timedelta(minutes=1) restriction = Restriction(name='Test', starts_at=start_time, ends_at=end_time, is_global=False) with pytest.raises(AssertionError): restriction.save()
def _check_restrictions(cls): # If there are already users in the DB, don't bother if User.query.count() > 0: return if Restriction.query.count() == 0: if click.confirm( orange('There are no permissions specified') + ' - that means, that by default ' 'users will not have access to any resources. Would you like to create ' 'a default permission together with a default group now? (All users ' 'would have access to every resource)', default=True): default_group = Group(name='users') default_group._is_default = True default_group.save() default_restriction = Restriction( name='can always use everything', starts_at=datetime.utcnow(), is_global=True) default_restriction.apply_to_group(default_group) click.echo( green( 'Created a default group: {} and a permission "{}" '. format(default_group.name, default_restriction.name) + 'allowing access to every resource ' 'at any time.')) else: click.echo( orange( '[•] OK - not creating any permissions. Remember that you need to define permissions' ' in order for users to be able to access the resources.' ))
def create(restriction: Dict[str, Any]) -> Tuple[Content, HttpStatusCode]: try: new_restriction = Restriction(name=restriction.get('name'), starts_at=restriction['startsAt'], is_global=restriction['isGlobal'], ends_at=DateUtils.try_parse_string( restriction.get('endsAt'))) new_restriction.save() except AssertionError as e: content = { 'msg': RESTRICTION['create']['failure']['invalid'].format(reason=e) } status = HTTPStatus.UNPROCESSABLE_ENTITY.value except Exception as e: content = {'msg': GENERAL['internal_error'] + str(e)} status = HTTPStatus.INTERNAL_SERVER_ERROR.value else: content = { 'msg': RESTRICTION['create']['success'], 'restriction': new_restriction.as_dict(include_groups=True, include_users=True, include_resources=True) } status = HTTPStatus.CREATED.value finally: return content, status
def test_it_should_be_impossible_to_create_or_edit_restriction_that_already_expired(tables): start_time = datetime.utcnow() - timedelta(hours=5) end_time = start_time + timedelta(hours=1) restriction = Restriction(name='Test', starts_at=start_time, ends_at=end_time, is_global=False) with pytest.raises(AssertionError): restriction.save()
def test_restriction_creation(tables): starts_at = datetime.utcnow() + timedelta(minutes=5) duration = timedelta(hours=12) new_restriction = Restriction(name='TestRestriction', starts_at=starts_at, ends_at=starts_at + duration, is_global=False) new_restriction.save() assert new_restriction.id is not None
def test_get_global_restrictions_returns_them(tables): starts_at = datetime.utcnow() + timedelta(minutes=5) duration = timedelta(hours=12) new_restriction = Restriction(name='TestRestriction', starts_at=starts_at, ends_at=starts_at + duration, is_global=True) new_restriction.save() assert new_restriction in Restriction.get_global_restrictions()
def restriction(): start_time = datetime.datetime.utcnow() + timedelta(minutes=5) end_time = start_time + timedelta(hours=8) restriction = Restriction(name='TestRestriction', starts_at=start_time, ends_at=end_time, is_global=False) restriction.save() return restriction
def test_delete_restriction(tables, client, restriction, new_user): new_user.save() restriction.apply_to_user(new_user) resp = client.delete(ENDPOINT + '/' + str(restriction.id), headers=HEADERS) assert resp.status_code == HTTPStatus.OK assert restriction not in new_user.get_restrictions() with pytest.raises(NoResultFound): Restriction.get(restriction.id)
def test_get_all_restrictions_with_data(tables, client): # Create new restriction and save it to the DB start_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=5) end_time = start_time + datetime.timedelta(hours=8) restriction = Restriction(name='TestRestriction', starts_at=start_time, ends_at=end_time, is_global=False) restriction.save() resp = client.get(ENDPOINT, headers=HEADERS) resp_json = json.loads(resp.data.decode('utf-8')) assert resp.status_code == HTTPStatus.OK assert len(resp_json) == 1
def delete(id: RestrictionId) -> Tuple[Content, HttpStatusCode]: try: restriction_to_destroy = Restriction.get(id) users = restriction_to_destroy.get_all_affected_users() restriction_to_destroy.destroy() for user in users: ReservationVerifier.update_user_reservations_statuses( user, have_users_permissions_increased=False) except AssertionError as error_message: content, status = { 'msg': str(error_message) }, HTTPStatus.FORBIDDEN.value except NoResultFound: content, status = { 'msg': RESTRICTION['not_found'] }, HTTPStatus.NOT_FOUND.value except Exception as e: content, status = { 'msg': GENERAL['internal_error'] + str(e) }, HTTPStatus.INTERNAL_SERVER_ERROR.value else: content, status = { 'msg': RESTRICTION['delete']['success'] }, HTTPStatus.OK.value finally: return content, status
def get_all() -> Tuple[List[Any], HttpStatusCode]: return [ restriction.as_dict(include_groups=True, include_users=True, include_resources=True) for restriction in Restriction.all() ], HTTPStatus.OK.value
def test_restriction_without_schedules_is_active_only_when_between_start_and_end_dates(tables): start_time = datetime.utcnow() - timedelta(hours=5) end_time = datetime.utcnow() + timedelta(hours=5) active_restriction = Restriction(name='ActiveRestriction', starts_at=start_time, ends_at=end_time, is_global=False) active_restriction.save() start_time = datetime.utcnow() + timedelta(hours=1) inactive_restriction = Restriction(name='InactiveRestriction', starts_at=start_time, ends_at=end_time, is_global=False) inactive_restriction.save() assert active_restriction.is_active is True assert inactive_restriction.is_active is False
def test_restriction_with_schedules_is_active_only_when_at_least_one_of_its_schedules_is_active(tables, active_schedule, inactive_schedule): start_time = datetime.utcnow() - timedelta(hours=5) end_time = datetime.utcnow() + timedelta(hours=5) restriction = Restriction(name='ActiveRestriction', starts_at=start_time, ends_at=end_time, is_global=False) restriction.save() restriction.add_schedule(inactive_schedule) assert restriction.is_active is False restriction.add_schedule(active_schedule) assert restriction.is_active is True
def test_create_indefinte_retriction(tables, client): data = { 'name': 'Test restriction', 'startsAt': '2100-01-01T10:00:00.000Z', 'isGlobal': False } resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data)) resp_json = json.loads(resp.data.decode('utf-8')) assert resp.status_code == HTTPStatus.CREATED assert Restriction.get(resp_json['restriction']['id']) is not None
def get_active_restrictions(self, include_global=True): """ :param include_global: If set to true will also include global restrictions (which apply to all resources) :return: Active restrictions (according to start/end times and schedules) assigned to given entity. """ from tensorhive.models.Restriction import Restriction restrictions = super(Resource, self).get_active_restrictions() if include_global: restrictions = list( set(restrictions + Restriction.get_global_restrictions( include_expired=False))) return restrictions
def test_restriction_with_dates_passed_as_string_gets_added_successfully(tables): new_restriction = Restriction( name='TestRestriction', is_global=False ) new_restriction.starts_at = '2020-09-29T18:07:44.191Z' new_restriction.ends_at = '2120-09-30T18:07:44.191Z' new_restriction.save()
def get_restrictions(self, include_expired=False, include_global=True): """ :param include_expired: If set to true will also return restrictions that have already expired. :param include_global: If set to true will also include global restrictions (which apply to all resources) :return: Restrictions assigned to given resource. """ from tensorhive.models.Restriction import Restriction restrictions = super(Resource, self).get_restrictions(include_expired) if include_global: restrictions = list( set(restrictions + Restriction.get_global_restrictions( include_expired=include_expired))) return restrictions
def permissive_restriction(new_user): start_time = datetime.datetime.utcnow() - timedelta(days=10) end_time = None restriction = Restriction(name='PermissiveRestriction', starts_at=start_time, ends_at=end_time, is_global=True) restriction.apply_to_user(new_user) restriction.save() return restriction
def test_update_restriction_incorrect_data(tables, client, restriction): old_start_date = restriction.starts_at old_end_date = restriction.ends_at data = { 'startsAt': '2200-01-01T10:00:00.000Z', # start date is after the end date, this request shouldn't be accepted 'endsAt': '2199-02-01T10:00:00.000Z', } resp = client.put(ENDPOINT + '/' + str(restriction.id), headers=HEADERS, data=json.dumps(data)) db_session.remove( ) # make sure we'll get the restriction from the DB, and not from memory restriction = Restriction.get(restriction.id) assert resp.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert restriction.starts_at == old_start_date assert restriction.ends_at == old_end_date
def add_schedule(restriction_id: RestrictionId, schedule_id: ScheduleId) -> Tuple[Content, HttpStatusCode]: restriction = None try: restriction = Restriction.get(restriction_id) schedule = RestrictionSchedule.get(schedule_id) restriction.add_schedule(schedule) have_users_permissions_increased = len( restriction.schedules) > 1 # if added another schedule for user in restriction.get_all_affected_users(): ReservationVerifier.update_user_reservations_statuses( user, have_users_permissions_increased) except NoResultFound: if restriction is None: content, status = { 'msg': RESTRICTION['not_found'] }, HTTPStatus.NOT_FOUND.value else: content, status = { 'msg': SCHEDULE['not_found'] }, HTTPStatus.NOT_FOUND.value except InvalidRequestException: content, status = { 'msg': RESTRICTION['schedules']['add']['failure']['duplicate'] }, HTTPStatus.CONFLICT.value except AssertionError as e: content, status = {'msg': RESTRICTION['schedules']['add']['failure']['assertions'].format(reason=e)}, \ HTTPStatus.UNPROCESSABLE_ENTITY.value except Exception as e: log.critical(e) content, status = { 'msg': GENERAL['internal_error'] }, HTTPStatus.INTERNAL_SERVER_ERROR.value else: content, status = { 'msg': RESTRICTION['schedules']['add']['success'], 'restriction': restriction.as_dict(include_groups=True, include_users=True, include_resources=True) }, HTTPStatus.OK.value finally: return content, status
def update(id: RestrictionId, newValues: Dict[str, Any]) -> Tuple[Content, HttpStatusCode]: new_values = newValues allowed_fields = {'name', 'startsAt', 'endsAt', 'isGlobal'} try: assert set(new_values.keys()).issubset( allowed_fields), 'invalid field is present' restriction = Restriction.get(id) for field_name, new_value in new_values.items(): field_name = snakecase(field_name) assert (field_name is not None) and hasattr(restriction, field_name), \ 'restriction has no {} field'.format(field_name) setattr(restriction, field_name, new_value) restriction.save() for user in restriction.get_all_affected_users(): ReservationVerifier.update_user_reservations_statuses( user, have_users_permissions_increased=True) ReservationVerifier.update_user_reservations_statuses( user, have_users_permissions_increased=False) except NoResultFound: content, status = { 'msg': RESTRICTION['not_found'] }, HTTPStatus.NOT_FOUND.value except AssertionError as e: content, status = {'msg': RESTRICTION['update']['failure']['assertions'].format(reason=e)}, \ HTTPStatus.UNPROCESSABLE_ENTITY.value except Exception as e: log.critical(e) content, status = { 'msg': GENERAL['internal_error'] }, HTTPStatus.INTERNAL_SERVER_ERROR.value else: content, status = { 'msg': RESTRICTION['update']['success'], 'restriction': restriction.as_dict(include_groups=True, include_users=True, include_resources=True) }, HTTPStatus.OK.value finally: return content, status
def remove_from_group(restriction_id: RestrictionId, group_id: GroupId) -> Tuple[Content, HttpStatusCode]: restriction = None try: restriction = Restriction.get(restriction_id) group = Group.get(group_id) restriction.remove_from_group(group) for user in group.users: ReservationVerifier.update_user_reservations_statuses( user, have_users_permissions_increased=False) except NoResultFound: if restriction is None: content, status = { 'msg': RESTRICTION['not_found'] }, HTTPStatus.NOT_FOUND.value else: content, status = { 'msg': GENERAL['not_found'] }, HTTPStatus.NOT_FOUND.value except InvalidRequestException: content, status = { 'msg': RESTRICTION['groups']['remove']['failure']['not_found'] }, HTTPStatus.NOT_FOUND.value except AssertionError as e: content, status = {'msg': RESTRICTION['groups']['remove']['failure']['assertions'].format(reason=e)}, \ HTTPStatus.UNPROCESSABLE_ENTITY.value except Exception as e: log.critical(e) content, status = { 'msg': GENERAL['internal_error'] }, HTTPStatus.INTERNAL_SERVER_ERROR.value else: content, status = { 'msg': RESTRICTION['groups']['remove']['success'], 'restriction': restriction.as_dict(include_groups=True, include_users=True, include_resources=True) }, HTTPStatus.OK.value finally: return content, status
def remove_from_resources_by_hostname( restriction_id: RestrictionId, hostname: str) -> Tuple[Content, HttpStatusCode]: restriction = None try: restriction = Restriction.get(restriction_id) resources = Resource.get_by_hostname(hostname) if resources: restriction.remove_from_resources(resources) for user in restriction.get_all_affected_users(): ReservationVerifier.update_user_reservations_statuses( user, have_users_permissions_increased=False) else: raise NoResultFound except NoResultFound: if restriction is None: content, status = { 'msg': RESTRICTION['not_found'] }, HTTPStatus.NOT_FOUND.value else: content, status = { 'msg': NODES['hostname']['not_found'] }, HTTPStatus.NOT_FOUND.value except AssertionError as e: content, status = {'msg': RESTRICTION['hosts']['remove']['failure']['assertions'].format(reason=e)}, \ HTTPStatus.UNPROCESSABLE_ENTITY.value except Exception as e: log.critical(e) content, status = { 'msg': GENERAL['internal_error'] }, HTTPStatus.INTERNAL_SERVER_ERROR.value else: content, status = { 'msg': RESTRICTION['hosts']['remove']['success'], 'restriction': restriction.as_dict(include_groups=True, include_users=True, include_resources=True) }, HTTPStatus.OK.value finally: return content, status
def apply_to_user(restriction_id: RestrictionId, user_id: UserId) -> Tuple[Content, HttpStatusCode]: restriction = None try: restriction = Restriction.get(restriction_id) user = User.get(user_id) restriction.apply_to_user(user) ReservationVerifier.update_user_reservations_statuses( user, have_users_permissions_increased=True) except NoResultFound: if restriction is None: content, status = { 'msg': RESTRICTION['not_found'] }, HTTPStatus.NOT_FOUND.value else: content, status = { 'msg': USER['not_found'] }, HTTPStatus.NOT_FOUND.value except InvalidRequestException: content, status = { 'msg': RESTRICTION['users']['apply']['failure']['duplicate'] }, HTTPStatus.CONFLICT.value except AssertionError as e: content, status = {'msg': RESTRICTION['users']['apply']['failure']['assertions'].format(reason=e)}, \ HTTPStatus.UNPROCESSABLE_ENTITY.value except Exception as e: log.critical(e) content, status = { 'msg': GENERAL['internal_error'] }, HTTPStatus.INTERNAL_SERVER_ERROR.value else: content, status = { 'msg': RESTRICTION['users']['apply']['success'], 'restriction': restriction.as_dict(include_groups=True, include_users=True, include_resources=True) }, HTTPStatus.OK.value finally: return content, status
def test_indefinite_restriction_creation(tables): starts_at = datetime.utcnow() + timedelta(minutes=5) new_restriction = Restriction(name='TestRestriction', starts_at=starts_at, is_global=False) new_restriction.save() assert new_restriction.id is not None
def test_create_reservation_that_is_covered_by_two_separate_restrictions( tables, client, new_user): r1_start = '2101-01-01T00:00:00.000Z' r1_end = '2101-01-02T00:00:00.000Z' r2_start = '2101-01-02T00:00:00.000Z' r2_end = '2101-01-02T23:59:00.000Z' r1 = Restriction(name='FirstRestriction', starts_at=r1_start, ends_at=r1_end, is_global=False) r2 = Restriction(name='SecondRestriction', starts_at=r2_start, ends_at=r2_end, is_global=False) new_user.save() r1.apply_to_user(new_user) r2.apply_to_user(new_user) resource = Resource(id='0123456789012345678901234567890123456789') resource.save() r1.apply_to_resource(resource) r2.apply_to_resource(resource) data = { 'title': 'Test reservation', 'description': 'Test reservation', 'resourceId': '0123456789012345678901234567890123456789', 'userId': new_user.id, 'start': '2101-01-01T10:00:00.000Z', 'end': '2101-01-02T12:00:00.000Z' } resp = client.post(ENDPOINT, headers=HEADERS, data=json.dumps(data)) resp_json = json.loads(resp.data.decode('utf-8')) assert resp.status_code == HTTPStatus.CREATED assert Reservation.get(resp_json['reservation']['id']) is not None