When a user accepts an org invite, send a notification email to the
person who sent the invite with membership details (member name, email,
org name, role) and an optional View Organization button.
Added build_invite_accepted_html() template to email_templates.py,
wired it into the accept_invite() handler, and added a test case.
Previously, SSH key fingerprints were globally unique across all users,
preventing the same key from being registered by different users. This
change makes fingerprint uniqueness scoped to individual users.
- Remove global unique constraints on payload and fingerprint columns
- Add composite unique constraint on (user_id, fingerprint)
- Make add_ssh_key operation idempotent for same user
- Return tuple (SSHKey, is_new) from service to indicate creation status
- Update API to return 200 for existing keys, 201 for new keys
BREAKING CHANGE: API behavior changed - duplicate key addition now
returns 200 OK instead of 409 Conflict. Service method signature changed
from returning SSHKey to tuple[SSHKey, bool].
Handle edge case where removing a member would leave an organization
without any owners. Service layer raises ValueError for this scenario,
which the API endpoint catches and converts to a forbidden response
with actionable error message about transferring ownership.
Add 10 organization limit per user to prevent abuse. Includes
graceful fallback if count service is unavailable.
- Add get_user_org_count method to OrganizationService
- Check org count before allowing new organization creation
- Improve invite email mismatch error message for logged-in users
Add POST /api/v1/contact endpoint to handle contact form submissions
from the marketing website. Includes:
- ContactSchema for validation with HTML sanitization
- Honeypot field for spam protection
- Rate limiting (5 per hour)
- Email notification to info@secuird.tech via NotificationService
Add get_active_memberships() method to User model that filters out
soft-deleted memberships and memberships of deleted organizations.
Update all usages of organization_memberships to use this method,
ensuring consistent handling of soft-deleted records across the
codebase. Also add deleted_at filters to CA queries in SSH helpers.
- Update org invite, password reset, email verification, and account activation emails to use HTML templates
- Update MFA deadline reminder and suspension notifications to use HTML templates
- Add html_body parameter to _send_email_async for rich email content
Add pluggable email provider system supporting SMTP, Mailgun, and SendGrid
with factory pattern for runtime provider selection. Includes branded HTML
email templates for verification, password reset, MFA notifications, and
organization invites.
Also rebrands all email content from Gatehouse to Secuird, adds email
provider configuration options, and fixes duplicate log handlers in
development mode.
Refractor Codes into sub file/folders
Admin can remove users'/members mfa/2fa, unlink account from oauth provider
Admin can add/reset password
Different Email (OIDC + Manual)-Same Account; (Block Linking and authorize if available)
- OAuth Callback to Use Gatehouse UI to login instead of Backend Served dull ui
- Setup Autoregister of user + org, on oauth
- Microsoft Oauth Support
- OIDCRefreshToken.access_token_id had a narrow Column increased to VAR(255) and remove FK to sessions.id which had no use
- client_id and client.id mismatch ,backup-code consumption
Add flag_modified() calls after modifying provider_data dictionary to
explicitly mark the field as changed. SQLAlchemy does not automatically
track mutations to JSON fields, which could result in changes not being
persisted to the database.