Merge remote-tracking branch 'origin/master'
# Conflicts: # ui/src/pages/OrderList.vue
This commit is contained in:
@@ -262,6 +262,11 @@ func InitRoutes(pgDB *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) *mux.Router
|
||||
rdPerm := "/api/roles/{roleId}/departments/{deptCode}/permissions"
|
||||
rdHandler := routes.NewRoleDepartmentPermissionHandler(pgDB)
|
||||
|
||||
bindV3(r, pgDB,
|
||||
"/api/role-dept-permissions/list", "GET",
|
||||
"user", "update",
|
||||
wrapV3(http.HandlerFunc(rdHandler.List)),
|
||||
)
|
||||
bindV3(r, pgDB,
|
||||
rdPerm, "GET",
|
||||
"user", "update",
|
||||
@@ -407,6 +412,8 @@ func InitRoutes(pgDB *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) *mux.Router
|
||||
{"/api/order/update", "POST", "update", http.HandlerFunc(routes.UpdateOrderHandler)},
|
||||
{"/api/order/get/{id}", "GET", "view", routes.GetOrderByIDHandler(mssql)},
|
||||
{"/api/orders/list", "GET", "view", routes.OrderListRoute(mssql)},
|
||||
{"/api/orders/close-ready", "GET", "update", routes.OrderCloseReadyListRoute(mssql)},
|
||||
{"/api/orders/bulk-close", "POST", "update", routes.OrderBulkCloseRoute(mssql)},
|
||||
{"/api/orders/export", "GET", "export", routes.OrderListExcelRoute(mssql)},
|
||||
{"/api/order/check/{id}", "GET", "view", routes.OrderExistsHandler(mssql)},
|
||||
{"/api/order/validate", "POST", "insert", routes.ValidateOrderHandler(mssql)},
|
||||
|
||||
@@ -34,6 +34,67 @@ DO UPDATE SET
|
||||
|
||||
`
|
||||
|
||||
// LIST (role+department sets with summary)
|
||||
const ListRoleDepartmentPermissionSets = `
|
||||
WITH role_dept AS (
|
||||
SELECT DISTINCT
|
||||
p.role_id,
|
||||
p.department_code
|
||||
FROM mk_sys_role_department_permissions p
|
||||
),
|
||||
base AS (
|
||||
SELECT
|
||||
rd.role_id,
|
||||
COALESCE(NULLIF(r.title, ''), r.code, rd.role_id::text) AS role_title,
|
||||
rd.department_code,
|
||||
COALESCE(d.title, rd.department_code) AS department_title
|
||||
FROM role_dept rd
|
||||
LEFT JOIN dfrole r
|
||||
ON r.id = rd.role_id
|
||||
LEFT JOIN mk_dprt d
|
||||
ON d.code = rd.department_code
|
||||
WHERE
|
||||
($1 = '' OR
|
||||
COALESCE(NULLIF(r.title, ''), r.code, '') ILIKE '%' || $1 || '%' OR
|
||||
COALESCE(d.title, '') ILIKE '%' || $1 || '%' OR
|
||||
rd.department_code ILIKE '%' || $1 || '%' OR
|
||||
rd.role_id::text ILIKE '%' || $1 || '%')
|
||||
),
|
||||
perm_agg AS (
|
||||
SELECT
|
||||
p.role_id,
|
||||
p.department_code,
|
||||
LOWER(p.module_code) AS module_code,
|
||||
LOWER(p.action) AS action,
|
||||
BOOL_OR(p.allowed) AS has_allowed
|
||||
FROM mk_sys_role_department_permissions p
|
||||
GROUP BY
|
||||
p.role_id,
|
||||
p.department_code,
|
||||
LOWER(p.module_code),
|
||||
LOWER(p.action)
|
||||
)
|
||||
SELECT
|
||||
b.role_id,
|
||||
b.role_title,
|
||||
b.department_code,
|
||||
b.department_title,
|
||||
COALESCE(
|
||||
(
|
||||
SELECT jsonb_object_agg(pa.module_code || '|' || pa.action, pa.has_allowed)
|
||||
FROM perm_agg pa
|
||||
WHERE
|
||||
pa.role_id = b.role_id
|
||||
AND pa.department_code = b.department_code
|
||||
),
|
||||
'{}'::jsonb
|
||||
) AS module_flags
|
||||
FROM base b
|
||||
ORDER BY
|
||||
b.role_title,
|
||||
b.department_title
|
||||
`
|
||||
|
||||
// ======================================================
|
||||
// 📦 MODULES
|
||||
// ======================================================
|
||||
@@ -45,3 +106,20 @@ SELECT
|
||||
FROM mk_sys_modules
|
||||
ORDER BY id
|
||||
`
|
||||
|
||||
const GetModuleActionLookup = `
|
||||
SELECT DISTINCT
|
||||
LOWER(x.module_code) AS module_code,
|
||||
LOWER(x.action) AS action
|
||||
FROM (
|
||||
SELECT module_code, action FROM mk_sys_routes
|
||||
UNION ALL
|
||||
SELECT module_code, action FROM mk_sys_role_department_permissions
|
||||
) x
|
||||
WHERE
|
||||
x.module_code IS NOT NULL
|
||||
AND x.action IS NOT NULL
|
||||
ORDER BY
|
||||
LOWER(x.module_code),
|
||||
LOWER(x.action)
|
||||
`
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -24,6 +25,30 @@ type Row struct {
|
||||
CanAccess bool `json:"can_access"`
|
||||
}
|
||||
|
||||
type RoleDeptPermissionSummary struct {
|
||||
RoleID int `json:"role_id"`
|
||||
RoleTitle string `json:"role_title"`
|
||||
DepartmentCode string `json:"department_code"`
|
||||
DepartmentTitle string `json:"department_title"`
|
||||
ModuleFlags map[string]bool `json:"module_flags"`
|
||||
}
|
||||
|
||||
type ModuleLookupOption struct {
|
||||
Value string `json:"value"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
type ModuleActionLookupOption struct {
|
||||
ModuleCode string `json:"module_code"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
type RoleDeptPermissionListResponse struct {
|
||||
Modules []ModuleLookupOption `json:"modules"`
|
||||
ModuleActions []ModuleActionLookupOption `json:"module_actions"`
|
||||
Rows []RoleDeptPermissionSummary `json:"rows"`
|
||||
}
|
||||
|
||||
type RoleDepartmentPermissionHandler struct {
|
||||
DB *sql.DB
|
||||
Repo *permissions.RoleDepartmentPermissionRepo
|
||||
@@ -37,6 +62,109 @@ func NewRoleDepartmentPermissionHandler(db *sql.DB) *RoleDepartmentPermissionHan
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================
|
||||
LIST
|
||||
====================================================== */
|
||||
|
||||
func (h *RoleDepartmentPermissionHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
claims, ok := auth.GetClaimsFromContext(r.Context())
|
||||
if !ok || claims == nil {
|
||||
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
|
||||
modRows, err := h.DB.Query(queries.GetModuleLookup)
|
||||
if err != nil {
|
||||
http.Error(w, "module lookup error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer modRows.Close()
|
||||
|
||||
modules := make([]ModuleLookupOption, 0, 32)
|
||||
for modRows.Next() {
|
||||
var m ModuleLookupOption
|
||||
if err := modRows.Scan(&m.Value, &m.Label); err != nil {
|
||||
http.Error(w, "module lookup scan error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
modules = append(modules, m)
|
||||
}
|
||||
|
||||
if err := modRows.Err(); err != nil {
|
||||
http.Error(w, "module lookup rows error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
actionRows, err := h.DB.Query(queries.GetModuleActionLookup)
|
||||
if err != nil {
|
||||
http.Error(w, "module action lookup error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer actionRows.Close()
|
||||
|
||||
moduleActions := make([]ModuleActionLookupOption, 0, 128)
|
||||
for actionRows.Next() {
|
||||
var a ModuleActionLookupOption
|
||||
if err := actionRows.Scan(&a.ModuleCode, &a.Action); err != nil {
|
||||
http.Error(w, "module action scan error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
moduleActions = append(moduleActions, a)
|
||||
}
|
||||
|
||||
if err := actionRows.Err(); err != nil {
|
||||
http.Error(w, "module action rows error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := h.DB.Query(queries.ListRoleDepartmentPermissionSets, search)
|
||||
if err != nil {
|
||||
http.Error(w, "db error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
list := make([]RoleDeptPermissionSummary, 0, 128)
|
||||
for rows.Next() {
|
||||
var item RoleDeptPermissionSummary
|
||||
var rawFlags []byte
|
||||
if err := rows.Scan(
|
||||
&item.RoleID,
|
||||
&item.RoleTitle,
|
||||
&item.DepartmentCode,
|
||||
&item.DepartmentTitle,
|
||||
&rawFlags,
|
||||
); err != nil {
|
||||
http.Error(w, "scan error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
item.ModuleFlags = map[string]bool{}
|
||||
if len(rawFlags) > 0 {
|
||||
if err := json.Unmarshal(rawFlags, &item.ModuleFlags); err != nil {
|
||||
http.Error(w, "module flags parse error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
http.Error(w, "rows error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
_ = json.NewEncoder(w).Encode(RoleDeptPermissionListResponse{
|
||||
Modules: modules,
|
||||
ModuleActions: moduleActions,
|
||||
Rows: list,
|
||||
})
|
||||
}
|
||||
|
||||
/* ======================================================
|
||||
GET
|
||||
====================================================== */
|
||||
|
||||
Reference in New Issue
Block a user