好烦啊-- :<
1.先定义modes:
superset\superset\models\user.py
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from flask_appbuilder.security.sqla.models import User
from sqlalchemy import String, Column, Boolean
from typing import Union
from superset import db
def id_or_slug_filter(models_name, id_or_slug):
if isinstance(id_or_slug, int):
return models_name.id == id_or_slug
if id_or_slug.isdigit():
return models_name.id == int(id_or_slug)
return models_name.slug == id_or_slug
class UserV2(User):
__tablename__ = "ab_user"
@classmethod
def get(cls, id_or_slug: Union[str, int]):
query = db.session.query(UserV2).filter(id_or_slug_filter(UserV2, id_or_slug))
return query.one_or_none()
@classmethod
def get_user_by_cn_name(cls, cn_name: Union[str]):
query = db.session.query(UserV2).filter(UserV2.username == cn_name)
return query.one_or_none()
@classmethod
def get_model_by_username(cls, username: Union[str]):
query = db.session.query(UserV2).filter(UserV2.username == username)
return query.one_or_none()
def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
def __repr__(self):
return self.username
2.新增注册接口接口
superset\superset\views\users\api.py
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from flask import g, Response, request
from flask_appbuilder.api import expose, safe, BaseApi
from flask_appbuilder.models.sqla.interface import SQLAInterface
from flask_appbuilder.security.sqla.models import User
from flask_jwt_extended.exceptions import NoAuthorizationError
from superset import appbuilder
from superset.models.user import UserV2
from superset.views.base_api import BaseSupersetApi
from superset.views.users.schemas import UserResponseSchema
from superset.views.utils import bootstrap_user_data
user_response_schema = UserResponseSchema()
class CurrentUserRestApi(BaseSupersetApi):
"""An API to get information about the current user"""
resource_name = "me"
openapi_spec_tag = "Current User"
openapi_spec_component_schemas = (UserResponseSchema,)
@expose("/", methods=("GET",))
@safe
def get_me(self) -> Response:
"""Get the user object corresponding to the agent making the request.
---
get:
summary: Get the user object
description: >-
Gets the user object corresponding to the agent making the request,
or returns a 401 error if the user is unauthenticated.
responses:
200:
description: The current user
content:
application/json:
schema:
type: object
properties:
result:
$ref: '#/components/schemas/UserResponseSchema'
401:
$ref: '#/components/responses/401'
"""
try:
if g.user is None or g.user.is_anonymous:
return self.response_401()
except NoAuthorizationError:
return self.response_401()
return self.response(200, result=user_response_schema.dump(g.user))
@expose("/roles/", methods=("GET",))
@safe
def get_my_roles(self) -> Response:
"""Get the user roles corresponding to the agent making the request.
---
get:
summary: Get the user roles
description: >-
Gets the user roles corresponding to the agent making the request,
or returns a 401 error if the user is unauthenticated.
responses:
200:
description: The current user
content:
application/json:
schema:
type: object
properties:
result:
$ref: '#/components/schemas/UserResponseSchema'
401:
$ref: '#/components/responses/401'
"""
try:
if g.user is None or g.user.is_anonymous:
return self.response_401()
except NoAuthorizationError:
return self.response_401()
user = bootstrap_user_data(g.user, include_perms=True)
return self.response(200, result=user)
class UserRestApi(BaseApi):
"""
继承Flask-appbuilder原生用户视图类, 扩展用户操作的接口类
"""
route_base = "/api/v1/users"
datamodel = SQLAInterface(UserV2)
include_route_methods = {
"register"
}
@expose("/register/", methods=("POST",))
@safe
def register(self) -> Response:
"""Get the user roles corresponding to the agent making the request.
---
get:
summary: Get the user roles
description: >-
Gets the user roles corresponding to the agent making the request,
or returns a 401 error if the user is unauthenticated.
responses:
200:
description: The current user
content:
application/json:
schema:
type: object
properties:
result:
$ref: '#/components/schemas/UserResponseSchema'
401:
$ref: '#/components/responses/401'
"""
try:
data = request.get_json()
username = data.get("username")
user_models = UserV2.get_model_by_username(username)
if username and not user_models:
result = appbuilder.sm.add_user(
username,
data.get("first_name"),
data.get("last_name"),
data.get("email"),
appbuilder.sm.find_role(data.get("role")),
data.get("password"),
)
if result:
return self.response(200, result={
"status": "Success",
"message": "ok",
})
else:
return self.response_401()
else:
return self.response_401()
except NoAuthorizationError:
return self.response_401()
3. 增加api导入
superset\superset\initialization_init_.py
...
from superset.views.users.api import UserRestApi
...
appbuilder.add_api(UserRestApi)
4. postman 测试:
参数:
{
"username": "1213",
"first_name": "122",
"last_name":"last_name",
"email":"email@qq.com",
"role":"admin",
"password":"sasadasd121324rd"
}