feat: harden loose-offline sync for user JWT, schema, and console ops
Enable Binding-scoped agent push/pull, empty-table schema ensure, SyncPage inspect/drop-table, default module import, and agent-bound publish docs from the 宇恒联调意见. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -99,11 +99,14 @@ func (l *AgentAdminLogic) Create(req *types.AgentCreateReq) (*types.AgentCreateR
|
||||
return nil, err
|
||||
}
|
||||
acc, secret, err := st.Create(l.ctx, authx.TenantID(l.ctx), authx.UserID(l.ctx), agentstore.CreateInput{
|
||||
Name: req.Name,
|
||||
Perms: perms,
|
||||
AppSlugs: req.AppSlugs,
|
||||
Status: agentstore.StatusActive,
|
||||
RoleID: roleID,
|
||||
Name: req.Name,
|
||||
Perms: perms,
|
||||
AppSlugs: req.AppSlugs,
|
||||
Status: agentstore.StatusActive,
|
||||
RoleID: roleID,
|
||||
ChannelID: req.ChannelID,
|
||||
OnlineDBID: req.OnlineDBID,
|
||||
DatabaseName: req.DatabaseName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -161,6 +164,15 @@ func (l *AgentAdminLogic) Update(agentID int64, req *types.AgentUpdateReq) (*age
|
||||
if req.AppSlugs != nil {
|
||||
in.AppSlugs = req.AppSlugs
|
||||
}
|
||||
if req.ChannelID != nil {
|
||||
in.ChannelID = req.ChannelID
|
||||
}
|
||||
if req.OnlineDBID != nil {
|
||||
in.OnlineDBID = req.OnlineDBID
|
||||
}
|
||||
if req.DatabaseName != nil {
|
||||
in.DatabaseName = req.DatabaseName
|
||||
}
|
||||
if req.RoleID != nil {
|
||||
roleID, perms, err := l.resolvePerms(*req.RoleID, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -68,17 +68,18 @@ func (l *PublishLogic) ListApps() (*types.AppListResp, error) {
|
||||
}
|
||||
st := it.Status
|
||||
out = append(out, types.AppListItem{
|
||||
AppID: it.AppID,
|
||||
Slug: it.Slug,
|
||||
Name: it.Name,
|
||||
Status: string(st),
|
||||
StatusLabel: meta.StatusLabelCN(st),
|
||||
Building: meta.IsBuilding(st),
|
||||
SchemaName: it.SchemaName,
|
||||
PageCount: it.PageCount,
|
||||
EntityCount: it.EntityCount,
|
||||
UpdatedAt: it.UpdatedAt.UTC().Format(time.RFC3339),
|
||||
CreatedAt: it.CreatedAt.UTC().Format(time.RFC3339),
|
||||
AppID: it.AppID,
|
||||
Slug: it.Slug,
|
||||
Name: it.Name,
|
||||
Status: string(st),
|
||||
StatusLabel: meta.StatusLabelCN(st),
|
||||
Building: meta.IsBuilding(st),
|
||||
SchemaName: it.SchemaName,
|
||||
DatabaseName: it.DatabaseName,
|
||||
PageCount: it.PageCount,
|
||||
EntityCount: it.EntityCount,
|
||||
UpdatedAt: it.UpdatedAt.UTC().Format(time.RFC3339),
|
||||
CreatedAt: it.CreatedAt.UTC().Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
return &types.AppListResp{Items: out, Scope: scope}, nil
|
||||
@@ -115,6 +116,7 @@ func (l *PublishLogic) SaveDraft(slug string, req *types.DraftReq) (*types.AppLi
|
||||
if bp.Storage.Engine == "" {
|
||||
bp.Storage.Engine = "postgres"
|
||||
}
|
||||
bp.EnsureDefaultImportExport()
|
||||
// 草稿允许尚未完全合法;尽量校验,失败则仍以宽松方式保存关键字段
|
||||
_ = bp.Validate(slug)
|
||||
|
||||
@@ -255,12 +257,27 @@ func (l *PublishLogic) Publish(slug string, req *types.PublishReq) (*types.Publi
|
||||
}
|
||||
}
|
||||
|
||||
bp.EnsureDefaultImportExport()
|
||||
if err := bp.Validate(slug); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
schemaName := bp.AssignSchemaName(tenantID)
|
||||
dbName := bp.AssignDatabaseName(tenantID)
|
||||
// Z8c:智能体若绑定了 database_name,新建模块优先落到该库(database_per_app)
|
||||
if authx.Role(l.ctx) == authx.RoleAgent && l.svcCtx.Agents != nil {
|
||||
if aid := authx.AgentID(l.ctx); aid > 0 {
|
||||
if acc, err := l.svcCtx.Agents.Get(l.ctx, tenantID, aid); err == nil && acc != nil {
|
||||
if dn := strings.TrimSpace(acc.DatabaseName); dn != "" {
|
||||
if !exists || existing.DatabaseName == "" {
|
||||
bp.Storage.Mode = "database_per_app"
|
||||
schemaName = bp.AssignSchemaName(tenantID)
|
||||
dbName = dn
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ddl, err := schema.BuildPostgresDDL(bp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user