Files
yunzerwebsiteallinone/go/controllers/app_password_store.go
T
2026-11-03 09:00:29 +08:00

244 lines
8.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package controllers
import (
"strconv"
"strings"
"server/middleware"
"server/models"
"server/pkg/identity"
"server/pkg/jwtutil"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
beego "github.com/beego/beego/v2/server/web"
)
// ==================== 移动端 PasswordStore ====================
//
// 移动端「账号管理」(密码库)接口。与 Web 端 /backend/passwordStore 同一套数据
// (yz_backend_password_store,一个平台下挂多个账号),按 JWT 中的 tid + user_id
// 隔离,小程序「账号管理」页面调用。
type AppPasswordStoreController struct {
beego.Controller
}
// 只放行移动端与租户端令牌:/api/** 仅被 uniapp 调用,平台令牌不该能打移动端接口。
func (c *AppPasswordStoreController) appPwdClaims() (*jwtutil.Claims, error) {
claims, err := identity.Claims(c.Ctx.Request.Header.Get("Authorization"), identity.EndApp, identity.EndBackend)
if err != nil {
return nil, err
}
if claims.UserID <= 0 || claims.TenantId <= 0 {
return nil, orm.ErrNoRows
}
return claims, nil
}
// GetList GET /api/passwordStore/list?keyword=
func (c *AppPasswordStoreController) GetList() {
cl, e := c.appPwdClaims()
if e != nil {
passwordReply(&c.Controller, 401, "未登录或无权限", nil)
return
}
qs := models.Orm.QueryTable(new(models.BackendPasswordStore)).
Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID)
if k := strings.TrimSpace(c.GetString("keyword")); k != "" {
cond := orm.NewCondition().
Or("platform__icontains", k).
Or("url__icontains", k).
Or("accounts__icontains", k).
Or("remark__icontains", k)
qs = qs.SetCond(orm.NewCondition().And("is_deleted", 0).And("tid", cl.TenantId).And("user_id", cl.UserID).AndCond(cond))
}
var rows []models.BackendPasswordStore
if _, e = qs.OrderBy("-id").All(&rows); e != nil && e != orm.ErrNoRows {
logs.Error("[passwordStore] app list failed: %v", e)
passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
return
}
res := make([]PasswordStoreItemDTO, 0, len(rows))
for _, row := range rows {
res = append(res, PasswordStoreItemDTO{
ID: row.ID, Tid: row.Tid, Platform: row.Platform, URL: row.URL,
Accounts: accountsFromJSON(row.Accounts), Remark: row.Remark,
UserID: row.UserID, CreateTime: row.CreateTime, UpdateTime: row.UpdateTime,
})
}
passwordReply(&c.Controller, 200, "success", map[string]interface{}{"list": res, "total": len(res)})
}
// GetDetail GET /api/passwordStore/detail/:id
func (c *AppPasswordStoreController) GetDetail() {
cl, e := c.appPwdClaims()
if e != nil {
passwordReply(&c.Controller, 401, "未登录或无权限", nil)
return
}
id, e := strconv.Atoi(c.Ctx.Input.Param(":id"))
if e != nil {
passwordReply(&c.Controller, 400, "参数错误", nil)
return
}
var m models.BackendPasswordStore
e = models.Orm.QueryTable(new(models.BackendPasswordStore)).
Filter("id", id).Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID).One(&m)
if e == orm.ErrNoRows {
passwordReply(&c.Controller, 404, "记录不存在", nil)
return
}
if e != nil {
logs.Error("[passwordStore] app detail failed: %v", e)
passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
return
}
passwordReply(&c.Controller, 200, "success", PasswordStoreItemDTO{
ID: m.ID, Tid: m.Tid, Platform: m.Platform, URL: m.URL,
Accounts: accountsFromJSON(m.Accounts), Remark: m.Remark,
UserID: m.UserID, CreateTime: m.CreateTime, UpdateTime: m.UpdateTime,
})
}
// Create POST /api/passwordStore/create
func (c *AppPasswordStoreController) Create() {
cl, e := c.appPwdClaims()
if e != nil {
passwordReply(&c.Controller, 401, "未登录或无权限", nil)
return
}
p, e := parsePassword(&c.Controller)
if e != nil {
passwordReply(&c.Controller, 400, e.Error(), nil)
return
}
if !validPassword(p) {
passwordReply(&c.Controller, 400, "请输入平台名称", nil)
return
}
if e := validateAccountsUnique(p.Accounts); e != nil {
passwordReply(&c.Controller, 400, e.Error(), nil)
return
}
qs := models.Orm.QueryTable(new(models.BackendPasswordStore)).
Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID)
if existing, e := findSamePlatformRecord(qs, 0, p.Platform, p.URL); e != nil {
passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
return
} else if existing > 0 {
passwordReply(&c.Controller, 400, "同平台同网址记录已存在,请勿重复添加", nil)
return
}
m := models.BackendPasswordStore{
Tid: cl.TenantId, UserID: uint64(cl.UserID),
Platform: p.Platform, URL: p.URL,
Accounts: accountsToJSON(p.Accounts), Remark: p.Remark,
}
if _, e = models.Orm.Insert(&m); e != nil {
logs.Error("[passwordStore] app create failed: %v", e)
passwordReply(&c.Controller, 500, "创建失败: "+e.Error(), nil)
return
}
passwordReply(&c.Controller, 200, "success", PasswordStoreItemDTO{
ID: m.ID, Tid: m.Tid, Platform: m.Platform, URL: m.URL,
Accounts: p.Accounts, Remark: m.Remark,
UserID: m.UserID, CreateTime: m.CreateTime, UpdateTime: m.UpdateTime,
})
}
// Update POST /api/passwordStore/update/:id
func (c *AppPasswordStoreController) Update() {
cl, e := c.appPwdClaims()
if e != nil {
passwordReply(&c.Controller, 401, "未登录或无权限", nil)
return
}
id, e := strconv.Atoi(c.Ctx.Input.Param(":id"))
if e != nil {
passwordReply(&c.Controller, 400, "参数错误", nil)
return
}
p, e := parsePassword(&c.Controller)
if e != nil {
passwordReply(&c.Controller, 400, e.Error(), nil)
return
}
if !validPassword(p) {
passwordReply(&c.Controller, 400, "请输入平台名称", nil)
return
}
if e := validateAccountsUnique(p.Accounts); e != nil {
passwordReply(&c.Controller, 400, e.Error(), nil)
return
}
var m models.BackendPasswordStore
e = models.Orm.QueryTable(new(models.BackendPasswordStore)).
Filter("id", id).Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID).One(&m)
if e == orm.ErrNoRows {
passwordReply(&c.Controller, 404, "记录不存在", nil)
return
}
if e != nil {
logs.Error("[passwordStore] app update query failed: %v", e)
passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
return
}
qs := models.Orm.QueryTable(new(models.BackendPasswordStore)).
Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID)
if existing, e := findSamePlatformRecord(qs, m.ID, p.Platform, p.URL); e != nil {
passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
return
} else if existing > 0 {
passwordReply(&c.Controller, 400, "同平台同网址记录已存在,请勿重复添加", nil)
return
}
m.Platform = p.Platform
m.URL = p.URL
m.Remark = p.Remark
m.Accounts = accountsToJSON(p.Accounts)
if _, e = models.Orm.Update(&m); e != nil {
logs.Error("[passwordStore] app update failed: %v", e)
passwordReply(&c.Controller, 500, "更新失败: "+e.Error(), nil)
return
}
passwordReply(&c.Controller, 200, "success", PasswordStoreItemDTO{
ID: m.ID, Tid: m.Tid, Platform: m.Platform, URL: m.URL,
Accounts: p.Accounts, Remark: m.Remark,
UserID: m.UserID, CreateTime: m.CreateTime, UpdateTime: m.UpdateTime,
})
}
// Delete DELETE /api/passwordStore/delete/:id
func (c *AppPasswordStoreController) Delete() {
cl, e := c.appPwdClaims()
if e != nil {
passwordReply(&c.Controller, 401, "未登录或无权限", nil)
return
}
id, e := strconv.Atoi(c.Ctx.Input.Param(":id"))
if e != nil {
passwordReply(&c.Controller, 400, "参数错误", nil)
return
}
var m models.BackendPasswordStore
e = models.Orm.QueryTable(new(models.BackendPasswordStore)).
Filter("id", id).Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID).One(&m)
if e == orm.ErrNoRows {
passwordReply(&c.Controller, 404, "记录不存在", nil)
return
}
if e != nil {
logs.Error("[passwordStore] app delete query failed: %v", e)
passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
return
}
if _, e = models.Orm.Delete(&m); e != nil {
logs.Error("[passwordStore] app delete failed: %v", e)
passwordReply(&c.Controller, 500, "删除失败: "+e.Error(), nil)
return
}
middleware.WriteDeleteLog(uint64(cl.UserID), cl.TenantId, "passwordStore", m.Platform)
passwordReply(&c.Controller, 200, "success", nil)
}