178 lines
5.1 KiB
Go
178 lines
5.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/wmms/wmms/internal/model"
|
|
"github.com/wmms/wmms/pkg/database"
|
|
)
|
|
|
|
type OrganizationRepository struct{}
|
|
|
|
var ErrProtectedRole = errors.New("super administrator role cannot be changed")
|
|
|
|
func NewOrganizationRepository() *OrganizationRepository { return &OrganizationRepository{} }
|
|
|
|
func (r *OrganizationRepository) List() ([]model.Organization, error) {
|
|
rows, err := database.DB.Query(`SELECT id, code, name, status, default_timezone, created_at, updated_at
|
|
FROM organizations ORDER BY id`)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
organizations := make([]model.Organization, 0)
|
|
for rows.Next() {
|
|
var item model.Organization
|
|
if err := rows.Scan(&item.ID, &item.Code, &item.Name, &item.Status, &item.DefaultTimezone, &item.CreatedAt, &item.UpdatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
organizations = append(organizations, item)
|
|
}
|
|
return organizations, rows.Err()
|
|
}
|
|
|
|
func (r *OrganizationRepository) Create(item *model.Organization) error {
|
|
result, err := database.DB.Exec(`INSERT INTO organizations (code, name, status, default_timezone) VALUES (?, ?, ?, ?)`, item.Code, item.Name, item.Status, item.DefaultTimezone)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
item.ID, err = result.LastInsertId()
|
|
return err
|
|
}
|
|
|
|
func (r *OrganizationRepository) Update(item *model.Organization) error {
|
|
_, err := database.DB.Exec(`UPDATE organizations SET name = ?, status = ?, default_timezone = ? WHERE id = ?`, item.Name, item.Status, item.DefaultTimezone, item.ID)
|
|
return err
|
|
}
|
|
|
|
func (r *OrganizationRepository) ListRoles() ([]model.Role, error) {
|
|
rows, err := database.DB.Query(`SELECT id, code, name, enabled, created_at, updated_at FROM roles ORDER BY id`)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
roles := make([]model.Role, 0)
|
|
roleIndexes := make(map[int64]int)
|
|
for rows.Next() {
|
|
var item model.Role
|
|
if err := rows.Scan(&item.ID, &item.Code, &item.Name, &item.Enabled, &item.CreatedAt, &item.UpdatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
item.Permissions = []model.Permission{}
|
|
roleIndexes[item.ID] = len(roles)
|
|
roles = append(roles, item)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
permissionRows, err := database.DB.Query(`SELECT rp.role_id, p.id, p.code, p.name
|
|
FROM role_permissions rp JOIN permissions p ON p.id = rp.permission_id
|
|
ORDER BY rp.role_id, p.code`)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer permissionRows.Close()
|
|
for permissionRows.Next() {
|
|
var roleID int64
|
|
var permission model.Permission
|
|
if err := permissionRows.Scan(&roleID, &permission.ID, &permission.Code, &permission.Name); err != nil {
|
|
return nil, err
|
|
}
|
|
if index, ok := roleIndexes[roleID]; ok {
|
|
roles[index].Permissions = append(roles[index].Permissions, permission)
|
|
}
|
|
}
|
|
return roles, permissionRows.Err()
|
|
}
|
|
|
|
func (r *OrganizationRepository) ListPermissions() ([]model.Permission, error) {
|
|
rows, err := database.DB.Query(`SELECT id, code, name FROM permissions ORDER BY code`)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
permissions := make([]model.Permission, 0)
|
|
for rows.Next() {
|
|
var permission model.Permission
|
|
if err := rows.Scan(&permission.ID, &permission.Code, &permission.Name); err != nil {
|
|
return nil, err
|
|
}
|
|
permissions = append(permissions, permission)
|
|
}
|
|
return permissions, rows.Err()
|
|
}
|
|
|
|
func (r *OrganizationRepository) UpdateRole(roleID int64, name string, enabled bool, permissionCodes []string) (err error) {
|
|
tx, err := database.DB.Begin()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
if err != nil {
|
|
_ = tx.Rollback()
|
|
}
|
|
}()
|
|
|
|
var roleCode string
|
|
if err = tx.QueryRow(`SELECT code FROM roles WHERE id = ? FOR UPDATE`, roleID).Scan(&roleCode); err != nil {
|
|
return err
|
|
}
|
|
if roleCode == "super_admin" {
|
|
return ErrProtectedRole
|
|
}
|
|
if _, err = tx.Exec(`UPDATE roles SET name = ?, enabled = ? WHERE id = ?`, name, enabled, roleID); err != nil {
|
|
return err
|
|
}
|
|
if _, err = tx.Exec(`DELETE FROM role_permissions WHERE role_id = ?`, roleID); err != nil {
|
|
return err
|
|
}
|
|
|
|
permissionCodes = uniqueStrings(permissionCodes)
|
|
if len(permissionCodes) > 0 {
|
|
placeholders := strings.TrimSuffix(strings.Repeat("?, ", len(permissionCodes)), ", ")
|
|
query := fmt.Sprintf(`INSERT INTO role_permissions (role_id, permission_id)
|
|
SELECT ?, id FROM permissions WHERE code IN (%s)`, placeholders)
|
|
args := make([]interface{}, 0, len(permissionCodes)+1)
|
|
args = append(args, roleID)
|
|
for _, code := range permissionCodes {
|
|
args = append(args, code)
|
|
}
|
|
result, execErr := tx.Exec(query, args...)
|
|
if execErr != nil {
|
|
err = execErr
|
|
return err
|
|
}
|
|
var affected int64
|
|
affected, err = result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if affected != int64(len(permissionCodes)) {
|
|
return fmt.Errorf("one or more permission codes do not exist")
|
|
}
|
|
}
|
|
return tx.Commit()
|
|
}
|
|
|
|
func uniqueStrings(values []string) []string {
|
|
seen := make(map[string]struct{}, len(values))
|
|
result := make([]string, 0, len(values))
|
|
for _, value := range values {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
continue
|
|
}
|
|
if _, exists := seen[value]; exists {
|
|
continue
|
|
}
|
|
seen[value] = struct{}{}
|
|
result = append(result, value)
|
|
}
|
|
return result
|
|
}
|