mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 07:41:27 +00:00
feat(invites): team invite links — admin create/revoke, public accept (#42)
* feat(branding): white-label — public /branding, admin write, shell theming app_settings branding.* keys (product name, logo/favicon URLs, accent color, docs/support links). Public GET /branding so login and shell theme pre-auth; admin writes via PUT /settings. useBranding() applies document.title, accent CSS var and favicon; BrandWordmark replaces hardcoded wordmarks; admin Platform settings gain a Branding form. MCP containr_branding_get + settings_update. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat(invites): team invite links — admin create/revoke, public accept Admins mint single-use invite links (sha256-hashed token at rest, optional email binding, configurable TTL). Public endpoints let the accept page validate the link and register — working even while public signup is disabled. - migration + sqlc queries/model for user_invites - POST /admin/invites (returns one-time token+url), GET list, DELETE revoke - GET /auth/invites/:token public validation, POST /auth/accept-invite - CLI containr invites list|create|revoke; MCP invites tools - /auth/accept-invite page (expired/used/invalid states, bound-email lock) - Admin page Team invites section: create, copy link, revoke - OpenAPI + generated types + CLI guide Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
b47ced0135
commit
50e39fe140
20 files changed
+1194
-4
No files matched your search
@@ -2702,6 +2702,112 @@ paths:
|
||||
'204':
|
||||
description: Deleted
|
||||
|
||||
/auth/invites/{token}:
|
||||
get:
|
||||
tags:
|
||||
- Invites
|
||||
summary: Validate an invite token (public)
|
||||
responses:
|
||||
'200':
|
||||
description: Invite state
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
valid: {type: boolean}
|
||||
used: {type: boolean}
|
||||
expired: {type: boolean}
|
||||
email: {type: string, nullable: true}
|
||||
expires_at: {type: string, format: date-time}
|
||||
'404':
|
||||
description: Invite not found
|
||||
|
||||
/auth/accept-invite:
|
||||
post:
|
||||
tags:
|
||||
- Invites
|
||||
summary: Register via an invite link (public)
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [token, name, email, password]
|
||||
properties:
|
||||
token: {type: string}
|
||||
name: {type: string}
|
||||
email: {type: string}
|
||||
password: {type: string, minLength: 8}
|
||||
responses:
|
||||
'201':
|
||||
description: Created session
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LoginResponse'
|
||||
'410':
|
||||
description: Invite used or expired
|
||||
|
||||
/admin/invites:
|
||||
get:
|
||||
tags:
|
||||
- Invites
|
||||
summary: List invites (admin)
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: All invites
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
invites:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
post:
|
||||
tags:
|
||||
- Invites
|
||||
summary: Create an invite link (admin)
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
email: {type: string, description: Optionally bind the invite to this email}
|
||||
expires_in_hours: {type: integer, default: 168, minimum: 1, maximum: 2160}
|
||||
responses:
|
||||
'201':
|
||||
description: Created invite with one-time token
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
invite: {type: object}
|
||||
token: {type: string, description: Shown once}
|
||||
url: {type: string}
|
||||
|
||||
/admin/invites/{id}:
|
||||
delete:
|
||||
tags:
|
||||
- Invites
|
||||
summary: Revoke an invite (admin)
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- {name: id, in: path, required: true, schema: {type: string}}
|
||||
responses:
|
||||
'204':
|
||||
description: Revoked
|
||||
|
||||
/branding:
|
||||
get:
|
||||
tags:
|
||||
|
||||
Reference in new issue
Block a user