* added toggle in dashboard
* fixing issue with env set
This commit is contained in:
lemonScaletech 2023-09-01 19:36:47 +05:30
parent 3f5283bf7f
commit 9fda8c01f5
15 changed files with 289 additions and 7 deletions

View File

@ -4,6 +4,7 @@ import InputField from '../InputField';
import { SwitchInputType } from '../../constants'; import { SwitchInputType } from '../../constants';
const Features = ({ variables, setVariables }: any) => { const Features = ({ variables, setVariables }: any) => {
// window.alert(variables)
return ( return (
<div> <div>
{' '} {' '}
@ -24,6 +25,8 @@ const Features = ({ variables, setVariables }: any) => {
/> />
</Flex> </Flex>
</Flex> </Flex>
<Flex> <Flex>
<Flex w="100%" justifyContent="start" alignItems="center"> <Flex w="100%" justifyContent="start" alignItems="center">
<Text fontSize="sm">Email Verification:</Text> <Text fontSize="sm">Email Verification:</Text>
@ -97,6 +100,7 @@ const Features = ({ variables, setVariables }: any) => {
also ignore the user MFA setting. also ignore the user MFA setting.
</Text> </Text>
</Flex> </Flex>
<Flex justifyContent="start" mb={3}> <Flex justifyContent="start" mb={3}>
<InputField <InputField
variables={variables} variables={variables}
@ -106,6 +110,46 @@ const Features = ({ variables, setVariables }: any) => {
/> />
</Flex> </Flex>
</Flex> </Flex>
{
!variables.DISABLE_MULTI_FACTOR_AUTHENTICATION &&
<Flex alignItems="center">
<Flex w="100%" alignItems="baseline" flexDir="column">
<Text fontSize="sm">TOTP:</Text>
<Text fontSize="x-small">
Note: to enable totp mfa
</Text>
</Flex>
<Flex justifyContent="start" mb={3}>
<InputField
variables={variables}
setVariables={setVariables}
inputType={SwitchInputType.DISABLE_TOTP_LOGIN}
hasReversedValue
/>
</Flex>
</Flex>
}
{!variables.DISABLE_MULTI_FACTOR_AUTHENTICATION &&
<Flex alignItems="center">
<Flex w="100%" alignItems="baseline" flexDir="column">
<Text fontSize="sm">EMAIL OTP:</Text>
<Text fontSize="x-small">
Note: to enable email otp mfa
</Text>
</Flex>
<Flex justifyContent="start" mb={3}>
<InputField
variables={variables}
setVariables={setVariables}
inputType={SwitchInputType.DISABLE_MAIL_OTP_LOGIN}
hasReversedValue
/>
</Flex>
</Flex>}
<Flex alignItems="center"> <Flex alignItems="center">
<Flex w="100%" alignItems="baseline" flexDir="column"> <Flex w="100%" alignItems="baseline" flexDir="column">
<Text fontSize="sm"> <Text fontSize="sm">

View File

@ -85,6 +85,8 @@ export const SwitchInputType = {
DISABLE_MULTI_FACTOR_AUTHENTICATION: 'DISABLE_MULTI_FACTOR_AUTHENTICATION', DISABLE_MULTI_FACTOR_AUTHENTICATION: 'DISABLE_MULTI_FACTOR_AUTHENTICATION',
ENFORCE_MULTI_FACTOR_AUTHENTICATION: 'ENFORCE_MULTI_FACTOR_AUTHENTICATION', ENFORCE_MULTI_FACTOR_AUTHENTICATION: 'ENFORCE_MULTI_FACTOR_AUTHENTICATION',
DISABLE_PLAYGROUND: 'DISABLE_PLAYGROUND', DISABLE_PLAYGROUND: 'DISABLE_PLAYGROUND',
DISABLE_TOTP_LOGIN: 'DISABLE_TOTP_LOGIN',
DISABLE_MAIL_OTP_LOGIN: 'DISABLE_MAIL_OTP_LOGIN',
}; };
export const DateInputType = { export const DateInputType = {
@ -169,6 +171,8 @@ export interface envVarTypes {
DEFAULT_AUTHORIZE_RESPONSE_TYPE: string; DEFAULT_AUTHORIZE_RESPONSE_TYPE: string;
DEFAULT_AUTHORIZE_RESPONSE_MODE: string; DEFAULT_AUTHORIZE_RESPONSE_MODE: string;
DISABLE_PLAYGROUND: boolean; DISABLE_PLAYGROUND: boolean;
DISABLE_TOTP_LOGIN: boolean;
DISABLE_MAIL_OTP_LOGIN: boolean;
} }
export const envSubViews = { export const envSubViews = {

View File

@ -74,6 +74,8 @@ export const EnvVariablesQuery = `
DEFAULT_AUTHORIZE_RESPONSE_TYPE DEFAULT_AUTHORIZE_RESPONSE_TYPE
DEFAULT_AUTHORIZE_RESPONSE_MODE DEFAULT_AUTHORIZE_RESPONSE_MODE
DISABLE_PLAYGROUND DISABLE_PLAYGROUND
DISABLE_TOTP_LOGIN
DISABLE_MAIL_OTP_LOGIN
} }
} }
`; `;

View File

@ -94,6 +94,8 @@ const Environment = () => {
DEFAULT_AUTHORIZE_RESPONSE_TYPE: '', DEFAULT_AUTHORIZE_RESPONSE_TYPE: '',
DEFAULT_AUTHORIZE_RESPONSE_MODE: '', DEFAULT_AUTHORIZE_RESPONSE_MODE: '',
DISABLE_PLAYGROUND: false, DISABLE_PLAYGROUND: false,
DISABLE_TOTP_LOGIN: false,
DISABLE_MAIL_OTP_LOGIN: true,
}); });
const [fieldVisibility, setFieldVisibility] = React.useState< const [fieldVisibility, setFieldVisibility] = React.useState<

View File

@ -160,9 +160,12 @@ const (
// EnvKeyDisableMultiFactorAuthentication is key for env variable DISABLE_MULTI_FACTOR_AUTHENTICATION // EnvKeyDisableMultiFactorAuthentication is key for env variable DISABLE_MULTI_FACTOR_AUTHENTICATION
// this variable is used to completely disable multi factor authentication. It will have no effect on profile preference // this variable is used to completely disable multi factor authentication. It will have no effect on profile preference
EnvKeyDisableMultiFactorAuthentication = "DISABLE_MULTI_FACTOR_AUTHENTICATION" EnvKeyDisableMultiFactorAuthentication = "DISABLE_MULTI_FACTOR_AUTHENTICATION"
// EnvKeyDisableTotpAuthentication is key for env variable DISABLE_TOTP_AUTHENTICATION // EnvKeyDisableTOTPLogin is key for env variable DISABLE_TOTP_LOGIN
// this variable is used to completely disable totp verification // this variable is used to completely disable totp verification
EnvKeyDisableTotpAuthentication = "DISABLE_TOTP_AUTHENTICATION" EnvKeyDisableTOTPLogin = "DISABLE_TOTP_LOGIN"
// EnvKeyDisableMailOTPLogin is key for env variable DISABLE_MAIL_OTP_LOGIN
// this variable is used to completely disable totp verification
EnvKeyDisableMailOTPLogin = "DISABLE_MAIL_OTP_LOGIN"
// EnvKeyDisablePhoneVerification is key for env variable DISABLE_PHONE_VERIFICATION // EnvKeyDisablePhoneVerification is key for env variable DISABLE_PHONE_VERIFICATION
// this variable is used to disable phone verification // this variable is used to disable phone verification
EnvKeyDisablePhoneVerification = "DISABLE_PHONE_VERIFICATION" EnvKeyDisablePhoneVerification = "DISABLE_PHONE_VERIFICATION"

45
server/env/env.go vendored
View File

@ -104,6 +104,8 @@ func InitAllEnv() error {
osDisableStrongPassword := os.Getenv(constants.EnvKeyDisableStrongPassword) osDisableStrongPassword := os.Getenv(constants.EnvKeyDisableStrongPassword)
osEnforceMultiFactorAuthentication := os.Getenv(constants.EnvKeyEnforceMultiFactorAuthentication) osEnforceMultiFactorAuthentication := os.Getenv(constants.EnvKeyEnforceMultiFactorAuthentication)
osDisableMultiFactorAuthentication := os.Getenv(constants.EnvKeyDisableMultiFactorAuthentication) osDisableMultiFactorAuthentication := os.Getenv(constants.EnvKeyDisableMultiFactorAuthentication)
osDisableTOTPLogin := os.Getenv(constants.EnvKeyDisableTOTPLogin)
osDisableMailOTPLogin := os.Getenv(constants.EnvKeyDisableMailOTPLogin)
// phone verification var // phone verification var
osDisablePhoneVerification := os.Getenv(constants.EnvKeyDisablePhoneVerification) osDisablePhoneVerification := os.Getenv(constants.EnvKeyDisablePhoneVerification)
osDisablePlayground := os.Getenv(constants.EnvKeyDisablePlayGround) osDisablePlayground := os.Getenv(constants.EnvKeyDisablePlayGround)
@ -689,6 +691,7 @@ func InitAllEnv() error {
envData[constants.EnvKeyDisableEmailVerification] = true envData[constants.EnvKeyDisableEmailVerification] = true
envData[constants.EnvKeyDisableMagicLinkLogin] = true envData[constants.EnvKeyDisableMagicLinkLogin] = true
envData[constants.EnvKeyIsEmailServiceEnabled] = false envData[constants.EnvKeyIsEmailServiceEnabled] = false
envData[constants.EnvKeyDisableMailOTPLogin] = true
} }
if envData[constants.EnvKeySmtpHost] != "" && envData[constants.EnvKeySmtpUsername] != "" && envData[constants.EnvKeySmtpPassword] != "" && envData[constants.EnvKeySenderEmail] != "" && envData[constants.EnvKeySmtpPort] != "" { if envData[constants.EnvKeySmtpHost] != "" && envData[constants.EnvKeySmtpUsername] != "" && envData[constants.EnvKeySmtpPassword] != "" && envData[constants.EnvKeySenderEmail] != "" && envData[constants.EnvKeySmtpPort] != "" {
@ -705,6 +708,7 @@ func InitAllEnv() error {
if envData[constants.EnvKeyDisableEmailVerification].(bool) { if envData[constants.EnvKeyDisableEmailVerification].(bool) {
envData[constants.EnvKeyDisableMagicLinkLogin] = true envData[constants.EnvKeyDisableMagicLinkLogin] = true
envData[constants.EnvKeyDisableMailOTPLogin] = true
} }
if val, ok := envData[constants.EnvKeyAllowedOrigins]; !ok || val == "" { if val, ok := envData[constants.EnvKeyAllowedOrigins]; !ok || val == "" {
@ -840,6 +844,47 @@ func InitAllEnv() error {
} }
} }
if _, ok := envData[constants.EnvKeyDisableTOTPLogin]; !ok {
envData[constants.EnvKeyDisableTOTPLogin] = osDisableTOTPLogin == "false"
}
if osDisableTOTPLogin != "" {
boolValue, err := strconv.ParseBool(osDisableTOTPLogin)
if err != nil {
return err
}
if boolValue != envData[constants.EnvKeyDisableTOTPLogin].(bool) {
envData[constants.EnvKeyDisableTOTPLogin] = boolValue
}
}
if _, ok := envData[constants.EnvKeyDisableMailOTPLogin]; !ok {
envData[constants.EnvKeyDisableMailOTPLogin] = osDisableMailOTPLogin == "true"
}
if osDisableMailOTPLogin != "" {
boolValue, err := strconv.ParseBool(osDisableMailOTPLogin)
if err != nil {
return err
}
if boolValue != envData[constants.EnvKeyDisableMailOTPLogin].(bool) {
envData[constants.EnvKeyDisableMailOTPLogin] = boolValue
}
}
if envData[constants.EnvKeyDisableTOTPLogin] == false && envData[constants.EnvKeyDisableMailOTPLogin].(bool) == false {
errors.New("can't enable both mfa")
}
if envData[constants.EnvKeyDisableMultiFactorAuthentication].(bool) {
envData[constants.EnvKeyDisableTOTPLogin] = true
envData[constants.EnvKeyDisableMailOTPLogin] = true
} else {
if !envData[constants.EnvKeyDisableMailOTPLogin].(bool) && !envData[constants.EnvKeyDisableTOTPLogin].(bool) {
errors.New("can't enable both mfa methods at same time")
envData[constants.EnvKeyDisableMailOTPLogin] = false
envData[constants.EnvKeyDisableTOTPLogin] = true
}
}
err = memorystore.Provider.UpdateEnvStore(envData) err = memorystore.Provider.UpdateEnvStore(envData)
if err != nil { if err != nil {
log.Debug("Error while updating env store: ", err) log.Debug("Error while updating env store: ", err)

View File

@ -196,7 +196,7 @@ func PersistEnv() error {
envValue := strings.TrimSpace(os.Getenv(key)) envValue := strings.TrimSpace(os.Getenv(key))
if envValue != "" { if envValue != "" {
switch key { switch key {
case constants.EnvKeyIsProd, constants.EnvKeyDisableBasicAuthentication, constants.EnvKeyDisableMobileBasicAuthentication, constants.EnvKeyDisableEmailVerification, constants.EnvKeyDisableLoginPage, constants.EnvKeyDisableMagicLinkLogin, constants.EnvKeyDisableSignUp, constants.EnvKeyDisableRedisForEnv, constants.EnvKeyDisableStrongPassword, constants.EnvKeyIsEmailServiceEnabled, constants.EnvKeyIsSMSServiceEnabled, constants.EnvKeyEnforceMultiFactorAuthentication, constants.EnvKeyDisableMultiFactorAuthentication, constants.EnvKeyAdminCookieSecure, constants.EnvKeyAppCookieSecure, constants.EnvKeyDisablePhoneVerification, constants.EnvKeyDisablePlayGround: case constants.EnvKeyIsProd, constants.EnvKeyDisableBasicAuthentication, constants.EnvKeyDisableMobileBasicAuthentication, constants.EnvKeyDisableEmailVerification, constants.EnvKeyDisableLoginPage, constants.EnvKeyDisableMagicLinkLogin, constants.EnvKeyDisableSignUp, constants.EnvKeyDisableRedisForEnv, constants.EnvKeyDisableStrongPassword, constants.EnvKeyIsEmailServiceEnabled, constants.EnvKeyIsSMSServiceEnabled, constants.EnvKeyEnforceMultiFactorAuthentication, constants.EnvKeyDisableMultiFactorAuthentication, constants.EnvKeyAdminCookieSecure, constants.EnvKeyAppCookieSecure, constants.EnvKeyDisablePhoneVerification, constants.EnvKeyDisablePlayGround, constants.EnvKeyDisableTOTPLogin, constants.EnvKeyDisableMailOTPLogin:
if envValueBool, err := strconv.ParseBool(envValue); err == nil { if envValueBool, err := strconv.ParseBool(envValue); err == nil {
if value.(bool) != envValueBool { if value.(bool) != envValueBool {
storeData[key] = envValueBool storeData[key] = envValueBool
@ -227,6 +227,11 @@ func PersistEnv() error {
storeData[constants.EnvKeyDisableMagicLinkLogin] = true storeData[constants.EnvKeyDisableMagicLinkLogin] = true
hasChanged = true hasChanged = true
} }
if !storeData[constants.EnvKeyDisableMailOTPLogin].(bool) {
storeData[constants.EnvKeyDisableMailOTPLogin] = true
hasChanged = true
}
} }
err = memorystore.Provider.UpdateEnvStore(storeData) err = memorystore.Provider.UpdateEnvStore(storeData)

View File

@ -97,11 +97,13 @@ type ComplexityRoot struct {
DisableEmailVerification func(childComplexity int) int DisableEmailVerification func(childComplexity int) int
DisableLoginPage func(childComplexity int) int DisableLoginPage func(childComplexity int) int
DisableMagicLinkLogin func(childComplexity int) int DisableMagicLinkLogin func(childComplexity int) int
DisableMailOtpLogin func(childComplexity int) int
DisableMultiFactorAuthentication func(childComplexity int) int DisableMultiFactorAuthentication func(childComplexity int) int
DisablePlayground func(childComplexity int) int DisablePlayground func(childComplexity int) int
DisableRedisForEnv func(childComplexity int) int DisableRedisForEnv func(childComplexity int) int
DisableSignUp func(childComplexity int) int DisableSignUp func(childComplexity int) int
DisableStrongPassword func(childComplexity int) int DisableStrongPassword func(childComplexity int) int
DisableTotpLogin func(childComplexity int) int
EnforceMultiFactorAuthentication func(childComplexity int) int EnforceMultiFactorAuthentication func(childComplexity int) int
FacebookClientID func(childComplexity int) int FacebookClientID func(childComplexity int) int
FacebookClientSecret func(childComplexity int) int FacebookClientSecret func(childComplexity int) int
@ -699,6 +701,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Env.DisableMagicLinkLogin(childComplexity), true return e.complexity.Env.DisableMagicLinkLogin(childComplexity), true
case "Env.DISABLE_MAIL_OTP_LOGIN":
if e.complexity.Env.DisableMailOtpLogin == nil {
break
}
return e.complexity.Env.DisableMailOtpLogin(childComplexity), true
case "Env.DISABLE_MULTI_FACTOR_AUTHENTICATION": case "Env.DISABLE_MULTI_FACTOR_AUTHENTICATION":
if e.complexity.Env.DisableMultiFactorAuthentication == nil { if e.complexity.Env.DisableMultiFactorAuthentication == nil {
break break
@ -734,6 +743,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Env.DisableStrongPassword(childComplexity), true return e.complexity.Env.DisableStrongPassword(childComplexity), true
case "Env.DISABLE_TOTP_LOGIN":
if e.complexity.Env.DisableTotpLogin == nil {
break
}
return e.complexity.Env.DisableTotpLogin(childComplexity), true
case "Env.ENFORCE_MULTI_FACTOR_AUTHENTICATION": case "Env.ENFORCE_MULTI_FACTOR_AUTHENTICATION":
if e.complexity.Env.EnforceMultiFactorAuthentication == nil { if e.complexity.Env.EnforceMultiFactorAuthentication == nil {
break break
@ -2384,6 +2400,8 @@ type Env {
DEFAULT_AUTHORIZE_RESPONSE_TYPE: String DEFAULT_AUTHORIZE_RESPONSE_TYPE: String
DEFAULT_AUTHORIZE_RESPONSE_MODE: String DEFAULT_AUTHORIZE_RESPONSE_MODE: String
DISABLE_PLAYGROUND: Boolean! DISABLE_PLAYGROUND: Boolean!
DISABLE_MAIL_OTP_LOGIN: Boolean!
DISABLE_TOTP_LOGIN: Boolean!
} }
type ValidateJWTTokenResponse { type ValidateJWTTokenResponse {
@ -2507,6 +2525,8 @@ input UpdateEnvInput {
DEFAULT_AUTHORIZE_RESPONSE_TYPE: String DEFAULT_AUTHORIZE_RESPONSE_TYPE: String
DEFAULT_AUTHORIZE_RESPONSE_MODE: String DEFAULT_AUTHORIZE_RESPONSE_MODE: String
DISABLE_PLAYGROUND: Boolean DISABLE_PLAYGROUND: Boolean
DISABLE_MAIL_OTP_LOGIN: Boolean
DISABLE_TOTP_LOGIN: Boolean
} }
input AdminLoginInput { input AdminLoginInput {
@ -6895,6 +6915,94 @@ func (ec *executionContext) fieldContext_Env_DISABLE_PLAYGROUND(ctx context.Cont
return fc, nil return fc, nil
} }
func (ec *executionContext) _Env_DISABLE_MAIL_OTP_LOGIN(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Env_DISABLE_MAIL_OTP_LOGIN(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.DisableMailOtpLogin, 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) fieldContext_Env_DISABLE_MAIL_OTP_LOGIN(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Env",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Boolean does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Env_DISABLE_TOTP_LOGIN(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Env_DISABLE_TOTP_LOGIN(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.DisableTotpLogin, 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) fieldContext_Env_DISABLE_TOTP_LOGIN(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Env",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Boolean does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Error_message(ctx context.Context, field graphql.CollectedField, obj *model.Error) (ret graphql.Marshaler) { func (ec *executionContext) _Error_message(ctx context.Context, field graphql.CollectedField, obj *model.Error) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Error_message(ctx, field) fc, err := ec.fieldContext_Error_message(ctx, field)
if err != nil { if err != nil {
@ -10810,6 +10918,10 @@ func (ec *executionContext) fieldContext_Query__env(ctx context.Context, field g
return ec.fieldContext_Env_DEFAULT_AUTHORIZE_RESPONSE_MODE(ctx, field) return ec.fieldContext_Env_DEFAULT_AUTHORIZE_RESPONSE_MODE(ctx, field)
case "DISABLE_PLAYGROUND": case "DISABLE_PLAYGROUND":
return ec.fieldContext_Env_DISABLE_PLAYGROUND(ctx, field) return ec.fieldContext_Env_DISABLE_PLAYGROUND(ctx, field)
case "DISABLE_MAIL_OTP_LOGIN":
return ec.fieldContext_Env_DISABLE_MAIL_OTP_LOGIN(ctx, field)
case "DISABLE_TOTP_LOGIN":
return ec.fieldContext_Env_DISABLE_TOTP_LOGIN(ctx, field)
} }
return nil, fmt.Errorf("no field named %q was found under type Env", field.Name) return nil, fmt.Errorf("no field named %q was found under type Env", field.Name)
}, },
@ -17196,7 +17308,7 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
asMap[k] = v asMap[k] = v
} }
fieldsInOrder := [...]string{"ACCESS_TOKEN_EXPIRY_TIME", "ADMIN_SECRET", "CUSTOM_ACCESS_TOKEN_SCRIPT", "OLD_ADMIN_SECRET", "SMTP_HOST", "SMTP_PORT", "SMTP_USERNAME", "SMTP_PASSWORD", "SMTP_LOCAL_NAME", "SENDER_EMAIL", "SENDER_NAME", "JWT_TYPE", "JWT_SECRET", "JWT_PRIVATE_KEY", "JWT_PUBLIC_KEY", "ALLOWED_ORIGINS", "APP_URL", "RESET_PASSWORD_URL", "APP_COOKIE_SECURE", "ADMIN_COOKIE_SECURE", "DISABLE_EMAIL_VERIFICATION", "DISABLE_BASIC_AUTHENTICATION", "DISABLE_MAGIC_LINK_LOGIN", "DISABLE_LOGIN_PAGE", "DISABLE_SIGN_UP", "DISABLE_REDIS_FOR_ENV", "DISABLE_STRONG_PASSWORD", "DISABLE_MULTI_FACTOR_AUTHENTICATION", "ENFORCE_MULTI_FACTOR_AUTHENTICATION", "ROLES", "PROTECTED_ROLES", "DEFAULT_ROLES", "JWT_ROLE_CLAIM", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "FACEBOOK_CLIENT_ID", "FACEBOOK_CLIENT_SECRET", "LINKEDIN_CLIENT_ID", "LINKEDIN_CLIENT_SECRET", "APPLE_CLIENT_ID", "APPLE_CLIENT_SECRET", "TWITTER_CLIENT_ID", "TWITTER_CLIENT_SECRET", "MICROSOFT_CLIENT_ID", "MICROSOFT_CLIENT_SECRET", "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID", "ORGANIZATION_NAME", "ORGANIZATION_LOGO", "DEFAULT_AUTHORIZE_RESPONSE_TYPE", "DEFAULT_AUTHORIZE_RESPONSE_MODE", "DISABLE_PLAYGROUND"} fieldsInOrder := [...]string{"ACCESS_TOKEN_EXPIRY_TIME", "ADMIN_SECRET", "CUSTOM_ACCESS_TOKEN_SCRIPT", "OLD_ADMIN_SECRET", "SMTP_HOST", "SMTP_PORT", "SMTP_USERNAME", "SMTP_PASSWORD", "SMTP_LOCAL_NAME", "SENDER_EMAIL", "SENDER_NAME", "JWT_TYPE", "JWT_SECRET", "JWT_PRIVATE_KEY", "JWT_PUBLIC_KEY", "ALLOWED_ORIGINS", "APP_URL", "RESET_PASSWORD_URL", "APP_COOKIE_SECURE", "ADMIN_COOKIE_SECURE", "DISABLE_EMAIL_VERIFICATION", "DISABLE_BASIC_AUTHENTICATION", "DISABLE_MAGIC_LINK_LOGIN", "DISABLE_LOGIN_PAGE", "DISABLE_SIGN_UP", "DISABLE_REDIS_FOR_ENV", "DISABLE_STRONG_PASSWORD", "DISABLE_MULTI_FACTOR_AUTHENTICATION", "ENFORCE_MULTI_FACTOR_AUTHENTICATION", "ROLES", "PROTECTED_ROLES", "DEFAULT_ROLES", "JWT_ROLE_CLAIM", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "FACEBOOK_CLIENT_ID", "FACEBOOK_CLIENT_SECRET", "LINKEDIN_CLIENT_ID", "LINKEDIN_CLIENT_SECRET", "APPLE_CLIENT_ID", "APPLE_CLIENT_SECRET", "TWITTER_CLIENT_ID", "TWITTER_CLIENT_SECRET", "MICROSOFT_CLIENT_ID", "MICROSOFT_CLIENT_SECRET", "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID", "ORGANIZATION_NAME", "ORGANIZATION_LOGO", "DEFAULT_AUTHORIZE_RESPONSE_TYPE", "DEFAULT_AUTHORIZE_RESPONSE_MODE", "DISABLE_PLAYGROUND", "DISABLE_MAIL_OTP_LOGIN", "DISABLE_TOTP_LOGIN"}
for _, k := range fieldsInOrder { for _, k := range fieldsInOrder {
v, ok := asMap[k] v, ok := asMap[k]
if !ok { if !ok {
@ -17627,6 +17739,22 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
if err != nil { if err != nil {
return it, err return it, err
} }
case "DISABLE_MAIL_OTP_LOGIN":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("DISABLE_MAIL_OTP_LOGIN"))
it.DisableMailOtpLogin, err = ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
case "DISABLE_TOTP_LOGIN":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("DISABLE_TOTP_LOGIN"))
it.DisableTotpLogin, err = ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
} }
} }
@ -18625,6 +18753,20 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
out.Values[i] = ec._Env_DISABLE_PLAYGROUND(ctx, field, obj) out.Values[i] = ec._Env_DISABLE_PLAYGROUND(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
case "DISABLE_MAIL_OTP_LOGIN":
out.Values[i] = ec._Env_DISABLE_MAIL_OTP_LOGIN(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
case "DISABLE_TOTP_LOGIN":
out.Values[i] = ec._Env_DISABLE_TOTP_LOGIN(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
invalids++ invalids++
} }

View File

@ -123,6 +123,8 @@ type Env struct {
DefaultAuthorizeResponseType *string `json:"DEFAULT_AUTHORIZE_RESPONSE_TYPE"` DefaultAuthorizeResponseType *string `json:"DEFAULT_AUTHORIZE_RESPONSE_TYPE"`
DefaultAuthorizeResponseMode *string `json:"DEFAULT_AUTHORIZE_RESPONSE_MODE"` DefaultAuthorizeResponseMode *string `json:"DEFAULT_AUTHORIZE_RESPONSE_MODE"`
DisablePlayground bool `json:"DISABLE_PLAYGROUND"` DisablePlayground bool `json:"DISABLE_PLAYGROUND"`
DisableMailOtpLogin bool `json:"DISABLE_MAIL_OTP_LOGIN"`
DisableTotpLogin bool `json:"DISABLE_TOTP_LOGIN"`
} }
type Error struct { type Error struct {
@ -382,6 +384,8 @@ type UpdateEnvInput struct {
DefaultAuthorizeResponseType *string `json:"DEFAULT_AUTHORIZE_RESPONSE_TYPE"` DefaultAuthorizeResponseType *string `json:"DEFAULT_AUTHORIZE_RESPONSE_TYPE"`
DefaultAuthorizeResponseMode *string `json:"DEFAULT_AUTHORIZE_RESPONSE_MODE"` DefaultAuthorizeResponseMode *string `json:"DEFAULT_AUTHORIZE_RESPONSE_MODE"`
DisablePlayground *bool `json:"DISABLE_PLAYGROUND"` DisablePlayground *bool `json:"DISABLE_PLAYGROUND"`
DisableMailOtpLogin *bool `json:"DISABLE_MAIL_OTP_LOGIN"`
DisableTotpLogin *bool `json:"DISABLE_TOTP_LOGIN"`
} }
type UpdateProfileInput struct { type UpdateProfileInput struct {

View File

@ -174,6 +174,8 @@ type Env {
DEFAULT_AUTHORIZE_RESPONSE_TYPE: String DEFAULT_AUTHORIZE_RESPONSE_TYPE: String
DEFAULT_AUTHORIZE_RESPONSE_MODE: String DEFAULT_AUTHORIZE_RESPONSE_MODE: String
DISABLE_PLAYGROUND: Boolean! DISABLE_PLAYGROUND: Boolean!
DISABLE_MAIL_OTP_LOGIN: Boolean!
DISABLE_TOTP_LOGIN: Boolean!
} }
type ValidateJWTTokenResponse { type ValidateJWTTokenResponse {
@ -297,6 +299,8 @@ input UpdateEnvInput {
DEFAULT_AUTHORIZE_RESPONSE_TYPE: String DEFAULT_AUTHORIZE_RESPONSE_TYPE: String
DEFAULT_AUTHORIZE_RESPONSE_MODE: String DEFAULT_AUTHORIZE_RESPONSE_MODE: String
DISABLE_PLAYGROUND: Boolean DISABLE_PLAYGROUND: Boolean
DISABLE_MAIL_OTP_LOGIN: Boolean
DISABLE_TOTP_LOGIN: Boolean
} }
input AdminLoginInput { input AdminLoginInput {

View File

@ -36,9 +36,11 @@ func InitMemStore() error {
constants.EnvKeyIsSMSServiceEnabled: false, constants.EnvKeyIsSMSServiceEnabled: false,
constants.EnvKeyEnforceMultiFactorAuthentication: false, constants.EnvKeyEnforceMultiFactorAuthentication: false,
constants.EnvKeyDisableMultiFactorAuthentication: false, constants.EnvKeyDisableMultiFactorAuthentication: false,
constants.EnvKeyDisableTOTPLogin: false,
constants.EnvKeyAppCookieSecure: true, constants.EnvKeyAppCookieSecure: true,
constants.EnvKeyAdminCookieSecure: true, constants.EnvKeyAdminCookieSecure: true,
constants.EnvKeyDisablePlayGround: true, constants.EnvKeyDisablePlayGround: true,
constants.EnvKeyDisableMailOTPLogin: true,
} }
requiredEnvs := RequiredEnvStoreObj.GetRequiredEnv() requiredEnvs := RequiredEnvStoreObj.GetRequiredEnv()

View File

@ -176,7 +176,7 @@ func (c *provider) GetEnvStore() (map[string]interface{}, error) {
return nil, err return nil, err
} }
for key, value := range data { for key, value := range data {
if key == constants.EnvKeyDisableBasicAuthentication || key == constants.EnvKeyDisableMobileBasicAuthentication || key == constants.EnvKeyDisableEmailVerification || key == constants.EnvKeyDisableLoginPage || key == constants.EnvKeyDisableMagicLinkLogin || key == constants.EnvKeyDisableRedisForEnv || key == constants.EnvKeyDisableSignUp || key == constants.EnvKeyDisableStrongPassword || key == constants.EnvKeyIsEmailServiceEnabled || key == constants.EnvKeyIsSMSServiceEnabled || key == constants.EnvKeyEnforceMultiFactorAuthentication || key == constants.EnvKeyDisableMultiFactorAuthentication || key == constants.EnvKeyAppCookieSecure || key == constants.EnvKeyAdminCookieSecure || key == constants.EnvKeyDisablePlayGround { if key == constants.EnvKeyDisableBasicAuthentication || key == constants.EnvKeyDisableMobileBasicAuthentication || key == constants.EnvKeyDisableEmailVerification || key == constants.EnvKeyDisableLoginPage || key == constants.EnvKeyDisableMagicLinkLogin || key == constants.EnvKeyDisableRedisForEnv || key == constants.EnvKeyDisableSignUp || key == constants.EnvKeyDisableStrongPassword || key == constants.EnvKeyIsEmailServiceEnabled || key == constants.EnvKeyIsSMSServiceEnabled || key == constants.EnvKeyEnforceMultiFactorAuthentication || key == constants.EnvKeyDisableMultiFactorAuthentication || key == constants.EnvKeyAppCookieSecure || key == constants.EnvKeyAdminCookieSecure || key == constants.EnvKeyDisablePlayGround || key == constants.EnvKeyDisableTOTPLogin || key == constants.EnvKeyDisableMailOTPLogin {
boolValue, err := strconv.ParseBool(value) boolValue, err := strconv.ParseBool(value)
if err != nil { if err != nil {
return res, err return res, err

View File

@ -203,6 +203,8 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
res.AdminCookieSecure = store[constants.EnvKeyAdminCookieSecure].(bool) res.AdminCookieSecure = store[constants.EnvKeyAdminCookieSecure].(bool)
res.AppCookieSecure = store[constants.EnvKeyAppCookieSecure].(bool) res.AppCookieSecure = store[constants.EnvKeyAppCookieSecure].(bool)
res.DisablePlayground = store[constants.EnvKeyDisablePlayGround].(bool) res.DisablePlayground = store[constants.EnvKeyDisablePlayGround].(bool)
res.DisableMailOtpLogin = store[constants.EnvKeyDisableMailOTPLogin].(bool)
res.DisableTotpLogin = store[constants.EnvKeyDisableTOTPLogin].(bool)
return res, nil return res, nil
} }

View File

@ -110,8 +110,18 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
log.Debug("MFA service not enabled: ", err) log.Debug("MFA service not enabled: ", err)
} }
isTOTPLoginDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableTOTPLogin)
if err != nil || !isTOTPLoginDisabled {
log.Debug("totp service not enabled: ", err)
}
isMailOTPDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMailOTPLogin)
if err != nil || !isMailOTPDisabled {
log.Debug("mail OTP service not enabled: ", err)
}
// If email service is not enabled continue the process in any way // If email service is not enabled continue the process in any way
if refs.BoolValue(user.IsMultiFactorAuthEnabled) && isEmailServiceEnabled && !isMFADisabled { if refs.BoolValue(user.IsMultiFactorAuthEnabled) && !isMailOTPDisabled && !isMFADisabled {
otp := utils.GenerateOTP() otp := utils.GenerateOTP()
expires := time.Now().Add(1 * time.Minute).Unix() expires := time.Now().Add(1 * time.Minute).Unix()
otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{ otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{
@ -150,14 +160,16 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
}, nil }, nil
} }
if !isMFADisabled && refs.BoolValue(user.IsMultiFactorAuthEnabled) { if !isMFADisabled && refs.BoolValue(user.IsMultiFactorAuthEnabled) && !isTOTPLoginDisabled {
if user.TotpSecret == nil { if user.TotpSecret == nil {
base64URL, err := db.Provider.GenerateTotp(ctx, user.ID) base64URL, err := db.Provider.GenerateTotp(ctx, user.ID)
if err != nil { if err != nil {
log.Debug("error while generating base64 url: ", err) log.Debug("error while generating base64 url: ", err)
} }
res.TotpBase64url = base64URL res.TotpBase64url = base64URL
} }
} }
code := "" code := ""

View File

@ -263,6 +263,17 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
} }
} }
if updatedData[constants.EnvKeyDisableMultiFactorAuthentication].(bool) {
updatedData[constants.EnvKeyDisableTOTPLogin] = true
updatedData[constants.EnvKeyDisableMailOTPLogin] = true
} else {
if !updatedData[constants.EnvKeyDisableMailOTPLogin].(bool) && !updatedData[constants.EnvKeyDisableTOTPLogin].(bool) {
errors.New("can't enable both mfa methods at same time")
updatedData[constants.EnvKeyDisableMailOTPLogin] = true
updatedData[constants.EnvKeyDisableTOTPLogin] = false
}
}
if updatedData[constants.EnvKeySmtpHost] != "" || updatedData[constants.EnvKeySmtpUsername] != "" || updatedData[constants.EnvKeySmtpPassword] != "" || updatedData[constants.EnvKeySenderEmail] != "" && updatedData[constants.EnvKeySmtpPort] != "" { if updatedData[constants.EnvKeySmtpHost] != "" || updatedData[constants.EnvKeySmtpUsername] != "" || updatedData[constants.EnvKeySmtpPassword] != "" || updatedData[constants.EnvKeySenderEmail] != "" && updatedData[constants.EnvKeySmtpPort] != "" {
updatedData[constants.EnvKeyIsEmailServiceEnabled] = true updatedData[constants.EnvKeyIsEmailServiceEnabled] = true
} }