Ejemplo n.º 1
0
    def post(self):
        """
        @api {POST} /api/v1/auth/register Register
        @apiVersion 0.0.1
        @apiName Register
        @apiGroup Authentication
        @apiDescription Register a user, generate their token and add them to the database

        @apiHeader {String} Content-Type="application/json" Content-Type (should be application/json for every post requests)

        @apiParam {String} email Email of the user
        @apiParam {String} password Password of the user

        @apiSuccess (Success) {String} auth_token Auth token to be used for requesting
        @apiSuccess (Success) {String} message Message
        @apiSuccess (Success) {String} status Status
        @apiSuccess (Success) {String} email Email of the user

        @apiSampleRequest /api/v1/auth/register

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -X POST -d '{"email": "*****@*****.**", "password": "******"}' http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/auth/register

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "auth_token": "some random sheet",
                "email": "*****@*****.**"
                "message": "Successfully registered",
                "status": "success"
            }
        """
        post_data = request.get_json()
        email = post_data.get('email')
        password = post_data.get('password')
        if re.match(r'[^@]+@[^@]+\.[^@]+',
                    email) and len(password) > 4 and not bool(
                        re.search(' +', password)):
            user = User.get_by_email(email)
            if not user:
                new_user = User.create(email, password)
                token = new_user.save()
                return response_auth('success', 'Successfully registered',
                                     email, token, 200)
            else:
                return response('failed',
                                'User already exists, please sign in', 400)
        return response(
            'failed',
            'Missing, wrong email format, or wrong password format (at least 5 characters and contain no spaces)',
            400)
Ejemplo n.º 2
0
def handle_400_errors(e):
    """
    Return a custom response for 400 errors.
    :param e:
    :return:
    """
    return response('failed', 'Bad Request', 400)
Ejemplo n.º 3
0
def handle_404_error(e):
    """
    Return a custom message for 404 errors.
    :param e:
    :return:
    """
    return response('failed', 'Account resource cannot be found', 404)
Ejemplo n.º 4
0
def route_not_found(e):
    """
    Return a custom 404 Http response message for missing or not found routes.
    :param e: Exception
    :return: Http Response
    """
    return response('failed', 'Endpoint not found', 404)
Ejemplo n.º 5
0
def internal_server_error(e):
    """
    Return a custom message for a 500 internal error
    :param e: Exception
    :return:
    """
    return response('failed', 'Internal server error', 500)
Ejemplo n.º 6
0
def method_not_found(e):
    """
    Custom response for methods not allowed for the requested URLs
    :param e: Exception
    :return:
    """
    return response('failed', 'The method is not allowed for the requested URL', 405)
Ejemplo n.º 7
0
    def post(self):
        """
        @api {POST} /api/v1/auth/login Login
        @apiVersion 0.0.1
        @apiName Login
        @apiGroup Authentication
        @apiDescription Login a user if the supplied credentials are correct.

        @apiHeader {String} Content-Type="application/json" Content-Type (should be application/json for every post requests)

        @apiParam {String} email Email of the user
        @apiParam {String} password Password of the user

        @apiSuccess (Success) {String} auth_token Auth token to be used for requesting
        @apiSuccess (Success) {String} message Message
        @apiSuccess (Success) {String} status Status
        @apiSuccess (Success) {String} email Email of the user

        @apiSampleRequest /api/v1/auth/login

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -X POST -d '{"email": "*****@*****.**", "password": "******"}' http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/auth/login

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "auth_token": "some random sheet",
                "email": "*****@*****.**",
                "message": "Successfully logged in",
                "status": "success"
            }
        """
        post_data = request.get_json()
        email = post_data.get('email')
        password = post_data.get('password')
        if re.match(r'[^@]+@[^@]+\.[^@]+',
                    email) and len(password) > 4 and not bool(
                        re.search(' +', password)):
            user = User.get_by_email(email)
            if user and bcrypt.check_password_hash(user.password, password):
                return response_auth('success', 'Successfully logged in',
                                     email, user.encode_auth_token(), 200)
            return response('failed',
                            'User does not exist or password is incorrect',
                            400)
        return response('failed', 'Missing or wrong email or password format',
                        400)
Ejemplo n.º 8
0
    def post(self):
        """
        @api {POST} /api/v1/auth/logout Logout
        @apiVersion 0.0.1
        @apiName Logout
        @apiGroup Authentication
        @apiDescription Logout a user and blacklist the auth token.

        @apiHeader {String} Authorization Users auth token

        @apiHeaderExample {json} Header-Example:
        {
            "Authorization": "Bearer auth_token_here"
        }

        @apiParam {Object} . Nothing is required here

        @apiSuccess (Success) {String} message Message
        @apiSuccess (Success) {String} status Status

        @apiSampleRequest /api/v1/auth/logout

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -H "Authorization": "Bearer auth_token_here" -X POST -d '{}' http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/auth/logout

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "message": "Successfully logged out",
                "status": "success"
            }
        """
        ctx = _request_ctx_stack.top
        auth_token = ctx.token
        token = BlacklistedToken.create(auth_token)
        token.blacklist()
        ctx.user = None
        ctx.token = None
        return response('success', 'Successfully logged out', 200)
Ejemplo n.º 9
0
    def post(self):
        """
        @api {POST} /api/v1/categories Create category for an account
        @apiVersion 0.0.1
        @apiName CreateCategory
        @apiGroup Categories
        @apiDescription Create a category for an account

        @apiHeader {String} Authorization Users auth token
        @apiHeader {String} Content-Type="application/json" Content-Type (should be application/json for every post requests)

        @apiHeaderExample {json} Header-Example:
        {
            "Authorization": "Bearer auth_token_here"
        }

        @apiParam {Number} acc_id Account ID
        @apiParam {String} name Category name
        @apiParam {String} type Category type
        @apiParam {Number=null} parent_id Parent category ID (omit if no parent)

        @apiParamExample {json} Request-Example:
        {
            "acc_id": 1,
            "name": "Cat",
            "type": "expense"
        }

        @apiParamExample {json} Request-Example with parent_id:
        {
            "acc_id": 1,
            "parent_id": 1,
            "name": "Dog meat",
            "type": "expense"
        }

        @apiSuccess (Success) {String} status Status
        @apiSuccess (Success) {String} message Message

        @apiSampleRequest /api/v1/transactions

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -H "Authorization": "Bearer auth_token_here" -X POST
            -d '{"acc_id": 1, "name": "Cat", "type": "expense"}'
            http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/categories

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "message": "Successfully created new category",
                "status": "success"
            }
        """
        ctx = _request_ctx_stack.top
        current_user = ctx.user
        request_body = request.get_json()
        acc_id, parent_id, name, type = get_dict_value_by_key(
            request_body, 'acc_id', 'parent_id', 'name', 'type')
        account = Account.get_by_id(acc_id, current_user.id)
        if account is None:
            return response('failed', 'This account belongs to another user',
                            401)
        new_category = Category.create(name, type.lower(), acc_id)
        if parent_id:
            parent_category = Category.get_by_id(parent_id)
            parent_category.children.append(new_category)
        try:
            new_category.save()
        except IntegrityError:
            return response('failed', 'Duplicate category name', 400)
        else:
            return response('success', 'Successfully created new category',
                            200)
Ejemplo n.º 10
0
    def get(self, acc_id):
        """
        @api {GET} /api/v1/categories/:id Get all categories of an account
        @apiVersion 0.0.1
        @apiName GetAllCategories
        @apiGroup Categories
        @apiDescription Get all categories of an account (default and user-created categories)

        @apiHeader {String} Authorization Users auth token
        @apiHeader {String} Content-Type="application/json" Content-Type (should be application/json for every post requests)

        @apiHeaderExample {json} Header-Example:
        {
            "Authorization": "Bearer auth_token_here"
        }

        @apiParam {Number} id Account ID
        @apiParam {String="expense","income"} [type] Category type

        @apiSuccess (Success) {Object[]} categories List of categories
        @apiSuccess (Success) {String} categories.id Category ID
        @apiSuccess (Success) {Number} categories.name Name
        @apiSuccess (Success) {String} categories.type Type
        @apiSuccess (Success) {Object[]} categories.subcategories Subcategories

        @apiSampleRequest /api/v1/categories

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -H "Authorization": "Bearer auth_token_here"
            http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/categories/13

        @apiExample cURL example with params
        $ curl -H "Content-Type: application/json" -H "Authorization": "Bearer auth_token_here"
            http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/categories/13?type=expense

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "categories": [
                    {
                        "id": 1,
                        "name": "Food & Beverage",
                        "subcategories": [
                            {
                                "id": 28,
                                "name": "Restaurants",
                                "subcategories": [],
                                "type": "expense"
                            },
                            {
                                "id": 29,
                                "name": "Café",
                                "subcategories": [],
                                "type": "expense"
                            }
                        ],
                        "type": "expense"
                    },
                    {
                        "id": 2,
                        "name": "Bill & Utilities",
                        "subcategories": [
                            {
                                "id": 30,
                                "name": "Phone",
                                "subcategories": [],
                                "type": "expense"
                            },
                            {
                                "id": 31,
                                "name": "Water",
                                "subcategories": [],
                                "type": "expense"
                            },
                            {
                                "id": 32,
                                "name": "Electricity",
                                "subcategories": [],
                                "type": "expense"
                            },
                            {
                                "id": 33,
                                "name": "Gas",
                                "subcategories": [],
                                "type": "expense"
                            },
                            {
                                "id": 34,
                                "name": "Television",
                                "subcategories": [],
                                "type": "expense"
                            },
                            {
                                "id": 35,
                                "name": "Internet",
                                "subcategories": [],
                                "type": "expense"
                            },
                            {
                                "id": 36,
                                "name": "Rental",
                                "subcategories": [],
                                "type": "expense"
                            }
                        ],
                        "type": "expense"
                    }
                ],
                "status": "success"
            }
        """
        ctx = _request_ctx_stack.top
        current_user = ctx.user
        account = Account.get_by_id(acc_id, current_user.id)
        if account is None:
            return response('failed', 'This account belongs to another user',
                            401)
        category_type = request.args.get('type')
        default_categories = Category.get_default_categories(category_type)
        account_categories = account.get_categories(category_type)
        all_categories = [*default_categories, *account_categories]
        return response_get_categories(all_categories, acc_id, 200)
Ejemplo n.º 11
0
    def post(self):
        """
        @api {POST} /api/v1/transactions Create transaction for an account
        @apiVersion 0.0.1
        @apiName CreateTransaction
        @apiGroup Transactions
        @apiDescription Create a transaction for an account

        @apiHeader {String} Authorization Users auth token
        @apiHeader {String} Content-Type="application/json" Content-Type (should be application/json for every post requests)

        @apiHeaderExample {json} Header-Example:
        {
            "Authorization": "Bearer auth_token_here"
        }

        @apiParam {Number} acc_id Account ID
        @apiParam {Number} cat_id Category ID
        @apiParam {String} created_at Create time
        @apiParam {String} note Note
        @apiParam {Number} amount Amount

        @apiParamExample {json} Request-Example:
        {
            "acc_id": 13,
            "cat_id": 20,
            "created_at": "2018-12-14T03:55",
            "note": "note",
            "amount": 60000000
        }

        @apiSuccess (Success) {String} created_at Date created
        @apiSuccess (Success) {Number} pre_bal Pre-transaction balance
        @apiSuccess (Success) {Number} post_bal Post-transaction balance
        @apiSuccess (Success) {String} category Category
        @apiSuccess (Success) {String} note Note
        @apiSuccess (Success) {Number} amount Amount
        @apiSuccess (Success) {String} status Status
        @apiSuccess (Success) {String="expense","income"} type Transaction type

        @apiSampleRequest /api/v1/transactions

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -H "Authorization": "Bearer auth_token_here" -X POST
            -d '{"acc_id": 13, "cat_id": 20, "note": "note", "amount": 60000000}'
            http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/transactions

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "amount": 60000000,
                "category": "Salary",
                "created_at": "2018-12-14T03:55:00",
                "note": "note",
                "pre_bal": 40000,
                "post_bal": 60040000,
                "status": "success",
                "type": "income"
            }
        """
        ctx = _request_ctx_stack.top
        current_user = ctx.user
        request_body = request.get_json()
        acc_id, cat_id, created_at, note, amount = get_dict_value_by_key(
            request_body, 'acc_id', 'cat_id', 'created_at', 'note', 'amount')
        try:
            account = Account.get_by_id(acc_id, current_user.id)
            if account is None:
                return response('failed',
                                'This account belongs to another user', 401)
            category = Category.get_by_id(cat_id)
            cur_bal = account.get_current_balance()
            post_bal = account.update_balance(category.type, amount)
        except ValueError:
            return response(
                'failed',
                'Failed to create transaction, please check your balance', 400)
        else:
            new_transaction = Transaction.create(
                account_id=acc_id,
                category_id=cat_id,
                created_at=created_at,
                transaction_type=category.type,
                note=note,
                amount=amount,
                pre_transaction_balance=cur_bal,
                post_transaction_balance=post_bal)
            new_transaction.save()
            return response_created_transaction(new_transaction, 200)
Ejemplo n.º 12
0
    def get(self, acc_id):
        """
        @api {GET} /api/v1/transactions/:id Get all transactions of an account
        @apiVersion 0.0.1
        @apiName GetAllTransactions
        @apiGroup Transactions
        @apiDescription Get all transactions of an account (10 transactions per page)

        @apiHeader {String} Authorization Users auth token
        @apiHeader {String} Content-Type="application/json" Content-Type (should be application/json for every post requests)

        @apiHeaderExample {json} Header-Example:
        {
            "Authorization": "Bearer auth_token_here"
        }

        @apiParam {Number} id Account ID

        @apiSuccess (Success) {Object[]} transactions List of transactions
        @apiSuccess (Success) {String} transactions.created_at Date created
        @apiSuccess (Success) {Number} transactions.amount Amount (in VND)
        @apiSuccess (Success) {String} transactions.category Category
        @apiSuccess (Success) {String} transactions.note Note
        @apiSuccess (Success) {Number} transactions.pre_bal Pre-transaction balance
        @apiSuccess (Success) {Number} transactions.post_bal Post-transaction balance
        @apiSuccess (Success) {String="expense","income"} transactions.type Transaction type
        @apiSuccess (Success) {String} next Next page
        @apiSuccess (Success) {String} previous Previous page
        @apiSuccess (Success) {String} status Status
        @apiSuccess (Success) {Number} total Total number of transactions

        @apiSampleRequest /api/v1/transactions

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -H "Authorization": "Bearer auth_token_here"
            http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/transactions/13

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "next": null,
                "previous": null,
                "status": "success",
                "total": 2,
                "transactions": [
                    {
                        "amount": 60000,
                        "category": "Bill & Utilities",
                        "created_at": "2018-12-12T17:38:47",
                        "note": "note",
                        "pre_bal": 100000,
                        "post_bal": 160000,
                        "type": "expense"
                    },
                    {
                        "amount": 60000000,
                        "category": "Salary",
                        "created_at": "2018-12-12T17:40:38",
                        "note": "note",
                        "pre_bal": 40000,
                        "post_bal": 60040000,
                        "type": "income"
                    }
                ]
            }
        """
        ctx = _request_ctx_stack.top
        current_user = ctx.user
        account = Account.get_by_id(acc_id, current_user.id)
        if account is None:
            return response('failed', 'This account belongs to another user',
                            401)
        page = request.args.get('page', 1, type=int)
        return response_paginate_transactions(account, page, 200)
Ejemplo n.º 13
0
    def post(self):
        """
        @api {POST} /api/v1/accounts Create account for an user
        @apiVersion 0.0.1
        @apiName CreateAccount
        @apiGroup Accounts
        @apiDescription Create an account for an authenticated user

        @apiHeader {String} Authorization Users auth token
        @apiHeader {String} Content-Type="application/json" Content-Type (should be application/json for every post requests)

        @apiHeaderExample {json} Header-Example:
        {
            "Authorization": "Bearer auth_token_here"
        }

        @apiParam {String} name Name of the account
        @apiParam {Number} ini_bal Initial balance
        @apiParam {String} type Account type [credit, cash]
        @apiParam {Number} limit Credit account limit (need to specify if the account type is credit, otherwise none required)

        @apiSuccess (Success) {Number} id Account ID
        @apiSuccess (Success) {String} created Date created
        @apiSuccess (Success) {Number} cur_bal Current balance
        @apiSuccess (Success) {Number} ini_bal Initial balance
        @apiSuccess (Success) {Number} limit Credit account limit (not available for cash account type)
        @apiSuccess (Success) {String} name Account name
        @apiSuccess (Success) {String} status Status
        @apiSuccess (Success) {String} type Account type

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -H "Authorization": "Bearer auth_token_here" -X POST
            -d '{"name": "tep_acc1", "ini_bal": 100000, "type": "credit", "limit": 10000}' http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/accounts

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "id": 1,
                "created": "2018-11-28T09:31:35",
                "cur_bal": 100000,
                "ini_bal": 100000,
                "limit": 10000,
                "name": "tep_acc1",
                "status": "success",
                "type": "credit"
            }
        """
        ctx = _request_ctx_stack.top
        current_user = ctx.user
        request_body = request.get_json()
        name = request_body.get('name')
        account_type = request_body.get('type')
        initial_balance = request_body.get('ini_bal')
        if name:
            try:
                acc_factory = AccountFactory()
                if account_type == 'credit':
                    limit = request_body.get('limit')
                    if limit is None:
                        return response(
                            'failed',
                            'Please specify a credit limit for a credit account',
                            400)
                    new_account = acc_factory.create_account(
                        name=name,
                        account_type=account_type,
                        user_id=current_user.id,
                        initial_balance=initial_balance,
                        limit=limit)
                else:
                    new_account = acc_factory.create_account(
                        name=name,
                        account_type=account_type,
                        user_id=current_user.id,
                        initial_balance=initial_balance)
                new_account.save()
            except IntegrityError:
                return response('failed', 'Duplicate account name', 400)
            else:
                return response_created_account(new_account, 200)
        return response('failed', 'Missing account name attribute', 400)
Ejemplo n.º 14
0
    def post(self):
        """
        @api {POST} /api/v1/accounts/saving Create a saving account for an user
        @apiVersion 0.0.1
        @apiName CreateSavingAccount
        @apiGroup Accounts
        @apiDescription Create a saving account for an authenticated user

        @apiHeader {String} Authorization Users auth token
        @apiHeader {String} Content-Type="application/json" Content-Type (should be application/json for every post requests)

        @apiHeaderExample {json} Header-Example:
        {
            "Authorization": "Bearer auth_token_here"
        }

        @apiParam {String} name Name of the account
        @apiParam {Number} acc_id Source account ID
        @apiParam {Number} ini_bal Initial balance
        @apiParam {Number} duration Saving duration (as months)
        @apiParam {Number} rate Saving monthly interest rate

        @apiParamExample {json} Request-Example:
        {
            "acc_id": 1,
            "name": "tep_sav1",
            "ini_bal": 1000000,
            "duration": 3,
            "rate": 0.1
        }

        @apiSuccess (Success) {Number} id Account ID
        @apiSuccess (Success) {String} created Date created
        @apiSuccess (Success) {Number} cur_bal Current balance
        @apiSuccess (Success) {Number} ini_bal Initial balance
        @apiSuccess (Success) {Number} duration Saving duration (as days)
        @apiSuccess (Success) {Number} rate Saving monthly interest rate
        @apiSuccess (Success) {String} name Saving account name
        @apiSuccess (Success) {Object} src_acc Source account informations
        @apiSuccess (Success) {Number} src_acc.id Account ID
        @apiSuccess (Success) {String} src_acc.created Date created
        @apiSuccess (Success) {Number} src_acc.cur_bal Current balance
        @apiSuccess (Success) {Number} src_acc.ini_bal Initial balance
        @apiSuccess (Success) {Number} src_acc.limit Credit account limit (not available for cash account type)
        @apiSuccess (Success) {String} src_acc.name Account name
        @apiSuccess (Success) {String} src_acc.type Account type

        @apiExample cURL example
        $ curl -H "Content-Type: application/json" -H "Authorization": "Bearer auth_token_here" -X POST
            -d '{"acc_id": 1, "name": "tep_sav1", "ini_bal": 1000000, "duration": 3, "rate": 0.1}'
            http://ec2-35-153-68-36.compute-1.amazonaws.com/api/v1/accounts/saving

        @apiSuccessExample {json} Success-Response:
            HTTP/1.0 200 OK
            {
                "created": "2018-12-20T14:07:46",
                "cur_bal": 1000000,
                "duration": 90,
                "id": 1,
                "ini_bal": 1000000,
                "name": "tep_sav1",
                "rate": 0.1,
                "src_acc": {
                    "created": "2018-12-13T03:09:48",
                    "cur_bal": 158400000,
                    "id": 1,
                    "ini_bal": 100000000,
                    "limit": null,
                    "name": "tepacc",
                    "type": "cash"
                }
            }
        """
        ctx = _request_ctx_stack.top
        current_user = ctx.user
        request_body = request.get_json()
        acc_id, name, ini_bal, duration, rate = get_dict_value_by_key(
            request_body, 'acc_id', 'name', 'ini_bal', 'duration', 'rate')
        account = Account.get_by_id(acc_id, current_user.id)
        if account is None:
            return response('failed', 'This account belongs to another user',
                            401)
        try:
            new_saving_account = SavingAccount.create(account_id=acc_id,
                                                      user_id=current_user.id,
                                                      name=name,
                                                      initial_balance=ini_bal,
                                                      duration=duration,
                                                      interest_rate=rate)
            new_saving_account.save()
            account.update_balance('expense', ini_bal)
        except IntegrityError:
            return response('failed', 'Duplicate account name', 400)
        except ValueError:
            return response('failed', 'Please check your balance', 400)
        else:
            return response_created_account(new_saving_account, 200)