Beispiel #1
0
    def wrapper(*args, **kwargs):

        try:
            jwt_required(lambda: None)()
        except UserLoadError:
            raise InternalServerError('unable to load user')
        except UserClaimsVerificationError:
            raise Unauthorized('invalid or expired user info')
        except JWTExtendedException as ex:
            raise Unauthorized('authorization error: ' + str(ex))

        identity = get_jwt_identity()

        if identity['type'] == User.Normal:
            # fail if the user is still suspended
            if current_user.suspended():
                raise Unauthorized('user is suspended')

        if identity['type'] == User.Student:
            # make sure the read access is synced up
            current_user.check_read_access()

        # verify that the user has the correct permissions for this view
        if permissions and len(
                set(permissions).intersection(
                    current_user.permissions_list)) == 0:
            raise Unauthorized()

        return fn(*args, **kwargs)
Beispiel #2
0
class ProfileApi(BaseResource):
    """
    :URL: ``/api/auth/profile/``
    """
    endpoints = ['/profile/']
    method_decorators = {'get': [jwt_required()], 'put': [jwt_required()]}

    def get(self):
        """
        * Authorization header containing access token is required

        :status_code: 200
        :response:
            .. code-block:: python

                {
                    "user": UserObject
                }
        """
        return {"user": current_user.dict()}

    def put(self):
        """
        * Authorization header containing refresh token is required

        :status_code: 200
        :response:
            .. code-block:: python

                {
                    "message": "Profile successfully updated"
                    "user": UserObject
                }
        """
        data = request.get_json()
        fields = {
            "first_name": data.get('first_name'),
            "last_name": data.get('last_name'),
            "email": data.get('email'),
            "password": data.get('password'),
        }
        for field in fields:
            if data.get(field):
                setattr(current_user, field, data[field])

        db.session.commit()
        return {
            "message": "Profile successfully updated",
            'user': current_user.dict()
        }
Beispiel #3
0
def init_app(app):
    for version in routes.ROUTES:
        SWAGGER_URL = f'/{version}/api/docs'
        API_URL = f'/static/{version}/swagger.json'
        blueprint = Blueprint(version, __name__)
        module = 'project.server.controllers.%s.' % version

        swaggerui_blueprint = get_swaggerui_blueprint(
            SWAGGER_URL,
            API_URL,
            config={'app_name': "Sql Module"},
        )

        for route in routes.ROUTES[version]:
            endpoint = route.get('endpoint')
            function = route.get('function')
            method = route.get('method')
            rule = route.get('rule')
            opts = route.get('opts', {})
            auth_required = opts.get('auth_required', False)
            __import__(module + endpoint, fromlist=[''])
            view_function = restful.restful(**opts)(getattr(
                sys.modules[module + endpoint], function))
            if auth_required:
                view_function = jwt_required(
                    restful.restful(**opts)(getattr(
                        sys.modules[module + endpoint], function)))
            blueprint.add_url_rule(rule,
                                   endpoint=endpoint + ' ' + function,
                                   view_func=view_function,
                                   methods=[method],
                                   strict_slashes=False)
        app.register_blueprint(blueprint, url_prefix='/' + version)
        app.register_blueprint(swaggerui_blueprint, url_prefix=SWAGGER_URL)
Beispiel #4
0
    def protection_decorator(fn):
        @wraps(fn)
        def decorator(*args, **kwargs):

            # decode JWT-token
            identity = get_jwt_identity()
            claims = get_jwt_claims()

            # check that identity has access to endpoint
            g.type = claims["type"]
            log.debug(f"Endpoint accessed as {g.type}")
            if g.type not in types:
                log.warning(
                    f"Illegal attempt from {g.type} to access endpoint")
                raise Exception(f"{g.type}'s are not allowed!")

            # do some specific stuff per identity
            g.user = g.container = g.node = None
            if g.type == 'user':
                user = get_and_update_authenticatable_info(identity)
                g.user = user
                assert g.user.type == g.type
            elif g.type == 'node':
                node = get_and_update_authenticatable_info(identity)
                g.node = node
                assert g.node.type == g.type
            elif g.type == 'container':
                g.container = identity
            else:
                raise Exception(f"Unknown entity: {g.type}")

            return fn(*args, **kwargs)

        return jwt_required(decorator)
Beispiel #5
0
def doc_login_required(
        func: Callable[..., Callable[..., Any]]) -> Callable[..., Any]:
    """
    登录限制装饰器

    为API添加登录限制,同时添加OpenAPI注释,使用装饰器后
    只有带有合法jwt token的请求才能访问。

    用法:
    >>> class SampleView(MethodView):
            @doc_login_required
            def get(self):
                return {'code': 0}
    """
    # pylint: disable=W0212
    # 获取登录函数
    auth_required_func = jwt_required(func)

    # 封装函数
    @wraps(func)
    def wrapper(*args: Any, **kwargs: Any) -> Any:
        return auth_required_func(*args, **kwargs)

    # 增加验证
    wrapper = __set_apidoc(wrapper, func)  # type: ignore

    return wrapper
Beispiel #6
0
def doc_login_required(func: Callable) -> Callable:
    """
    登录限制装饰器

    为API添加登录限制,同时添加OpenAPI注释,使用装饰器后
    只有带有合法jwt token的请求才能访问。

    用法:
    >>> class SampleView(MethodView):
            @doc_login_required
            def get(self):
                return {'code': 0}
    """
    # pylint: disable=W0212
    # 获取登录函数
    auth_required_func = jwt_required(func)

    # 封装函数
    @wraps(func)
    def wrapper(*args: Any, **kwargs: Any) -> Any:
        return auth_required_func(*args, **kwargs)

    # 增加验证
    wrapper._apidoc = getattr(func, "_apidoc", {})
    wrapper._apidoc.setdefault("security", [{"api_key": []}])

    return wrapper
Beispiel #7
0
def jwt_logged_user(fct, is_anonymous=False):
    def decoredFuntion(*p, **pn):
        if fjwt.get_current_user().isAnonymous() != is_anonymous:
            raise NotFoundError
        return fct(*p, **pn)

    return fjwt.jwt_required(decoredFuntion)
Beispiel #8
0
class Users(Resource):
    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument('id',
                                 required=True,
                                 type=int,
                                 help="id can't be blank and it be a number")
        self.parser.add_argument(
            'limit',
            required=True,
            type=int,
            help="limit can't be blank and it be a number")
        self.parser.add_argument(
            'timeout',
            required=True,
            type=int,
            help="timeout can't be blank and it be a number")

    decorators = [jwt_required()]

    def get(self):
        args = self.parser.parse_args()
        get_f = GetFriends(timeout=float(args['timeout']))
        result = get_f.parse_friends(id_user=args['id'],
                                     limit=int(args['limit']))
        return result
Beispiel #9
0
    def protection_decorator(fn):
        @wraps(fn)
        def decorator(*args, **kwargs):

            # decode JWT-token
            identity = get_jwt_identity()
            claims = get_jwt_claims()

            roles = set(claims['roles'])
            type_set = set(types)
            intersection = type_set.intersection(roles)

            # log.debug(f'roles: {roles}')
            # log.debug(f'type_set: {type_set}')
            # log.debug(f'intersection: {intersection}')
            # log.debug(f'len(intersection): {len(intersection)}')

            # Root may do everything :-)
            is_root_or_for_everyone = ('root' in roles) or ('everyone'
                                                            in types)

            if len(intersection) == 0 and not is_root_or_for_everyone:
                abort(403)

            return fn(*args, **kwargs)

        return jwt_required(decorator)
Beispiel #10
0
def graphql_view():
    """
    Create a GraphQL interface with GraphiQL
    and protected through an access token.
    """
    view = GraphQLView.as_view("", schema=schema, graphiql=False)
    return jwt_required(view)
Beispiel #11
0
 def decorator(f):
     if Envs.DEBUG:
         @wraps(f)
         def wrapper(*args, **kwargs):
             return f(*args, **kwargs)
     else:
         wrapper = flask_jwt_extended.jwt_required(
             *jwt_args, **jwt_kwargs)(f)
     return wrapper
Beispiel #12
0
 def decor(*args, **kwargs):
     try:
         return jwt_required(func)(*args, **kwargs)
     except NoAuthorizationError:
         raise NotAuthorizedError
     except ExpiredSignatureError:
         raise TokenGoneOffError
     except InvalidTokenError:
         raise M4MInvalidTokenError
Beispiel #13
0
class UserList(Resource):
    """Creation and get_all

    ---
    get:
      tags:
        - api
      responses:
        200:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResult'
                  - type: object
                    properties:
                      results:
                        type: array
                        items:
                          $ref: '#/components/schemas/UserSchema'
    post:
      tags:
        - api
      requestBody:
        content:
          application/json:
            schema:
              UserSchema
      responses:
        201:
          content:
            application/json:
              schema:
                type: object
                properties:
                  msg:
                    type: string
                    example: user created
                  user: UserSchema
    """

    method_decorators = [jwt_required()]

    def get(self):
        schema = UserSchema(many=True)
        query = User.query
        return paginate(query, schema)

    def post(self):
        schema = UserSchema()
        user = schema.load(request.json)

        db.session.add(user)
        db.session.commit()

        return {"msg": "user created", "user": schema.dump(user)}, 201
def graphql():
    view = GraphQLView.as_view('graphql',
                               schema=auth_required_schema,
                               graphiql=True,
                               get_context=lambda: {
                                   'session': session,
                                   'request': request,
                                   'uid': get_jwt_identity()
                               })
    return jwt_required(view)
Beispiel #15
0
def authenticate(func: Callable) -> Callable:
    """
    Decorator to add jwt view authentication.
    Reference: https://github.com/tiangolo/full-stack-flask-couchdb/tree/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/api/api_v1.
    """

    func = api_doc(
        security=current_app.config.get("APISPEC_SECURITY_PARAMS", []))(
            jwt_required(func))
    return func
Beispiel #16
0
class ResetPassword(MethodView):

    decorators = [jwt_required()]

    @validate_input(PasswordSchema)
    def patch(self, data: PasswordSchema):

        user_services.reset_password(get_jwt_identity(), data.password)

        return {}, 204
Beispiel #17
0
def user_required(f):
    def __inner__(self, *args, **kwargs):
        identify = get_jwt_identity()
        user = models.User.find_by_username(identify)
        if user and user.role in ['admin', 'user']:
            return f(self, user, *args, **kwargs)
        return {
            'message': 'Not found',
        }, 404

    return jwt_required(__inner__)
    def wrapped(*args, **qwargs):

        try:
            return jwt_required(fn)(*args, **qwargs)
        except NoAuthorizationError:
            pass

        api_key = request.values.get('apiKey', '')

        if api_key != (settings.DEFAULT_API_KEY or API_KEI_TOKEN):
            raise AuthenticationError("Invalid api token")
        return fn(*args, ** qwargs)
Beispiel #19
0
class ChangePassword(MethodView):

    decorators = [jwt_required()]

    @validate_input(NewPasswordSchema)
    def patch(self, data: NewPasswordSchema):

        if user_services.change_password(get_jwt_identity(),
                                         password=data.password,
                                         new_password=data.new_passowrd):
            return {}, 204

        return {'error': 'invalid password'}, 400
Beispiel #20
0
        def wrapper(*args, **kwargs):
            nonlocal f

            # called in reverse order, self_only after auth steps
            if self_only:
                f = __self_only(f)

            f = __load_user_to_g(f)

            if auth_method is AuthType.JWT:
                f = jwt_required(f)
            elif auth_method is AuthType.Simple:
                f = httpauth.login_required(f)
            return f(*args, **kwargs)
Beispiel #21
0
class UserCurrent(MethodView):

    decorators = [jwt_required()]

    def get(self):

        user = user_services.get_by_id(get_jwt_identity())
        output_schema = filters.get_schema(query_string=request.args,
                                           schema_cls=UserOutputSchema)
        output_fields = filters.get_fields(request.args)

        response = output_schema.from_orm(user).dict(include=output_fields)

        return response, 200
Beispiel #22
0
class TokenRefresh(MethodView):

    decorators = [jwt.jwt_required(refresh=True)]

    def get(self):

        user_id = jwt.get_jwt_identity()
        user, token, refresh_token = auth_services.token_refresh(user_id)

        return {
            'user': UserOutputSchema.from_orm(user).dict(),
            'token': token,
            'refresh_token': refresh_token
        }, 200
Beispiel #23
0
def admin_required(view_function):
    @wraps(view_function)
    def wrapper(*args, **kwargs):
        current_user = get_current_user()

        if current_user.role == 'admin':
            authorized = True
        else:
            authorized = False

        if not authorized:
            raise PermissionDeniedException("Insufficient Privilege")

        return view_function(*args, **kwargs)

    return jwt_required(wrapper)
Beispiel #24
0
    def decoratoruserrole(apifunction):
        @wraps(apifunction)
        def wrapper(*args, **kwargs):
            jwt_data = _decode_jwt_from_request(request_type='access')

            if ACCESS[jwt_data["identity"][1]] >= ACCESS[urole]:
                isRoleAuthorized = True
            else:
                isRoleAuthorized = False

            if not isRoleAuthorized:
                raise NoAuthorizationError(
                    "You are not authorized user to access the API")

            return apifunction(*args, **kwargs)

        return jwt_required(wrapper)
Beispiel #25
0
class MediaStorage(MethodView):

    decorators = [jwt_required()]

    allowed_formats = ['jpg', 'png', 'mp4']

    def get(self):

        media_format = request.args.get('media_format')

        if not media_format or media_format not in self.allowed_formats:
            return {'media_format': ['Must be one of: jpg, mp4, png']}, 401

        file_key = f'{uuid.uuid4().hex}.{media_format}'

        url = storage.put_url(file_key=file_key)

        return {'media_url': url, 'media_name': file_key}, 200
Beispiel #26
0
def configure_graphql(app: Flask):
    from yaits_api.services.users import get_user_by_id

    class FlaskAuthorizationMiddleware(object):
        def resolve(self, next, root, info, **kwargs):
            identity = get_jwt_identity()
            user = get_user_by_id(identity['unique_id'])
            info.context.yaits_user = user
            return next(root, info, **kwargs)

    graphql_view = jwt_required(
        GraphQLView.as_view(
            'graphql',
            schema=schema,
            graphiql=True,
            middleware=[FlaskAuthorizationMiddleware()],
        ))

    app.add_url_rule('/graphql',
                     view_func=graphql_view,
                     methods=['POST', 'GET'])
Beispiel #27
0
def api_auth_required(f):
    auth_decorated = jwt_required(f)

    @wraps(f)
    def decorated():
        if request.method == "OPTIONS":
            return f()

        session_user = current_user._get_current_object()
        if isinstance(session_user, FreeUser):
            logging.debug(f"Authentication bypassed`")
            return f()

        if session_user.is_authenticated:
            logging.debug(
                f"@{session_user.username} authenticated via `session`")
            return f()

        logging.debug("JWT authentication pending")
        return auth_decorated()

    return decorated
Beispiel #28
0
class RefreshTokenApi(BaseResource):
    """
    :URL: ``/api/auth/refresh-token/``
    """
    endpoints = ['/refresh-token/']
    method_decorators = [jwt_required(refresh=True)]

    def post(self):
        """
        * Authorization header containing refresh token is required

        :status_code: 200
        :response:
            .. code-block:: json

                {
                    "access_token": "access_token"
                }
        """
        current_user = get_jwt_identity()
        access_token = create_access_token(identity=current_user)
        return {'access_token': access_token}
Beispiel #29
0
def create_app(configname='default_config', app_name=None, modules=None):
    print 'start server'

    app = Flask(__name__,
                static_folder='./static',
                template_folder='templates')
    print 'config name: ', configname
    app.config.from_pyfile(os.path.join('config', configname + '.py'))
    global server_app
    server_app = app
    configure_logging(app)
    configure_extensions(app)
    if not app.config['PRODUCTION']:
        authentication.register_authenticator(DummyAuthenticator())
    authentication.register_authenticator(GMIAuthenticator())
    authentication.register_authenticator(BoxAuthenticator())

    app.register_blueprint(api)
    app.register_blueprint(auth)

    graphql_sec_view = jwt_required(
        CustomGraphQLView.as_view('graphql', schema=schema, graphiql=False))
    app.add_url_rule('/graphql', view_func=graphql_sec_view)
    if not app.config['PRODUCTION']:
        graphql_view = CustomGraphQLView.as_view('graphql_insec',
                                                 schema=schema,
                                                 graphiql=True)
        app.add_url_rule('/graphql_insec', view_func=graphql_view)

    server_app = app
    signal.signal(signal.SIGINT, exit_handler)
    app.logger.info('Server Created')

    @app.teardown_appcontext
    def shutdown_session(exception=None):
        db.session.remove()

    return app
Beispiel #30
0
def _make_resource(func, api, method, requires_authentication=False):
    location = 'form' if method in ['put', 'post'] else 'args'
    compat = True if (func._methods is not None) else False
    parser = make_parser(func._spec, location=location, compat=compat)

    @api.expect(parser, validate=True, strict=True)
    def _method(self):
        req = parser.parse_args()
        output = func(**req)
        return jsonify(output)

    error_docs = func._spec['error_docs']
    security = 'bearer_token' if requires_authentication else None
    _method = api.doc(responses=error_docs, security=security)(_method)

    if requires_authentication:
        _method = jwt_required()(_method)

    _method.__doc__ = func._spec['docstring']

    Tranquilized = type('Tranquilized', (Resource, ), {method: _method})

    return Tranquilized