def get_user_by_id(user_id: int) -> User: user = User().get_by_id(user_id) if user is None: raise NotFound() return user
def get_user_by_username(username: str) -> User: user = User().get_by_username(username) if user is None: raise NotFound() return user
def test_admin_role_is_recognized_as_a_validator(self, mock_user): # Arrange stub_user = User() stub_user.role = UserRole.ADMIN.value mock_user.return_value = stub_user # Act / Assert self.assertTrue(UserService.is_user_validator(123))
def test_mapper_role_is_not_recognized_as_a_validator(self, mock_user): # Arrange stub_user = User() stub_user.role = UserRole.MAPPER.value mock_user.return_value = stub_user # Act / Assert self.assertFalse(UserService.is_user_validator(123))
def test_user_not_identified_as_pm(self, mock_user): # Arrange test_user = User() test_user.role = UserRole.MAPPER.value mock_user.return_value = test_user # Act / Assert self.assertFalse(UserService.is_user_a_project_manager(123))
def create_canned_user() -> User: """ Generate a canned user in the DB """ test_user = User() test_user.id = TEST_USER_ID test_user.username = '******' test_user.mapping_level = 1 test_user.create() return test_user
def get_project_summary(self, preferred_locale) -> ProjectSummary: """ Create Project Summary model for postgis project object""" summary = ProjectSummary() summary.project_id = self.id priority = self.priority if priority == 0: summary.priority = 'URGENT' elif priority == 1: summary.priority = 'HIGH' elif priority == 2: summary.priority = 'MEDIUM' else: summary.priority = 'LOW' summary.author = User().get_by_id(self.author_id).username polygon = to_shape(self.geometry) polygon_aea = transform( partial( pyproj.transform, pyproj.Proj(init='EPSG:4326'), pyproj.Proj( proj='aea', lat1=polygon.bounds[1], lat2=polygon.bounds[3])), polygon) area = polygon_aea.area/1000000 summary.area = area summary.campaign_tag = self.campaign_tag summary.changeset_comment = self.changeset_comment summary.created = self.created summary.last_updated = self.last_updated summary.due_date = self.due_date summary.mapper_level = MappingLevel(self.mapper_level).name summary.mapper_level_enforced = self.enforce_mapper_level summary.validator_level_enforced = self.enforce_validator_role summary.organisation_tag = self.organisation_tag summary.status = ProjectStatus(self.status).name summary.entities_to_map = self.entities_to_map centroid_geojson = db.session.scalar(self.centroid.ST_AsGeoJSON()) summary.aoi_centroid = geojson.loads(centroid_geojson) summary.percent_mapped = Project.calculate_tasks_percent('mapped', self.total_tasks, self.tasks_mapped, self.tasks_validated, self.tasks_bad_imagery) summary.percent_validated = Project.calculate_tasks_percent('validated', self.total_tasks, self.tasks_mapped, self.tasks_validated, self.tasks_bad_imagery) summary.percent_bad_imagery = Project.calculate_tasks_percent('bad_imagery', self.total_tasks, self.tasks_mapped, self.tasks_validated, self.tasks_bad_imagery) project_info = ProjectInfo.get_dto_for_locale(self.id, preferred_locale, self.default_locale) summary.name = project_info.name summary.short_description = project_info.short_description return summary
def test_pm_not_allowed_to_add_admin_role_when_setting_role( self, mock_admin): # Arrange admin = User() admin.role = UserRole.PROJECT_MANAGER.value mock_admin.return_value = admin # Act with self.assertRaises(UserServiceError): UserService.add_role_to_user(1, 'test', 'ADMIN')
def test_user_correctly_identified_as_pm(self, mock_user): # Arrange test_proj = Project() test_user = User() test_user.role = UserRole.PROJECT_MANAGER.value mock_user.return_value = test_user # Act / Assert self.assertTrue(UserService.is_user_a_project_manager(123)) self.assertTrue(test_proj)
def _get_project_and_base_dto(self, project_id): """ Populates a project DTO with properties common to all roles """ project = Project.get(project_id) if project is None: return None, None aoi = project.area_of_interest base_dto = ProjectDTO() base_dto.project_id = project_id base_dto.project_status = ProjectStatus(project.status).name base_dto.default_locale = project.default_locale base_dto.project_priority = ProjectPriority(project.priority).name base_dto.area_of_interest = aoi.get_aoi_geometry_as_geojson() base_dto.enforce_mapper_level = project.enforce_mapper_level base_dto.enforce_validator_role = project.enforce_validator_role base_dto.private = project.private base_dto.mapper_level = MappingLevel(project.mapper_level).name base_dto.entities_to_map = project.entities_to_map base_dto.changeset_comment = project.changeset_comment base_dto.due_date = project.due_date base_dto.imagery = project.imagery base_dto.josm_preset = project.josm_preset base_dto.campaign_tag = project.campaign_tag base_dto.organisation_tag = project.organisation_tag base_dto.license_id = project.license_id base_dto.last_updated = project.last_updated base_dto.author = User().get_by_id(project.author_id).username if project.private: # If project is private it should have a list of allowed users allowed_usernames = [] for user in project.allowed_users: allowed_usernames.append(user.username) base_dto.allowed_usernames = allowed_usernames if project.mapping_types: mapping_types = [] for mapping_type in project.mapping_types: mapping_types.append(MappingTypes(mapping_type).name) base_dto.mapping_types = mapping_types if project.priority_areas: geojson_areas = [] for priority_area in project.priority_areas: geojson_areas.append(priority_area.get_as_geojson()) base_dto.priority_areas = geojson_areas return project, base_dto
def test_get_intersecting_projects(self, get_dto_for_locale, _get_intersecting_projects, get_user_by_username, validate_bbox_area, _make_4326_polygon_from_bbox): if self.skip_tests: return # arrange _make_4326_polygon_from_bbox mock _make_4326_polygon_from_bbox.return_value = Polygon([ (34.68826225820438, -12.59912449955007), (34.68826225820438, -11.57858317689196), (32.50198296132938, -11.57858317689196), (32.50198296132938, -12.59912449955007), (34.68826225820438, -12.59912449955007) ]) # arrange validate_bbox_area mock validate_bbox_area.return_value = True # arrange get_user_by_username mock get_user_by_username.return_value = User(id=3488526) # arrange _get_intersecting_projects mock polygon = json.dumps(get_canned_json('search_bbox_feature.json')) project = Project(id=2274, status=0, default_locale='en', geometry=polygon) projects = [project] _get_intersecting_projects.return_value = projects # arrange get_dto_for_locale mock get_dto_for_locale.return_value = ProjectInfo( name='PEPFAR Kenya: Homa Bay') # arrange dto dto = ProjectSearchBBoxDTO() dto.bbox = map(float, '34.404,-1.034, 34.717,-0.624'.split(',')) dto.preferred_locale = 'en' dto.input_srid = 4326 dto.project_author = 3488526 dto.validate() # arrange expected result expected = json.dumps(get_canned_json('search_bbox_result.json')) # act result = ProjectSearchService.get_projects_geojson(dto) # assert self.assertEqual(str(expected), str(expected))
def _get_project_and_base_dto(self): """ Populates a project DTO with properties common to all roles """ base_dto = ProjectDTO() base_dto.project_id = self.id base_dto.project_status = ProjectStatus(self.status).name base_dto.default_locale = self.default_locale base_dto.project_priority = ProjectPriority(self.priority).name base_dto.area_of_interest = self.get_aoi_geometry_as_geojson() base_dto.enforce_mapper_level = self.enforce_mapper_level base_dto.enforce_validator_role = self.enforce_validator_role base_dto.private = self.private base_dto.mapper_level = MappingLevel(self.mapper_level).name base_dto.entities_to_map = self.entities_to_map base_dto.changeset_comment = self.changeset_comment base_dto.due_date = self.due_date base_dto.imagery = self.imagery base_dto.josm_preset = self.josm_preset base_dto.campaign_tag = self.campaign_tag base_dto.organisation_tag = self.organisation_tag base_dto.license_id = self.license_id base_dto.created = self.created base_dto.last_updated = self.last_updated base_dto.id_custom_imagery = self.id_custom_imagery base_dto.id_custom_presets = self.id_custom_presets base_dto.id_min_editable_zoom = self.id_min_editable_zoom base_dto.author = User().get_by_id(self.author_id).username base_dto.active_mappers = Project.get_active_mappers(self.id) base_dto.task_creation_mode = TaskCreationMode( self.task_creation_mode).name if self.private: # If project is private it should have a list of allowed users allowed_usernames = [] for user in self.allowed_users: allowed_usernames.append(user.username) base_dto.allowed_usernames = allowed_usernames if self.mapping_types: mapping_types = [] for mapping_type in self.mapping_types: mapping_types.append(MappingTypes(mapping_type).name) base_dto.mapping_types = mapping_types if self.priority_areas: geojson_areas = [] for priority_area in self.priority_areas: geojson_areas.append(priority_area.get_as_geojson()) base_dto.priority_areas = geojson_areas return self, base_dto
def test_update_after_mapping_increments_counter(self): # Arrange test_project = Project() test_project.tasks_mapped = 0 test_user = User() test_user.tasks_mapped = 0 # Act StatsService._set_counters_after_mapping(test_project, test_user) # Assert self.assertEqual(test_project.tasks_mapped, 1) self.assertEqual(test_user.tasks_mapped, 1)
def test_update_after_mapping_increments_counter(self): # Arrange test_project = Project() test_project.tasks_mapped = 0 test_user = User() test_user.tasks_mapped = 0 # Act StatsService._update_tasks_stats(test_project, test_user, TaskStatus.READY, TaskStatus.MAPPED) # Assert self.assertEqual(test_project.tasks_mapped, 1) self.assertEqual(test_user.tasks_mapped, 1)
def test_update_after_flagging_bad_imagery(self): # Arrange test_project = Project() test_project.tasks_bad_imagery = 0 test_user = User() test_user.tasks_invalidated = 0 # Act StatsService._update_tasks_stats(test_project, test_user, TaskStatus.READY, TaskStatus.BADIMAGERY) # Assert self.assertEqual(test_project.tasks_bad_imagery, 1)
def test_as_dto_will_not_return_email_if_owner(self): if self.skip_tests: return # Arrange test_user = User() test_user.role = UserRole.MAPPER.value test_user.mapping_level = MappingLevel.BEGINNER.value test_user.username = '******' test_user.email_address = '*****@*****.**' # Act user_dto = test_user.as_dto('mrtest') # Assert self.assertTrue(user_dto.email_address)
def test_update_after_invalidating_mapped_task_sets_counters_correctly(self, last_status): # Arrange test_project = Project() test_project.tasks_mapped = 1 test_user = User() test_user.tasks_invalidated = 0 last_status.return_value = TaskStatus.MAPPED # Act StatsService._set_counters_after_invalidated(1, test_project, test_user) # Assert self.assertEqual(test_project.tasks_mapped, 0) self.assertEqual(test_user.tasks_invalidated, 1)
def test_update_after_invalidating_bad_imagery_task_sets_counters_correctly(self, last_status): # Arrange test_project = Project() test_project.tasks_bad_imagery = 1 test_user = User() test_user.tasks_invalidated = 0 last_status.return_value = TaskStatus.BADIMAGERY # Act StatsService._set_counters_after_invalidated(1, test_project, test_user) # Assert self.assertEqual(test_project.tasks_bad_imagery, 0) self.assertEqual(test_user.tasks_invalidated, 1)
def test_update_after_invalidating_validated_task_sets_counters_correctly( self): # Arrange test_project = Project() test_project.tasks_validated = 1 test_user = User() test_user.tasks_invalidated = 0 # Act StatsService._update_tasks_stats(test_project, test_user, TaskStatus.VALIDATED, TaskStatus.INVALIDATED) # Assert self.assertEqual(test_project.tasks_validated, 0) self.assertEqual(test_user.tasks_invalidated, 1)
def register_user(osm_id, username, changeset_count): """ Creates user in DB :param osm_id: Unique OSM user id :param username: OSM Username :param changeset_count: OSM changeset count """ new_user = User() new_user.id = osm_id new_user.username = username if changeset_count > ADVANCED_MAPPER_LEVEL: new_user.mapping_level = MappingLevel.ADVANCED.value elif INTERMEDIATE_MAPPER_LEVEL < changeset_count < ADVANCED_MAPPER_LEVEL: new_user.mapping_level = MappingLevel.INTERMEDIATE.value else: new_user.mapping_level = MappingLevel.BEGINNER.value new_user.create() return new_user
def setUp(self): # Arrange test_user = User() test_user.role = UserRole.MAPPER.value test_user.id = 12 test_user.mapping_level = MappingLevel.BEGINNER.value test_user.username = '******' test_user.email_address = '*****@*****.**' self.test_user = test_user """ Setup test context so we can connect to database """ self.app = create_app() self.ctx = self.app.app_context() self.ctx.push() if self.skip_tests: return
def create_user(user_dto: UserDTO): """ Creates a new admin user record :param user_dto: DTO containing all user details :return: User if created successfully :raises UserExistsError if username already exists """ # Check if username already exists if User.get_by_username(user_dto.username) is not None: raise UserExistsError( f'Cannot create account. Username {user_dto.username} already exists.' ) new_user = User() new_user.username = user_dto.username new_user.password = UserService._hash_password( user_dto.password) # Hash password so not storing in plaintext new_user.role = UserRole[user_dto.role].value new_user.create() return new_user
def register_user(osm_id, username, changeset_count): """ Creates user in DB :param osm_id: Unique OSM user id :param username: OSM Username :param changeset_count: OSM changeset count """ new_user = User() new_user.id = osm_id new_user.username = username intermediate_level = current_app.config['MAPPER_LEVEL_INTERMEDIATE'] advanced_level = current_app.config['MAPPER_LEVEL_ADVANCED'] if changeset_count > advanced_level: new_user.mapping_level = MappingLevel.ADVANCED.value elif intermediate_level < changeset_count < advanced_level: new_user.mapping_level = MappingLevel.INTERMEDIATE.value else: new_user.mapping_level = MappingLevel.BEGINNER.value new_user.create() return new_user
def test_tasks_state_representation(self): # Arrange test_project = Project() test_project.tasks_mapped = 0 test_project.tasks_validated = 0 test_project.tasks_bad_imagery = 0 test_mapper = User() test_mapper.tasks_mapped = 0 test_mapper.tasks_validated = 0 test_mapper.tasks_invalidated = 0 test_validator = User() test_validator.tasks_mapped = 0 test_validator.tasks_validated = 0 test_validator.tasks_invalidated = 0 test_admin = User() test_admin.tasks_mapped = 0 test_admin.tasks_validated = 0 test_admin.tasks_invalidated = 0 # Mapper marks task as mapped StatsService._update_tasks_stats(test_project, test_mapper, TaskStatus.READY, TaskStatus.MAPPED) # Validator marks task as bad imagery StatsService._update_tasks_stats(test_project, test_validator, TaskStatus.MAPPED, TaskStatus.BADIMAGERY) # Admin undos marking task as bad imagery StatsService._update_tasks_stats(test_project, test_admin, TaskStatus.BADIMAGERY, TaskStatus.MAPPED, 'undo') # Validator marks task as invalid StatsService._update_tasks_stats(test_project, test_validator, TaskStatus.MAPPED, TaskStatus.INVALIDATED) # Mapper marks task as mapped StatsService._update_tasks_stats(test_project, test_mapper, TaskStatus.INVALIDATED, TaskStatus.MAPPED) # Admin undos marking task as mapped (test_mapper is given to the function though, as the author of the # last_change - compare with MappingServer.undo_mapping() method) StatsService._update_tasks_stats(test_project, test_mapper, TaskStatus.MAPPED, TaskStatus.INVALIDATED, 'undo') # Mapper marks task as mapped StatsService._update_tasks_stats(test_project, test_mapper, TaskStatus.INVALIDATED, TaskStatus.MAPPED) # Validator marks task as valid StatsService._update_tasks_stats(test_project, test_validator, TaskStatus.MAPPED, TaskStatus.VALIDATED) # Assert self.assertEqual(test_project.tasks_mapped, 0) self.assertEqual(test_project.tasks_validated, 1) self.assertEqual(test_project.tasks_bad_imagery, 0) self.assertEqual(test_mapper.tasks_mapped, 2) self.assertEqual(test_mapper.tasks_validated, 0) self.assertEqual(test_mapper.tasks_invalidated, 0) self.assertEqual(test_validator.tasks_mapped, 0) self.assertEqual(test_validator.tasks_validated, 1) self.assertEqual(test_validator.tasks_invalidated, 1) self.assertEqual(test_admin.tasks_mapped, 0) self.assertEqual(test_admin.tasks_validated, 0) self.assertEqual(test_admin.tasks_invalidated, 0)
def get_project_summary(self, preferred_locale) -> ProjectSummary: """ Create Project Summary model for postgis project object""" summary = ProjectSummary() summary.project_id = self.id priority = self.priority if priority == 0: summary.priority = 'URGENT' elif priority == 1: summary.priority = 'HIGH' elif priority == 2: summary.priority = 'MEDIUM' else: summary.priority = 'LOW' summary.author = User().get_by_id(self.author_id).username polygon = to_shape(self.geometry) polygon_aea = transform( partial( pyproj.transform, pyproj.Proj(init='EPSG:4326'), pyproj.Proj( proj='aea', lat1=polygon.bounds[1], lat2=polygon.bounds[3])), polygon) area = polygon_aea.area/1000000 summary.area = area summary.campaign_tag = self.campaign_tag summary.changeset_comment = self.changeset_comment summary.created = self.created summary.last_updated = self.last_updated summary.due_date = self.due_date summary.mapper_level = MappingLevel(self.mapper_level).name summary.mapper_level_enforced = self.enforce_mapper_level summary.validator_level_enforced = self.enforce_validator_role summary.organisation_tag = self.organisation_tag summary.status = ProjectStatus(self.status).name summary.total_mappers = db.session.query(User).filter(User.projects_mapped.any(self.id)).count() unique_mappers = TaskHistory.query.filter( TaskHistory.action == 'LOCKED_FOR_MAPPING', TaskHistory.project_id == self.id ).distinct(TaskHistory.user_id).count() unique_validators = TaskHistory.query.filter( TaskHistory.action == 'LOCKED_FOR_VALIDATION', TaskHistory.project_id == self.id ).distinct(TaskHistory.user_id).count() summary.total_tasks = self.total_tasks summary.total_comments = db.session.query(ProjectChat).filter(ProjectChat.project_id == self.id).count() summary.entities_to_map = self.entities_to_map centroid_geojson = db.session.scalar(self.centroid.ST_AsGeoJSON()) summary.aoi_centroid = geojson.loads(centroid_geojson) summary.percent_mapped = int(((self.tasks_mapped + self.tasks_bad_imagery) / self.total_tasks) * 100) summary.percent_validated = int((self.tasks_validated / self.total_tasks) * 100) summary.percent_bad_imagery = int((self.tasks_bad_imagery / self.total_tasks) * 100) project_info = ProjectInfo.get_dto_for_locale(self.id, preferred_locale, self.default_locale) summary.name = project_info.name summary.short_description = project_info.short_description summary.total_time_spent = 0 summary.total_mapping_time = 0 summary.total_validation_time = 0 summary.average_mapping_time = 0 summary.average_validation_time = 0 sql = '''SELECT SUM(TO_TIMESTAMP(action_text, 'HH24:MI:SS')::TIME) FROM task_history WHERE action='LOCKED_FOR_MAPPING'and project_id = {0};'''.format(self.id) total_mapping_time = db.engine.execute(sql) for row in total_mapping_time: total_mapping_time = row[0] if total_mapping_time: total_mapping_seconds = total_mapping_time.total_seconds() summary.total_mapping_time = total_mapping_seconds summary.total_time_spent += summary.total_mapping_time if unique_mappers: average_mapping_time = total_mapping_seconds/unique_mappers summary.average_mapping_time = average_mapping_time sql = '''SELECT SUM(TO_TIMESTAMP(action_text, 'HH24:MI:SS')::TIME) FROM task_history WHERE action='LOCKED_FOR_VALIDATION' and project_id = {0};'''.format(self.id) total_validation_time = db.engine.execute(sql) for row in total_validation_time: total_validation_time = row[0] if total_validation_time: total_validation_seconds = total_validation_time.total_seconds() summary.total_validation_time = total_validation_seconds summary.total_time_spent += summary.total_validation_time if unique_validators: average_validation_time = total_validation_seconds/unique_validators summary.average_validation_time = average_validation_time return summary