backend/api/users/resources.py (139 lines of code) (raw):
from flask_restful import Resource, current_app, request
from schematics.exceptions import DataError
from backend.models.dtos.user_dto import UserSearchQuery
from backend.services.users.authentication_service import token_auth
from backend.services.users.user_service import UserService, NotFound
from backend.services.project_service import ProjectService
class UsersRestAPI(Resource):
@token_auth.login_required
def get(self, user_id):
"""
Get user information by id
---
tags:
- users
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded session token
required: true
type: string
default: Token sessionTokenHere==
- name: user_id
in: path
description: The id of the user
required: true
type: integer
default: 1
responses:
200:
description: User found
401:
description: Unauthorized - Invalid credentials
404:
description: User not found
500:
description: Internal Server Error
"""
try:
user_dto = UserService.get_user_dto_by_id(
user_id, token_auth.current_user()
)
return user_dto.to_primitive(), 200
except NotFound:
return {"Error": "User not found"}, 404
except Exception as e:
error_msg = f"Userid GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": "Unable to fetch user details"}, 500
class UsersAllAPI(Resource):
@token_auth.login_required
def get(self):
"""
Get paged list of all usernames
---
tags:
- users
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded sesesion token
required: true
type: string
default: Token sessionTokenHere==
- in: query
name: page
description: Page of results user requested
type: integer
- in: query
name: username
description: Full or part username
type: string
- in: query
name: role
description: Role of User, eg ADMIN, PROJECT_MANAGER
type: string
- in: query
name: level
description: Level of User, eg BEGINNER
type: string
responses:
200:
description: Users found
401:
description: Unauthorized - Invalid credentials
500:
description: Internal Server Error
"""
try:
query = UserSearchQuery()
query.page = (
int(request.args.get("page")) if request.args.get("page") else 1
)
query.username = request.args.get("username")
query.mapping_level = request.args.get("level")
query.role = request.args.get("role")
query.validate()
except DataError as e:
current_app.logger.error(f"Error validating request: {str(e)}")
return {"Error": "Unable to fetch user list"}, 400
try:
users_dto = UserService.get_all_users(query)
return users_dto.to_primitive(), 200
except Exception as e:
error_msg = f"User GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": "Unable to fetch user list"}, 500
class UsersQueriesUsernameAPI(Resource):
@token_auth.login_required
def get(self, username):
"""
Get user information by OpenStreetMap username
---
tags:
- users
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded session token
required: true
type: string
default: Token sessionTokenHere==
- name: username
in: path
description: Mapper's OpenStreetMap username
required: true
type: string
default: Thinkwhere
responses:
200:
description: User found
401:
description: Unauthorized - Invalid credentials
404:
description: User not found
500:
description: Internal Server Error
"""
try:
user_dto = UserService.get_user_dto_by_username(
username, token_auth.current_user()
)
return user_dto.to_primitive(), 200
except NotFound:
return {"Error": "User not found"}, 404
except Exception as e:
error_msg = f"User GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": "Unable to fetch user details"}, 500
class UsersQueriesUsernameFilterAPI(Resource):
@token_auth.login_required
def get(self, username):
"""
Get paged lists of users matching OpenStreetMap username filter
---
tags:
- users
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded session token
required: true
type: string
default: Token sessionTokenHere==
- name: username
in: path
description: Mapper's partial or full OpenStreetMap username
type: string
default: ab
- in: query
name: page
description: Page of results user requested
type: integer
- in: query
name: projectId
description: Optional, promote project participants to head of results
type: integer
responses:
200:
description: Users found
401:
description: Unauthorized - Invalid credentials
404:
description: User not found
500:
description: Internal Server Error
"""
try:
page = int(request.args.get("page")) if request.args.get("page") else 1
project_id = request.args.get("projectId", None, int)
users_dto = UserService.filter_users(username, project_id, page)
return users_dto.to_primitive(), 200
except NotFound:
return {"Error": "User not found"}, 404
except Exception as e:
error_msg = f"User GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": "Unable to fetch matching users"}, 500
class UsersQueriesOwnLockedAPI(Resource):
@token_auth.login_required
def get(self):
"""
Gets any locked task on the project for the logged in user
---
tags:
- mapping
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded session token
required: true
type: string
default: Token sessionTokenHere==
responses:
200:
description: Task user is working on
401:
description: Unauthorized - Invalid credentials
404:
description: User is not working on any tasks
500:
description: Internal Server Error
"""
try:
locked_tasks = ProjectService.get_task_for_logged_in_user(
token_auth.current_user()
)
return locked_tasks.to_primitive(), 200
except Exception as e:
error_msg = f"UsersQueriesOwnLockedAPI - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": error_msg}, 500
class UsersQueriesOwnLockedDetailsAPI(Resource):
@token_auth.login_required
def get(self):
"""
Gets details of any locked task for the logged in user
---
tags:
- mapping
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded session token
required: true
type: string
default: Token sessionTokenHere==
- in: header
name: Accept-Language
description: Language user is requesting
type: string
required: true
default: en
responses:
200:
description: Task user is working on
401:
description: Unauthorized - Invalid credentials
404:
description: User is not working on any tasks
500:
description: Internal Server Error
"""
try:
preferred_locale = request.environ.get("HTTP_ACCEPT_LANGUAGE")
locked_tasks = ProjectService.get_task_details_for_logged_in_user(
token_auth.current_user(), preferred_locale
)
return locked_tasks.to_primitive(), 200
except NotFound:
return {"Error": "User has no locked tasks"}, 404
except Exception as e:
error_msg = f"UsersQueriesOwnLockedDetailsAPI - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": error_msg}, 500
class UsersQueriesFavoritesAPI(Resource):
@token_auth.login_required
def get(self):
"""
Get projects favorited by a user
---
tags:
- favorites
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded session token
required: true
type: string
default: Token sessionTokenHere==
responses:
200:
description: Projects favorited by user
404:
description: User not found
500:
description: Internal Server Error
"""
try:
favs_dto = UserService.get_projects_favorited(token_auth.current_user())
return favs_dto.to_primitive(), 200
except NotFound:
return {"Error": "User not found"}, 404
except Exception as e:
error_msg = f"UserFavorites GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": error_msg}, 500
class UsersQueriesInterestsAPI(Resource):
@token_auth.login_required
def get(self, username):
"""
Get interests by username
---
tags:
- interests
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded session token
required: true
type: string
default: Token sessionTokenHere==
- name: username
in: path
description: Mapper's OpenStreetMap username
required: true
type: string
responses:
200:
description: User interests returned
404:
description: User not found
500:
description: Internal Server Error
"""
try:
user = UserService.get_user_by_username(username)
interests_dto = UserService.get_interests(user)
return interests_dto.to_primitive(), 200
except NotFound:
return {"Error": "User not found"}, 404
except Exception as e:
error_msg = f"UserInterests GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": error_msg}, 500
class UsersRecommendedProjectsAPI(Resource):
@token_auth.login_required
def get(self, username):
"""
Get recommended projects for a user
---
tags:
- users
produces:
- application/json
parameters:
- in: header
name: Accept-Language
description: Language user is requesting
type: string
required: true
default: en
- in: header
name: Authorization
description: Base64 encoded session token
required: true
type: string
default: Token sessionTokenHere==
- name: username
in: path
description: Mapper's OpenStreetMap username
required: true
type: string
default: Thinkwhere
responses:
200:
description: Recommended projects found
401:
description: Unauthorized - Invalid credentials
403:
description: Forbidden
404:
description: No recommended projects found
500:
description: Internal Server Error
"""
try:
locale = (
request.environ.get("HTTP_ACCEPT_LANGUAGE")
if request.environ.get("HTTP_ACCEPT_LANGUAGE")
else "en"
)
user_dto = UserService.get_recommended_projects(username, locale)
return user_dto.to_primitive(), 200
except NotFound:
return {"Error": "User or mapping not found"}, 404
except Exception as e:
error_msg = f"User GET - unhandled error: {str(e)}"
current_app.logger.critical(error_msg)
return {"Error": error_msg}, 500