예제 #1
0
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))
예제 #2
0
    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 {}
예제 #3
0
    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 {}
예제 #4
0
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))
예제 #5
0
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))
예제 #6
0
    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
예제 #7
0
def _get_document(document_id):
    document = DBSession.query(Document).get(document_id)

    if not document:
        raise HTTPBadRequest('Unknown document {}'.format(document_id))

    return document
예제 #8
0
def _get_user(user_id):
    user = DBSession.query(User).get(user_id)

    if not user:
        raise HTTPBadRequest('Unknown user {}'.format(user_id))

    return user
예제 #9
0
    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)
예제 #10
0
    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 {}
예제 #11
0
    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 {}
예제 #12
0
    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 {}
예제 #13
0
    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 {}
예제 #14
0
    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}
예제 #15
0
    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}
예제 #16
0
    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
예제 #17
0
    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 {}
예제 #18
0
    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 {}
예제 #19
0
    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 {}
예제 #20
0
 def get_user(self):
     userid = self.request.authenticated_userid
     return DBSession.query(User).get(userid)
예제 #21
0
 def post(self):
     request = self.request
     userid = request.authenticated_userid
     user = DBSession.query(User).get(userid)
     user.lang = request.validated['lang']
     return {}
예제 #22
0
    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
예제 #23
0
 def get_user(self):
     userid = self.request.authenticated_userid
     return DBSession.query(User).get(userid)
예제 #24
0
 def post(self):
     request = self.request
     userid = request.authenticated_userid
     user = DBSession.query(User).get(userid)
     user.lang = request.validated['lang']
     return {}
예제 #25
0
    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