Skip to content

Commit 75622c0

Browse files
committed
feat(auth): add ACKIFY_ORGANISATION_DOMAIN to restrict document creation by email domain
When set, only users whose email matches the organisation domain can create documents. Admins bypass this restriction. Empty value preserves current behavior (all users allowed). Exposed in admin settings UI and install script.
1 parent 5bdaf1b commit 75622c0

20 files changed

Lines changed: 84 additions & 16 deletions

File tree

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Application Configuration
22
ACKIFY_BASE_URL=https://sign.your-domain.com
33
ACKIFY_ORGANISATION="Your Organization Name"
4+
# Optional: Restrict document creation to users with this email domain
5+
# Leave empty to allow all authenticated users to create documents
6+
# ACKIFY_ORGANISATION_DOMAIN=your-company.com
47
ACKIFY_LOG_LEVEL=info
58
ACKIFY_LOG_FORMAT=classic
69

backend/internal/application/services/config_service.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ func (s *ConfigService) seedFromENV(ctx context.Context) error {
366366
general := models.GeneralConfig{
367367
Organisation: s.envConfig.App.Organisation,
368368
OnlyAdminCanCreate: s.envConfig.App.OnlyAdminCanCreate,
369+
OrganisationDomain: s.envConfig.App.OrganisationDomain,
369370
AllowedDomains: s.envConfig.App.AllowedDomains,
370371
}
371372
if err := s.upsertSection(ctx, models.ConfigCategoryGeneral, general, nil, "system"); err != nil {

backend/internal/presentation/api/config/handler.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ func NewHandler(configProvider configProvider) *Handler {
2727

2828
// Response represents the public configuration exposed to the frontend
2929
type Response struct {
30-
SMTPEnabled bool `json:"smtpEnabled"`
31-
StorageEnabled bool `json:"storageEnabled"`
32-
OnlyAdminCanCreate bool `json:"onlyAdminCanCreate"`
33-
OAuthEnabled bool `json:"oauthEnabled"`
34-
MagicLinkEnabled bool `json:"magicLinkEnabled"`
30+
SMTPEnabled bool `json:"smtpEnabled"`
31+
StorageEnabled bool `json:"storageEnabled"`
32+
OnlyAdminCanCreate bool `json:"onlyAdminCanCreate"`
33+
OrganisationDomain string `json:"organisationDomain"`
34+
OAuthEnabled bool `json:"oauthEnabled"`
35+
MagicLinkEnabled bool `json:"magicLinkEnabled"`
3536
}
3637

3738
// HandleGetConfig handles GET /api/v1/config
@@ -42,6 +43,7 @@ func (h *Handler) HandleGetConfig(w http.ResponseWriter, r *http.Request) {
4243
SMTPEnabled: cfg.SMTP.IsConfigured(),
4344
StorageEnabled: cfg.Storage.IsEnabled(),
4445
OnlyAdminCanCreate: cfg.General.OnlyAdminCanCreate,
46+
OrganisationDomain: cfg.General.OrganisationDomain,
4547
OAuthEnabled: cfg.OIDC.Enabled,
4648
MagicLinkEnabled: cfg.MagicLink.Enabled,
4749
}

backend/pkg/config/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ type AppConfig struct {
6767
SecureCookies bool
6868
AdminEmails []string
6969
OnlyAdminCanCreate bool
70+
OrganisationDomain string // If set, only users with this email domain can create documents
7071
AllowedDomains []string // Whitelist of allowed domains for document URLs (supports wildcards like *.company.com)
7172
SMTPEnabled bool // True if SMTP is configured (for email reminders)
7273
AuthRateLimit int // Global auth rate limit (requests per minute), default: 5
@@ -238,6 +239,9 @@ func Load() (*Config, error) {
238239
// Parse admin-only document creation flag
239240
config.App.OnlyAdminCanCreate = getEnvBool("ACKIFY_ONLY_ADMIN_CAN_CREATE", false)
240241

242+
// Parse organisation domain for document creation restriction
243+
config.App.OrganisationDomain = strings.TrimSpace(getEnv("ACKIFY_ORGANISATION_DOMAIN", ""))
244+
241245
// Parse allowed domains whitelist for document URLs
242246
allowedDomainsStr := getEnv("ACKIFY_ALLOWED_DOMAINS", "")
243247
if allowedDomainsStr != "" {

backend/pkg/models/tenant_config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type TenantConfig struct {
5757
type GeneralConfig struct {
5858
Organisation string `json:"organisation"`
5959
OnlyAdminCanCreate bool `json:"only_admin_can_create"`
60+
OrganisationDomain string `json:"organisation_domain"`
6061
AllowedDomains []string `json:"allowed_domains"`
6162
}
6263

backend/pkg/web/auth/simple_authorizer.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,18 @@ func (a *SimpleAuthorizer) IsAdmin(_ context.Context, userEmail string) bool {
4444

4545
// CanCreateDocument implements providers.Authorizer.
4646
func (a *SimpleAuthorizer) CanCreateDocument(ctx context.Context, userEmail string) bool {
47-
cfg := a.configProvider.GetConfig()
48-
if !cfg.General.OnlyAdminCanCreate {
47+
if a.IsAdmin(ctx, userEmail) {
4948
return true
5049
}
51-
return a.IsAdmin(ctx, userEmail)
50+
cfg := a.configProvider.GetConfig()
51+
if cfg.General.OnlyAdminCanCreate {
52+
return false
53+
}
54+
if domain := cfg.General.OrganisationDomain; domain != "" {
55+
normalized := strings.ToLower(strings.TrimSpace(userEmail))
56+
return strings.HasSuffix(normalized, "@"+strings.ToLower(domain))
57+
}
58+
return true
5259
}
5360

5461
// CanManageDocument implements providers.Authorizer.

compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ services:
2626
ACKIFY_LOG_LEVEL: "${ACKIFY_LOG_LEVEL}"
2727
ACKIFY_BASE_URL: "${ACKIFY_BASE_URL}"
2828
ACKIFY_ORGANISATION: "${ACKIFY_ORGANISATION}"
29+
ACKIFY_ORGANISATION_DOMAIN: "${ACKIFY_ORGANISATION_DOMAIN:-}"
2930
ACKIFY_DB_DSN: "postgres://ackify_app:${ACKIFY_APP_PASSWORD}@ackify-db:5432/ackify?sslmode=disable"
3031
ACKIFY_OAUTH_PROVIDER: "${ACKIFY_OAUTH_PROVIDER}"
3132
ACKIFY_OAUTH_CLIENT_ID: "${ACKIFY_OAUTH_CLIENT_ID}"

install/.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
ACKIFY_BASE_URL=https://your-domain.com
99
ACKIFY_ORGANISATION="Your Organization Name"
1010

11+
# Optional: Restrict document creation to users with this email domain
12+
# Leave empty to allow all authenticated users to create documents
13+
# ACKIFY_ORGANISATION_DOMAIN=your-company.com
14+
1115
# ==========================================
1216
# Database Configuration
1317
# ==========================================

install/compose.yml.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ services:
2626
ACKIFY_LOG_FORMAT: "${ACKIFY_LOG_FORMAT:-classic}"
2727
ACKIFY_BASE_URL: "${ACKIFY_BASE_URL}"
2828
ACKIFY_ORGANISATION: "${ACKIFY_ORGANISATION}"
29+
ACKIFY_ORGANISATION_DOMAIN: "${ACKIFY_ORGANISATION_DOMAIN:-}"
2930
ACKIFY_ADMIN_EMAILS: "${ACKIFY_ADMIN_EMAILS}"
3031
ACKIFY_ONLY_ADMIN_CAN_CREATE: "${ACKIFY_ONLY_ADMIN_CAN_CREATE:-false}"
3132
ACKIFY_LISTEN_ADDR: ":8080"

install/install.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,19 @@ if [ "$UPDATE_MODE" = true ] && has_env "ACKIFY_BASE_URL"; then
245245
# Use existing values in update mode
246246
APP_BASE_URL=$(get_env "ACKIFY_BASE_URL")
247247
APP_ORGANISATION=$(get_env "ACKIFY_ORGANISATION")
248+
APP_ORGANISATION_DOMAIN=$(get_env "ACKIFY_ORGANISATION_DOMAIN")
248249
print_header "🌐 Basic Configuration (existing)"
249250
print_success "Base URL: ${APP_BASE_URL}"
250251
print_success "Organization: ${APP_ORGANISATION}"
252+
if [ -n "$APP_ORGANISATION_DOMAIN" ]; then
253+
print_success "Organization Domain: ${APP_ORGANISATION_DOMAIN}"
254+
fi
251255
else
252256
print_header "🌐 Basic Configuration"
253257
echo ""
254258
APP_BASE_URL=$(prompt_input "Application Base URL (e.g., https://ackify.example.com)" "http://localhost:8080")
255259
APP_ORGANISATION=$(prompt_input "Organization Name" "My Organization")
260+
APP_ORGANISATION_DOMAIN=$(prompt_input "Organization Email Domain (e.g., company.com, leave empty to allow all)" "")
256261
print_success "Base configuration set"
257262
fi
258263

@@ -889,6 +894,7 @@ cat > .env <<EOF
889894
# ==========================================
890895
ACKIFY_BASE_URL=${APP_BASE_URL}
891896
ACKIFY_ORGANISATION=${APP_ORGANISATION}
897+
ACKIFY_ORGANISATION_DOMAIN=${APP_ORGANISATION_DOMAIN}
892898

893899
# ==========================================
894900
# Database Configuration

0 commit comments

Comments
 (0)