add admin login and optimize the swagger definition

pull/21891/head
ytqh 1 year ago
parent bc039efdaf
commit db36e3edf9

@ -0,0 +1,8 @@
from flask import Blueprint
from libs.external_api import ExternalApi
bp = Blueprint("admin_api", __name__, url_prefix="/admin")
api = ExternalApi(bp)
from .auth import login

@ -0,0 +1,124 @@
from flask import Blueprint
from flask_restful import Api, Resource # type: ignore
from controllers.admin import api
class SendVerificationCodeApi(Resource):
def post(self):
"""Send verification code to admin's phone number.
---
tags:
- admin
summary: Send Verification Code
description: Sends a verification code to the provided admin phone number for authentication
parameters:
- in: body
name: body
required: true
schema:
type: object
required:
- phone
properties:
phone:
type: string
description: Admin's phone number
example: "13800138000"
responses:
200:
description: Code sent successfully
schema:
type: object
properties:
success:
type: boolean
message:
type: string
400:
description: Invalid phone number format
404:
description: Phone number not registered as admin
"""
pass
class LoginApi(Resource):
def post(self):
"""Admin login with phone number and verification code.
---
tags:
- admin
summary: Admin Login
description: Authenticates an admin using phone number and verification code
parameters:
- in: body
name: body
required: true
schema:
type: object
required:
- phone
- code
properties:
phone:
type: string
description: Admin's phone number
example: "13800138000"
code:
type: string
description: Verification code
example: "123456"
responses:
200:
description: Login successful
schema:
type: object
properties:
token:
type: string
description: JWT access token
user:
type: object
properties:
id:
type: string
phone:
type: string
name:
type: string
role:
type: string
enum: [admin, super_admin]
400:
description: Invalid or expired verification code
404:
description: Phone number not registered
"""
pass
class LogoutApi(Resource):
def post(self):
"""Admin logout.
---
tags:
- admin
summary: Admin Logout
description: Logs out the authenticated admin and invalidates the JWT token
security:
- JWT: []
responses:
200:
description: Logout successful
schema:
type: object
properties:
success:
type: boolean
401:
description: Missing or invalid token
"""
pass
# Register the resources
api.add_resource(SendVerificationCodeApi, '/auth/send-code')
api.add_resource(LoginApi, '/auth/login')
api.add_resource(LogoutApi, '/auth/logout')

@ -4,8 +4,6 @@ import flask_login # type: ignore
from flask import request from flask import request
from flask_restful import Resource, reqparse # type: ignore from flask_restful import Resource, reqparse # type: ignore
import services
from configs import dify_config
from constants.languages import languages from constants.languages import languages
from controllers.service_api import api from controllers.service_api import api
from controllers.service_api.auth.error import ( from controllers.service_api.auth.error import (
@ -21,10 +19,8 @@ from controllers.service_api.error import (
) )
from events.tenant_event import tenant_was_created from events.tenant_event import tenant_was_created
from libs.helper import email, extract_remote_ip from libs.helper import email, extract_remote_ip
from libs.password import valid_password
from models.account import Account from models.account import Account
from services.account_service import AccountService, RegisterService, TenantService from services.account_service import AccountService, TenantService
from services.billing_service import BillingService
from services.errors.account import AccountRegisterError from services.errors.account import AccountRegisterError
from services.errors.workspace import WorkSpaceNotAllowedCreateError from services.errors.workspace import WorkSpaceNotAllowedCreateError
from services.feature_service import FeatureService from services.feature_service import FeatureService
@ -34,11 +30,23 @@ class LogoutApi(Resource):
def get(self): def get(self):
"""Logout user. """Logout user.
--- ---
tags:
- user-end
summary: Logout User summary: Logout User
description: Logs out the authenticated user and invalidates the session. description: Logs out the authenticated user and invalidates the session
security:
- JWT: []
responses: responses:
200: 200:
description: Successfully logged out. description: Successfully logged out
schema:
type: object
properties:
result:
type: string
example: "success"
401:
description: Unauthorized, invalid or missing token
""" """
account = cast(Account, flask_login.current_user) account = cast(Account, flask_login.current_user)
if isinstance(account, flask_login.AnonymousUserMixin): if isinstance(account, flask_login.AnonymousUserMixin):
@ -52,26 +60,42 @@ class EmailCodeLoginSendEmailApi(Resource):
def post(self): def post(self):
"""Send email code for login. """Send email code for login.
--- ---
tags:
- user-end
summary: Email Code Login Email Sending summary: Email Code Login Email Sending
description: Sends an email with a verification code for login. description: Sends an email with a verification code for login
parameters: parameters:
- in: body - in: body
name: email name: body
required: true required: true
schema:
type: object
required:
- email
properties:
email:
type: string type: string
description: The user's email. description: The user's email
- in: body language:
name: language
required: false
type: string type: string
description: Preferred language for the email. description: Preferred language for the email
enum: ["en-US", "zh-Hans"]
responses: responses:
200: 200:
description: Successfully sent the email code along with token data. description: Successfully sent the email code
schema:
type: object
properties:
result:
type: string
example: "success"
data:
type: object
description: Token data
429: 429:
description: Too many requests, IP limit reached. description: Too many requests, IP limit reached
404: 404:
description: Account not found. description: Account not found
""" """
parser = reqparse.RequestParser() parser = reqparse.RequestParser()
parser.add_argument("email", type=email, required=True, location="json") parser.add_argument("email", type=email, required=True, location="json")
@ -106,29 +130,44 @@ class EmailCodeLoginApi(Resource):
def post(self): def post(self):
"""Login using email code. """Login using email code.
--- ---
tags:
- user-end
summary: Email Code Login summary: Email Code Login
description: Allows the user to login using a verification code and token sent via email. description: Allows the user to login using a verification code and token sent via email
parameters: parameters:
- in: body - in: body
name: email name: body
required: true required: true
schema:
type: object
required:
- email
- code
- token
properties:
email:
type: string type: string
description: The user's email. description: The user's email
- in: body code:
name: code
required: true
type: string type: string
description: The verification code sent to the email. description: The verification code sent to the email
- in: body token:
name: token
required: true
type: string type: string
description: The token associated with the email code login. description: The token associated with the email code login
responses: responses:
200: 200:
description: Successfully logged in, returns token pair data. description: Successfully logged in
schema:
type: object
properties:
result:
type: string
example: "success"
data:
type: object
description: Token pair data
400: 400:
description: Invalid token, email or code. description: Invalid token, email or code
""" """
parser = reqparse.RequestParser() parser = reqparse.RequestParser()
parser.add_argument("email", type=str, required=True, location="json") parser.add_argument("email", type=str, required=True, location="json")
@ -182,19 +221,38 @@ class RefreshTokenApi(Resource):
def post(self): def post(self):
"""Refresh authentication token. """Refresh authentication token.
--- ---
tags:
- user-end
summary: Refresh Token summary: Refresh Token
description: Refreshes an access token using a valid refresh token. description: Refreshes an access token using a valid refresh token
security:
- JWT: []
parameters: parameters:
- in: body - in: body
name: refresh_token name: body
required: true required: true
schema:
type: object
required:
- refresh_token
properties:
refresh_token:
type: string type: string
description: The refresh token provided in the request. description: The refresh token provided in the request
responses: responses:
200: 200:
description: Successfully refreshed token, returns new token pair. description: Successfully refreshed token
schema:
type: object
properties:
result:
type: string
example: "success"
data:
type: object
description: New token pair data
401: 401:
description: Failed to refresh the token due to invalid or expired refresh token. description: Unauthorized, invalid or missing token
""" """
parser = reqparse.RequestParser() parser = reqparse.RequestParser()
parser.add_argument("refresh_token", type=str, required=True, location="json") parser.add_argument("refresh_token", type=str, required=True, location="json")

@ -12,6 +12,7 @@ def init_app(app: DifyApp):
from controllers.inner_api import bp as inner_api_bp from controllers.inner_api import bp as inner_api_bp
from controllers.service_api import bp as service_api_bp from controllers.service_api import bp as service_api_bp
from controllers.web import bp as web_bp from controllers.web import bp as web_bp
from controllers.admin import bp as admin_bp
CORS( CORS(
service_api_bp, service_api_bp,
@ -46,3 +47,10 @@ def init_app(app: DifyApp):
app.register_blueprint(files_bp) app.register_blueprint(files_bp)
app.register_blueprint(inner_api_bp) app.register_blueprint(inner_api_bp)
CORS(
admin_bp,
resources={r"/*": {"origins": dify_config.CONSOLE_CORS_ALLOW_ORIGINS}},
supports_credentials=True,
)
app.register_blueprint(admin_bp)

@ -7,7 +7,15 @@ def init_app(app: DifyApp):
app.config['SWAGGER'] = { app.config['SWAGGER'] = {
'title': 'API Docs', 'title': 'API Docs',
'uiversion': 3 'uiversion': 3,
'securityDefinitions': {
'JWT': {
'type': 'apiKey',
'name': 'access-token', # name of the cookie
'in': 'header', # specify that auth is in cookie
'description': 'JWT Authorization cookie'
}
}
} }
Swagger(app) Swagger(app)

Loading…
Cancel
Save