ilk
This commit is contained in:
203
svc/routes/permission_matrix_v2.go
Normal file
203
svc/routes/permission_matrix_v2.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"bssapp-backend/auth"
|
||||
"bssapp-backend/internal/auditlog"
|
||||
"bssapp-backend/permissions"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func GetRolePermissionMatrix(db *sql.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
claims, ok := auth.GetClaimsFromContext(r.Context())
|
||||
if !ok || claims == nil {
|
||||
http.Error(w, "unauthorized", 401)
|
||||
return
|
||||
}
|
||||
|
||||
roleID, _ := strconv.Atoi(mux.Vars(r)["id"])
|
||||
|
||||
rows, err := db.Query(`
|
||||
SELECT
|
||||
module_code,
|
||||
action,
|
||||
allowed
|
||||
FROM mk_sys_role_permissions
|
||||
WHERE role_id=$1
|
||||
`, roleID)
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, "db error", 500)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var list []permissions.PermissionMatrixRow
|
||||
|
||||
for rows.Next() {
|
||||
|
||||
var row permissions.PermissionMatrixRow
|
||||
|
||||
if err := rows.Scan(
|
||||
&row.Module,
|
||||
&row.Action,
|
||||
&row.Allowed,
|
||||
); err != nil {
|
||||
http.Error(w, "scan error", 500)
|
||||
return
|
||||
}
|
||||
|
||||
row.Source = "role"
|
||||
|
||||
list = append(list, row)
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(list)
|
||||
}
|
||||
}
|
||||
|
||||
func SaveRolePermissionMatrix(db *sql.DB) http.HandlerFunc {
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
claims, ok := auth.GetClaimsFromContext(r.Context())
|
||||
if !ok || claims == nil {
|
||||
http.Error(w, "unauthorized", 401)
|
||||
return
|
||||
}
|
||||
|
||||
roleID, _ := strconv.Atoi(mux.Vars(r)["id"])
|
||||
|
||||
var list []permissions.PermissionMatrixRow
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&list); err != nil {
|
||||
http.Error(w, "bad payload", 400)
|
||||
return
|
||||
}
|
||||
|
||||
repo := permissions.NewPermissionRepository(db)
|
||||
|
||||
// ================= OLD =================
|
||||
|
||||
oldRows, _ := repo.GetPermissionMatrixForRoles([]int{roleID})
|
||||
|
||||
oldMap := map[string]bool{}
|
||||
|
||||
for _, p := range oldRows {
|
||||
key := p.Module + ":" + p.Action
|
||||
oldMap[key] = p.Allowed
|
||||
}
|
||||
|
||||
// ================= DIFF =================
|
||||
|
||||
var changes []map[string]any
|
||||
|
||||
for _, p := range list {
|
||||
|
||||
key := p.Module + ":" + p.Action
|
||||
|
||||
oldVal, ok := oldMap[key]
|
||||
if !ok {
|
||||
oldVal = false
|
||||
}
|
||||
|
||||
if oldVal != p.Allowed {
|
||||
|
||||
changes = append(changes, map[string]any{
|
||||
"module": p.Module,
|
||||
"action": p.Action,
|
||||
"before": oldVal,
|
||||
"after": p.Allowed,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ================= SAVE =================
|
||||
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
http.Error(w, "tx error", 500)
|
||||
return
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
stmt, err := tx.Prepare(`
|
||||
INSERT INTO mk_sys_role_permissions
|
||||
(role_id,module_code,action,allowed)
|
||||
VALUES ($1,$2,$3,$4)
|
||||
|
||||
ON CONFLICT
|
||||
(role_id,module_code,action)
|
||||
DO UPDATE SET allowed=EXCLUDED.allowed
|
||||
`)
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, "prepare error", 500)
|
||||
return
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
for _, p := range list {
|
||||
|
||||
if _, err := stmt.Exec(
|
||||
roleID,
|
||||
p.Module,
|
||||
p.Action,
|
||||
p.Allowed,
|
||||
); err != nil {
|
||||
http.Error(w, "exec error", 500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
http.Error(w, "commit error", 500)
|
||||
return
|
||||
}
|
||||
|
||||
// ================= AUDIT =================
|
||||
|
||||
if len(changes) > 0 {
|
||||
|
||||
var roleCode string
|
||||
|
||||
_ = db.QueryRow(`
|
||||
SELECT code FROM dfrole WHERE id=$1
|
||||
`, roleID).Scan(&roleCode)
|
||||
|
||||
auditlog.Enqueue(r.Context(), auditlog.ActivityLog{
|
||||
|
||||
ActionType: "role_permission_change",
|
||||
ActionCategory: "role_permission",
|
||||
|
||||
ActionTarget: fmt.Sprintf("/api/roles/%d/permissions", roleID),
|
||||
|
||||
Description: "role permission matrix updated",
|
||||
|
||||
Username: claims.Username,
|
||||
RoleCode: claims.RoleCode,
|
||||
DfUsrID: int64(claims.ID),
|
||||
|
||||
ChangeBefore: map[string]any{
|
||||
"permissions": oldRows,
|
||||
},
|
||||
|
||||
ChangeAfter: map[string]any{
|
||||
"changes": changes,
|
||||
},
|
||||
|
||||
IsSuccess: true,
|
||||
})
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]bool{
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user