backend/models/dtos/user_dto.py (175 lines of code) (raw):
from schematics import Model
from schematics.exceptions import ValidationError
from schematics.types import (
StringType,
IntType,
EmailType,
LongType,
BooleanType,
)
from schematics.types.compound import ListType, ModelType, BaseType
from backend.models.dtos.stats_dto import Pagination
from backend.models.dtos.mapping_dto import TaskDTO
from backend.models.dtos.interests_dto import InterestDTO
from backend.models.postgis.statuses import MappingLevel, UserRole
def is_known_mapping_level(value):
""" Validates that supplied mapping level is known value """
if value.upper() == "ALL":
return True
try:
value = value.split(",")
for level in value:
MappingLevel[level.upper()]
except KeyError:
raise ValidationError(
f"Unknown mappingLevel: {value} Valid values are {MappingLevel.BEGINNER.name}, "
f"{MappingLevel.INTERMEDIATE.name}, {MappingLevel.ADVANCED.name}, ALL"
)
def is_known_role(value):
""" Validates that supplied user role is known value """
try:
value = value.split(",")
for role in value:
UserRole[role.upper()]
except KeyError:
raise ValidationError(
f"Unknown mappingRole: {value} Valid values are {UserRole.ADMIN.name}, "
f"{UserRole.READ_ONLY.name}, {UserRole.MAPPER.name}"
)
class UserDTO(Model):
""" DTO for User """
id = LongType()
username = StringType()
role = StringType()
mapping_level = StringType(
serialized_name="mappingLevel", validators=[is_known_mapping_level]
)
projects_mapped = IntType(serialized_name="projectsMapped")
email_address = EmailType(serialized_name="emailAddress")
is_email_verified = EmailType(
serialized_name="isEmailVerified", serialize_when_none=False
)
is_expert = BooleanType(serialized_name="isExpert", serialize_when_none=False)
twitter_id = StringType(serialized_name="twitterId")
facebook_id = StringType(serialized_name="facebookId")
linkedin_id = StringType(serialized_name="linkedinId")
slack_id = StringType(serialized_name="slackId")
irc_id = StringType(serialized_name="ircId")
skype_id = StringType(serialized_name="skypeId")
city = StringType(serialized_name="city")
country = StringType(serialized_name="country")
name = StringType(serialized_name="name")
picture_url = StringType(serialized_name="pictureUrl")
default_editor = StringType(serialized_name="defaultEditor")
mentions_notifications = BooleanType(serialized_name="mentionsNotifications")
comments_notifications = BooleanType(serialized_name="commentsNotifications")
projects_notifications = BooleanType(serialized_name="projectsNotifications")
tasks_notifications = BooleanType(serialized_name="tasksNotifications")
teams_notifications = BooleanType(serialized_name="teamsNotifications")
# these are read only
gender = StringType(
serialized_name="gender",
choices=("MALE", "FEMALE", "SELF_DESCRIBE", "PREFER_NOT"),
)
self_description_gender = StringType(
serialized_name="selfDescriptionGender", default=None
)
def validate_self_description(self, data, value):
if (
data["gender"] == "SELF_DESCRIBE"
and data["self_description_gender"] is None
):
raise ValueError("selfDescription field is not defined")
return value
class UserCountryContributed(Model):
""" DTO for country a user has contributed """
name = StringType(required=True)
mapped = IntType(required=True)
validated = IntType(required=True)
total = IntType(required=True)
class UserCountriesContributed(Model):
""" DTO for countries a user has contributed """
def __init__(self):
super().__init__()
self.countries_contributed = []
countries_contributed = ListType(
ModelType(UserCountryContributed), serialized_name="countries"
)
total = IntType()
class UserContributionDTO(Model):
date = StringType()
count = IntType()
class UserStatsDTO(Model):
""" DTO containing statistics about the user """
total_time_spent = IntType(serialized_name="totalTimeSpent")
time_spent_mapping = IntType(serialized_name="timeSpentMapping")
time_spent_validating = IntType(serialized_name="timeSpentValidating")
projects_mapped = IntType(serialized_name="projectsMapped")
countries_contributed = ModelType(
UserCountriesContributed, serialized_name="countriesContributed"
)
contributions_by_day = ListType(
ModelType(UserContributionDTO), serialized_name="contributionsByDay"
)
tasks_mapped = IntType(serialized_name="tasksMapped")
tasks_validated = IntType(serialized_name="tasksValidated")
tasks_invalidated = IntType(serialized_name="tasksInvalidated")
tasks_invalidated_by_others = IntType(serialized_name="tasksInvalidatedByOthers")
tasks_validated_by_others = IntType(serialized_name="tasksValidatedByOthers")
contributions_interest = ListType(
ModelType(InterestDTO), serialized_name="ContributionsByInterest"
)
class UserOSMDTO(Model):
""" DTO containing OSM details for the user """
account_created = StringType(required=True, serialized_name="accountCreated")
changeset_count = IntType(required=True, serialized_name="changesetCount")
class MappedProject(Model):
""" Describes a single project a user has mapped """
project_id = IntType(serialized_name="projectId")
name = StringType()
tasks_mapped = IntType(serialized_name="tasksMapped")
tasks_validated = IntType(serialized_name="tasksValidated")
status = StringType()
centroid = BaseType()
class UserMappedProjectsDTO(Model):
""" DTO for projects a user has mapped """
def __init__(self):
super().__init__()
self.mapped_projects = []
mapped_projects = ListType(
ModelType(MappedProject), serialized_name="mappedProjects"
)
class UserSearchQuery(Model):
""" Describes a user search query, that a user may submit to filter the list of users """
username = StringType()
role = StringType(validators=[is_known_role])
mapping_level = StringType(
serialized_name="mappingLevel", validators=[is_known_mapping_level]
)
page = IntType()
def __hash__(self):
""" Make object hashable so we can cache user searches"""
return hash((self.username, self.role, self.mapping_level, self.page))
class ListedUser(Model):
""" Describes a user within the User List """
id = LongType()
username = StringType()
role = StringType()
mapping_level = StringType(serialized_name="mappingLevel")
picture_url = StringType(serialized_name="pictureUrl")
class UserRegisterEmailDTO(Model):
""" DTO containing data for user registration with email model """
id = IntType(serialize_when_none=False)
email = StringType(required=True)
success = BooleanType(default=False)
details = StringType()
class ProjectParticipantUser(Model):
""" Describes a user who has participated in a project """
username = StringType()
project_id = LongType(serialized_name="projectId")
is_participant = BooleanType(serialized_name="isParticipant")
class UserSearchDTO(Model):
""" Paginated list of TM users """
def __init__(self):
super().__init__()
self.users = []
pagination = ModelType(Pagination)
users = ListType(ModelType(ListedUser))
class UserFilterDTO(Model):
""" DTO to hold all Tasking Manager users """
def __init__(self):
super().__init__()
self.usernames = []
self.users = []
pagination = ModelType(Pagination)
usernames = ListType(StringType)
users = ListType(ModelType(ProjectParticipantUser))
class UserTaskDTOs(Model):
""" Describes an array of Task DTOs"""
def __init__(self):
""" DTO constructor initialise all arrays to empty"""
super().__init__()
self.user_tasks = []
user_tasks = ListType(ModelType(TaskDTO), serialized_name="tasks")
pagination = ModelType(Pagination)