diff --git a/dashboard/src/components/EnvComponents/DatabaseCredentials.tsx b/dashboard/src/components/EnvComponents/DatabaseCredentials.tsx index 12c85e1..1cc6db9 100644 --- a/dashboard/src/components/EnvComponents/DatabaseCredentials.tsx +++ b/dashboard/src/components/EnvComponents/DatabaseCredentials.tsx @@ -1,88 +1,88 @@ -import React from "react"; -import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react"; +import React from 'react'; +import { Flex, Stack, Center, Text, useMediaQuery } from '@chakra-ui/react'; -import InputField from "../../components/InputField"; -import { TextInputType } from "../../constants"; +import InputField from '../../components/InputField'; +import { TextInputType } from '../../constants'; const DatabaseCredentials = ({ variables, setVariables }: any) => { - const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)"); - return ( -
- {" "} - - Database Credentials - - - - Note: Database related environment variables cannot be updated from - dashboard :( - - - - DataBase Name: - -
- -
-
- - - DataBase Type: - -
- -
-
- - - DataBase URL: - -
- -
-
-
-
- ); + const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)'); + return ( +
+ {' '} + + Database Credentials + + + + Note: Database related environment variables cannot be updated from + dashboard + + + + DataBase Name: + +
+ +
+
+ + + DataBase Type: + +
+ +
+
+ + + DataBase URL: + +
+ +
+
+
+
+ ); }; -export default DatabaseCredentials; \ No newline at end of file +export default DatabaseCredentials; diff --git a/dashboard/src/components/EnvComponents/UICustomization.tsx b/dashboard/src/components/EnvComponents/Features.tsx similarity index 81% rename from dashboard/src/components/EnvComponents/UICustomization.tsx rename to dashboard/src/components/EnvComponents/Features.tsx index 756c739..2d2d066 100644 --- a/dashboard/src/components/EnvComponents/UICustomization.tsx +++ b/dashboard/src/components/EnvComponents/Features.tsx @@ -3,7 +3,7 @@ import { Flex, Stack, Text } from '@chakra-ui/react'; import InputField from '../InputField'; import { SwitchInputType } from '../../constants'; -const UICustomization = ({ variables, setVariables }: any) => { +const Features = ({ variables, setVariables }: any) => { return (
{' '} @@ -71,9 +71,23 @@ const UICustomization = ({ variables, setVariables }: any) => { /> + + + + Disable Redis for storing environment variables: + + + + + +
); }; -export default UICustomization; +export default Features; diff --git a/dashboard/src/components/EnvComponents/SessionStorage.tsx b/dashboard/src/components/EnvComponents/SessionStorage.tsx index 8570f47..23e36af 100644 --- a/dashboard/src/components/EnvComponents/SessionStorage.tsx +++ b/dashboard/src/components/EnvComponents/SessionStorage.tsx @@ -1,36 +1,41 @@ -import React from "react"; -import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react"; -import InputField from "../InputField"; +import React from 'react'; +import { Flex, Stack, Center, Text, useMediaQuery } from '@chakra-ui/react'; +import InputField from '../InputField'; const SessionStorage = ({ variables, setVariables, RedisURL }: any) => { - const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)"); - return ( -
- {" "} - - Session Storage - - - - - Redis URL: - -
- -
-
-
-
- ); + const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)'); + return ( +
+ {' '} + + Session Storage + + + Note: Database related environment variables cannot be updated from + dashboard + + + + + Redis URL: + +
+ +
+
+
+
+ ); }; -export default SessionStorage; \ No newline at end of file +export default SessionStorage; diff --git a/dashboard/src/components/InviteMembersModal.tsx b/dashboard/src/components/InviteMembersModal.tsx index 2878722..9ede01b 100644 --- a/dashboard/src/components/InviteMembersModal.tsx +++ b/dashboard/src/components/InviteMembersModal.tsx @@ -22,7 +22,7 @@ import { InputRightElement, Text, Link, - Tooltip + Tooltip, } from '@chakra-ui/react'; import { useClient } from 'urql'; import { FaUserPlus, FaMinusCircle, FaPlus, FaUpload } from 'react-icons/fa'; @@ -187,22 +187,22 @@ const InviteMembersModal = ({ isDisabled={disabled} size="sm" > -
- {disabled ? ( - - Invite Members - - ) : ( - "Invite Members" - )} -
{" "} +
+ {disabled ? ( + + Invite Members + + ) : ( + 'Invite Members' + )} +
{' '} diff --git a/dashboard/src/components/Menu.tsx b/dashboard/src/components/Menu.tsx index 7822062..8593bb0 100644 --- a/dashboard/src/components/Menu.tsx +++ b/dashboard/src/components/Menu.tsx @@ -98,9 +98,9 @@ const LinkItems: Array = [ }, { name: 'Access Token', icon: SiOpenaccess, route: '/access-token' }, { - name: 'UI Customization', + name: 'Features', icon: BiCustomize, - route: '/ui-customization', + route: '/features', }, { name: 'Database', icon: RiDatabase2Line, route: '/db-cred' }, { diff --git a/dashboard/src/constants.ts b/dashboard/src/constants.ts index 3b9986f..e0f9d3d 100644 --- a/dashboard/src/constants.ts +++ b/dashboard/src/constants.ts @@ -62,6 +62,7 @@ export const SwitchInputType = { DISABLE_EMAIL_VERIFICATION: 'DISABLE_EMAIL_VERIFICATION', DISABLE_BASIC_AUTHENTICATION: 'DISABLE_BASIC_AUTHENTICATION', DISABLE_SIGN_UP: 'DISABLE_SIGN_UP', + DISABLE_REDIS_FOR_ENV: 'DISABLE_REDIS_FOR_ENV', }; export const DateInputType = { @@ -138,7 +139,7 @@ export const envSubViews = { WHITELIST_VARIABLES: 'whitelist-variables', ORGANIZATION_INFO: 'organization-info', ACCESS_TOKEN: 'access-token', - UI_CUSTOMIZATION: 'ui-customization', + FEATURES: 'features', ADMIN_SECRET: 'admin-secret', DB_CRED: 'db-cred', }; diff --git a/dashboard/src/graphql/queries/index.ts b/dashboard/src/graphql/queries/index.ts index 1adf02c..cd55475 100644 --- a/dashboard/src/graphql/queries/index.ts +++ b/dashboard/src/graphql/queries/index.ts @@ -49,6 +49,7 @@ export const EnvVariablesQuery = ` DISABLE_EMAIL_VERIFICATION, DISABLE_BASIC_AUTHENTICATION, DISABLE_SIGN_UP, + DISABLE_REDIS_FOR_ENV, CUSTOM_ACCESS_TOKEN_SCRIPT, DATABASE_NAME, DATABASE_TYPE, diff --git a/dashboard/src/pages/Environment.tsx b/dashboard/src/pages/Environment.tsx index 78f79c4..169c62f 100644 --- a/dashboard/src/pages/Environment.tsx +++ b/dashboard/src/pages/Environment.tsx @@ -25,7 +25,7 @@ import EmailConfigurations from '../components/EnvComponents/EmailConfiguration' import DomainWhiteListing from '../components/EnvComponents/DomainWhitelisting'; import OrganizationInfo from '../components/EnvComponents/OrganizationInfo'; import AccessToken from '../components/EnvComponents/AccessToken'; -import UICustomization from '../components/EnvComponents/UICustomization'; +import Features from '../components/EnvComponents/Features'; import SecurityAdminSecret from '../components/EnvComponents/SecurityAdminSecret'; import DatabaseCredentials from '../components/EnvComponents/DatabaseCredentials'; @@ -259,12 +259,9 @@ const Environment = () => { setVariables={setEnvVariables} /> ); - case envSubViews.UI_CUSTOMIZATION: + case envSubViews.FEATURES: return ( - + ); case envSubViews.ADMIN_SECRET: return ( diff --git a/server/constants/env.go b/server/constants/env.go index 4886bd7..4f02e64 100644 --- a/server/constants/env.go +++ b/server/constants/env.go @@ -111,6 +111,8 @@ const ( EnvKeyDisableLoginPage = "DISABLE_LOGIN_PAGE" // EnvKeyDisableSignUp key for env variable DISABLE_SIGN_UP EnvKeyDisableSignUp = "DISABLE_SIGN_UP" + // EnvKeyDisableRedisForEnv key for env variable DISABLE_REDIS_FOR_ENV + EnvKeyDisableRedisForEnv = "DISABLE_REDIS_FOR_ENV" // Slice variables // EnvKeyRoles key for env variable ROLES diff --git a/server/env/env.go b/server/env/env.go index c110a60..e80fbe4 100644 --- a/server/env/env.go +++ b/server/env/env.go @@ -78,6 +78,7 @@ func InitAllEnv() error { osDisableMagicLinkLogin := os.Getenv(constants.EnvKeyDisableMagicLinkLogin) osDisableLoginPage := os.Getenv(constants.EnvKeyDisableLoginPage) osDisableSignUp := os.Getenv(constants.EnvKeyDisableSignUp) + osDisableRedisForEnv := os.Getenv(constants.EnvKeyDisableRedisForEnv) // os slice vars osAllowedOrigins := os.Getenv(constants.EnvKeyAllowedOrigins) @@ -430,6 +431,19 @@ func InitAllEnv() error { } } + if _, ok := envData[constants.EnvKeyDisableRedisForEnv]; !ok { + envData[constants.EnvKeyDisableRedisForEnv] = osDisableRedisForEnv == "true" + } + if osDisableRedisForEnv != "" { + boolValue, err := strconv.ParseBool(osDisableRedisForEnv) + if err != nil { + return err + } + if boolValue != envData[constants.EnvKeyDisableRedisForEnv].(bool) { + envData[constants.EnvKeyDisableRedisForEnv] = boolValue + } + } + // no need to add nil check as its already done above if envData[constants.EnvKeySmtpHost] == "" || envData[constants.EnvKeySmtpUsername] == "" || envData[constants.EnvKeySmtpPassword] == "" || envData[constants.EnvKeySenderEmail] == "" && envData[constants.EnvKeySmtpPort] == "" { envData[constants.EnvKeyDisableEmailVerification] = true @@ -450,7 +464,6 @@ func InitAllEnv() error { envData[constants.EnvKeyAllowedOrigins] = osAllowedOrigins } - ////// Roles ///// if val, ok := envData[constants.EnvKeyRoles]; !ok || val == "" { envData[constants.EnvKeyRoles] = osRoles if envData[constants.EnvKeyRoles] == "" { @@ -461,9 +474,7 @@ func InitAllEnv() error { envData[constants.EnvKeyRoles] = osRoles } roles := strings.Split(envData[constants.EnvKeyRoles].(string), ",") - ////// Roles ///// - ////// Default Role ///// if val, ok := envData[constants.EnvKeyDefaultRoles]; !ok || val == "" { envData[constants.EnvKeyDefaultRoles] = osDefaultRoles if envData[constants.EnvKeyDefaultRoles] == "" { @@ -483,19 +494,13 @@ func InitAllEnv() error { return fmt.Errorf("Default role %s is not defined in roles", role) } } - ////// Default Role ///// - ////// Roles ///// if val, ok := envData[constants.EnvKeyProtectedRoles]; !ok || val == "" { envData[constants.EnvKeyProtectedRoles] = osProtectedRoles - if envData[constants.EnvKeyProtectedRoles] == "" { - envData[constants.EnvKeyProtectedRoles] = "user" - } } if osProtectedRoles != "" && envData[constants.EnvKeyProtectedRoles] != osProtectedRoles { envData[constants.EnvKeyProtectedRoles] = osProtectedRoles } - ////// Roles ///// err = memorystore.Provider.UpdateEnvStore(envData) if err != nil { diff --git a/server/env/persist_env.go b/server/env/persist_env.go index ecedcb5..f01f975 100644 --- a/server/env/persist_env.go +++ b/server/env/persist_env.go @@ -3,6 +3,7 @@ package env import ( "encoding/json" "os" + "reflect" "strconv" "strings" @@ -14,8 +15,46 @@ import ( "github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/utils" ) +func fixBackwardCompatibility(data map[string]interface{}) (bool, map[string]interface{}) { + result := data + // check if env data is stored in older format + hasOlderFormat := false + if _, ok := result["bool_env"]; ok { + for key, value := range result["bool_env"].(map[string]interface{}) { + result[key] = value + } + hasOlderFormat = true + delete(result, "bool_env") + } + + if _, ok := result["string_env"]; ok { + for key, value := range result["string_env"].(map[string]interface{}) { + result[key] = value + } + hasOlderFormat = true + delete(result, "string_env") + } + + if _, ok := result["slice_env"]; ok { + for key, value := range result["slice_env"].(map[string]interface{}) { + typeOfValue := reflect.TypeOf(value) + if strings.Contains(typeOfValue.String(), "[]string") { + result[key] = strings.Join(value.([]string), ",") + } + if strings.Contains(typeOfValue.String(), "[]interface") { + result[key] = strings.Join(utils.ConvertInterfaceToStringSlice(value), ",") + } + } + hasOlderFormat = true + delete(result, "slice_env") + } + + return hasOlderFormat, result +} + // GetEnvData returns the env data from database func GetEnvData() (map[string]interface{}, error) { var result map[string]interface{} @@ -53,41 +92,16 @@ func GetEnvData() (map[string]interface{}, error) { return result, err } - ///////// start backward compatibility /////////// - // check if env data is stored in older format - hasOlderFormat := false - if _, ok := result["bool_env"]; ok { - for key, value := range result["bool_env"].(map[string]interface{}) { - result[key] = value - } - hasOlderFormat = true - delete(result, "bool_env") - } - - if _, ok := result["string_env"]; ok { - for key, value := range result["string_env"].(map[string]interface{}) { - result[key] = value - } - hasOlderFormat = true - delete(result, "string_env") - } - - if _, ok := result["slice_env"]; ok { - for key, value := range result["slice_env"].(map[string]interface{}) { - result[key] = strings.Join(value.([]string), ",") - } - hasOlderFormat = true - delete(result, "slice_env") - } + hasOlderFormat, result := fixBackwardCompatibility(result) if hasOlderFormat { - err := memorystore.Provider.UpdateEnvStore(result) + err = memorystore.Provider.UpdateEnvStore(result) if err != nil { - log.Fatal("Error while updating env store: ", err) + log.Debug("Error while updating env store: ", err) return result, err } + } - ///////// end backward compatibility /////////// return result, err } @@ -99,7 +113,11 @@ func PersistEnv() error { if err != nil { // AES encryption needs 32 bit key only, so we chop off last 4 characters from 36 bit uuid hash := uuid.New().String()[:36-4] - memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEncryptionKey, hash) + err := memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEncryptionKey, hash) + if err != nil { + log.Debug("Error while updating encryption env variable: ", err) + return err + } encodedHash := crypto.EncryptB64(hash) res, err := memorystore.Provider.GetEnvStore() @@ -157,6 +175,16 @@ func PersistEnv() error { return err } + hasOlderFormat, result := fixBackwardCompatibility(storeData) + if hasOlderFormat { + err = memorystore.Provider.UpdateEnvStore(result) + if err != nil { + log.Debug("Error while updating env store: ", err) + return err + } + + } + // if env is changed via env file or OS env // give that higher preference and update db, but we don't recommend it diff --git a/server/go.mod b/server/go.mod index be8365e..13e3e52 100644 --- a/server/go.mod +++ b/server/go.mod @@ -20,7 +20,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 github.com/ugorji/go v1.2.6 // indirect github.com/vektah/gqlparser/v2 v2.2.0 diff --git a/server/graph/generated/generated.go b/server/graph/generated/generated.go index c8cb538..3e9271e 100644 --- a/server/graph/generated/generated.go +++ b/server/graph/generated/generated.go @@ -59,7 +59,6 @@ type ComplexityRoot struct { AppURL func(childComplexity int) int ClientID func(childComplexity int) int ClientSecret func(childComplexity int) int - CookieName func(childComplexity int) int CustomAccessTokenScript func(childComplexity int) int DatabaseHost func(childComplexity int) int DatabaseName func(childComplexity int) int @@ -346,13 +345,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Env.ClientSecret(childComplexity), true - case "Env.COOKIE_NAME": - if e.complexity.Env.CookieName == nil { - break - } - - return e.complexity.Env.CookieName(childComplexity), true - case "Env.CUSTOM_ACCESS_TOKEN_SCRIPT": if e.complexity.Env.CustomAccessTokenScript == nil { break @@ -1423,13 +1415,13 @@ type Response { type Env { ACCESS_TOKEN_EXPIRY_TIME: String ADMIN_SECRET: String - DATABASE_NAME: String! - DATABASE_URL: String! - DATABASE_TYPE: String! - DATABASE_USERNAME: String! - DATABASE_PASSWORD: String! - DATABASE_HOST: String! - DATABASE_PORT: String! + DATABASE_NAME: String + DATABASE_URL: String + DATABASE_TYPE: String + DATABASE_USERNAME: String + DATABASE_PASSWORD: String + DATABASE_HOST: String + DATABASE_PORT: String CLIENT_ID: String! CLIENT_SECRET: String! CUSTOM_ACCESS_TOKEN_SCRIPT: String @@ -1445,13 +1437,12 @@ type Env { ALLOWED_ORIGINS: [String!] APP_URL: String REDIS_URL: String - COOKIE_NAME: String RESET_PASSWORD_URL: String - DISABLE_EMAIL_VERIFICATION: Boolean - DISABLE_BASIC_AUTHENTICATION: Boolean - DISABLE_MAGIC_LINK_LOGIN: Boolean - DISABLE_LOGIN_PAGE: Boolean - DISABLE_SIGN_UP: Boolean + DISABLE_EMAIL_VERIFICATION: Boolean! + 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!] @@ -1492,8 +1483,6 @@ input UpdateEnvInput { JWT_PUBLIC_KEY: String ALLOWED_ORIGINS: [String!] APP_URL: String - REDIS_URL: String - COOKIE_NAME: String RESET_PASSWORD_URL: String DISABLE_EMAIL_VERIFICATION: Boolean DISABLE_BASIC_AUTHENTICATION: Boolean @@ -2356,14 +2345,11 @@ func (ec *executionContext) _Env_DATABASE_NAME(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _Env_DATABASE_URL(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -2391,14 +2377,11 @@ func (ec *executionContext) _Env_DATABASE_URL(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _Env_DATABASE_TYPE(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -2426,14 +2409,11 @@ func (ec *executionContext) _Env_DATABASE_TYPE(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _Env_DATABASE_USERNAME(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -2461,14 +2441,11 @@ func (ec *executionContext) _Env_DATABASE_USERNAME(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _Env_DATABASE_PASSWORD(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -2496,14 +2473,11 @@ func (ec *executionContext) _Env_DATABASE_PASSWORD(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _Env_DATABASE_HOST(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -2531,14 +2505,11 @@ func (ec *executionContext) _Env_DATABASE_HOST(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _Env_DATABASE_PORT(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -2566,14 +2537,11 @@ func (ec *executionContext) _Env_DATABASE_PORT(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _Env_CLIENT_ID(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -3062,38 +3030,6 @@ func (ec *executionContext) _Env_REDIS_URL(ctx context.Context, field graphql.Co return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) _Env_COOKIE_NAME(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.CookieName, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*string) - fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) -} - func (ec *executionContext) _Env_RESET_PASSWORD_URL(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -3151,11 +3087,14 @@ func (ec *executionContext) _Env_DISABLE_EMAIL_VERIFICATION(ctx context.Context, return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*bool) + res := resTmp.(bool) fc.Result = res - return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Env_DISABLE_BASIC_AUTHENTICATION(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -3183,11 +3122,14 @@ func (ec *executionContext) _Env_DISABLE_BASIC_AUTHENTICATION(ctx context.Contex return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*bool) + res := resTmp.(bool) fc.Result = res - return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Env_DISABLE_MAGIC_LINK_LOGIN(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -3215,11 +3157,14 @@ func (ec *executionContext) _Env_DISABLE_MAGIC_LINK_LOGIN(ctx context.Context, f return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*bool) + res := resTmp.(bool) fc.Result = res - return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Env_DISABLE_LOGIN_PAGE(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -3247,11 +3192,14 @@ func (ec *executionContext) _Env_DISABLE_LOGIN_PAGE(ctx context.Context, field g return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*bool) + res := resTmp.(bool) fc.Result = res - return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Env_DISABLE_SIGN_UP(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -3279,11 +3227,14 @@ func (ec *executionContext) _Env_DISABLE_SIGN_UP(ctx context.Context, field grap return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*bool) + res := resTmp.(bool) fc.Result = res - return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Env_ROLES(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { @@ -8431,22 +8382,6 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob if err != nil { return it, err } - case "REDIS_URL": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("REDIS_URL")) - it.RedisURL, err = ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } - case "COOKIE_NAME": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("COOKIE_NAME")) - it.CookieName, err = ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } case "RESET_PASSWORD_URL": var err error @@ -8943,39 +8878,18 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj out.Values[i] = ec._Env_ADMIN_SECRET(ctx, field, obj) case "DATABASE_NAME": out.Values[i] = ec._Env_DATABASE_NAME(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } case "DATABASE_URL": out.Values[i] = ec._Env_DATABASE_URL(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } case "DATABASE_TYPE": out.Values[i] = ec._Env_DATABASE_TYPE(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } case "DATABASE_USERNAME": out.Values[i] = ec._Env_DATABASE_USERNAME(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } case "DATABASE_PASSWORD": out.Values[i] = ec._Env_DATABASE_PASSWORD(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } case "DATABASE_HOST": out.Values[i] = ec._Env_DATABASE_HOST(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } case "DATABASE_PORT": out.Values[i] = ec._Env_DATABASE_PORT(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } case "CLIENT_ID": out.Values[i] = ec._Env_CLIENT_ID(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -9012,20 +8926,33 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj out.Values[i] = ec._Env_APP_URL(ctx, field, obj) case "REDIS_URL": out.Values[i] = ec._Env_REDIS_URL(ctx, field, obj) - case "COOKIE_NAME": - out.Values[i] = ec._Env_COOKIE_NAME(ctx, field, obj) case "RESET_PASSWORD_URL": out.Values[i] = ec._Env_RESET_PASSWORD_URL(ctx, field, obj) case "DISABLE_EMAIL_VERIFICATION": out.Values[i] = ec._Env_DISABLE_EMAIL_VERIFICATION(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "DISABLE_BASIC_AUTHENTICATION": out.Values[i] = ec._Env_DISABLE_BASIC_AUTHENTICATION(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "DISABLE_MAGIC_LINK_LOGIN": out.Values[i] = ec._Env_DISABLE_MAGIC_LINK_LOGIN(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "DISABLE_LOGIN_PAGE": out.Values[i] = ec._Env_DISABLE_LOGIN_PAGE(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "DISABLE_SIGN_UP": out.Values[i] = ec._Env_DISABLE_SIGN_UP(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "ROLES": out.Values[i] = ec._Env_ROLES(ctx, field, obj) case "PROTECTED_ROLES": diff --git a/server/graph/model/models_gen.go b/server/graph/model/models_gen.go index 1660c9c..af15c51 100644 --- a/server/graph/model/models_gen.go +++ b/server/graph/model/models_gen.go @@ -26,13 +26,13 @@ type DeleteUserInput struct { type Env struct { AccessTokenExpiryTime *string `json:"ACCESS_TOKEN_EXPIRY_TIME"` AdminSecret *string `json:"ADMIN_SECRET"` - DatabaseName string `json:"DATABASE_NAME"` - DatabaseURL string `json:"DATABASE_URL"` - DatabaseType string `json:"DATABASE_TYPE"` - DatabaseUsername string `json:"DATABASE_USERNAME"` - DatabasePassword string `json:"DATABASE_PASSWORD"` - DatabaseHost string `json:"DATABASE_HOST"` - DatabasePort string `json:"DATABASE_PORT"` + DatabaseName *string `json:"DATABASE_NAME"` + DatabaseURL *string `json:"DATABASE_URL"` + DatabaseType *string `json:"DATABASE_TYPE"` + DatabaseUsername *string `json:"DATABASE_USERNAME"` + DatabasePassword *string `json:"DATABASE_PASSWORD"` + DatabaseHost *string `json:"DATABASE_HOST"` + DatabasePort *string `json:"DATABASE_PORT"` ClientID string `json:"CLIENT_ID"` ClientSecret string `json:"CLIENT_SECRET"` CustomAccessTokenScript *string `json:"CUSTOM_ACCESS_TOKEN_SCRIPT"` @@ -48,13 +48,12 @@ type Env struct { AllowedOrigins []string `json:"ALLOWED_ORIGINS"` AppURL *string `json:"APP_URL"` RedisURL *string `json:"REDIS_URL"` - CookieName *string `json:"COOKIE_NAME"` ResetPasswordURL *string `json:"RESET_PASSWORD_URL"` - DisableEmailVerification *bool `json:"DISABLE_EMAIL_VERIFICATION"` - 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"` + DisableEmailVerification bool `json:"DISABLE_EMAIL_VERIFICATION"` + 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"` @@ -199,8 +198,6 @@ type UpdateEnvInput struct { JwtPublicKey *string `json:"JWT_PUBLIC_KEY"` AllowedOrigins []string `json:"ALLOWED_ORIGINS"` AppURL *string `json:"APP_URL"` - RedisURL *string `json:"REDIS_URL"` - CookieName *string `json:"COOKIE_NAME"` ResetPasswordURL *string `json:"RESET_PASSWORD_URL"` DisableEmailVerification *bool `json:"DISABLE_EMAIL_VERIFICATION"` DisableBasicAuthentication *bool `json:"DISABLE_BASIC_AUTHENTICATION"` diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls index d3bae73..84797ee 100644 --- a/server/graph/schema.graphqls +++ b/server/graph/schema.graphqls @@ -89,13 +89,13 @@ type Response { type Env { ACCESS_TOKEN_EXPIRY_TIME: String ADMIN_SECRET: String - DATABASE_NAME: String! - DATABASE_URL: String! - DATABASE_TYPE: String! - DATABASE_USERNAME: String! - DATABASE_PASSWORD: String! - DATABASE_HOST: String! - DATABASE_PORT: String! + DATABASE_NAME: String + DATABASE_URL: String + DATABASE_TYPE: String + DATABASE_USERNAME: String + DATABASE_PASSWORD: String + DATABASE_HOST: String + DATABASE_PORT: String CLIENT_ID: String! CLIENT_SECRET: String! CUSTOM_ACCESS_TOKEN_SCRIPT: String @@ -112,11 +112,12 @@ type Env { APP_URL: String REDIS_URL: String RESET_PASSWORD_URL: String - DISABLE_EMAIL_VERIFICATION: Boolean - DISABLE_BASIC_AUTHENTICATION: Boolean - DISABLE_MAGIC_LINK_LOGIN: Boolean - DISABLE_LOGIN_PAGE: Boolean - DISABLE_SIGN_UP: Boolean + DISABLE_EMAIL_VERIFICATION: Boolean! + DISABLE_BASIC_AUTHENTICATION: Boolean! + DISABLE_MAGIC_LINK_LOGIN: Boolean! + DISABLE_LOGIN_PAGE: Boolean! + DISABLE_SIGN_UP: Boolean! + DISABLE_REDIS_FOR_ENV: Boolean! ROLES: [String!] PROTECTED_ROLES: [String!] DEFAULT_ROLES: [String!] @@ -157,13 +158,13 @@ input UpdateEnvInput { JWT_PUBLIC_KEY: String ALLOWED_ORIGINS: [String!] APP_URL: String - REDIS_URL: String RESET_PASSWORD_URL: String DISABLE_EMAIL_VERIFICATION: Boolean DISABLE_BASIC_AUTHENTICATION: Boolean DISABLE_MAGIC_LINK_LOGIN: Boolean DISABLE_LOGIN_PAGE: Boolean DISABLE_SIGN_UP: Boolean + DISABLE_REDIS_FOR_ENV: Boolean ROLES: [String!] PROTECTED_ROLES: [String!] DEFAULT_ROLES: [String!] diff --git a/server/memorystore/memory_store.go b/server/memorystore/memory_store.go index a3c43c8..df4091b 100644 --- a/server/memorystore/memory_store.go +++ b/server/memorystore/memory_store.go @@ -1,6 +1,8 @@ package memorystore import ( + "encoding/json" + log "github.com/sirupsen/logrus" "github.com/authorizerdev/authorizer/server/constants" @@ -30,8 +32,26 @@ func InitMemStore() error { constants.EnvKeyDisableSignUp: false, } - redisURL := RequiredEnvStoreObj.GetRequiredEnv().RedisURL - if redisURL != "" { + requiredEnvs := RequiredEnvStoreObj.GetRequiredEnv() + requiredEnvMap := make(map[string]interface{}) + requiredEnvBytes, err := json.Marshal(requiredEnvs) + if err != nil { + log.Debug("Error while marshalling required envs: ", err) + return err + } + err = json.Unmarshal(requiredEnvBytes, &requiredEnvMap) + if err != nil { + log.Debug("Error while unmarshalling required envs: ", err) + return err + } + + // merge default envs with required envs + for key, val := range requiredEnvMap { + defaultEnvs[key] = val + } + + redisURL := requiredEnvs.RedisURL + if redisURL != "" && !requiredEnvs.disableRedisForEnv { log.Info("Initializing Redis memory store") Provider, err = redis.NewRedisProvider(redisURL) if err != nil { diff --git a/server/memorystore/providers/redis/provider.go b/server/memorystore/providers/redis/provider.go index ce9840d..a91a300 100644 --- a/server/memorystore/providers/redis/provider.go +++ b/server/memorystore/providers/redis/provider.go @@ -15,9 +15,12 @@ type RedisClient interface { Del(ctx context.Context, keys ...string) *redis.IntCmd HDel(ctx context.Context, key string, fields ...string) *redis.IntCmd HMGet(ctx context.Context, key string, fields ...string) *redis.SliceCmd + HSet(ctx context.Context, key string, values ...interface{}) *redis.IntCmd + HGet(ctx context.Context, key, field string) *redis.StringCmd HGetAll(ctx context.Context, key string) *redis.StringStringMapCmd Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.StatusCmd Get(ctx context.Context, key string) *redis.StringCmd + Scan(ctx context.Context, cursor uint64, match string, count int64) *redis.ScanCmd } type provider struct { diff --git a/server/memorystore/providers/redis/store.go b/server/memorystore/providers/redis/store.go index dada48c..43dd761 100644 --- a/server/memorystore/providers/redis/store.go +++ b/server/memorystore/providers/redis/store.go @@ -1,16 +1,18 @@ package redis import ( + "strconv" "strings" + "github.com/authorizerdev/authorizer/server/constants" log "github.com/sirupsen/logrus" ) var ( // session store prefix - sessionStorePrefix = "authorizer_session_" + sessionStorePrefix = "authorizer_session:" // env store prefix - envStorePrefix = "authorizer_env_" + envStorePrefix = "authorizer_env" ) // ClearStore clears the redis store for authorizer related tokens @@ -94,9 +96,8 @@ func (c *provider) RemoveState(key string) error { // UpdateEnvStore to update the whole env store object func (c *provider) UpdateEnvStore(store map[string]interface{}) error { for key, value := range store { - err := c.store.Set(c.ctx, envStorePrefix+key, value, 0).Err() + err := c.store.HSet(c.ctx, envStorePrefix, key, value).Err() if err != nil { - log.Debug("Error saving redis token: ", err) return err } } @@ -105,19 +106,28 @@ func (c *provider) UpdateEnvStore(store map[string]interface{}) error { // GetEnvStore returns the whole env store object func (c *provider) GetEnvStore() (map[string]interface{}, error) { - var res map[string]interface{} - err := c.store.HGetAll(c.ctx, envStorePrefix+"*").Scan(res) + res := make(map[string]interface{}) + data, err := c.store.HGetAll(c.ctx, envStorePrefix).Result() if err != nil { - log.Debug("error getting token from redis store: ", err) return nil, err } - + for key, value := range data { + if key == constants.EnvKeyDisableBasicAuthentication || key == constants.EnvKeyDisableEmailVerification || key == constants.EnvKeyDisableLoginPage || key == constants.EnvKeyDisableMagicLinkLogin || key == constants.EnvKeyDisableRedisForEnv || key == constants.EnvKeyDisableSignUp { + boolValue, err := strconv.ParseBool(value) + if err != nil { + return res, err + } + res[key] = boolValue + } else { + res[key] = value + } + } return res, nil } // UpdateEnvVariable to update the particular env variable func (c *provider) UpdateEnvVariable(key string, value interface{}) error { - err := c.store.Set(c.ctx, envStorePrefix+key, value, 0).Err() + err := c.store.HSet(c.ctx, envStorePrefix, key, value).Err() if err != nil { log.Debug("Error saving redis token: ", err) return err @@ -128,10 +138,9 @@ func (c *provider) UpdateEnvVariable(key string, value interface{}) error { // GetStringStoreEnvVariable to get the string env variable from env store func (c *provider) GetStringStoreEnvVariable(key string) (string, error) { var res string - err := c.store.Get(c.ctx, envStorePrefix+key).Scan(&res) + err := c.store.HGet(c.ctx, envStorePrefix, key).Scan(&res) if err != nil { - log.Debug("error getting token from redis store: ", err) - return "", err + return "", nil } return res, nil @@ -140,10 +149,9 @@ func (c *provider) GetStringStoreEnvVariable(key string) (string, error) { // GetBoolStoreEnvVariable to get the bool env variable from env store func (c *provider) GetBoolStoreEnvVariable(key string) (bool, error) { var res bool - err := c.store.Get(c.ctx, envStorePrefix+key).Scan(res) + err := c.store.HGet(c.ctx, envStorePrefix, key).Scan(res) if err != nil { - log.Debug("error getting token from redis store: ", err) - return false, err + return false, nil } return res, nil diff --git a/server/memorystore/required_env_store.go b/server/memorystore/required_env_store.go index 43073fd..a5f3a81 100644 --- a/server/memorystore/required_env_store.go +++ b/server/memorystore/required_env_store.go @@ -15,18 +15,19 @@ import ( // RequiredEnv holds information about required envs type RequiredEnv struct { - EnvPath string - DatabaseURL string - DatabaseType string - DatabaseName string - DatabaseHost string - DatabasePort string - DatabaseUsername string - DatabasePassword string - DatabaseCert string - DatabaseCertKey string - DatabaseCACert string - RedisURL string + EnvPath string `json:"ENV_PATH"` + DatabaseURL string `json:"DATABASE_URL"` + DatabaseType string `json:"DATABASE_TYPE"` + DatabaseName string `json:"DATABASE_NAME"` + DatabaseHost string `json:"DATABASE_HOST"` + DatabasePort string `json:"DATABASE_PORT"` + DatabaseUsername string `json:"DATABASE_USERNAME"` + DatabasePassword string `json:"DATABASE_PASSWORD"` + DatabaseCert string `json:"DATABASE_CERT"` + DatabaseCertKey string `json:"DATABASE_CERT_KEY"` + DatabaseCACert string `json:"DATABASE_CA_CERT"` + RedisURL string `json:"REDIS_URL"` + disableRedisForEnv bool `json:"DISABLE_REDIS_FOR_ENV"` } // RequiredEnvObj is a simple in-memory store for sessions. @@ -83,6 +84,7 @@ func InitRequiredEnv() error { dbCertKey := os.Getenv(constants.EnvKeyDatabaseCertKey) dbCACert := os.Getenv(constants.EnvKeyDatabaseCACert) redisURL := os.Getenv(constants.EnvKeyRedisURL) + disableRedisForEnv := os.Getenv(constants.EnvKeyDisableRedisForEnv) == "true" if strings.TrimSpace(redisURL) == "" { if cli.ARG_REDIS_URL != nil && *cli.ARG_REDIS_URL != "" { @@ -90,6 +92,11 @@ func InitRequiredEnv() error { } } + // set default db name for non sql dbs + if dbName == "" { + dbName = "authorizer" + } + if strings.TrimSpace(dbType) == "" { if cli.ARG_DB_TYPE != nil && *cli.ARG_DB_TYPE != "" { dbType = strings.TrimSpace(*cli.ARG_DB_TYPE) @@ -119,18 +126,19 @@ func InitRequiredEnv() error { } requiredEnv := RequiredEnv{ - EnvPath: envPath, - DatabaseURL: dbURL, - DatabaseType: dbType, - DatabaseName: dbName, - DatabaseHost: dbHost, - DatabasePort: dbPort, - DatabaseUsername: dbUsername, - DatabasePassword: dbPassword, - DatabaseCert: dbCert, - DatabaseCertKey: dbCertKey, - DatabaseCACert: dbCACert, - RedisURL: redisURL, + EnvPath: envPath, + DatabaseURL: dbURL, + DatabaseType: dbType, + DatabaseName: dbName, + DatabaseHost: dbHost, + DatabasePort: dbPort, + DatabaseUsername: dbUsername, + DatabasePassword: dbPassword, + DatabaseCert: dbCert, + DatabaseCertKey: dbCertKey, + DatabaseCACert: dbCACert, + RedisURL: redisURL, + disableRedisForEnv: disableRedisForEnv, } RequiredEnvStoreObj = &RequiredEnvStore{ diff --git a/server/resolvers/env.go b/server/resolvers/env.go index 925aa2a..d63aff4 100644 --- a/server/resolvers/env.go +++ b/server/resolvers/env.go @@ -3,6 +3,7 @@ package resolvers import ( "context" "fmt" + "strings" log "github.com/sirupsen/logrus" @@ -16,7 +17,7 @@ import ( // EnvResolver is a resolver for config query // This is admin only query func EnvResolver(ctx context.Context) (*model.Env, error) { - var res *model.Env + res := &model.Env{} gc, err := utils.GinContextFromContext(ctx) if err != nil { @@ -35,100 +36,119 @@ func EnvResolver(ctx context.Context) (*model.Env, error) { log.Debug("Failed to get env store: ", err) return res, err } - accessTokenExpiryTime := store[constants.EnvKeyAccessTokenExpiryTime].(string) - adminSecret := store[constants.EnvKeyAdminSecret].(string) - clientID := store[constants.EnvKeyClientID].(string) - clientSecret := store[constants.EnvKeyClientSecret].(string) - databaseURL := store[constants.EnvKeyDatabaseURL].(string) - databaseName := store[constants.EnvKeyDatabaseName].(string) - databaseType := store[constants.EnvKeyDatabaseType].(string) - databaseUsername := store[constants.EnvKeyDatabaseUsername].(string) - databasePassword := store[constants.EnvKeyDatabasePassword].(string) - databaseHost := store[constants.EnvKeyDatabaseHost].(string) - databasePort := store[constants.EnvKeyDatabasePort].(string) - customAccessTokenScript := store[constants.EnvKeyCustomAccessTokenScript].(string) - smtpHost := store[constants.EnvKeySmtpHost].(string) - smtpPort := store[constants.EnvKeySmtpPort].(string) - smtpUsername := store[constants.EnvKeySmtpUsername].(string) - smtpPassword := store[constants.EnvKeySmtpPassword].(string) - senderEmail := store[constants.EnvKeySenderEmail].(string) - jwtType := store[constants.EnvKeyJwtType].(string) - jwtSecret := store[constants.EnvKeyJwtSecret].(string) - jwtRoleClaim := store[constants.EnvKeyJwtRoleClaim].(string) - jwtPublicKey := store[constants.EnvKeyJwtPublicKey].(string) - jwtPrivateKey := store[constants.EnvKeyJwtPrivateKey].(string) - appURL := store[constants.EnvKeyAppURL].(string) - redisURL := store[constants.EnvKeyRedisURL].(string) - resetPasswordURL := store[constants.EnvKeyResetPasswordURL].(string) - googleClientID := store[constants.EnvKeyGoogleClientID].(string) - googleClientSecret := store[constants.EnvKeyGoogleClientSecret].(string) - facebookClientID := store[constants.EnvKeyFacebookClientID].(string) - facebookClientSecret := store[constants.EnvKeyFacebookClientSecret].(string) - githubClientID := store[constants.EnvKeyGithubClientID].(string) - githubClientSecret := store[constants.EnvKeyGithubClientSecret].(string) - organizationName := store[constants.EnvKeyOrganizationName].(string) - organizationLogo := store[constants.EnvKeyOrganizationLogo].(string) + + if val, ok := store[constants.EnvKeyAccessTokenExpiryTime]; ok { + res.AccessTokenExpiryTime = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyAdminSecret]; ok { + res.AdminSecret = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyClientID]; ok { + res.ClientID = val.(string) + } + if val, ok := store[constants.EnvKeyClientSecret]; ok { + res.ClientSecret = val.(string) + } + if val, ok := store[constants.EnvKeyDatabaseURL]; ok { + res.DatabaseURL = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyDatabaseName]; ok { + res.DatabaseName = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyDatabaseType]; ok { + res.DatabaseType = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyDatabaseUsername]; ok { + res.DatabaseUsername = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyDatabasePassword]; ok { + res.DatabasePassword = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyDatabaseHost]; ok { + res.DatabaseHost = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyDatabasePort]; ok { + res.DatabasePort = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyCustomAccessTokenScript]; ok { + res.CustomAccessTokenScript = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeySmtpHost]; ok { + res.SMTPHost = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeySmtpPort]; ok { + res.SMTPPort = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeySmtpUsername]; ok { + res.SMTPUsername = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeySmtpPassword]; ok { + res.SMTPPassword = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeySenderEmail]; ok { + res.SenderEmail = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyJwtType]; ok { + res.JwtType = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyJwtSecret]; ok { + res.JwtSecret = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyJwtRoleClaim]; ok { + res.JwtRoleClaim = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyJwtPublicKey]; ok { + res.JwtPublicKey = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyJwtPrivateKey]; ok { + res.JwtPrivateKey = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyAppURL]; ok { + res.AppURL = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyRedisURL]; ok { + res.RedisURL = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyResetPasswordURL]; ok { + res.ResetPasswordURL = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyGoogleClientID]; ok { + res.GoogleClientID = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyGoogleClientSecret]; ok { + res.GoogleClientSecret = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyFacebookClientID]; ok { + res.FacebookClientID = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyFacebookClientSecret]; ok { + res.FacebookClientSecret = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyGithubClientID]; ok { + res.GithubClientID = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyGithubClientSecret]; ok { + res.GithubClientSecret = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyOrganizationName]; ok { + res.OrganizationName = utils.NewStringRef(val.(string)) + } + if val, ok := store[constants.EnvKeyOrganizationLogo]; ok { + res.OrganizationLogo = utils.NewStringRef(val.(string)) + } // string slice vars - allowedOrigins := utils.ConvertInterfaceToStringSlice(store[constants.EnvKeyAllowedOrigins]) - roles := utils.ConvertInterfaceToStringSlice(store[constants.EnvKeyRoles]) - defaultRoles := utils.ConvertInterfaceToStringSlice(store[constants.EnvKeyDefaultRoles]) - protectedRoles := utils.ConvertInterfaceToStringSlice(store[constants.EnvKeyProtectedRoles]) + res.AllowedOrigins = strings.Split(store[constants.EnvKeyAllowedOrigins].(string), ",") + res.Roles = strings.Split(store[constants.EnvKeyRoles].(string), ",") + res.DefaultRoles = strings.Split(store[constants.EnvKeyDefaultRoles].(string), ",") + res.ProtectedRoles = strings.Split(store[constants.EnvKeyProtectedRoles].(string), ",") // bool vars - disableEmailVerification := store[constants.EnvKeyDisableEmailVerification].(bool) - disableBasicAuthentication := store[constants.EnvKeyDisableBasicAuthentication].(bool) - disableMagicLinkLogin := store[constants.EnvKeyDisableMagicLinkLogin].(bool) - disableLoginPage := store[constants.EnvKeyDisableLoginPage].(bool) - disableSignUp := store[constants.EnvKeyDisableSignUp].(bool) + res.DisableEmailVerification = store[constants.EnvKeyDisableEmailVerification].(bool) + res.DisableBasicAuthentication = store[constants.EnvKeyDisableBasicAuthentication].(bool) + res.DisableMagicLinkLogin = store[constants.EnvKeyDisableMagicLinkLogin].(bool) + res.DisableLoginPage = store[constants.EnvKeyDisableLoginPage].(bool) + res.DisableSignUp = store[constants.EnvKeyDisableSignUp].(bool) - if accessTokenExpiryTime == "" { - accessTokenExpiryTime = "30m" - } - - res = &model.Env{ - AccessTokenExpiryTime: &accessTokenExpiryTime, - AdminSecret: &adminSecret, - DatabaseName: databaseName, - DatabaseURL: databaseURL, - DatabaseType: databaseType, - DatabaseUsername: databaseUsername, - DatabasePassword: databasePassword, - DatabaseHost: databaseHost, - DatabasePort: databasePort, - ClientID: clientID, - ClientSecret: clientSecret, - CustomAccessTokenScript: &customAccessTokenScript, - SMTPHost: &smtpHost, - SMTPPort: &smtpPort, - SMTPPassword: &smtpPassword, - SMTPUsername: &smtpUsername, - SenderEmail: &senderEmail, - JwtType: &jwtType, - JwtSecret: &jwtSecret, - JwtPrivateKey: &jwtPrivateKey, - JwtPublicKey: &jwtPublicKey, - JwtRoleClaim: &jwtRoleClaim, - AllowedOrigins: allowedOrigins, - AppURL: &appURL, - RedisURL: &redisURL, - ResetPasswordURL: &resetPasswordURL, - DisableEmailVerification: &disableEmailVerification, - DisableBasicAuthentication: &disableBasicAuthentication, - DisableMagicLinkLogin: &disableMagicLinkLogin, - DisableLoginPage: &disableLoginPage, - DisableSignUp: &disableSignUp, - Roles: roles, - ProtectedRoles: protectedRoles, - DefaultRoles: defaultRoles, - GoogleClientID: &googleClientID, - GoogleClientSecret: &googleClientSecret, - GithubClientID: &githubClientID, - GithubClientSecret: &githubClientSecret, - FacebookClientID: &facebookClientID, - FacebookClientSecret: &facebookClientSecret, - OrganizationName: &organizationName, - OrganizationLogo: &organizationLogo, - } return res, nil } diff --git a/server/resolvers/update_env.go b/server/resolvers/update_env.go index 91f0825..d7023a0 100644 --- a/server/resolvers/update_env.go +++ b/server/resolvers/update_env.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "reflect" + "strings" log "github.com/sirupsen/logrus" @@ -169,11 +170,8 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model updatedData[key] = value.(bool) } if fieldType == "[]interface {}" { - stringArr := []string{} - for _, v := range value.([]interface{}) { - stringArr = append(stringArr, v.(string)) - } - updatedData[key] = stringArr + stringArr := utils.ConvertInterfaceToStringSlice(value) + updatedData[key] = strings.Join(stringArr, ",") } } } diff --git a/server/resolvers/update_user.go b/server/resolvers/update_user.go index ca52f63..b1b72b6 100644 --- a/server/resolvers/update_user.go +++ b/server/resolvers/update_user.go @@ -165,7 +165,6 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod roles = strings.Split(rolesString, ",") } protectedRolesString, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyProtectedRoles) - fmt.Println(protectedRolesString) protectedRoles := []string{} if err != nil { log.Debug("Error getting protected roles: ", err) diff --git a/server/test/env_test.go b/server/test/env_test.go index b02cca7..725a834 100644 --- a/server/test/env_test.go +++ b/server/test/env_test.go @@ -25,7 +25,6 @@ func envTests(t *testing.T, s TestSetup) { assert.Nil(t, err) req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) res, err := resolvers.EnvResolver(ctx) - assert.Nil(t, err) assert.Equal(t, *res.AdminSecret, adminSecret) }) diff --git a/server/test/test.go b/server/test/test.go index d89a361..86866e2 100644 --- a/server/test/test.go +++ b/server/test/test.go @@ -93,7 +93,7 @@ func testSetup() TestSetup { memorystore.Provider.UpdateEnvVariable(constants.EnvKeySmtpUsername, "lakhan@yopmail.com") memorystore.Provider.UpdateEnvVariable(constants.EnvKeySmtpPassword, "test") memorystore.Provider.UpdateEnvVariable(constants.EnvKeySenderEmail, "info@yopmail.com") - memorystore.Provider.UpdateEnvVariable(constants.EnvKeyProtectedRoles, []string{"admin"}) + memorystore.Provider.UpdateEnvVariable(constants.EnvKeyProtectedRoles, "admin") memorystore.InitMemStore() db.InitDB() env.InitAllEnv() diff --git a/server/test/update_user_test.go b/server/test/update_user_test.go index 5fc2cd9..ca197f7 100644 --- a/server/test/update_user_test.go +++ b/server/test/update_user_test.go @@ -45,7 +45,7 @@ func updateUserTest(t *testing.T, s TestSetup) { // supplier is not part of envs assert.Error(t, err) adminRole = "admin" - memorystore.Provider.UpdateEnvVariable(constants.EnvKeyProtectedRoles, []string{adminRole}) + memorystore.Provider.UpdateEnvVariable(constants.EnvKeyProtectedRoles, adminRole) newRoles = []*string{&adminRole, &userRole} _, err = resolvers.UpdateUserResolver(ctx, model.UpdateUserInput{ ID: user.ID, diff --git a/server/token/auth_token.go b/server/token/auth_token.go index a977c41..65cb0d1 100644 --- a/server/token/auth_token.go +++ b/server/token/auth_token.go @@ -192,7 +192,7 @@ func GetAccessToken(gc *gin.Context) (string, error) { // Function to validate access token for authorizer apis (profile, update_profile) func ValidateAccessToken(gc *gin.Context, accessToken string) (map[string]interface{}, error) { - var res map[string]interface{} + res := make(map[string]interface{}) if accessToken == "" { return res, fmt.Errorf(`unauthorized`) @@ -222,7 +222,7 @@ func ValidateAccessToken(gc *gin.Context, accessToken string) (map[string]interf // Function to validate refreshToken func ValidateRefreshToken(gc *gin.Context, refreshToken string) (map[string]interface{}, error) { - var res map[string]interface{} + res := make(map[string]interface{}) if refreshToken == "" { return res, fmt.Errorf(`unauthorized`) diff --git a/server/utils/refs.go b/server/utils/refs.go new file mode 100644 index 0000000..3dd87cd --- /dev/null +++ b/server/utils/refs.go @@ -0,0 +1,6 @@ +package utils + +// NewStringRef returns a reference to a string with given value +func NewStringRef(v string) *string { + return &v +}