diff --git a/accountant/views/accounts.py b/accountant/views/accounts.py index 3a8211e..0f17e4b 100644 --- a/accountant/views/accounts.py +++ b/accountant/views/accounts.py @@ -140,13 +140,14 @@ range_parser.add_argument( 401: 'Unauthorized' }) class AccountListResource(Resource): + """Resource used to handle account lists.""" + @requires_auth @ns.response(200, 'OK', [account_model]) @marshal_with_field(fields.List(Object(account_model))) def get(self): - """ - Returns accounts with their balances. - """ + """ Returns accounts with their balances.""" + return Account.query().all(), 200 @requires_auth @@ -155,9 +156,8 @@ class AccountListResource(Resource): @ns.response(406, 'Invalid account data') @marshal_with_field(Object(account_model)) def post(self): - """ - Create a new account. - """ + """Create a new account.""" + data = ns.apis[0].payload # A new account MUST NOT have an id; @@ -191,13 +191,14 @@ class AccountListResource(Resource): 404: 'Account not found' }) class AccountResource(Resource): + """Resource to handle accounts.""" + @requires_auth @ns.response(200, 'OK', account_model) @marshal_with_field(Object(account_model)) def get(self, id): - """ - Get an account. - """ + """Get an account.""" + account = Account.query().get(id) if not account: @@ -216,9 +217,8 @@ class AccountResource(Resource): @ns.response(406, 'Invalid account data') @marshal_with_field(Object(account_model)) def post(self, id): - """ - Update an account. - """ + """Update an account.""" + data = ns.apis[0].payload # Check ID consistency. @@ -250,9 +250,7 @@ class AccountResource(Resource): @ns.response(204, 'Account deleted', account_model) @marshal_with_field(Object(account_model)) def delete(self, id): - """ - Delete an account. - """ + """Delete an account.""" # Need to get the object to update it. account = Account.query().get(id) @@ -270,6 +268,8 @@ class AccountResource(Resource): @ns.route('//solds') class SoldsResource(Resource): + """Resource to expose solds.""" + @requires_auth @ns.doc( security='apikey', @@ -280,9 +280,8 @@ class SoldsResource(Resource): }) @marshal_with_field(Object(solds_model)) def get(self, id): - """ - Get solds for a specific account and date range. - """ + """Get solds for a specific account and date range.""" + account = Account.query().get(id) if not account: @@ -298,6 +297,8 @@ class SoldsResource(Resource): @ns.route('//balance') class BalanceResource(Resource): + """Resource to expose balances.""" + @requires_auth @ns.doc( security='apikey', @@ -309,9 +310,8 @@ class BalanceResource(Resource): @ns.expect(range_parser) @marshal_with_field(Object(balance_model)) def get(self, id): - """ - Get account balance for a specific date range. - """ + """Get account balance for a specific date range.""" + account = Account.query().get(id) if not account: @@ -329,6 +329,8 @@ class BalanceResource(Resource): @ns.route("//category") class CategoryResource(Resource): + """Resource to expose categories.""" + @requires_auth @ns.doc( security='apikey', @@ -340,9 +342,8 @@ class CategoryResource(Resource): @ns.expect(range_parser) @marshal_with_field(fields.List(Object(category_model))) def get(self, id): - """ - Get account category balances for a specific date range. - """ + """Get account category balances for a specific date range.""" + data = range_parser.parse_args() return Operation.get_categories_for_range(id, **data).all() @@ -350,6 +351,8 @@ class CategoryResource(Resource): @ns.route('//ohlc') class OHLCResource(Resource): + """Resource to expose OHLC.""" + @requires_auth @ns.doc( security='apikey', @@ -361,9 +364,8 @@ class OHLCResource(Resource): @ns.expect(range_parser) @marshal_with_field(fields.List(Object(ohlc_model))) def get(self, id): - """ - Get OHLC data for a specific date range and account. - """ + """Get OHLC data for a specific date range and account.""" + data = range_parser.parse_args() return Operation.get_ohlc_per_day_for_range(id, **data).all() diff --git a/accountant/views/operations.py b/accountant/views/operations.py index cfa4820..42ad4b4 100644 --- a/accountant/views/operations.py +++ b/accountant/views/operations.py @@ -110,14 +110,15 @@ account_range_parser.add_argument( 401: 'Unauthorized' }) class OperationListResource(Resource): + """Resource to handle operation lists.""" + @requires_auth @ns.response(200, 'OK', [operation_with_sold_model]) @ns.expect(parser=account_range_parser) @marshal_with_field(fields.List(Object(operation_with_sold_model))) def get(self): - """ - Get operations with solds for a specific account. - """ + """Get operations with solds for a specific account.""" + data = account_range_parser.parse_args() return Operation.query( @@ -133,9 +134,8 @@ class OperationListResource(Resource): @ns.response(406, 'Invalid operation data') @marshal_with_field(Object(operation_model)) def post(self): - """ - Create a new operation. - """ + """Create a new operation.""" + data = ns.apis[0].payload account_id = data['account_id'] @@ -172,13 +172,14 @@ class OperationListResource(Resource): 404: 'Operation not found' }) class OperationResource(Resource): + """Resource to handle operations.""" + @requires_auth @ns.response(200, 'OK', operation_model) @marshal_with_field(Object(operation_model)) def get(self, id): - """ - Get operation. - """ + """Get operation.""" + operation = db.session.query(Operation).get(id) if not operation: @@ -195,6 +196,8 @@ class OperationResource(Resource): @ns.response(406, 'Invalid operation data') @marshal_with_field(Object(operation_model)) def post(self, id): + """Update an operation.""" + data = ns.apis[0].payload # Check ID consistency. @@ -226,6 +229,8 @@ class OperationResource(Resource): @ns.response(204, 'Operation deleted', operation_model) @marshal_with_field(Object(operation_model)) def delete(self, id): + """Delete an operation.""" + operation = db.session.query(Operation).get(id) if not operation: diff --git a/accountant/views/scheduled_operations.py b/accountant/views/scheduled_operations.py index 0eb83b9..e104815 100644 --- a/accountant/views/scheduled_operations.py +++ b/accountant/views/scheduled_operations.py @@ -87,14 +87,15 @@ account_id_parser.add_argument( 401: 'Unauthorized', }) class ScheduledOperationListResource(Resource): + """Resource to handle scheduled operation lists.""" + @requires_auth @ns.expect(account_id_parser) @ns.response(200, 'OK', [scheduled_operation_model]) @marshal_with_field(fields.List(Object(scheduled_operation_model))) def get(self): - """ - Get all scheduled operation for an account. - """ + """Get all scheduled operation for an account.""" + data = account_id_parser.parse_args() return ScheduledOperation.query().filter_by(**data).all(), 200 @@ -106,9 +107,8 @@ class ScheduledOperationListResource(Resource): @ns.response(406, 'Invalid operation data') @marshal_with_field(Object(scheduled_operation_model)) def post(self): - """ - Add a new scheduled operation. - """ + """Add a new scheduled operation.""" + data = ns.apis[0].payload account_id = data['account_id'] @@ -149,13 +149,14 @@ class ScheduledOperationListResource(Resource): 404: 'Scheduled operation not found' }) class ScheduledOperationResource(Resource): + """Resource to handle scheduled operations.""" + @requires_auth @ns.response(200, 'OK', scheduled_operation_model) @marshal_with_field(Object(scheduled_operation_model)) def get(self, id): - """ - Get scheduled operation. - """ + """Get scheduled operation.""" + scheduled_operation = ScheduledOperation.query().get(id) if not scheduled_operation: @@ -172,9 +173,8 @@ class ScheduledOperationResource(Resource): @ns.expect(scheduled_operation_model) @marshal_with_field(Object(scheduled_operation_model)) def post(self, id): - """ - Update a scheduled operation. - """ + """Update a scheduled operation.""" + data = ns.apis[0].payload # Check ID consistency. @@ -211,9 +211,8 @@ class ScheduledOperationResource(Resource): @ns.response(409, 'Cannot be deleted') @marshal_with_field(Object(scheduled_operation_model)) def delete(self, id): - """ - Delete a scheduled operation. - """ + """Delete a scheduled operation.""" + scheduled_operation = ScheduledOperation.query().get(id) if not scheduled_operation: diff --git a/accountant/views/users.py b/accountant/views/users.py index 4961fed..3b5ca2d 100644 --- a/accountant/views/users.py +++ b/accountant/views/users.py @@ -28,17 +28,26 @@ from ..models.users import User def load_user_from_token(token): + """Load user from token.""" + return User.verify_auth_token(token) def load_user_from_auth(auth): + """Load a user from authenticated session.""" + token = auth.replace('Bearer ', '', 1) return load_user_from_token(token) def requires_auth(f): @wraps(f) + """Decorator to check user authentication before handling a request.""" + def wrapped(*args, **data): + """Check user authentication from requests headers and return 401 if + unauthorized.""" + user = None if 'Authorization' in request.headers: @@ -107,6 +116,8 @@ login_model = ns.model('Login', { @ns.route('/login') class LoginResource(Resource): + """Resource to handle login operations.""" + @ns.marshal_with(token_model) @ns.doc( responses={ @@ -115,9 +126,8 @@ class LoginResource(Resource): }) @ns.expect(login_model) def post(self): - """ - Login to retrieve authentication token. - """ + """Login to retrieve authentication token.""" + data = ns.apis[0].payload user = User.query().filter( @@ -146,7 +156,6 @@ class LoginResource(Resource): }) @marshal_with_field(Object(user_model)) def get(self): - """ - Get authenticated user information. - """ + """Get authenticated user information.""" + return g.user, 200