feat: restrict signup invite links to a specific email domain

This commit is contained in:
ItalyPaleAle
2026-07-16 06:44:59 -07:00
parent 525946e94e
commit fdfaac8a35
25 changed files with 442 additions and 35 deletions
+28 -5
View File
@@ -1,6 +1,7 @@
package usersignup
import (
"strings"
"time"
"github.com/pocket-id/pocket-id/backend/internal/model"
@@ -11,11 +12,12 @@ import (
type SignupToken struct {
model.Base
Token string `json:"token"`
ExpiresAt datatype.DateTime `json:"expiresAt" sortable:"true"`
UsageLimit int `json:"usageLimit" sortable:"true"`
UsageCount int `json:"usageCount" sortable:"true"`
UserGroups []model.UserGroup `gorm:"many2many:signup_tokens_user_groups;"`
Token string `json:"token"`
ExpiresAt datatype.DateTime `json:"expiresAt" sortable:"true"`
UsageLimit int `json:"usageLimit" sortable:"true"`
UsageCount int `json:"usageCount" sortable:"true"`
EmailDomain *string `json:"emailDomain"`
UserGroups []model.UserGroup `gorm:"many2many:signup_tokens_user_groups;"`
}
func (st *SignupToken) IsExpired() bool {
@@ -29,3 +31,24 @@ func (st *SignupToken) IsUsageLimitReached() bool {
func (st *SignupToken) IsValid() bool {
return !st.IsExpired() && !st.IsUsageLimitReached()
}
// HasEmailDomainRestriction reports whether the token limits sign-ups to a specific email domain
func (st *SignupToken) HasEmailDomainRestriction() bool {
return st.EmailDomain != nil && *st.EmailDomain != ""
}
// EmailMatchesDomain reports whether the given email address is allowed by the token's domain restriction
// It returns true when the token has no restriction
// The comparison is case-insensitive
func (st *SignupToken) EmailMatchesDomain(email string) bool {
if !st.HasEmailDomainRestriction() {
return true
}
at := strings.LastIndexByte(email, '@')
if at < 0 {
return false
}
return strings.EqualFold(email[at+1:], *st.EmailDomain)
}