From 96edb43b6787eb86d9ba9f888f7096bf8d57dcc7 Mon Sep 17 00:00:00 2001 From: Anik Ghosh Date: Wed, 16 Mar 2022 22:49:18 +0530 Subject: [PATCH] feat: disable user signup --- dashboard/src/constants.ts | 1 + dashboard/src/graphql/queries/index.ts | 1 + dashboard/src/pages/Environment.tsx | 14 ++++ dashboard/src/pages/Users.tsx | 1 + server/constants/env.go | 2 + server/env/env.go | 1 + server/envstore/store.go | 1 + server/graph/generated/generated.go | 101 +++++++++++++++++++++++++ server/graph/model/models_gen.go | 3 + server/graph/schema.graphqls | 3 + server/handlers/oauth_callback.go | 4 + server/resolvers/env.go | 2 + server/resolvers/magic_link_login.go | 5 +- server/resolvers/signup.go | 5 ++ server/utils/meta.go | 1 + 15 files changed, 144 insertions(+), 1 deletion(-) diff --git a/dashboard/src/constants.ts b/dashboard/src/constants.ts index ead6fdd..582ca52 100644 --- a/dashboard/src/constants.ts +++ b/dashboard/src/constants.ts @@ -60,6 +60,7 @@ export const SwitchInputType = { DISABLE_MAGIC_LINK_LOGIN: 'DISABLE_MAGIC_LINK_LOGIN', DISABLE_EMAIL_VERIFICATION: 'DISABLE_EMAIL_VERIFICATION', DISABLE_BASIC_AUTHENTICATION: 'DISABLE_BASIC_AUTHENTICATION', + DISABLE_SIGN_UP: 'DISABLE_SIGN_UP', }; export const DateInputType = { diff --git a/dashboard/src/graphql/queries/index.ts b/dashboard/src/graphql/queries/index.ts index 698452e..fe35528 100644 --- a/dashboard/src/graphql/queries/index.ts +++ b/dashboard/src/graphql/queries/index.ts @@ -48,6 +48,7 @@ export const EnvVariablesQuery = ` DISABLE_MAGIC_LINK_LOGIN, DISABLE_EMAIL_VERIFICATION, DISABLE_BASIC_AUTHENTICATION, + DISABLE_SIGN_UP, CUSTOM_ACCESS_TOKEN_SCRIPT, DATABASE_NAME, DATABASE_TYPE, diff --git a/dashboard/src/pages/Environment.tsx b/dashboard/src/pages/Environment.tsx index 06480bc..f3df0e6 100644 --- a/dashboard/src/pages/Environment.tsx +++ b/dashboard/src/pages/Environment.tsx @@ -68,6 +68,7 @@ interface envVarTypes { DISABLE_MAGIC_LINK_LOGIN: boolean; DISABLE_EMAIL_VERIFICATION: boolean; DISABLE_BASIC_AUTHENTICATION: boolean; + DISABLE_SIGN_UP: boolean; OLD_ADMIN_SECRET: string; DATABASE_NAME: string; DATABASE_TYPE: string; @@ -114,6 +115,7 @@ export default function Environment() { DISABLE_MAGIC_LINK_LOGIN: false, DISABLE_EMAIL_VERIFICATION: false, DISABLE_BASIC_AUTHENTICATION: false, + DISABLE_SIGN_UP: false, OLD_ADMIN_SECRET: '', DATABASE_NAME: '', DATABASE_TYPE: '', @@ -694,6 +696,18 @@ export default function Environment() { /> + + + Disable Sign Up: + + + + + diff --git a/dashboard/src/pages/Users.tsx b/dashboard/src/pages/Users.tsx index a9d1d05..09d8171 100644 --- a/dashboard/src/pages/Users.tsx +++ b/dashboard/src/pages/Users.tsx @@ -184,6 +184,7 @@ export default function Users() { } updateUserList(); }; + console.log('userList ==>> ', userList); return ( diff --git a/server/constants/env.go b/server/constants/env.go index 4206c37..f391750 100644 --- a/server/constants/env.go +++ b/server/constants/env.go @@ -67,6 +67,8 @@ const ( EnvKeyDisableMagicLinkLogin = "DISABLE_MAGIC_LINK_LOGIN" // EnvKeyDisableLoginPage key for env variable DISABLE_LOGIN_PAGE EnvKeyDisableLoginPage = "DISABLE_LOGIN_PAGE" + // EnvKeyDisableSignUp key for env variable DISABLE_SIGN_UP + EnvKeyDisableSignUp = "DISABLE_SIGN_UP" // EnvKeyRoles key for env variable ROLES EnvKeyRoles = "ROLES" // EnvKeyProtectedRoles key for env variable PROTECTED_ROLES diff --git a/server/env/env.go b/server/env/env.go index d430e2f..8770441 100644 --- a/server/env/env.go +++ b/server/env/env.go @@ -281,6 +281,7 @@ func InitAllEnv() error { envData.BoolEnv[constants.EnvKeyDisableEmailVerification] = os.Getenv(constants.EnvKeyDisableEmailVerification) == "true" envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = os.Getenv(constants.EnvKeyDisableMagicLinkLogin) == "true" envData.BoolEnv[constants.EnvKeyDisableLoginPage] = os.Getenv(constants.EnvKeyDisableLoginPage) == "true" + envData.BoolEnv[constants.EnvKeyDisableSignUp] = os.Getenv(constants.EnvKeyDisableSignUp) == "true" // no need to add nil check as its already done above if envData.StringEnv[constants.EnvKeySmtpHost] == "" || envData.StringEnv[constants.EnvKeySmtpUsername] == "" || envData.StringEnv[constants.EnvKeySmtpPassword] == "" || envData.StringEnv[constants.EnvKeySenderEmail] == "" && envData.StringEnv[constants.EnvKeySmtpPort] == "" { diff --git a/server/envstore/store.go b/server/envstore/store.go index c7cb122..e473615 100644 --- a/server/envstore/store.go +++ b/server/envstore/store.go @@ -41,6 +41,7 @@ var defaultStore = &EnvStore{ constants.EnvKeyDisableMagicLinkLogin: false, constants.EnvKeyDisableEmailVerification: false, constants.EnvKeyDisableLoginPage: false, + constants.EnvKeyDisableSignUp: false, }, SliceEnv: map[string][]string{}, }, diff --git a/server/graph/generated/generated.go b/server/graph/generated/generated.go index 92150c2..3dd7e42 100644 --- a/server/graph/generated/generated.go +++ b/server/graph/generated/generated.go @@ -68,6 +68,7 @@ type ComplexityRoot struct { DisableEmailVerification func(childComplexity int) int DisableLoginPage func(childComplexity int) int DisableMagicLinkLogin func(childComplexity int) int + DisableSignUp func(childComplexity int) int FacebookClientID func(childComplexity int) int FacebookClientSecret func(childComplexity int) int GithubClientID func(childComplexity int) int @@ -105,6 +106,7 @@ type ComplexityRoot struct { IsGithubLoginEnabled func(childComplexity int) int IsGoogleLoginEnabled func(childComplexity int) int IsMagicLinkLoginEnabled func(childComplexity int) int + IsSignUpEnabled func(childComplexity int) int Version func(childComplexity int) int } @@ -383,6 +385,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Env.DisableMagicLinkLogin(childComplexity), true + case "Env.DISABLE_SIGN_UP": + if e.complexity.Env.DisableSignUp == nil { + break + } + + return e.complexity.Env.DisableSignUp(childComplexity), true + case "Env.FACEBOOK_CLIENT_ID": if e.complexity.Env.FacebookClientID == nil { break @@ -600,6 +609,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Meta.IsMagicLinkLoginEnabled(childComplexity), true + case "Meta.is_sign_up_enabled": + if e.complexity.Meta.IsSignUpEnabled == nil { + break + } + + return e.complexity.Meta.IsSignUpEnabled(childComplexity), true + case "Meta.version": if e.complexity.Meta.Version == nil { break @@ -1197,6 +1213,7 @@ type Meta { is_email_verification_enabled: Boolean! is_basic_authentication_enabled: Boolean! is_magic_link_login_enabled: Boolean! + is_sign_up_enabled: Boolean! } type User { @@ -1286,6 +1303,7 @@ type Env { DISABLE_BASIC_AUTHENTICATION: Boolean DISABLE_MAGIC_LINK_LOGIN: Boolean DISABLE_LOGIN_PAGE: Boolean + DISABLE_SIGN_UP: Boolean ROLES: [String!] PROTECTED_ROLES: [String!] DEFAULT_ROLES: [String!] @@ -1322,6 +1340,7 @@ input UpdateEnvInput { DISABLE_BASIC_AUTHENTICATION: Boolean DISABLE_MAGIC_LINK_LOGIN: Boolean DISABLE_LOGIN_PAGE: Boolean + DISABLE_SIGN_UP: Boolean ROLES: [String!] PROTECTED_ROLES: [String!] DEFAULT_ROLES: [String!] @@ -2826,6 +2845,38 @@ func (ec *executionContext) _Env_DISABLE_LOGIN_PAGE(ctx context.Context, field g return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) } +func (ec *executionContext) _Env_DISABLE_SIGN_UP(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Env", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DisableSignUp, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*bool) + fc.Result = res + return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) +} + func (ec *executionContext) _Env_ROLES(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -3560,6 +3611,41 @@ func (ec *executionContext) _Meta_is_magic_link_login_enabled(ctx context.Contex return ec.marshalNBoolean2bool(ctx, field.Selections, res) } +func (ec *executionContext) _Meta_is_sign_up_enabled(ctx context.Context, field graphql.CollectedField, obj *model.Meta) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Meta", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsSignUpEnabled, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + func (ec *executionContext) _Mutation_signup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -7607,6 +7693,14 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob if err != nil { return it, err } + case "DISABLE_SIGN_UP": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("DISABLE_SIGN_UP")) + it.DisableSignUp, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } case "ROLES": var err error @@ -8075,6 +8169,8 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj out.Values[i] = ec._Env_DISABLE_MAGIC_LINK_LOGIN(ctx, field, obj) case "DISABLE_LOGIN_PAGE": out.Values[i] = ec._Env_DISABLE_LOGIN_PAGE(ctx, field, obj) + case "DISABLE_SIGN_UP": + out.Values[i] = ec._Env_DISABLE_SIGN_UP(ctx, field, obj) case "ROLES": out.Values[i] = ec._Env_ROLES(ctx, field, obj) case "PROTECTED_ROLES": @@ -8193,6 +8289,11 @@ func (ec *executionContext) _Meta(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalids++ } + case "is_sign_up_enabled": + out.Values[i] = ec._Meta_is_sign_up_enabled(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } diff --git a/server/graph/model/models_gen.go b/server/graph/model/models_gen.go index 9c02828..1ebad63 100644 --- a/server/graph/model/models_gen.go +++ b/server/graph/model/models_gen.go @@ -49,6 +49,7 @@ type Env struct { DisableBasicAuthentication *bool `json:"DISABLE_BASIC_AUTHENTICATION"` DisableMagicLinkLogin *bool `json:"DISABLE_MAGIC_LINK_LOGIN"` DisableLoginPage *bool `json:"DISABLE_LOGIN_PAGE"` + DisableSignUp *bool `json:"DISABLE_SIGN_UP"` Roles []string `json:"ROLES"` ProtectedRoles []string `json:"PROTECTED_ROLES"` DefaultRoles []string `json:"DEFAULT_ROLES"` @@ -103,6 +104,7 @@ type Meta struct { IsEmailVerificationEnabled bool `json:"is_email_verification_enabled"` IsBasicAuthenticationEnabled bool `json:"is_basic_authentication_enabled"` IsMagicLinkLoginEnabled bool `json:"is_magic_link_login_enabled"` + IsSignUpEnabled bool `json:"is_sign_up_enabled"` } type OAuthRevokeInput struct { @@ -184,6 +186,7 @@ type UpdateEnvInput struct { DisableBasicAuthentication *bool `json:"DISABLE_BASIC_AUTHENTICATION"` DisableMagicLinkLogin *bool `json:"DISABLE_MAGIC_LINK_LOGIN"` DisableLoginPage *bool `json:"DISABLE_LOGIN_PAGE"` + DisableSignUp *bool `json:"DISABLE_SIGN_UP"` Roles []string `json:"ROLES"` ProtectedRoles []string `json:"PROTECTED_ROLES"` DefaultRoles []string `json:"DEFAULT_ROLES"` diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls index fdea73d..13f2a1b 100644 --- a/server/graph/schema.graphqls +++ b/server/graph/schema.graphqls @@ -21,6 +21,7 @@ type Meta { is_email_verification_enabled: Boolean! is_basic_authentication_enabled: Boolean! is_magic_link_login_enabled: Boolean! + is_sign_up_enabled: Boolean! } type User { @@ -110,6 +111,7 @@ type Env { DISABLE_BASIC_AUTHENTICATION: Boolean DISABLE_MAGIC_LINK_LOGIN: Boolean DISABLE_LOGIN_PAGE: Boolean + DISABLE_SIGN_UP: Boolean ROLES: [String!] PROTECTED_ROLES: [String!] DEFAULT_ROLES: [String!] @@ -146,6 +148,7 @@ input UpdateEnvInput { DISABLE_BASIC_AUTHENTICATION: Boolean DISABLE_MAGIC_LINK_LOGIN: Boolean DISABLE_LOGIN_PAGE: Boolean + DISABLE_SIGN_UP: Boolean ROLES: [String!] PROTECTED_ROLES: [String!] DEFAULT_ROLES: [String!] diff --git a/server/handlers/oauth_callback.go b/server/handlers/oauth_callback.go index 1d28234..0c6ffd5 100644 --- a/server/handlers/oauth_callback.go +++ b/server/handlers/oauth_callback.go @@ -71,6 +71,10 @@ func OAuthCallbackHandler() gin.HandlerFunc { existingUser, err := db.Provider.GetUserByEmail(user.Email) if err != nil { + if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) { + c.JSON(400, gin.H{"error": "signup is disabled for this instance"}) + return + } // user not registered, register user and generate session token user.SignupMethods = provider // make sure inputRoles don't include protected roles diff --git a/server/resolvers/env.go b/server/resolvers/env.go index 623d6b3..d56ea89 100644 --- a/server/resolvers/env.go +++ b/server/resolvers/env.go @@ -53,6 +53,7 @@ func EnvResolver(ctx context.Context) (*model.Env, error) { disableBasicAuthentication := store.BoolEnv[constants.EnvKeyDisableBasicAuthentication] disableMagicLinkLogin := store.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] disableLoginPage := store.BoolEnv[constants.EnvKeyDisableLoginPage] + disableSignUp := store.BoolEnv[constants.EnvKeyDisableSignUp] roles := store.SliceEnv[constants.EnvKeyRoles] defaultRoles := store.SliceEnv[constants.EnvKeyDefaultRoles] protectedRoles := store.SliceEnv[constants.EnvKeyProtectedRoles] @@ -92,6 +93,7 @@ func EnvResolver(ctx context.Context) (*model.Env, error) { DisableBasicAuthentication: &disableBasicAuthentication, DisableMagicLinkLogin: &disableMagicLinkLogin, DisableLoginPage: &disableLoginPage, + DisableSignUp: &disableSignUp, Roles: roles, ProtectedRoles: protectedRoles, DefaultRoles: defaultRoles, diff --git a/server/resolvers/magic_link_login.go b/server/resolvers/magic_link_login.go index 05d0708..b69ea91 100644 --- a/server/resolvers/magic_link_login.go +++ b/server/resolvers/magic_link_login.go @@ -43,8 +43,11 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu // find user with email existingUser, err := db.Provider.GetUserByEmail(params.Email) - if err != nil { + if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) { + return res, fmt.Errorf(`signup is disabled for this instance`) + } + user.SignupMethods = constants.SignupMethodMagicLinkLogin // define roles for new user if len(params.Roles) > 0 { diff --git a/server/resolvers/signup.go b/server/resolvers/signup.go index 0f49a87..749f5a1 100644 --- a/server/resolvers/signup.go +++ b/server/resolvers/signup.go @@ -28,9 +28,14 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR return res, err } + if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) { + return res, fmt.Errorf(`signup is disabled for this instance`) + } + if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) { return res, fmt.Errorf(`basic authentication is disabled for this instance`) } + if params.ConfirmPassword != params.Password { return res, fmt.Errorf(`password and confirm password does not match`) } diff --git a/server/utils/meta.go b/server/utils/meta.go index bf33250..18588c4 100644 --- a/server/utils/meta.go +++ b/server/utils/meta.go @@ -17,5 +17,6 @@ func GetMetaInfo() model.Meta { IsBasicAuthenticationEnabled: !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication), IsEmailVerificationEnabled: !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification), IsMagicLinkLoginEnabled: !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin), + IsSignUpEnabled: !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp), } }