Esempio n. 1
0
    def delete(self):
        """
        Delete a user.

        Example request::

            http -j DELETE :/api/users/1 Authorization:"Token ..."
            http -j :/api/users/1/delete Authorization:"Token ..."

        Example response::

            HTTP/1.1 204 No Content
        """
        # Initialize request variables
        request = self.request
        id = int(request.matchdict['id'])

        try:
            # Delete the user
            user = User.find(id)
            DBSession.delete(user)
        except NoResultFound:
            raise HTTPNotFound
        else:
            return Response(status='204 No Content',
                            content_type='application/json')
    def delete(self):
        """
        Delete a user.

        Example request::

            http -j DELETE :/api/users/1 Authorization:"Token ..."
            http -j :/api/users/1/delete Authorization:"Token ..."

        Example response::

            HTTP/1.1 204 No Content
        """
        # Initialize request variables
        request = self.request
        id = int(request.matchdict['id'])

        try:
            # Delete the user
            user = User.find(id)
            DBSession.delete(user)
        except NoResultFound:
            raise HTTPNotFound
        else:
            return Response(status='204 No Content',
                            content_type='application/json')
Esempio n. 3
0
    def forgot_password(self):
        """
        Send "forgot password" email for user.

        :returns: A JSON object containing:

            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/forgot_password [email protected]

        Example response::

            HTTP/1.1 200 OK
        """
        # Initialize request variables
        request = self.request
        params = self.validation_results or request.POST
        errors = self.validation_errors

        # Check and process form submission
        if errors:
            request.response.status = '422 Unprocessable Entity'
        else:
            try:
                user = User.by_email(params['email'])
                user.password_reset_token = generate_secret()
                user.password_reset_sent = datetime.utcnow()
            except:
                errors['_global'] = 'Invalid email address.'
                request.response.status = '422 Unprocessable Entity'
            else:
                # Prep email
                link = request.route_url('users',
                                         action='reset_password',
                                         _query=dict(
                                             email=user.email,
                                             token=user.password_reset_token))
                html = render('emails/forgot_password.jinja2', dict(link=link))
                text = html2text(html)

                # Send email
                mailer = get_mailer(request)
                message = Message(subject='Starter Password Reset',
                                  recipients=[user.email],
                                  sender='*****@*****.**',
                                  body=text,
                                  html=html)
                mailer.send(message)

        return dict(data=None, errors=errors)
    def forgot_password(self):
        """
        Send "forgot password" email for user.

        :returns: A JSON object containing:

            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/forgot_password [email protected]

        Example response::

            HTTP/1.1 200 OK
        """
        # Initialize request variables
        request = self.request
        params = self.validation_results or request.POST
        errors = self.validation_errors

        # Check and process form submission
        if errors:
            request.response.status = '422 Unprocessable Entity'
        else:
            try:
                user = User.by_email(params['email'])
                user.password_reset_token = generate_secret()
                user.password_reset_sent = datetime.utcnow()
            except:
                errors['_global'] = 'Invalid email address.'
                request.response.status = '422 Unprocessable Entity'
            else:
                # Prep email
                link = request.route_url(
                    'users',
                    action='reset_password',
                    _query=dict(email=user.email,
                                token=user.password_reset_token)
                )
                html = render('emails/forgot_password.jinja2', dict(link=link))
                text = html2text(html)

                # Send email
                mailer = get_mailer(request)
                message = Message(subject='Starter Password Reset',
                                  recipients=[user.email],
                                  sender='*****@*****.**',
                                  body=text, html=html)
                mailer.send(message)

        return dict(data=None, errors=errors)
Esempio n. 5
0
    def read(self):
        """
        Read a user.

        :returns: A JSON object containing:

            :data: An object reflecting the requested user.

        Example request::

            http -j :/api/users/1 Authorization:"Token ..."

        Example response:

        .. code-block:: json

            {
                "data": {
                    "created": "2014-09-23T09:38:25.131009+00:00",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": "******",
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user",
                    "updated": "2014-09-23T09:38:25.130992+00:00"
                }
            }
        """
        # Initialize request variables
        request = self.request
        id = int(request.matchdict['id'])

        # Load the user
        try:
            user = User.find(id)
        except NoResultFound:
            raise HTTPNotFound

        return dict(data=user)
    def read(self):
        """
        Read a user.

        :returns: A JSON object containing:

            :data: An object reflecting the requested user.

        Example request::

            http -j :/api/users/1 Authorization:"Token ..."

        Example response:

        .. code-block:: json

            {
                "data": {
                    "created": "2014-09-23T09:38:25.131009+00:00",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": "******",
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user",
                    "updated": "2014-09-23T09:38:25.130992+00:00"
                }
            }
        """
        # Initialize request variables
        request = self.request
        id = int(request.matchdict['id'])

        # Load the user
        try:
            user = User.find(id)
        except NoResultFound:
            raise HTTPNotFound

        return dict(data=user)
Esempio n. 7
0
    def register(self):
        """
        Register a user.

        :returns: A JSON object containing:

            :data:    An object reflecting the registered user.
            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/register [email protected] password=secret confirm=secret profile:='{"first_name": "John", "last_name": "Smith"}'

        Example response:

        .. code-block:: json

            {
                "data": {
                    "api_token": "1a2b3c4d5e",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": "******",
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user"
                },
                "errors": {}
            }
        """
        # Initialize request variables
        request = self.request
        flash = request.session.flash
        params = self.validation_results or request.POST
        errors = self.validation_errors
        data = None

        # Check and process form submission
        if errors:
            request.response.status = '422 Unprocessable Entity'
        else:
            try:
                user = User(email=params['email'], password=params['password'])
                user.last_login = datetime.utcnow()
                user.profile = UserProfile(**params['profile'])

                DBSession.add(user)
                DBSession.flush()
            except Exception as exc:
                if 'unique' in str(exc).lower():
                    errors['email'] = 'Email address is already registered'
                    request.response.status = '422 Unprocessable Entity'
                else:
                    errors['_global'] = 'Unable to process register'
                    logger.error('Failed to register user: %s' % exc)
                    request.response.status = '500 Internal Server Error'
            else:
                data = dict(id=user.id,
                            email=user.email,
                            role=user.role,
                            last_login=user.last_login.isoformat(),
                            api_token=user.api_token)
                data['profile'] = dict(first_name=user.profile.first_name,
                                       last_name=user.profile.last_name)

        return dict(data=data, errors=errors)
Esempio n. 8
0
    def index(self):
        """
        List all users.

        :param int page: The page number to load (e.g. ``/api/users/?page=2``).

        :returns: A JSON object containing:

            :data: A list of ``User`` objects.
            :meta: Pagination information.

        Example request::

            http -j :/api/users/ Authorization:"Token ..."

        Example response:

        .. code-block:: json

            {
                "data": [
                    {
                        "created": "2014-09-19T12:34:07.937062+00:00",
                        "email": "*****@*****.**",
                        "id": 1,
                        "last_login": "******",
                        "profile": {
                            "first_name": "John",
                            "last_name": "Smith"
                        },
                        "role": "user",
                        "updated": "2014-09-19T12:47:08.303298+00:00"
                    },
                    {
                        "created": "2014-09-19T12:34:07.938278+00:00",
                        "email": "*****@*****.**",
                        "id": 2,
                        "last_login": null,
                        "profile": {
                            "first_name": "Jane",
                            "last_name": "Smith"
                        },
                        "role": "superuser",
                        "updated": "2014-09-19T12:34:07.938270+00:00"
                    }
                ],
                "meta": {
                    "item_count": 2,
                    "items_per_page": 100,
                    "page": 1,
                    "page_count": 1
                }
            }
        """
        # Initialize request variables
        request = self.request
        params = self.validation_results

        meta = {}

        # Initialize pager
        page = SqlalchemyOrmPage(User.query,
                                 page=params.get('page', 1),
                                 items_per_page=self.items_per_page,
                                 item_count=User.count())

        # Build "meta" object
        for key in ['page', 'page_count', 'item_count', 'items_per_page']:
            meta[key] = getattr(page, key)

        return dict(data=page.items, meta=meta)
Esempio n. 9
0
    def login(self):
        """
        Log in a user.

        :returns: A JSON object containing:

            :data:    An object reflecting the logged in user.
            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/login [email protected] password=user

        Example response:

        .. code-block:: json

            {
                "data": {
                    "api_token": "1a2b3c4d5e",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": "******",
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user"
                },
                "errors": {}
            }
        """
        # Initialize request variables
        request = self.request
        params = self.validation_results or request.POST
        errors = self.validation_errors
        data = None

        # Set up response variables
        email = params.get('email')
        password = params.get('password')

        # Check and process form submission
        if errors:
            request.response.status = '422 Unprocessable Entity'
        else:
            # If user validates, set header and redirect
            user = User.filter_by(email=email).first()

            if user and user.check_password(password):
                # Update last login timestamp
                user.last_login = datetime.utcnow()

                data = dict(id=user.id,
                            email=user.email,
                            role=user.role,
                            last_login=user.last_login.isoformat(),
                            api_token=user.api_token)
                data['profile'] = dict(first_name=user.profile.first_name,
                                       last_name=user.profile.last_name)

            # Otherwise, set error message
            else:
                request.response.status = '422 Unprocessable Entity'
                errors['_global'] = 'Invalid email or password.'

        return dict(data=data, errors=errors)
Esempio n. 10
0
    def update(self):
        """
        Update a user.

        :returns: A JSON object containing:

            :data:    An object reflecting the updated user.
            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/1 [email protected] password=secret profile:='{"first_name": "John", "last_name": "Smith"}' Authorization:"Token ..."

        Example response:

        .. code-block:: json

            {
                "data": {
                    "created": "2014-09-19T12:34:07.937062+00:00",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": "******",
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user",
                    "updated": "2014-09-24T11:47:00.648593+00:00"
                },
                "errors": {}
            }
        """
        # Initialize request variables
        request = self.request
        id = int(request.matchdict['id'])
        params = self.validation_results
        errors = self.validation_errors

        user = None

        # Load the user
        try:
            user = User.find(id)
        except NoResultFound:
            raise HTTPNotFound

        if errors:
            user = None
            request.response.status = '422 Unprocessable Entity'
        elif not params:
            # There doesn't seem to be any data posted
            raise HTTPBadRequest
        else:
            try:
                # Pop profile
                profile = params.pop('profile', {})

                # Update the user
                for key, value in params.items():
                    if value:
                        setattr(user, key, value)

                DBSession.flush()

                if profile:
                    # Update the profile
                    for key, value in profile.items():
                        if value:
                            setattr(user.profile, key, value)

                    DBSession.flush()
            except Exception as exc:
                # Prepare the "error" response
                user = None

                if 'unique' in str(exc).lower():
                    errors['email'] = 'Email address must be unique'
                    request.response.status = '422 Unprocessable Entity'
                else:
                    errors['_global'] = 'Unable to process update'
                    logger.error('Failed to update user: %s' % exc)
                    request.response.status = '500 Internal Server Error'

        return dict(data=user, errors=errors)
Esempio n. 11
0
    def create(self):
        """
        Create a user.

        :returns: A JSON object containing:

            :data:   An object reflecting the created user.
            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/ [email protected] password=secret profile:='{"first_name": "John", "last_name": "Smith"}' Authorization:"Token ..."

        Example response:

        .. code-block:: json

            {
                "errors": {},
                "data": {
                    "created": "2014-09-23T09:38:25.131009+00:00",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": null,
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user",
                    "updated": "2014-09-23T09:38:25.130992+00:00"
                }
            }
        """
        # Initialize request variables
        request = self.request
        params = self.validation_results
        errors = self.validation_errors

        user = None

        if errors:
            request.response.status = '422 Unprocessable Entity'
        else:
            try:
                user = User(params['email'],
                            params['password'],
                            role=params['role'])
                user.profile = UserProfile(**params['profile'])

                DBSession.add(user)
                DBSession.flush()
            except Exception as exc:
                # Prepare the "error" response
                user = None

                if 'unique' in str(exc).lower():
                    errors['email'] = 'Email address must be unique'
                    request.response.status = '422 Unprocessable Entity'
                else:
                    errors['_global'] = 'Unable to process create'
                    logger.error('Failed to create user: %s' % exc)
                    request.response.status = '500 Internal Server Error'
            else:
                request.response.status = '201 Created'

        return dict(data=user, errors=errors)
    def register(self):
        """
        Register a user.

        :returns: A JSON object containing:

            :data:    An object reflecting the registered user.
            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/register [email protected] password=secret confirm=secret profile:='{"first_name": "John", "last_name": "Smith"}'

        Example response:

        .. code-block:: json

            {
                "data": {
                    "api_token": "1a2b3c4d5e",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": "******",
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user"
                },
                "errors": {}
            }
        """
        # Initialize request variables
        request = self.request
        flash = request.session.flash
        params = self.validation_results or request.POST
        errors = self.validation_errors
        data = None

        # Check and process form submission
        if errors:
            request.response.status = '422 Unprocessable Entity'
        else:
            try:
                user = User(email=params['email'], password=params['password'])
                user.last_login = datetime.utcnow()
                user.profile = UserProfile(**params['profile'])

                DBSession.add(user)
                DBSession.flush()
            except Exception as exc:
                if 'unique' in str(exc).lower():
                    errors['email'] = 'Email address is already registered'
                    request.response.status = '422 Unprocessable Entity'
                else:
                    errors['_global'] = 'Unable to process register'
                    logger.error('Failed to register user: %s' % exc)
                    request.response.status = '500 Internal Server Error'
            else:
                data = dict(id=user.id, email=user.email, role=user.role,
                            last_login=user.last_login.isoformat(),
                            api_token=user.api_token)
                data['profile'] = dict(first_name=user.profile.first_name,
                                       last_name=user.profile.last_name)

        return dict(data=data, errors=errors)
    def index(self):
        """
        List all users.

        :param int page: The page number to load (e.g. ``/api/users/?page=2``).

        :returns: A JSON object containing:

            :data: A list of ``User`` objects.
            :meta: Pagination information.

        Example request::

            http -j :/api/users/ Authorization:"Token ..."

        Example response:

        .. code-block:: json

            {
                "data": [
                    {
                        "created": "2014-09-19T12:34:07.937062+00:00",
                        "email": "*****@*****.**",
                        "id": 1,
                        "last_login": "******",
                        "profile": {
                            "first_name": "John",
                            "last_name": "Smith"
                        },
                        "role": "user",
                        "updated": "2014-09-19T12:47:08.303298+00:00"
                    },
                    {
                        "created": "2014-09-19T12:34:07.938278+00:00",
                        "email": "*****@*****.**",
                        "id": 2,
                        "last_login": null,
                        "profile": {
                            "first_name": "Jane",
                            "last_name": "Smith"
                        },
                        "role": "superuser",
                        "updated": "2014-09-19T12:34:07.938270+00:00"
                    }
                ],
                "meta": {
                    "item_count": 2,
                    "items_per_page": 100,
                    "page": 1,
                    "page_count": 1
                }
            }
        """
        # Initialize request variables
        request = self.request
        params = self.validation_results

        meta = {}

        # Initialize pager
        page = SqlalchemyOrmPage(User.query,
                                 page=params.get('page', 1),
                                 items_per_page=self.items_per_page,
                                 item_count=User.count())

        # Build "meta" object
        for key in ['page', 'page_count', 'item_count', 'items_per_page']:
            meta[key] = getattr(page, key)

        return dict(data=page.items, meta=meta)
    def login(self):
        """
        Log in a user.

        :returns: A JSON object containing:

            :data:    An object reflecting the logged in user.
            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/login [email protected] password=user

        Example response:

        .. code-block:: json

            {
                "data": {
                    "api_token": "1a2b3c4d5e",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": "******",
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user"
                },
                "errors": {}
            }
        """
        # Initialize request variables
        request = self.request
        params = self.validation_results or request.POST
        errors = self.validation_errors
        data = None

        # Set up response variables
        email = params.get('email')
        password = params.get('password')

        # Check and process form submission
        if errors:
            request.response.status = '422 Unprocessable Entity'
        else:
            # If user validates, set header and redirect
            user = User.filter_by(email=email).first()

            if user and user.check_password(password):
                # Update last login timestamp
                user.last_login = datetime.utcnow()

                data = dict(id=user.id, email=user.email, role=user.role,
                            last_login=user.last_login.isoformat(),
                            api_token=user.api_token)
                data['profile'] = dict(first_name=user.profile.first_name,
                                       last_name=user.profile.last_name)

            # Otherwise, set error message
            else:
                request.response.status = '422 Unprocessable Entity'
                errors['_global'] = 'Invalid email or password.'

        return dict(data=data, errors=errors)
    def update(self):
        """
        Update a user.

        :returns: A JSON object containing:

            :data:    An object reflecting the updated user.
            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/1 [email protected] password=secret profile:='{"first_name": "John", "last_name": "Smith"}' Authorization:"Token ..."

        Example response:

        .. code-block:: json

            {
                "data": {
                    "created": "2014-09-19T12:34:07.937062+00:00",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": "******",
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user",
                    "updated": "2014-09-24T11:47:00.648593+00:00"
                },
                "errors": {}
            }
        """
        # Initialize request variables
        request = self.request
        id = int(request.matchdict['id'])
        params = self.validation_results
        errors = self.validation_errors

        user = None

        # Load the user
        try:
            user = User.find(id)
        except NoResultFound:
            raise HTTPNotFound

        if errors:
            user = None
            request.response.status = '422 Unprocessable Entity'
        elif not params:
            # There doesn't seem to be any data posted
            raise HTTPBadRequest
        else:
            try:
                # Pop profile
                profile = params.pop('profile', {})

                # Update the user
                for key, value in params.items():
                    if value:
                        setattr(user, key, value)

                DBSession.flush()

                if profile:
                    # Update the profile
                    for key, value in profile.items():
                        if value:
                            setattr(user.profile, key, value)

                    DBSession.flush()
            except Exception as exc:
                # Prepare the "error" response
                user = None

                if 'unique' in str(exc).lower():
                    errors['email'] = 'Email address must be unique'
                    request.response.status = '422 Unprocessable Entity'
                else:
                    errors['_global'] = 'Unable to process update'
                    logger.error('Failed to update user: %s' % exc)
                    request.response.status = '500 Internal Server Error'

        return dict(data=user, errors=errors)
    def create(self):
        """
        Create a user.

        :returns: A JSON object containing:

            :data:   An object reflecting the created user.
            :errors: ``null`` if no error was encountered, otherwise an object
                     containing the error message(s).

        Example request::

            http -j POST :/api/users/ [email protected] password=secret profile:='{"first_name": "John", "last_name": "Smith"}' Authorization:"Token ..."

        Example response:

        .. code-block:: json

            {
                "errors": {},
                "data": {
                    "created": "2014-09-23T09:38:25.131009+00:00",
                    "email": "*****@*****.**",
                    "id": 1,
                    "last_login": null,
                    "profile": {
                        "first_name": "John",
                        "last_name": "Smith"
                    },
                    "role": "user",
                    "updated": "2014-09-23T09:38:25.130992+00:00"
                }
            }
        """
        # Initialize request variables
        request = self.request
        params = self.validation_results
        errors = self.validation_errors

        user = None

        if errors:
            request.response.status = '422 Unprocessable Entity'
        else:
            try:
                user = User(params['email'], params['password'],
                            role=params['role'])
                user.profile = UserProfile(**params['profile'])

                DBSession.add(user)
                DBSession.flush()
            except Exception as exc:
                # Prepare the "error" response
                user = None

                if 'unique' in str(exc).lower():
                    errors['email'] = 'Email address must be unique'
                    request.response.status = '422 Unprocessable Entity'
                else:
                    errors['_global'] = 'Unable to process create'
                    logger.error('Failed to create user: %s' % exc)
                    request.response.status = '500 Internal Server Error'
            else:
                request.response.status = '201 Created'

        return dict(data=user, errors=errors)