- 新增图像生成接口,支持试用、积分和自定义API Key模式 - 实现生成图片结果异步上传至MinIO存储,带重试机制 - 优化积分预扣除和异常退还逻辑,保障用户积分准确 - 添加获取生成历史记录接口,支持时间范围和分页 - 提供本地字典配置接口,支持模型、比例、提示模板和尺寸 - 实现图片批量上传接口,支持S3兼容对象存储 feat(admin): 增加管理员角色管理与权限分配接口 - 实现角色列表查询、角色创建、更新及删除功能 - 增加权限列表查询接口 - 实现用户角色分配接口,便于统一管理用户权限 - 增加系统字典增删查改接口,支持分类过滤和排序 - 权限控制全面覆盖管理接口,保证安全访问 feat(auth): 完善用户登录注册及权限相关接口与页面 - 实现手机号验证码发送及校验功能,保障注册安全 - 支持手机号注册、登录及退出接口,集成日志记录 - 增加修改密码功能,验证原密码后更新 - 提供动态导航菜单接口,基于权限展示不同菜单 - 实现管理界面路由及日志、角色、字典管理页面访问权限控制 - 添加系统日志查询接口,支持关键词和等级筛选 feat(app): 初始化Flask应用并配置蓝图与数据库 - 创建应用程序工厂,加载配置,初始化数据库和Redis客户端 - 注册认证、API及管理员蓝图,整合路由 - 根路由渲染主页模板 - 应用上下文中自动创建数据库表,保证运行环境准备完毕 feat(database): 提供数据库创建与迁移支持脚本 - 新增数据库创建脚本,支持自动检测是否已存在 - 添加数据库表初始化脚本,支持创建和删除所有表 - 实现RBAC权限初始化,包含基础权限和角色创建 - 新增字段手动修复脚本,添加用户API Key和积分字段 - 强制迁移脚本支持清理连接和修复表结构,初始化默认数据及角色分配 feat(config): 新增系统配置参数 - 配置数据库、Redis、Session和MinIO相关参数 - 添加AI接口地址及试用Key配置 - 集成阿里云短信服务配置及开发模式相关参数 feat(extensions): 初始化数据库、Redis和MinIO客户端 - 创建全局SQLAlchemy数据库实例和Redis客户端 - 配置基于boto3的MinIO兼容S3客户端 chore(logs): 添加示例系统日志文件 - 记录用户请求、验证码发送成功与失败的日志信息
258 lines
9.4 KiB
Python
258 lines
9.4 KiB
Python
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
|
# may not use this file except in compliance with the License. A copy of
|
|
# the License is located at
|
|
#
|
|
# https://aws.amazon.com/apache2.0/
|
|
#
|
|
# or in the "license" file accompanying this file. This file 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.
|
|
|
|
import logging
|
|
|
|
from botocore import xform_name
|
|
|
|
from boto3.docs.docstring import ActionDocstring
|
|
from boto3.utils import inject_attribute
|
|
|
|
from .model import Action
|
|
from .params import create_request_parameters
|
|
from .response import RawHandler, ResourceHandler
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ServiceAction:
|
|
"""
|
|
A class representing a callable action on a resource, for example
|
|
``sqs.get_queue_by_name(...)`` or ``s3.Bucket('foo').delete()``.
|
|
The action may construct parameters from existing resource identifiers
|
|
and may return either a raw response or a new resource instance.
|
|
|
|
:type action_model: :py:class`~boto3.resources.model.Action`
|
|
:param action_model: The action model.
|
|
|
|
:type factory: ResourceFactory
|
|
:param factory: The factory that created the resource class to which
|
|
this action is attached.
|
|
|
|
:type service_context: :py:class:`~boto3.utils.ServiceContext`
|
|
:param service_context: Context about the AWS service
|
|
"""
|
|
|
|
def __init__(self, action_model, factory=None, service_context=None):
|
|
self._action_model = action_model
|
|
|
|
# In the simplest case we just return the response, but if a
|
|
# resource is defined, then we must create these before returning.
|
|
resource_response_model = action_model.resource
|
|
if resource_response_model:
|
|
self._response_handler = ResourceHandler(
|
|
search_path=resource_response_model.path,
|
|
factory=factory,
|
|
resource_model=resource_response_model,
|
|
service_context=service_context,
|
|
operation_name=action_model.request.operation,
|
|
)
|
|
else:
|
|
self._response_handler = RawHandler(action_model.path)
|
|
|
|
def __call__(self, parent, *args, **kwargs):
|
|
"""
|
|
Perform the action's request operation after building operation
|
|
parameters and build any defined resources from the response.
|
|
|
|
:type parent: :py:class:`~boto3.resources.base.ServiceResource`
|
|
:param parent: The resource instance to which this action is attached.
|
|
:rtype: dict or ServiceResource or list(ServiceResource)
|
|
:return: The response, either as a raw dict or resource instance(s).
|
|
"""
|
|
operation_name = xform_name(self._action_model.request.operation)
|
|
|
|
# First, build predefined params and then update with the
|
|
# user-supplied kwargs, which allows overriding the pre-built
|
|
# params if needed.
|
|
params = create_request_parameters(parent, self._action_model.request)
|
|
params.update(kwargs)
|
|
|
|
logger.debug(
|
|
'Calling %s:%s with %r',
|
|
parent.meta.service_name,
|
|
operation_name,
|
|
params,
|
|
)
|
|
|
|
response = getattr(parent.meta.client, operation_name)(*args, **params)
|
|
|
|
logger.debug('Response: %r', response)
|
|
|
|
return self._response_handler(parent, params, response)
|
|
|
|
|
|
class BatchAction(ServiceAction):
|
|
"""
|
|
An action which operates on a batch of items in a collection, typically
|
|
a single page of results from the collection's underlying service
|
|
operation call. For example, this allows you to delete up to 999
|
|
S3 objects in a single operation rather than calling ``.delete()`` on
|
|
each one individually.
|
|
|
|
:type action_model: :py:class`~boto3.resources.model.Action`
|
|
:param action_model: The action model.
|
|
|
|
:type factory: ResourceFactory
|
|
:param factory: The factory that created the resource class to which
|
|
this action is attached.
|
|
|
|
:type service_context: :py:class:`~boto3.utils.ServiceContext`
|
|
:param service_context: Context about the AWS service
|
|
"""
|
|
|
|
def __call__(self, parent, *args, **kwargs):
|
|
"""
|
|
Perform the batch action's operation on every page of results
|
|
from the collection.
|
|
|
|
:type parent:
|
|
:py:class:`~boto3.resources.collection.ResourceCollection`
|
|
:param parent: The collection iterator to which this action
|
|
is attached.
|
|
:rtype: list(dict)
|
|
:return: A list of low-level response dicts from each call.
|
|
"""
|
|
service_name = None
|
|
client = None
|
|
responses = []
|
|
operation_name = xform_name(self._action_model.request.operation)
|
|
|
|
# Unlike the simple action above, a batch action must operate
|
|
# on batches (or pages) of items. So we get each page, construct
|
|
# the necessary parameters and call the batch operation.
|
|
for page in parent.pages():
|
|
params = {}
|
|
for index, resource in enumerate(page):
|
|
# There is no public interface to get a service name
|
|
# or low-level client from a collection, so we get
|
|
# these from the first resource in the collection.
|
|
if service_name is None:
|
|
service_name = resource.meta.service_name
|
|
if client is None:
|
|
client = resource.meta.client
|
|
|
|
create_request_parameters(
|
|
resource,
|
|
self._action_model.request,
|
|
params=params,
|
|
index=index,
|
|
)
|
|
|
|
if not params:
|
|
# There are no items, no need to make a call.
|
|
break
|
|
|
|
params.update(kwargs)
|
|
|
|
logger.debug(
|
|
'Calling %s:%s with %r', service_name, operation_name, params
|
|
)
|
|
|
|
response = getattr(client, operation_name)(*args, **params)
|
|
|
|
logger.debug('Response: %r', response)
|
|
|
|
responses.append(self._response_handler(parent, params, response))
|
|
|
|
return responses
|
|
|
|
|
|
class WaiterAction:
|
|
"""
|
|
A class representing a callable waiter action on a resource, for example
|
|
``s3.Bucket('foo').wait_until_bucket_exists()``.
|
|
The waiter action may construct parameters from existing resource
|
|
identifiers.
|
|
|
|
:type waiter_model: :py:class`~boto3.resources.model.Waiter`
|
|
:param waiter_model: The action waiter.
|
|
:type waiter_resource_name: string
|
|
:param waiter_resource_name: The name of the waiter action for the
|
|
resource. It usually begins with a
|
|
``wait_until_``
|
|
"""
|
|
|
|
def __init__(self, waiter_model, waiter_resource_name):
|
|
self._waiter_model = waiter_model
|
|
self._waiter_resource_name = waiter_resource_name
|
|
|
|
def __call__(self, parent, *args, **kwargs):
|
|
"""
|
|
Perform the wait operation after building operation
|
|
parameters.
|
|
|
|
:type parent: :py:class:`~boto3.resources.base.ServiceResource`
|
|
:param parent: The resource instance to which this action is attached.
|
|
"""
|
|
client_waiter_name = xform_name(self._waiter_model.waiter_name)
|
|
|
|
# First, build predefined params and then update with the
|
|
# user-supplied kwargs, which allows overriding the pre-built
|
|
# params if needed.
|
|
params = create_request_parameters(parent, self._waiter_model)
|
|
params.update(kwargs)
|
|
|
|
logger.debug(
|
|
'Calling %s:%s with %r',
|
|
parent.meta.service_name,
|
|
self._waiter_resource_name,
|
|
params,
|
|
)
|
|
|
|
client = parent.meta.client
|
|
waiter = client.get_waiter(client_waiter_name)
|
|
response = waiter.wait(**params)
|
|
|
|
logger.debug('Response: %r', response)
|
|
|
|
|
|
class CustomModeledAction:
|
|
"""A custom, modeled action to inject into a resource."""
|
|
|
|
def __init__(self, action_name, action_model, function, event_emitter):
|
|
"""
|
|
:type action_name: str
|
|
:param action_name: The name of the action to inject, e.g.
|
|
'delete_tags'
|
|
|
|
:type action_model: dict
|
|
:param action_model: A JSON definition of the action, as if it were
|
|
part of the resource model.
|
|
|
|
:type function: function
|
|
:param function: The function to perform when the action is called.
|
|
The first argument should be 'self', which will be the resource
|
|
the function is to be called on.
|
|
|
|
:type event_emitter: :py:class:`botocore.hooks.BaseEventHooks`
|
|
:param event_emitter: The session event emitter.
|
|
"""
|
|
self.name = action_name
|
|
self.model = action_model
|
|
self.function = function
|
|
self.emitter = event_emitter
|
|
|
|
def inject(self, class_attributes, service_context, event_name, **kwargs):
|
|
resource_name = event_name.rsplit(".")[-1]
|
|
action = Action(self.name, self.model, {})
|
|
self.function.__name__ = self.name
|
|
self.function.__doc__ = ActionDocstring(
|
|
resource_name=resource_name,
|
|
event_emitter=self.emitter,
|
|
action_model=action,
|
|
service_model=service_context.service_model,
|
|
include_signature=False,
|
|
)
|
|
inject_attribute(class_attributes, self.name, self.function)
|