组织初始化接口 GET /api/auth/organizations 现在为每项授权公司附带
warehouse 摘要({id, name, status, location: {id, name, status} | null} | null),
结构与切换接口一致,供普通用户在公司切换器直接展示,无需放开管理员仓库配置接口。
- model:新增 WarehouseSummary/LocationSummary/OrganizationSummary,
OrganizationAccess 每项改为内嵌公司资料再加 warehouse 摘要。
- repository:新增 WarehouseRepository.Summary 复用切换接口的解析规则;
ListAccessible 逐公司补齐摘要,仓库或库位配置不唯一时报错而非随意取第一条,
无仓库、无库位或已停用如实返回,不回退旧公司数据。
- service:Switch 复用 List 已解析的摘要,响应格式保持不变。
- 测试:新增服务层 sqlmock 用例与仓储层 MySQL 集成用例,
覆盖启用唯一仓库加启用库位、无仓库、仓库停用三类。
62 lines
2.4 KiB
Go
62 lines
2.4 KiB
Go
package repository
|
||
|
||
import (
|
||
"database/sql"
|
||
"github.com/wmms/wmms/internal/model"
|
||
"github.com/wmms/wmms/pkg/database"
|
||
)
|
||
|
||
// Authorization is evaluated from current database grants and enabled roles on
|
||
// every call, so role changes and grant revocation do not wait for JWT expiry.
|
||
func (r *OrganizationRepository) ListAccessible(userID int64) (*model.OrganizationAccess, error) {
|
||
rows, err := database.DB.Query(`SELECT o.id,o.code,o.name,o.status,o.default_timezone,o.created_at,o.updated_at,
|
||
COALESCE(g.is_default,0) FROM organizations o
|
||
LEFT JOIN user_organizations g ON g.organization_id=o.id AND g.user_id=?
|
||
WHERE o.status='active' AND (g.user_id IS NOT NULL OR EXISTS(
|
||
SELECT 1 FROM user_roles ur JOIN roles r ON r.id=ur.role_id
|
||
WHERE ur.user_id=? AND r.code='super_admin' AND r.enabled=1)) ORDER BY o.id`, userID, userID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
defer rows.Close()
|
||
access := &model.OrganizationAccess{Organizations: make([]model.OrganizationSummary, 0)}
|
||
for rows.Next() {
|
||
var item model.OrganizationSummary
|
||
var isDefault bool
|
||
if err := rows.Scan(&item.ID, &item.Code, &item.Name, &item.Status, &item.DefaultTimezone, &item.CreatedAt, &item.UpdatedAt, &isDefault); err != nil {
|
||
return nil, err
|
||
}
|
||
access.Organizations = append(access.Organizations, item)
|
||
if isDefault {
|
||
id := item.ID
|
||
access.DefaultOrganizationID = &id
|
||
}
|
||
}
|
||
if err := rows.Err(); err != nil {
|
||
return nil, err
|
||
}
|
||
// 逐公司补齐仓库、库位摘要,供普通用户在公司切换器直接展示。查询复用
|
||
// WarehouseRepository;公司或库位配置不唯一时 Summary 会报错,不随意取第一条。
|
||
warehouses := NewWarehouseRepository()
|
||
for i := range access.Organizations {
|
||
summary, err := warehouses.Summary(access.Organizations[i].ID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
access.Organizations[i].Warehouse = summary
|
||
}
|
||
return access, nil
|
||
}
|
||
|
||
func (r *OrganizationRepository) CanAccess(userID, organizationID int64) (bool, error) {
|
||
var allowed bool
|
||
err := database.DB.QueryRow(`SELECT EXISTS(SELECT 1 FROM organizations o WHERE o.id=? AND o.status='active'
|
||
AND (EXISTS(SELECT 1 FROM user_organizations g WHERE g.user_id=? AND g.organization_id=o.id)
|
||
OR EXISTS(SELECT 1 FROM user_roles ur JOIN roles r ON r.id=ur.role_id
|
||
WHERE ur.user_id=? AND r.code='super_admin' AND r.enabled=1)))`, organizationID, userID, userID).Scan(&allowed)
|
||
if err == sql.ErrNoRows {
|
||
return false, nil
|
||
}
|
||
return allowed, err
|
||
}
|