feat(group): 1st implementation of Groups

this implements first version (manageable only by admin right now)

    routes:

        GET /api/groups
        List subject groups (paginated). Admin-only.

        POST /api/groups
        Create a new ReBAC subject group. Admin-only. The name must match the RFC 5321 local-part shape and be globally unique (case-insensitive).

        GET /api/groups/search
        Search non-virtual groups by name substring. Authenticated only (no admin role required) — backs the share-dialog recipient autocomplete.

        GET /api/groups/{id}
        Fetch a single group's details. Admin-only.

        DELETE /api/groups/{id}
        Delete a group. Cascades to `subject_group_members` (FK) and to `access_grants` rows referencing this group as a subject. Admin-only.

        PATCH /api/groups/{id}
        Update a group's metadata. Admin-only. v1 only persists name renames.

        GET /api/groups/{id}/effective-members
        List every user transitively reached through this group (members of members of members, etc.). Used by admin / audit tooling. Admin-only.

        GET /api/groups/{id}/members
        List the *direct* members of a group (one level only). Admin-only.

        POST /api/groups/{id}/members
        Add a member to a group. Exactly one of `user_id` / `group_id` must be provided. Adding a group-member runs a write-time cycle check and a nesting-depth check (max 8). Admin-only.

        DELETE /api/groups/{id}/members/group/{gid}
        Remove a nested group-member from a group. Admin-only.

        DELETE /api/groups/{id}/members/user/{uid}
        Remove a user-member from a group. Admin-only.

fix hurl

groups

round

groups
This commit is contained in:
Edouard Vanbelle
2026-05-30 23:35:47 +02:00
parent 41356b6490
commit 09985f8a95
54 changed files with 6421 additions and 145 deletions
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "فاتح",
"dark": "داكن",
"auto": "مثل النظام"
}
},
"manage_groups": "إدارة المجموعات"
},
"share": {
"dialogTitle": "رابط المشاركة",
@@ -336,7 +337,13 @@
"move_error": "خطأ في النقل",
"empty_name": "لا يمكن أن يكون الاسم فارغاً",
"name_exists": "ملف أو مجلد بهذا الاسم موجود بالفعل",
"generic_error": "حدث خطأ"
"generic_error": "حدث خطأ",
"group_name_invalid": "يجب أن يتطابق اسم المجموعة مع صيغة بادئة البريد الإلكتروني (حروف، أرقام، نقطة، شرطة، شرطة سفلية؛ 1–64 حرفًا).",
"group_cycle": "سينشئ هذا العضو مرجعًا دائريًا بين المجموعات.",
"group_depth_exceeded": "تتجاوز عمق التعشيش الحد الأقصى المسموح (8).",
"group_virtual_immutable": "مجموعة «Internal» تدار من قبل النظام ولا يمكن تعديلها.",
"group_not_found": "المجموعة غير موجودة.",
"group_name_taken": "توجد بالفعل مجموعة بهذا الاسم."
},
"breadcrumb": {
"home": "الرئيسية"
@@ -755,5 +762,31 @@
"today": "اليوم",
"last7days": "آخر 7 أيام",
"last30days": "آخر 30 يومًا"
},
"groups": {
"title": "إدارة المجموعات",
"create_button": "إنشاء مجموعة",
"create_dialog_title": "مجموعة جديدة",
"edit_dialog_title": "إعادة تسمية المجموعة",
"name_label": "الاسم",
"name_placeholder": "engineering",
"description_label": "الوصف (اختياري)",
"members_section": "الأعضاء",
"add_member_placeholder": "إضافة مستخدم أو مجموعة…",
"no_members": "لا يوجد أعضاء بعد.",
"remove_member": "إزالة",
"delete_group": "حذف المجموعة",
"delete_confirm": "حذف المجموعة \"{name}\"؟ سيتم إلغاء الصلاحيات المرتبطة بهذه المجموعة.",
"empty_state": "لا توجد مجموعات بعد.",
"load_more": "تحميل المزيد",
"back_to_list": "رجوع",
"loading": "جارٍ التحميل…",
"virtual_badge": "النظام",
"member_count_zero": "لا يوجد أعضاء",
"member_count_one": "عضو واحد",
"member_count_other": "{count} أعضاء",
"delete_confirm_label": "اكتب اسم المجموعة للتأكيد:",
"delete_confirm_mismatch": "اكتب اسم المجموعة كما هو للتأكيد.",
"virtual_internal_name": "داخلي"
}
}