feat: disable signups (#643)

* feat: disable signups

* feat: ui and password

* merge main

* fix: disable allow oauth
This commit is contained in:
Gabe Ruttner
2024-06-26 13:12:40 -07:00
committed by GitHub
parent dc2b544ba8
commit 35979bea68
16 changed files with 307 additions and 176 deletions
@@ -9,6 +9,22 @@ APIMeta:
example: 12345678-1234-1234-1234-123456789012
posthog:
$ref: "#/APIMetaPosthog"
allowSignup:
type: boolean
description: whether or not users can sign up for this instance
example: true
allowInvites:
type: boolean
description: whether or not users can invite other users to this instance
example: true
allowCreateTenant:
type: boolean
description: whether or not users can create new tenants
example: true
allowChangePassword:
type: boolean
description: whether or not users can change their password
example: true
APIMetaAuth:
type: object
+6 -2
View File
@@ -36,8 +36,12 @@ func (u *MetadataService) MetadataGet(ctx echo.Context, request gen.MetadataGetR
Auth: &gen.APIMetaAuth{
Schemes: &authTypes,
},
PylonAppId: &pylonAppID,
Posthog: posthogConfig,
PylonAppId: &pylonAppID,
Posthog: posthogConfig,
AllowSignup: &u.config.Runtime.AllowSignup,
AllowInvites: &u.config.Runtime.AllowInvites,
AllowCreateTenant: &u.config.Runtime.AllowCreateTenant,
AllowChangePassword: &u.config.Runtime.AllowChangePassword,
}
return gen.MetadataGet200JSONResponse(meta), nil
+6
View File
@@ -16,6 +16,12 @@ import (
func (t *TenantService) TenantCreate(ctx echo.Context, request gen.TenantCreateRequestObject) (gen.TenantCreateResponseObject, error) {
user := ctx.Get("user").(*db.UserModel)
if !t.config.Runtime.AllowCreateTenant {
return gen.TenantCreate400JSONResponse(
apierrors.NewAPIErrors("tenant signups are disabled"),
), nil
}
// validate the request
if apiErrors, err := t.config.Validator.ValidateAPI(request.Body); err != nil {
return nil, err
@@ -19,6 +19,12 @@ func (t *TenantService) TenantInviteCreate(ctx echo.Context, request gen.TenantI
tenant := ctx.Get("tenant").(*db.TenantModel)
tenantMember := ctx.Get("tenant-member").(*db.TenantMemberModel)
if !t.config.Runtime.AllowInvites {
return gen.TenantInviteCreate400JSONResponse(
apierrors.NewAPIErrors("tenant invites are disabled"),
), nil
}
// validate the request
if apiErrors, err := t.config.Validator.ValidateAPI(request.Body); err != nil {
return nil, err
+7
View File
@@ -15,6 +15,13 @@ import (
)
func (u *UserService) UserCreate(ctx echo.Context, request gen.UserCreateRequestObject) (gen.UserCreateResponseObject, error) {
if !u.config.Runtime.AllowSignup {
return gen.UserCreate400JSONResponse(
apierrors.NewAPIErrors("user signups are disabled"),
), nil
}
// validate the request
if apiErrors, err := u.config.Validator.ValidateAPI(request.Body); err != nil {
return nil, err
@@ -10,6 +10,10 @@ import (
// Note: we want all errors to redirect, otherwise the user will be greeted with raw JSON in the middle of the login flow.
func (u *UserService) UserUpdateGithubOauthStart(ctx echo.Context, _ gen.UserUpdateGithubOauthStartRequestObject) (gen.UserUpdateGithubOauthStartResponseObject, error) {
if !u.config.Runtime.AllowSignup {
return nil, redirect.GetRedirectWithError(ctx, u.config.Logger, nil, "User signup is disabled.")
}
state, err := authn.NewSessionHelpers(u.config).SaveOAuthState(ctx, "github")
if err != nil {
@@ -10,6 +10,10 @@ import (
// Note: we want all errors to redirect, otherwise the user will be greeted with raw JSON in the middle of the login flow.
func (u *UserService) UserUpdateGoogleOauthStart(ctx echo.Context, _ gen.UserUpdateGoogleOauthStartRequestObject) (gen.UserUpdateGoogleOauthStartResponseObject, error) {
if !u.config.Runtime.AllowSignup {
return nil, redirect.GetRedirectWithError(ctx, u.config.Logger, nil, "User signup is disabled.")
}
state, err := authn.NewSessionHelpers(u.config).SaveOAuthState(ctx, "google")
if err != nil {
@@ -16,6 +16,12 @@ func (u *UserService) UserUpdatePassword(ctx echo.Context, request gen.UserUpdat
// determine if the user exists before attempting to write the user
existingUser := ctx.Get("user").(*db.UserModel)
if !u.config.Runtime.AllowChangePassword {
return gen.UserUpdatePassword405JSONResponse(
apierrors.NewAPIErrors("password changes are disabled"),
), nil
}
// check that the server supports local registration
if !u.config.Auth.ConfigFile.BasicAuthEnabled {
return gen.UserUpdatePassword405JSONResponse(
+164 -151
View File
@@ -163,8 +163,19 @@ type APIErrors struct {
// APIMeta defines model for APIMeta.
type APIMeta struct {
Auth *APIMetaAuth `json:"auth,omitempty"`
Posthog *APIMetaPosthog `json:"posthog,omitempty"`
// AllowChangePassword whether or not users can change their password
AllowChangePassword *bool `json:"allowChangePassword,omitempty"`
// AllowCreateTenant whether or not users can create new tenants
AllowCreateTenant *bool `json:"allowCreateTenant,omitempty"`
// AllowInvites whether or not users can invite other users to this instance
AllowInvites *bool `json:"allowInvites,omitempty"`
// AllowSignup whether or not users can sign up for this instance
AllowSignup *bool `json:"allowSignup,omitempty"`
Auth *APIMetaAuth `json:"auth,omitempty"`
Posthog *APIMetaPosthog `json:"posthog,omitempty"`
// PylonAppId the Pylon app ID for usepylon.com chat support
PylonAppId *string `json:"pylonAppId,omitempty"`
@@ -7775,155 +7786,157 @@ func (sh *strictHandler) WorkflowVersionGetDefinition(ctx echo.Context, workflow
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
"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",
"9iF+UPIiw5F/7Psvty//GwAA//+uriXuBWoBAA==",
"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",
"DdOoEd9rAQA=",
}
// GetSwagger returns the content of the embedded swagger specification file
@@ -24,6 +24,7 @@ import {
import React from 'react';
import { useTenantContext } from '@/lib/atoms';
import { Spinner } from '@/components/ui/loading.tsx';
import useApiMeta from '@/pages/auth/hooks/use-api-meta';
interface TenantSwitcherProps {
className?: string;
@@ -35,6 +36,7 @@ export function TenantSwitcher({
memberships,
currTenant,
}: TenantSwitcherProps) {
const meta = useApiMeta();
const setCurrTenant = useTenantContext()[1];
const [open, setOpen] = React.useState(false);
@@ -85,15 +87,19 @@ export function TenantSwitcher({
</CommandItem>
))}
</CommandList>
<CommandSeparator />
<CommandList>
<Link to="/onboarding/create-tenant">
<CommandItem className="text-sm cursor-pointer">
<PlusCircledIcon className="mr-2 h-4 w-4" />
New Tenant
</CommandItem>
</Link>
</CommandList>
{meta?.data?.data.allowCreateTenant && (
<>
<CommandSeparator />
<CommandList>
<Link to="/onboarding/create-tenant">
<CommandItem className="text-sm cursor-pointer">
<PlusCircledIcon className="mr-2 h-4 w-4" />
New Tenant
</CommandItem>
</Link>
</CommandList>
</>
)}
</Command>
</PopoverContent>
</Popover>
@@ -17,6 +17,26 @@ export interface APIMeta {
*/
pylonAppId?: string;
posthog?: APIMetaPosthog;
/**
* whether or not users can sign up for this instance
* @example true
*/
allowSignup?: boolean;
/**
* whether or not users can invite other users to this instance
* @example true
*/
allowInvites?: boolean;
/**
* whether or not users can create new tenants
* @example true
*/
allowCreateTenant?: boolean;
/**
* whether or not users can change their password
* @example true
*/
allowChangePassword?: boolean;
}
export interface APIMetaAuth {
+11 -9
View File
@@ -47,15 +47,17 @@ export default function Login() {
return (
<div className="flex flex-row flex-1 w-full h-full">
<div className="container relative hidden flex-col items-center justify-center md:grid lg:max-w-none lg:grid-cols-2 lg:px-0">
<Link
to="/auth/register"
className={cn(
buttonVariants({ variant: 'ghost' }),
'absolute right-4 top-4 md:right-8 md:top-8',
)}
>
Register
</Link>
{meta?.data?.data.allowSignup && (
<Link
to="/auth/register"
className={cn(
buttonVariants({ variant: 'ghost' }),
'absolute right-4 top-4 md:right-8 md:top-8',
)}
>
Sign Up
</Link>
)}
<div className="lg:p-8 mx-auto w-screen">
<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<div className="flex flex-col space-y-2 text-center">
@@ -11,6 +11,7 @@ import { useApiError } from '@/lib/hooks';
import queryClient from '@/query-client';
import { ConfirmDialog } from '@/components/molecules/confirm-dialog';
import { useState } from 'react';
import useApiMeta from '@/pages/auth/hooks/use-api-meta';
export const columns = ({
onChangePasswordClick,
@@ -73,6 +74,7 @@ function MemberActions({
row: Row<TenantMember>;
onChangePasswordClick: (row: TenantMember) => void;
}) {
const meta = useApiMeta();
const { user } = useOutletContext<UserContextType>();
const { tenant } = useOutletContext<TenantContextType>();
@@ -85,7 +87,7 @@ function MemberActions({
const isCurrent = row.original.user.email !== user.email;
if (user.hasPassword && !isCurrent) {
if (user.hasPassword && !isCurrent && meta.data?.data.allowChangePassword) {
actions.push({
label: 'Change Password',
onClick: () => onChangePasswordClick(row.original),
@@ -21,8 +21,11 @@ import { UpdateInviteForm } from './components/update-invite-form';
import { DeleteInviteForm } from './components/delete-invite-form';
import { ChangePasswordDialog } from './components/change-password-dialog';
import { AxiosError } from 'axios';
import useApiMeta from '@/pages/auth/hooks/use-api-meta';
export default function Members() {
const meta = useApiMeta();
return (
<div className="flex-grow h-full w-full">
<div className="mx-auto max-w-7xl py-8 px-4 sm:px-6 lg:px-8">
@@ -31,8 +34,12 @@ export default function Members() {
</h2>
<Separator className="my-4" />
<MembersList />
<Separator className="my-4" />
<InvitesList />
{meta?.data?.data.allowInvites && (
<>
<Separator className="my-4" />
<InvitesList />
</>
)}
</div>
</div>
);
+13 -2
View File
@@ -160,8 +160,19 @@ type APIErrors struct {
// APIMeta defines model for APIMeta.
type APIMeta struct {
Auth *APIMetaAuth `json:"auth,omitempty"`
Posthog *APIMetaPosthog `json:"posthog,omitempty"`
// AllowChangePassword whether or not users can change their password
AllowChangePassword *bool `json:"allowChangePassword,omitempty"`
// AllowCreateTenant whether or not users can create new tenants
AllowCreateTenant *bool `json:"allowCreateTenant,omitempty"`
// AllowInvites whether or not users can invite other users to this instance
AllowInvites *bool `json:"allowInvites,omitempty"`
// AllowSignup whether or not users can sign up for this instance
AllowSignup *bool `json:"allowSignup,omitempty"`
Auth *APIMetaAuth `json:"auth,omitempty"`
Posthog *APIMetaPosthog `json:"posthog,omitempty"`
// PylonAppId the Pylon app ID for usepylon.com chat support
PylonAppId *string `json:"pylonAppId,omitempty"`
+17
View File
@@ -76,7 +76,20 @@ type ConfigFileRuntime struct {
// Enforce limits controls whether the server enforces tenant limits
EnforceLimits bool `mapstructure:"enforceLimits" json:"enforceLimits,omitempty" default:"false"`
// Default limit values
Limits LimitConfigFile `mapstructure:"limits" json:"limits,omitempty"`
// Allow new tenants to be created
AllowSignup bool `mapstructure:"allowSignup" json:"allowSignup,omitempty" default:"true"`
// Allow new invites to be created
AllowInvites bool `mapstructure:"allowInvites" json:"allowInvites,omitempty" default:"true"`
// Allow new tenants to be created
AllowCreateTenant bool `mapstructure:"allowCreateTenant" json:"allowCreateTenant,omitempty" default:"true"`
// Allow passwords to be changed
AllowChangePassword bool `mapstructure:"allowChangePassword" json:"allowChangePassword,omitempty" default:"true"`
}
type LimitConfigFile struct {
@@ -341,6 +354,10 @@ func BindAllEnv(v *viper.Viper) {
_ = v.BindEnv("runtime.shutdownWait", "SERVER_SHUTDOWN_WAIT")
_ = v.BindEnv("services", "SERVER_SERVICES")
_ = v.BindEnv("runtime.enforceLimits", "SERVER_ENFORCE_LIMITS")
_ = v.BindEnv("runtime.allowSignup", "SERVER_ALLOW_SIGNUP")
_ = v.BindEnv("runtime.allowInvites", "SERVER_ALLOW_INVITES")
_ = v.BindEnv("runtime.allowCreateTenant", "SERVER_ALLOW_CREATE_TENANT")
_ = v.BindEnv("runtime.allowChangePassword", "SERVER_ALLOW_CHANGE_PASSWORD")
// limit options
_ = v.BindEnv("runtime.limits.defaultWorkflowRunLimit", "SERVER_LIMITS_DEFAULT_WORKFLOW_RUN_LIMIT")