2018-05-07 11:57:53 +00:00
|
|
|
from flask_restful import Resource, abort
|
2018-10-31 20:43:27 +00:00
|
|
|
from flask import g, render_template, redirect
|
2018-05-08 14:45:09 +00:00
|
|
|
from marshmallow import Schema, fields
|
2018-05-07 11:57:53 +00:00
|
|
|
from webargs.flaskparser import use_args
|
2018-05-07 14:13:07 +00:00
|
|
|
from flasgger import swag_from
|
2018-10-10 18:54:38 +00:00
|
|
|
from app.api.blueprint import api
|
2018-10-06 11:38:27 +00:00
|
|
|
import app.accounts.api as accounts
|
2018-10-10 18:54:38 +00:00
|
|
|
from app.accounts.tasks import send_email_task
|
2018-10-06 12:07:40 +00:00
|
|
|
from app.api.auth_protection import ProtectedResource
|
2018-10-06 12:18:04 +00:00
|
|
|
from app.api.permission_protection import (requires_permission,
|
|
|
|
valid_permissions)
|
2018-11-03 14:54:13 +00:00
|
|
|
from app.api.schemas import BaseTimestampedResourceSchema
|
2018-10-31 20:43:27 +00:00
|
|
|
from flask import current_app as app
|
2018-05-06 19:42:21 +00:00
|
|
|
|
|
|
|
|
2018-11-03 14:54:13 +00:00
|
|
|
class UserSchema(BaseTimestampedResourceSchema):
|
2018-05-08 14:45:09 +00:00
|
|
|
username = fields.Str(required=True)
|
|
|
|
email = fields.Email(required=True)
|
|
|
|
password = fields.Str(required=True, load_only=True)
|
|
|
|
|
|
|
|
|
2018-09-22 17:01:50 +00:00
|
|
|
class RoleUpdateSchema(Schema):
|
|
|
|
role_id = fields.Integer(required=True, load_only=True, location='json')
|
|
|
|
|
|
|
|
|
2018-10-06 12:18:04 +00:00
|
|
|
def validate_role_permissions(permissions_list):
|
|
|
|
return set(permissions_list).issubset(valid_permissions)
|
|
|
|
|
|
|
|
|
2018-11-03 14:54:13 +00:00
|
|
|
class RoleSchema(BaseTimestampedResourceSchema):
|
2018-09-23 11:56:41 +00:00
|
|
|
id = fields.Integer(required=True, location='json')
|
2018-09-22 23:22:19 +00:00
|
|
|
display_name = fields.String(required=True, location='json')
|
|
|
|
permissions = fields.List(fields.String, required=True,
|
2018-10-06 12:18:04 +00:00
|
|
|
location='json', many=True,
|
|
|
|
validate=validate_role_permissions)
|
2018-09-22 23:22:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
class RoleCreationSchema(Schema):
|
|
|
|
display_name = fields.String(required=True, location='json')
|
|
|
|
permissions = fields.List(fields.String, required=True,
|
|
|
|
location='json', many=True)
|
|
|
|
|
|
|
|
|
2018-05-08 14:45:09 +00:00
|
|
|
class AccountResource(ProtectedResource):
|
2018-05-08 08:52:36 +00:00
|
|
|
@swag_from('swagger/get_account_spec.yaml')
|
|
|
|
def get(self, account_id):
|
|
|
|
if g.current_account.id == account_id:
|
2018-10-08 19:50:34 +00:00
|
|
|
return UserSchema().dump(g.current_account), 200
|
2018-05-08 08:52:36 +00:00
|
|
|
abort(403, message='You can only get your own account', status='error')
|
|
|
|
|
|
|
|
|
2018-09-22 23:22:19 +00:00
|
|
|
class RoleResource(ProtectedResource):
|
|
|
|
@swag_from('swagger/get_role_spec.yaml')
|
|
|
|
def get(self, role_id):
|
2018-10-08 19:50:34 +00:00
|
|
|
return RoleSchema().dump(
|
|
|
|
accounts.get_role(role_id)), 200
|
2018-09-22 23:22:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
class RolesResource(ProtectedResource):
|
2018-09-23 11:56:41 +00:00
|
|
|
@requires_permission('CREATE_ROLE', 'Role creation')
|
2018-10-08 19:50:34 +00:00
|
|
|
@use_args(RoleCreationSchema(), locations=('json',))
|
2018-09-22 23:22:19 +00:00
|
|
|
@swag_from('swagger/create_role_spec.yaml')
|
|
|
|
def post(self, args):
|
2018-10-24 20:20:50 +00:00
|
|
|
created_role = accounts.create_role(args['display_name'],
|
|
|
|
args['permissions'])
|
|
|
|
return RoleSchema().dump(created_role), 201
|
2018-09-22 23:22:19 +00:00
|
|
|
|
|
|
|
@swag_from('swagger/get_roles_spec.yaml')
|
|
|
|
def get(self):
|
2018-10-08 19:50:34 +00:00
|
|
|
return RoleSchema().dump(accounts.get_all_roles(), many=True), 200
|
2018-09-22 23:22:19 +00:00
|
|
|
|
|
|
|
|
2018-09-22 17:01:50 +00:00
|
|
|
class AccountRoleResource(ProtectedResource):
|
2018-10-08 19:50:34 +00:00
|
|
|
@use_args(RoleUpdateSchema(), locations=('json',))
|
2018-09-22 17:01:50 +00:00
|
|
|
@swag_from('swagger/update_account_role_spec.yaml')
|
|
|
|
def put(self, args, account_id):
|
|
|
|
if g.current_account.id == account_id:
|
|
|
|
abort(403, message='You may not change your own roles',
|
|
|
|
status='error')
|
2018-10-24 20:20:50 +00:00
|
|
|
updated_account = accounts.update_account_role(
|
|
|
|
account_id, args['role_id'])
|
|
|
|
return UserSchema().dump(updated_account), 200
|
2018-09-22 17:01:50 +00:00
|
|
|
|
|
|
|
|
2018-05-08 08:52:36 +00:00
|
|
|
class AccountListResource(Resource):
|
2018-10-08 19:50:34 +00:00
|
|
|
@use_args(UserSchema(), locations=('json',))
|
2018-05-07 14:13:07 +00:00
|
|
|
@swag_from('swagger/create_account_spec.yaml')
|
2018-05-07 11:57:53 +00:00
|
|
|
def post(self, args):
|
2018-05-06 19:42:21 +00:00
|
|
|
try:
|
2018-10-24 20:20:50 +00:00
|
|
|
created_account, emailtoken = accounts.create_account(
|
2018-05-06 19:42:21 +00:00
|
|
|
args['username'],
|
|
|
|
args['email'],
|
|
|
|
args['password'])
|
2018-10-10 18:54:38 +00:00
|
|
|
confirm_url = api.url_for(
|
|
|
|
AccountEmailTokenResource,
|
|
|
|
token=emailtoken, _external=True)
|
|
|
|
html = render_template(
|
|
|
|
'activate_mail.html',
|
|
|
|
confirm_url=confirm_url)
|
|
|
|
send_email_task.delay(
|
|
|
|
args['email'],
|
2018-10-31 22:25:54 +00:00
|
|
|
'ETF IoT Email confirmation',
|
2018-10-10 18:54:38 +00:00
|
|
|
html)
|
2018-10-24 20:20:50 +00:00
|
|
|
return UserSchema().dump(created_account), 201
|
2018-05-06 19:42:21 +00:00
|
|
|
except ValueError:
|
|
|
|
abort(422, message='Account already exists', status='error')
|
2018-10-10 18:54:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AccountEmailTokenResource(Resource):
|
|
|
|
def get(self, token):
|
2018-10-31 20:43:27 +00:00
|
|
|
success, email = accounts.confirm_email_token(token)
|
2018-10-10 18:54:38 +00:00
|
|
|
if success:
|
2018-10-31 22:25:54 +00:00
|
|
|
frontend_url = app.config['FRONTEND_URL']
|
2018-10-31 20:43:27 +00:00
|
|
|
html = render_template(
|
2018-10-31 22:25:54 +00:00
|
|
|
'welcome_to_iot.html',
|
|
|
|
frontend_url=frontend_url)
|
2018-10-31 20:43:27 +00:00
|
|
|
send_email_task.delay(
|
|
|
|
email,
|
2018-10-31 22:25:54 +00:00
|
|
|
'Welcome to ETF IoT!',
|
2018-10-31 20:43:27 +00:00
|
|
|
html)
|
2018-10-31 22:25:54 +00:00
|
|
|
return redirect(frontend_url)
|
2018-10-10 18:54:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AccountEmailTokenResendResource(Resource):
|
|
|
|
@use_args(UserSchema(), locations=('json',))
|
|
|
|
def post(self, args):
|
|
|
|
return '', 201
|