def validate_version(request, **kwargs): document_id = request.validated['document_id'] lang = request.validated['lang'] version_id = request.validated['version_id'] # check the version to revert to actually exists version_exists = DBSession.query( exists().where( and_(DocumentVersion.id == version_id, DocumentVersion.document_id == document_id, DocumentVersion.lang == lang)) ).scalar() if not version_exists: raise HTTPBadRequest('Unknown version {}/{}/{}'.format( document_id, lang, version_id)) # check the version to revert to is not the latest one last_version_id, = DBSession.query(DocumentVersion.id). \ filter(and_( DocumentVersion.document_id == document_id, DocumentVersion.lang == lang)). \ order_by(DocumentVersion.id.desc()).first() if version_id == last_version_id: raise HTTPBadRequest( 'Version {}/{}/{} is already the latest one'.format( document_id, lang, version_id))
def post(self): """ Tag the given document as todo. Creates a tag relation, so that the authenticated user is marking the given document as todo. Request: `POST` `/tags/add` Request body: {'document_id': @document_id@} """ document_id = self.request.validated['document_id'] document_type = ROUTE_TYPE user_id = self.request.authenticated_userid if get_tag_relation(user_id, document_id): raise HTTPBadRequest('This document is already tagged.') DBSession.add(DocumentTag( user_id=user_id, document_id=document_id, document_type=document_type)) DBSession.add(DocumentTagLog( user_id=user_id, document_id=document_id, document_type=document_type, is_creation=True)) notify_es_syncer(self.request.registry.queue_config) return {}
def post(self): """ Untag the given document. Request: `POST` `/tags/remove` Request body: {'document_id': @document_id@} """ document_id = self.request.validated['document_id'] document_type = ROUTE_TYPE user_id = self.request.authenticated_userid tag_relation = get_tag_relation(user_id, document_id) if tag_relation: DBSession.delete(tag_relation) DBSession.add(DocumentTagLog( user_id=user_id, document_id=document_id, document_type=document_type, is_creation=False)) else: log.warning( 'tried to delete not existing tag relation ' '({0}, {1})'.format(user_id, document_id)) raise HTTPBadRequest('This document has no such tag.') notify_es_syncer(self.request.registry.queue_config) return {}
def validate_user_id(request, **kwargs): """ Check that the user exists. """ user_id = request.validated['user_id'] user_exists_query = DBSession.query(User). \ filter(User.id == user_id). \ exists() user_exists = DBSession.query(user_exists_query).scalar() if not user_exists: request.errors.add( 'body', 'user_id', 'user {0} does not exist'.format(user_id))
def validate_document(request, **kwargs): """ Check that the document exists, is a route and not merged with another document. """ document_id = request.validated['document_id'] document_exists_query = DBSession.query(Document). \ filter(Document.document_id == document_id). \ filter(Document.type == ROUTE_TYPE). \ filter(Document.redirects_to.is_(None)). \ exists() document_exists = DBSession.query(document_exists_query).scalar() if not document_exists: request.errors.add('body', 'document_id', 'document {0} does not exist'.format(document_id))
def _get_models(self, document_id): document_type, = DBSession.query(Document.type). \ filter(Document.document_id == document_id).first() if document_type == WAYPOINT_TYPE: return Waypoint, WaypointLocale, ArchiveWaypoint, \ ArchiveWaypointLocale, document_type if document_type == ROUTE_TYPE: return Route, RouteLocale, ArchiveRoute, ArchiveRouteLocale, \ document_type if document_type == OUTING_TYPE: return Outing, OutingLocale, ArchiveOuting, ArchiveOutingLocale, \ document_type if document_type == IMAGE_TYPE: return Image, None, ArchiveImage, ArchiveDocumentLocale, \ document_type if document_type == ARTICLE_TYPE: return Article, None, ArchiveArticle, ArchiveDocumentLocale, \ document_type if document_type == BOOK_TYPE: return Book, None, ArchiveBook, ArchiveDocumentLocale, \ document_type if document_type == XREPORT_TYPE: return Xreport, XreportLocale, ArchiveXreport, \ ArchiveXreportLocale, document_type if document_type == AREA_TYPE: return Area, None, ArchiveArea, ArchiveDocumentLocale, \ document_type assert False
def _get_document(document_id): document = DBSession.query(Document).get(document_id) if not document: raise HTTPBadRequest('Unknown document {}'.format(document_id)) return document
def _get_user(user_id): user = DBSession.query(User).get(user_id) if not user: raise HTTPBadRequest('Unknown user {}'.format(user_id)) return user
def get_user(self, with_area_locales=True): user_id = self.request.authenticated_userid area_joinedload = joinedload(User.feed_filter_areas).load_only( Area.document_id, Area.area_type, Area.version, Area.protected, Area.type ) if with_area_locales: area_joinedload = area_joinedload.joinedload("locales").load_only("lang", "title", "version") return DBSession.query(User).options(area_joinedload).get(user_id)
def post(self): """ Unfollow the given user. Request: `POST` `/users/unfollow` Request body: {'user_id': @user_id@} """ followed_user_id = self.request.validated['user_id'] follower_user_id = self.request.authenticated_userid follower_relation = get_follower_relation( followed_user_id, follower_user_id) if follower_relation: DBSession.delete(follower_relation) else: log.warn( 'tried to delete not existing follower relation ' '({0}, {1})'.format(followed_user_id, follower_user_id)) return {}
def post(self): """ Unfollow the given user. Request: `POST` `/users/unfollow` Request body: {'user_id': @user_id@} """ followed_user_id = self.request.validated['user_id'] follower_user_id = self.request.authenticated_userid follower_relation = get_follower_relation(followed_user_id, follower_user_id) if follower_relation: DBSession.delete(follower_relation) else: log.warning('tried to delete not existing follower relation ' '({0}, {1})'.format(followed_user_id, follower_user_id)) return {}
def post(self): """ Follow the given user. Creates a follower relation, so that the authenticated user is following the given user. Request: `POST` `/users/follow` Request body: {'user_id': @user_id@} """ followed_user_id = self.request.validated['user_id'] follower_user_id = self.request.authenticated_userid follower_relation = get_follower_relation( followed_user_id, follower_user_id) if not follower_relation: DBSession.add(FollowedUser( followed_user_id=followed_user_id, follower_user_id=follower_user_id)) return {}
def post(self): """ Follow the given user. Creates a follower relation, so that the authenticated user is following the given user. Request: `POST` `/users/follow` Request body: {'user_id': @user_id@} """ followed_user_id = self.request.validated['user_id'] follower_user_id = self.request.authenticated_userid follower_relation = get_follower_relation(followed_user_id, follower_user_id) if not follower_relation: DBSession.add( FollowedUser(followed_user_id=followed_user_id, follower_user_id=follower_user_id)) return {}
def get(self): """Get the mailinglists subscriptions of the authenticated user. Request: `GET` `/users/mailinglists` Example response: {'avalanche': False, 'lawinen': True, 'valanghe': False, ...} """ user_id = self.request.authenticated_userid res = DBSession.query(Mailinglist.listname). \ filter(Mailinglist.user_id == user_id).all() subscribed_mailinglists = [list[0] for list in res] return {ml: ml in subscribed_mailinglists for ml in valid_mailinglists}
def get(self): """Get the mailinglists subscriptions of the authenticated user. Request: `GET` `/users/mailinglists` Example response: {'avalanche': False, 'lawinen': True, 'valanghe': False, ...} """ user_id = self.request.authenticated_userid res = DBSession.query(Mailinglist.listname). \ filter(Mailinglist.user_id == user_id).all() subscribed_mailinglists = [l[0] for l in res] return {ml: ml in subscribed_mailinglists for ml in valid_mailinglists}
def _get_archive_document(self, document_id, lang, version_id, archive_clazz, archive_locale_clazz): version = DBSession.query(DocumentVersion) \ .options(joinedload( DocumentVersion.document_archive.of_type(archive_clazz))) \ .options(joinedload( DocumentVersion.document_locales_archive.of_type( archive_locale_clazz))) \ .options(joinedload(DocumentVersion.document_geometry_archive)) \ .filter(DocumentVersion.id == version_id) \ .filter(DocumentVersion.document_id == document_id) \ .filter(DocumentVersion.lang == lang) \ .first() archive_document = version.document_archive archive_document.geometry = version.document_geometry_archive archive_document.locales = [version.document_locales_archive] return archive_document
def post(self): """Update mailinglist subscription statuses. Request: `POST` `/users/mailinglists` {'avalanche': False, 'lawinen': True, 'valanghe': False} """ user_id = self.request.authenticated_userid user = DBSession.query(User).get(user_id) subscribed_lists = DBSession.query(Mailinglist). \ filter(Mailinglist.user_id == user_id).all() subscribed_lists = {list.listname: list for list in subscribed_lists} subscribed_listnames = set(subscribed_lists.keys()) lists_to_add = [] removed_lists = False data = self.request.validated['mailinglists'] for listname in data: subscribe_status = data.get(listname, False) if subscribe_status and listname not in subscribed_listnames: # Add list lists_to_add.append(Mailinglist( listname=listname, email=user.email, user_id=user_id, user=user )) elif not subscribe_status and listname in subscribed_listnames: # Remove list removed_lists = True DBSession.delete(subscribed_lists[listname]) if lists_to_add: DBSession.add_all(lists_to_add) if lists_to_add or removed_lists: DBSession.flush() return {}
def post(self): """Update mailinglist subscription statuses. Request: `POST` `/users/mailinglists` {'avalanche': False, 'lawinen': True, 'valanghe': False} """ user_id = self.request.authenticated_userid user = DBSession.query(User).get(user_id) subscribed_lists = DBSession.query(Mailinglist). \ filter(Mailinglist.user_id == user_id).all() subscribed_lists = {l.listname: l for l in subscribed_lists} subscribed_listnames = set(subscribed_lists.keys()) lists_to_add = [] removed_lists = False data = self.request.validated['mailinglists'] for listname in data: subscribe_status = data.get(listname, False) if subscribe_status and listname not in subscribed_listnames: # Add list lists_to_add.append(Mailinglist( listname=listname, email=user.email, user_id=user_id, user=user )) elif not subscribe_status and listname in subscribed_listnames: # Remove list removed_lists = True DBSession.delete(subscribed_lists[listname]) if lists_to_add: DBSession.add_all(lists_to_add) if lists_to_add or removed_lists: DBSession.flush() return {}
def post(self): user = self.get_user(with_area_locales=False) validated = self.request.validated user.feed_followed_only = validated["followed_only"] user.feed_filter_activities = validated["activities"] # update filter areas: get all areas given in the request and # then set on `user.feed_filter_areas` area_ids = [a["document_id"] for a in validated["areas"]] areas = [] if area_ids: areas = ( DBSession.query(Area) .filter(Area.document_id.in_(area_ids)) .options(load_only(Area.document_id, Area.version, Area.type)) .all() ) user.feed_filter_areas = areas return {}
def get_user(self): userid = self.request.authenticated_userid return DBSession.query(User).get(userid)
def post(self): request = self.request userid = request.authenticated_userid user = DBSession.query(User).get(userid) user.lang = request.validated['lang'] return {}
def post(self): user = self.get_user() request = self.request validated = request.validated result = {} # Before all, check whether the user knows the current password current_password = validated['currentpassword'] if not user.validate_password(current_password): request.errors.add('body', 'currentpassword', 'Invalid password') return sync_sso = False # update password if a new password is provided if 'newpassword' in validated: user.password = validated['newpassword'] # start email validation procedure if a new email is provided email_link = None if 'email' in validated and validated['email'] != user.email: user.email_to_validate = validated['email'] user.update_validation_nonce( Purpose.change_email, VALIDATION_EXPIRE_DAYS) email_service = get_email_service(self.request) nonce = user.validation_nonce settings = request.registry.settings link = settings['mail.validate_change_email_url_template'].format( '#', nonce) email_link = link result['email'] = validated['email'] result['sent_email'] = True sync_sso = True update_search_index = False if 'name' in validated: user.name = validated['name'] result['name'] = user.name update_search_index = True sync_sso = True if 'forum_username' in validated: user.forum_username = validated['forum_username'] result['forum_username'] = user.forum_username update_search_index = True sync_sso = True if 'is_profile_public' in validated: user.is_profile_public = validated['is_profile_public'] # Synchronize everything except the new email (still stored # in the email_to_validate attribute while validation is pending). if sync_sso: try: client = get_discourse_client(request.registry.settings) client.sync_sso(user) except: log.error('Error syncing with discourse', exc_info=True) raise HTTPInternalServerError('Error with Discourse') try: DBSession.flush() except: log.warning('Error persisting user', exc_info=True) raise HTTPInternalServerError('Error persisting user') if email_link: email_service.send_change_email_confirmation(user, link) if update_search_index: # when user name changes, the search index has to be updated notify_es_syncer(self.request.registry.queue_config) # also update the cache version of the user profile update_cache_version(user.profile) return result
def post(self): user = self.get_user() request = self.request validated = request.validated result = {} # Before all, check whether the user knows the current password current_password = validated['currentpassword'] if not user.validate_password(current_password): request.errors.add('body', 'currentpassword', 'Invalid password') return sync_sso = False # update password if a new password is provided if 'newpassword' in validated: user.password = validated['newpassword'] # start email validation procedure if a new email is provided email_link = None if 'email' in validated and validated['email'] != user.email: user.email_to_validate = validated['email'] user.update_validation_nonce(Purpose.change_email, VALIDATION_EXPIRE_DAYS) email_service = get_email_service(self.request) nonce = user.validation_nonce settings = request.registry.settings link = settings['mail.validate_change_email_url_template'].format( '#', nonce) email_link = link result['email'] = validated['email'] result['sent_email'] = True sync_sso = True update_search_index = False if 'name' in validated: user.name = validated['name'] result['name'] = user.name update_search_index = True sync_sso = True if 'forum_username' in validated: user.forum_username = validated['forum_username'] result['forum_username'] = user.forum_username update_search_index = True sync_sso = True if 'is_profile_public' in validated: user.is_profile_public = validated['is_profile_public'] # Synchronize everything except the new email (still stored # in the email_to_validate attribute while validation is pending). if sync_sso: try: client = get_discourse_client(request.registry.settings) client.sync_sso(user) except Exception: log.error('Error syncing with discourse', exc_info=True) raise HTTPInternalServerError('Error with Discourse') try: DBSession.flush() except Exception: log.warning('Error persisting user', exc_info=True) raise HTTPInternalServerError('Error persisting user') if email_link: email_service.send_change_email_confirmation(user, link) if update_search_index: # when user name changes, the search index has to be updated notify_es_syncer(self.request.registry.queue_config) # also update the cache version of the user profile update_cache_version(user.profile) return result