@@ -372,14 +372,22 @@ User groups are plain name strings stored in the `usergroup` collection. Group
372372names must already exist before they can be assigned to users; otherwise the
373373API returns ` 400 ` .
374374
375- There is currently no REST endpoint for creating or deleting user groups. Use
376- MongoDB tooling to manage them. Example with ` mongosh ` :
375+ User groups are plain name strings stored in the ` usergroup ` collection. You
376+ can manage them via the API endpoints below or directly with MongoDB tooling.
377+ Example with ` mongosh ` :
377378
378379```
379380$ mongosh "mongodb://db:27017/kernelci"
380381> db.usergroup.insertOne({name: "runtime:lava-collabora:node-editor"})
381382```
382383
384+ Admin-only user group management endpoints are available:
385+
386+ - ` GET /user-groups ` (list; supports ` name ` filter)
387+ - ` GET /user-groups/<group-id> `
388+ - ` POST /user-groups ` with ` {"name": "runtime:lava-collabora:node-editor"} `
389+ - ` DELETE /user-groups/<group-id> ` (fails with ` 409 ` if assigned to users)
390+
383391Admin users can assign or remove groups via:
384392
385393- ` POST /user/invite ` with a ` groups ` list
@@ -393,12 +401,133 @@ Example using the helper script:
393401
394402```
395403$ ./scripts/usermanager.py list-users
404+ $ ./scripts/usermanager.py list-groups
405+ $ ./scripts/usermanager.py create-group runtime:lava-collabora:node-editor
396406$ ./scripts/usermanager.py update-user 615f30020eb7c3c6616e5ac3 \
397407 --data '{"groups": ["runtime:lava-collabora:node-editor"]}'
398408```
399409
400410Users cannot update their own groups; admin access is required.
401411
412+ ### Usermanager workflows (examples)
413+
414+ These examples use ` scripts/usermanager.py ` . It reads ` ./usermanager.toml ` or
415+ ` ~/.config/kernelci/usermanager.toml ` by default, and you can override with
416+ ` --api-url ` /` --token ` or ` KCI_API_URL ` /` KCI_API_TOKEN ` .
417+
418+ Common admin workflows:
419+
420+ - List users and capture IDs:
421+
422+ ```
423+ $ ./scripts/usermanager.py list-users
424+ $ ./scripts/usermanager.py get-user <USER-ID>
425+ ```
426+
427+ - Invite a user (optionally add groups):
428+
429+ ```
430+ $ ./scripts/usermanager.py invite \
431+ --username alice \
432+ --email alice@example.org \
433+ --groups runtime:pull-labs-demo:node-editor \
434+ --return-token
435+ ```
436+
437+ - Accept an invite manually (useful for service accounts or testing):
438+
439+ ```
440+ $ ./scripts/usermanager.py accept-invite --token "<INVITE-TOKEN>"
441+ ```
442+
443+ - Login to get a bearer token:
444+
445+ ```
446+ $ ./scripts/usermanager.py login --username alice
447+ ```
448+
449+ - Deactivate or reactivate a user:
450+
451+ ```
452+ $ ./scripts/usermanager.py update-user <USER-ID> --inactive
453+ $ ./scripts/usermanager.py update-user <USER-ID> --active
454+ ```
455+
456+ - Grant or revoke superuser:
457+
458+ ```
459+ $ ./scripts/usermanager.py update-user <USER-ID> --superuser
460+ $ ./scripts/usermanager.py update-user <USER-ID> --no-superuser
461+ ```
462+
463+ - Mark a user verified or unverified (admin only):
464+
465+ ```
466+ $ ./scripts/usermanager.py update-user <USER-ID> --verified
467+ $ ./scripts/usermanager.py update-user <USER-ID> --unverified
468+ ```
469+
470+ - Assign or remove groups:
471+
472+ ```
473+ $ ./scripts/usermanager.py update-user <USER-ID> \
474+ --add-group runtime:pull-labs-demo:node-editor
475+ $ ./scripts/usermanager.py update-user <USER-ID> \
476+ --remove-group runtime:pull-labs-demo:node-editor
477+ $ ./scripts/usermanager.py update-user <USER-ID> \
478+ --set-groups runtime:pull-labs-demo:node-editor,team-a
479+ ```
480+
481+ - Set a password (admin only, useful for service accounts):
482+
483+ ```
484+ $ ./scripts/usermanager.py update-user <USER-ID> --password "<new-password>"
485+ ```
486+
487+ - Manage user groups:
488+
489+ ```
490+ $ ./scripts/usermanager.py list-groups
491+ $ ./scripts/usermanager.py create-group runtime:pull-labs-demo:node-editor
492+ $ ./scripts/usermanager.py delete-group runtime:pull-labs-demo:node-editor
493+ ```
494+
495+ - Delete a user:
496+
497+ ```
498+ $ ./scripts/usermanager.py delete-user <USER-ID>
499+ ```
500+
501+ ### Permissions and node update rules
502+
503+ Node update permissions are determined by the user and the node being edited:
504+
505+ - Superusers can update any node.
506+ - The node owner can update their own nodes.
507+ - Users with group ` node:edit:any ` can update any node.
508+ - Users with a group listed in the node's ` user_groups ` can update that node.
509+ - Users with ` runtime:<runtime>:node-editor ` or ` runtime:<runtime>:node-admin `
510+ can update nodes whose ` data.runtime ` matches ` <runtime> ` .
511+
512+ Example: allow updates only for runtime ` pull-labs-demo ` :
513+
514+ ```
515+ $ mongosh "mongodb://db:27017/kernelci"
516+ > db.usergroup.insertOne({name: "runtime:pull-labs-demo:node-editor"})
517+ ```
518+
519+ ```
520+ $ ./scripts/usermanager.py update-user <USER-ID> \
521+ --add-group runtime:pull-labs-demo:node-editor
522+ ```
523+
524+ To remove a user group definition entirely, delete it in MongoDB:
525+
526+ ```
527+ $ mongosh "mongodb://db:27017/kernelci"
528+ > db.usergroup.deleteOne({name: "runtime:pull-labs-demo:node-editor"})
529+ ```
530+
402531
403532### Delete user matching user ID (Admin only)
404533
0 commit comments