fix: import cycle issues

This commit is contained in:
Lakhan Samani 2022-05-30 11:54:16 +05:30
parent 1146468a03
commit 7e3bd6a721
37 changed files with 349 additions and 239 deletions

View File

@ -1,4 +1,4 @@
package utils
package cli
var (
// ARG_DB_URL is the cli arg variable for the database url

View File

@ -4,7 +4,7 @@ import (
"net/url"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/gin-gonic/gin"
)
@ -12,8 +12,8 @@ import (
func SetAdminCookie(gc *gin.Context, token string) {
secure := true
httpOnly := true
hostname := utils.GetHost(gc)
host, _ := utils.GetHostParts(hostname)
hostname := parsers.GetHost(gc)
host, _ := parsers.GetHostParts(hostname)
gc.SetCookie(constants.AdminCookieName, token, 3600, "/", host, secure, httpOnly)
}
@ -37,7 +37,7 @@ func GetAdminCookie(gc *gin.Context) (string, error) {
func DeleteAdminCookie(gc *gin.Context) {
secure := true
httpOnly := true
hostname := utils.GetHost(gc)
host, _ := utils.GetHostParts(hostname)
hostname := parsers.GetHost(gc)
host, _ := parsers.GetHostParts(hostname)
gc.SetCookie(constants.AdminCookieName, "", -1, "/", host, secure, httpOnly)
}

View File

@ -5,7 +5,7 @@ import (
"net/url"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/gin-gonic/gin"
)
@ -13,9 +13,9 @@ import (
func SetSession(gc *gin.Context, sessionID string) {
secure := true
httpOnly := true
hostname := utils.GetHost(gc)
host, _ := utils.GetHostParts(hostname)
domain := utils.GetDomainName(hostname)
hostname := parsers.GetHost(gc)
host, _ := parsers.GetHostParts(hostname)
domain := parsers.GetDomainName(hostname)
if domain != "localhost" {
domain = "." + domain
}
@ -32,9 +32,9 @@ func SetSession(gc *gin.Context, sessionID string) {
func DeleteSession(gc *gin.Context) {
secure := true
httpOnly := true
hostname := utils.GetHost(gc)
host, _ := utils.GetHostParts(hostname)
domain := utils.GetDomainName(hostname)
hostname := parsers.GetHost(gc)
host, _ := parsers.GetHostParts(hostname)
domain := parsers.GetDomainName(hostname)
if domain != "localhost" {
domain = "." + domain
}

3
server/env/env.go vendored
View File

@ -11,6 +11,7 @@ import (
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -251,7 +252,7 @@ func InitAllEnv() error {
trimVal := strings.TrimSpace(val)
if trimVal != "" {
if trimVal != "*" {
host, port := utils.GetHostParts(trimVal)
host, port := parsers.GetHostParts(trimVal)
allowedOrigins = append(allowedOrigins, host+":"+port)
} else {
hasWildCard = true

View File

@ -15,6 +15,7 @@ import (
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// GetEnvData returns the env data from database
@ -138,7 +139,7 @@ func PersistEnv() error {
case constants.EnvKeyRoles, constants.EnvKeyDefaultRoles, constants.EnvKeyProtectedRoles:
envStringArr := strings.Split(envValue, ",")
originalValue := utils.ConvertInterfaceToStringSlice(value)
if !utils.IsStringArrayEqual(originalValue, envStringArr) {
if !validators.IsStringArrayEqual(originalValue, envStringArr) {
storeData[key] = envStringArr
hasChanged = true
}

View File

@ -9,7 +9,8 @@ import (
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/validators"
)
// State is the struct that holds authorizer url and redirect url
@ -22,7 +23,7 @@ type State struct {
// AppHandler is the handler for the /app route
func AppHandler() gin.HandlerFunc {
return func(c *gin.Context) {
hostname := utils.GetHost(c)
hostname := parsers.GetHost(c)
if isLoginPageDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableLoginPage); err != nil || isLoginPageDisabled {
log.Debug("Login page is disabled")
c.JSON(400, gin.H{"error": "login page is not enabled"})
@ -44,7 +45,7 @@ func AppHandler() gin.HandlerFunc {
redirect_uri = hostname + "/app"
} else {
// validate redirect url with allowed origins
if !utils.IsValidOrigin(redirect_uri) {
if !validators.IsValidOrigin(redirect_uri) {
log.Debug("Invalid redirect_uri")
c.JSON(400, gin.H{"error": "invalid redirect url"})
return

View File

@ -10,13 +10,14 @@ import (
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/oauth"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/validators"
)
// OAuthLoginHandler set host in the oauth state that is useful for redirecting to oauth_callback
func OAuthLoginHandler() gin.HandlerFunc {
return func(c *gin.Context) {
hostname := utils.GetHost(c)
hostname := parsers.GetHost(c)
// deprecating redirectURL instead use redirect_uri
redirectURI := strings.TrimSpace(c.Query("redirectURL"))
if redirectURI == "" {
@ -64,7 +65,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
log.Debug("Error getting protected roles: ", err)
}
if !utils.IsValidRoles(rolesSplit, append([]string{}, append(roles, protectedRoles...)...)) {
if !validators.IsValidRoles(rolesSplit, append([]string{}, append(roles, protectedRoles...)...)) {
log.Debug("Invalid roles: ", roles)
c.JSON(400, gin.H{
"error": "invalid role",

View File

@ -5,13 +5,13 @@ import (
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/parsers"
)
// OpenIDConfigurationHandler handler for open-id configurations
func OpenIDConfigurationHandler() gin.HandlerFunc {
return func(c *gin.Context) {
issuer := utils.GetHost(c)
issuer := parsers.GetHost(c)
jwtType, _ := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
c.JSON(200, gin.H{

View File

@ -13,6 +13,7 @@ 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/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -40,7 +41,7 @@ func VerifyEmailHandler() gin.HandlerFunc {
}
// verify if token exists in db
hostname := utils.GetHost(c)
hostname := parsers.GetHost(c)
claim, err := token.ParseJWTToken(tokenInQuery, hostname, verificationRequest.Nonce, verificationRequest.Email)
if err != nil {
log.Debug("Error parsing token: ", err)

View File

@ -6,13 +6,13 @@ import (
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/cli"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/env"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/oauth"
"github.com/authorizerdev/authorizer/server/routes"
"github.com/authorizerdev/authorizer/server/utils"
)
var VERSION string
@ -27,10 +27,10 @@ func (u LogUTCFormatter) Format(e *log.Entry) ([]byte, error) {
}
func main() {
utils.ARG_DB_URL = flag.String("database_url", "", "Database connection string")
utils.ARG_DB_TYPE = flag.String("database_type", "", "Database type, possible values are postgres,mysql,sqlite")
utils.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
utils.ARG_LOG_LEVEL = flag.String("log_level", "info", "Log level, possible values are debug,info,warn,error,fatal,panic")
cli.ARG_DB_URL = flag.String("database_url", "", "Database connection string")
cli.ARG_DB_TYPE = flag.String("database_type", "", "Database type, possible values are postgres,mysql,sqlite")
cli.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
cli.ARG_LOG_LEVEL = flag.String("log_level", "info", "Log level, possible values are debug,info,warn,error,fatal,panic")
flag.Parse()
// global log level
@ -41,7 +41,7 @@ func main() {
log.SetFormatter(LogUTCFormatter{&logrus.JSONFormatter{}})
var logLevel logrus.Level
switch *utils.ARG_LOG_LEVEL {
switch *cli.ARG_LOG_LEVEL {
case "debug":
logLevel = logrus.DebugLevel
case "info":
@ -107,5 +107,11 @@ func main() {
router := routes.InitRouter(log)
log.Info("Starting Authorizer: ", VERSION)
router.Run(":" + memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyPort))
port, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyPort)
if err != nil {
log.Info("Error while getting port from env using default port 8080: ", err)
port = "8080"
}
router.Run(":" + port)
}

View File

@ -2,8 +2,6 @@ package inmemory
import (
"strings"
"github.com/authorizerdev/authorizer/server/utils"
)
// ClearStore clears the in-memory store.
@ -105,6 +103,12 @@ func (c *provider) GetBoolStoreEnvVariable(key string) (bool, error) {
// GetSliceStoreEnvVariable to get the env variable from slice store object
func (c *provider) GetSliceStoreEnvVariable(key string) ([]string, error) {
res := c.envStore.Get(key)
resSlice := utils.ConvertInterfaceToStringSlice(res)
data := res.([]interface{})
var resSlice []string
for _, v := range data {
resSlice = append(resSlice, v.(string))
}
return resSlice, nil
}

View File

@ -9,8 +9,8 @@ import (
"github.com/joho/godotenv"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/cli"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/utils"
)
// RequiredEnv holds information about required envs
@ -62,8 +62,8 @@ func InitRequiredEnv() error {
}
}
if utils.ARG_ENV_FILE != nil && *utils.ARG_ENV_FILE != "" {
envPath = *utils.ARG_ENV_FILE
if cli.ARG_ENV_FILE != nil && *cli.ARG_ENV_FILE != "" {
envPath = *cli.ARG_ENV_FILE
}
log.Info("env path: ", envPath)
@ -85,8 +85,8 @@ func InitRequiredEnv() error {
redisURL := os.Getenv(constants.EnvKeyRedisURL)
if strings.TrimSpace(dbType) == "" {
if utils.ARG_DB_TYPE != nil && *utils.ARG_DB_TYPE != "" {
dbType = strings.TrimSpace(*utils.ARG_DB_TYPE)
if cli.ARG_DB_TYPE != nil && *cli.ARG_DB_TYPE != "" {
dbType = strings.TrimSpace(*cli.ARG_DB_TYPE)
}
if dbType == "" {
@ -96,8 +96,8 @@ func InitRequiredEnv() error {
}
if strings.TrimSpace(dbURL) == "" {
if utils.ARG_DB_URL != nil && *utils.ARG_DB_URL != "" {
dbURL = strings.TrimSpace(*utils.ARG_DB_URL)
if cli.ARG_DB_URL != nil && *cli.ARG_DB_URL != "" {
dbURL = strings.TrimSpace(*cli.ARG_DB_URL)
}
if dbURL == "" && dbPort == "" && dbHost == "" && dbUsername == "" && dbPassword == "" {

View File

@ -1,7 +1,7 @@
package middlewares
import (
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
"github.com/gin-gonic/gin"
)
@ -10,7 +10,7 @@ func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
origin := c.Request.Header.Get("Origin")
if utils.IsValidOrigin(origin) {
if validators.IsValidOrigin(origin) {
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
}

View File

@ -1,4 +1,4 @@
package utils
package parsers
import (
"net/url"
@ -19,7 +19,10 @@ func GetHost(c *gin.Context) string {
return authorizerURL
}
authorizerURL = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL)
authorizerURL, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL)
if err == nil {
authorizerURL = ""
}
if authorizerURL != "" {
return authorizerURL
}
@ -89,8 +92,8 @@ func GetDomainName(uri string) string {
// GetAppURL to get /app/ url if not configured by user
func GetAppURL(gc *gin.Context) string {
envAppURL := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAppURL)
if envAppURL == "" {
envAppURL, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAppURL)
if envAppURL == "" || err != nil {
envAppURL = GetHost(gc) + "/app"
}
return envAppURL

View File

@ -14,8 +14,10 @@ import (
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// ForgotPasswordResolver is a resolver for forgot password mutation
@ -39,7 +41,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
}
params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) {
if !validators.IsValidEmail(params.Email) {
log.Debug("Invalid email address: ", params.Email)
return res, fmt.Errorf("invalid email")
}
@ -53,13 +55,13 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
return res, fmt.Errorf(`user with this email not found`)
}
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
_, nonceHash, err := utils.GenerateNonce()
if err != nil {
log.Debug("Failed to generate nonce: ", err)
return res, err
}
redirectURL := utils.GetAppURL(gc) + "/reset-password"
redirectURL := parsers.GetAppURL(gc) + "/reset-password"
if params.RedirectURI != nil {
redirectURL = *params.RedirectURI
}

View File

@ -15,8 +15,10 @@ import (
emailservice "github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// InviteMembersResolver resolver to invite members
@ -54,7 +56,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
// filter valid emails
emails := []string{}
for _, email := range params.Emails {
if utils.IsValidEmail(email) {
if validators.IsValidEmail(email) {
emails = append(emails, email)
}
}
@ -93,9 +95,9 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
Email: email,
Roles: strings.Join(defaultRoles, ","),
}
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
verifyEmailURL := hostname + "/verify_email"
appURL := utils.GetAppURL(gc)
appURL := parsers.GetAppURL(gc)
redirectURL := appURL
if params.RedirectURI != nil {

View File

@ -17,6 +17,7 @@ import (
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// LoginResolver is a resolver for login mutation
@ -78,7 +79,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
}
currentRoles := strings.Split(user.Roles, ",")
if len(params.Roles) > 0 {
if !utils.IsValidRoles(params.Roles, currentRoles) {
if !validators.IsValidRoles(params.Roles, currentRoles) {
log.Debug("Invalid roles: ", params.Roles)
return res, fmt.Errorf(`invalid roles`)
}

View File

@ -14,8 +14,10 @@ import (
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// MagicLinkLoginResolver is a resolver for magic link login mutation
@ -41,7 +43,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) {
if !validators.IsValidEmail(params.Email) {
log.Debug("Invalid email")
return res, fmt.Errorf(`invalid email address`)
}
@ -77,7 +79,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
log.Debug("Error getting roles: ", err)
return res, err
}
if !utils.IsValidRoles(params.Roles, roles) {
if !validators.IsValidRoles(params.Roles, roles) {
log.Debug("Invalid roles: ", params.Roles)
return res, fmt.Errorf(`invalid roles`)
} else {
@ -158,7 +160,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
}
}
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
isEmailVerificationDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification)
if err != nil {
log.Debug("Error getting email verification disabled: ", err)
@ -178,7 +180,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
if params.Scope != nil && len(params.Scope) > 0 {
redirectURLParams = redirectURLParams + "&scope=" + strings.Join(params.Scope, " ")
}
redirectURL := utils.GetAppURL(gc)
redirectURL := parsers.GetAppURL(gc)
if params.RedirectURI != nil {
redirectURL = *params.RedirectURI
}

View File

@ -3,12 +3,90 @@ package resolvers
import (
"context"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// MetaResolver is a resolver for meta query
func MetaResolver(ctx context.Context) (*model.Meta, error) {
metaInfo := utils.GetMetaInfo()
clientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID)
if err != nil {
return nil, err
}
googleClientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID)
if err != nil {
log.Debug("Failed to get Google Client ID from environment variable", err)
googleClientID = ""
}
googleClientSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientSecret)
if err != nil {
log.Debug("Failed to get Google Client Secret from environment variable", err)
googleClientSecret = ""
}
facebookClientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientID)
if err != nil {
log.Debug("Failed to get Facebook Client ID from environment variable", err)
facebookClientID = ""
}
facebookClientSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientSecret)
if err != nil {
log.Debug("Failed to get Facebook Client Secret from environment variable", err)
facebookClientSecret = ""
}
githubClientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyGithubClientID)
if err != nil {
log.Debug("Failed to get Github Client ID from environment variable", err)
githubClientID = ""
}
githubClientSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyGithubClientSecret)
if err != nil {
log.Debug("Failed to get Github Client Secret from environment variable", err)
githubClientSecret = ""
}
isBasicAuthDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication)
if err != nil {
log.Debug("Failed to get Disable Basic Authentication from environment variable", err)
isBasicAuthDisabled = true
}
isEmailVerificationDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification)
if err != nil {
log.Debug("Failed to get Disable Email Verification from environment variable", err)
isEmailVerificationDisabled = true
}
isMagicLinkLoginDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin)
if err != nil {
log.Debug("Failed to get Disable Magic Link Login from environment variable", err)
isMagicLinkLoginDisabled = true
}
isSignUpDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp)
if err != nil {
log.Debug("Failed to get Disable Signup from environment variable", err)
isSignUpDisabled = true
}
metaInfo := model.Meta{
Version: constants.VERSION,
ClientID: clientID,
IsGoogleLoginEnabled: googleClientID != "" && googleClientSecret != "",
IsGithubLoginEnabled: githubClientID != "" && githubClientSecret != "",
IsFacebookLoginEnabled: facebookClientID != "" && facebookClientSecret != "",
IsBasicAuthenticationEnabled: !isBasicAuthDisabled,
IsEmailVerificationEnabled: !isEmailVerificationDisabled,
IsMagicLinkLoginEnabled: !isMagicLinkLoginDisabled,
IsSignUpEnabled: !isSignUpDisabled,
}
return &metaInfo, nil
}

View File

@ -12,8 +12,10 @@ import (
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// ResendVerifyEmailResolver is a resolver for resend verify email mutation
@ -27,12 +29,12 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
}
params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) {
if !validators.IsValidEmail(params.Email) {
log.Debug("Invalid email: ", params.Email)
return res, fmt.Errorf("invalid email")
}
if !utils.IsValidVerificationIdentifier(params.Identifier) {
if !validators.IsValidVerificationIdentifier(params.Identifier) {
log.Debug("Invalid verification identifier: ", params.Identifier)
return res, fmt.Errorf("invalid identifier")
}
@ -49,7 +51,7 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
log.Debug("Failed to delete verification request: ", err)
}
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
_, nonceHash, err := utils.GenerateNonce()
if err != nil {
log.Debug("Failed to generate nonce: ", err)

View File

@ -13,8 +13,10 @@ import (
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// ResetPasswordResolver is a resolver for reset password mutation
@ -48,13 +50,13 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
return res, fmt.Errorf(`passwords don't match`)
}
if !utils.IsValidPassword(params.Password) {
if !validators.IsValidPassword(params.Password) {
log.Debug("Invalid password")
return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`)
}
// verify if token exists in db
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email)
if err != nil {
log.Debug("Failed to parse token: ", err)

View File

@ -16,8 +16,10 @@ import (
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// SignupResolver is a resolver for signup mutation
@ -56,14 +58,14 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
return res, fmt.Errorf(`password and confirm password does not match`)
}
if !utils.IsValidPassword(params.Password) {
if !validators.IsValidPassword(params.Password) {
log.Debug("Invalid password")
return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`)
}
params.Email = strings.ToLower(params.Email)
if !utils.IsValidEmail(params.Email) {
if !validators.IsValidEmail(params.Email) {
log.Debug("Invalid email: ", params.Email)
return res, fmt.Errorf(`invalid email address`)
}
@ -95,7 +97,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
log.Debug("Error getting roles: ", err)
return res, err
}
if !utils.IsValidRoles(roles, params.Roles) {
if !validators.IsValidRoles(roles, params.Roles) {
log.Debug("Invalid roles: ", params.Roles)
return res, fmt.Errorf(`invalid roles`)
} else {
@ -168,7 +170,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
roles := strings.Split(user.Roles, ",")
userToReturn := user.AsAPIUser()
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
if !isEmailVerificationDisabled {
// insert verification request
_, nonceHash, err := utils.GenerateNonce()
@ -177,7 +179,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
return res, err
}
verificationType := constants.VerificationTypeBasicAuthSignup
redirectURL := utils.GetAppURL(gc)
redirectURL := parsers.GetAppURL(gc)
if params.RedirectURI != nil {
redirectURL = *params.RedirectURI
}

View File

@ -16,8 +16,10 @@ import (
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
"golang.org/x/crypto/bcrypt"
)
@ -121,14 +123,14 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
if params.Email != nil && user.Email != *params.Email {
// check if valid email
if !utils.IsValidEmail(*params.Email) {
if !validators.IsValidEmail(*params.Email) {
log.Debug("Failed to validate email: ", *params.Email)
return res, fmt.Errorf("invalid email address")
}
newEmail := strings.ToLower(*params.Email)
// check if valid email
if !utils.IsValidEmail(newEmail) {
if !validators.IsValidEmail(newEmail) {
log.Debug("Failed to validate new email: ", newEmail)
return res, fmt.Errorf("invalid new email address")
}
@ -150,7 +152,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
return res, err
}
if !isEmailVerificationDisabled {
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
user.EmailVerifiedAt = nil
hasEmailChanged = true
// insert verification request
@ -160,7 +162,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
return res, err
}
verificationType := constants.VerificationTypeUpdateEmail
redirectURL := utils.GetAppURL(gc)
redirectURL := parsers.GetAppURL(gc)
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL)
if err != nil {
log.Debug("Failed to create verification token: ", err)

View File

@ -14,8 +14,10 @@ import (
"github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
)
// UpdateUserResolver is a resolver for update user mutation
@ -97,7 +99,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
if params.Email != nil && user.Email != *params.Email {
// check if valid email
if !utils.IsValidEmail(*params.Email) {
if !validators.IsValidEmail(*params.Email) {
log.Debug("Invalid email: ", *params.Email)
return res, fmt.Errorf("invalid email address")
}
@ -113,7 +115,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
// TODO figure out how to do this
go memorystore.Provider.DeleteAllUserSession(user.ID)
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
user.Email = newEmail
user.EmailVerifiedAt = nil
// insert verification request
@ -123,7 +125,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
return res, err
}
verificationType := constants.VerificationTypeUpdateEmail
redirectURL := utils.GetAppURL(gc)
redirectURL := parsers.GetAppURL(gc)
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash, redirectURL)
if err != nil {
log.Debug("Failed to create verification token: ", err)
@ -163,12 +165,12 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
log.Debug("Error getting protected roles: ", err)
}
if !utils.IsValidRoles(inputRoles, append([]string{}, append(roles, protectedRoles...)...)) {
if !validators.IsValidRoles(inputRoles, append([]string{}, append(roles, protectedRoles...)...)) {
log.Debug("Invalid roles: ", params.Roles)
return res, fmt.Errorf("invalid list of roles")
}
if !utils.IsStringArrayEqual(inputRoles, currentRoles) {
if !validators.IsStringArrayEqual(inputRoles, currentRoles) {
rolesToSave = strings.Join(inputRoles, ",")
}

View File

@ -11,6 +11,7 @@ import (
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -49,7 +50,7 @@ func ValidateJwtTokenResolver(ctx context.Context, params model.ValidateJWTToken
userID = savedSessionSplit[1]
}
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
var claimRoles []string
var claims jwt.MapClaims

View File

@ -13,6 +13,7 @@ import (
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -34,7 +35,7 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
}
// verify if token exists in db
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email)
if err != nil {
log.Debug("Failed to parse token: ", err)

View File

@ -3,6 +3,7 @@ package test
import (
"testing"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/stretchr/testify/assert"
)
@ -10,7 +11,7 @@ import (
func TestGetHostName(t *testing.T) {
url := "http://test.herokuapp.com:80"
host, port := utils.GetHostParts(url)
host, port := parsers.GetHostParts(url)
expectedHost := "test.herokuapp.com"
assert.Equal(t, host, expectedHost, "hostname should be equal")

View File

@ -6,6 +6,7 @@ import (
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/utils"
"github.com/authorizerdev/authorizer/server/validators"
"github.com/stretchr/testify/assert"
)
@ -14,24 +15,24 @@ func TestIsValidEmail(t *testing.T) {
invalidEmail1 := "lakhan"
invalidEmail2 := "lakhan.me"
assert.True(t, utils.IsValidEmail(validEmail), "it should be valid email")
assert.False(t, utils.IsValidEmail(invalidEmail1), "it should be invalid email")
assert.False(t, utils.IsValidEmail(invalidEmail2), "it should be invalid email")
assert.True(t, validators.IsValidEmail(validEmail), "it should be valid email")
assert.False(t, validators.IsValidEmail(invalidEmail1), "it should be invalid email")
assert.False(t, validators.IsValidEmail(invalidEmail2), "it should be invalid email")
}
func TestIsValidOrigin(t *testing.T) {
// don't use portocal(http/https) for ALLOWED_ORIGINS while testing,
// as we trim them off while running the main function
memorystore.Provider.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyAllowedOrigins, []string{"localhost:8080", "*.google.com", "*.google.in", "*abc.*"})
assert.False(t, utils.IsValidOrigin("http://myapp.com"), "it should be invalid origin")
assert.False(t, utils.IsValidOrigin("http://appgoogle.com"), "it should be invalid origin")
assert.True(t, utils.IsValidOrigin("http://app.google.com"), "it should be valid origin")
assert.False(t, utils.IsValidOrigin("http://app.google.ind"), "it should be invalid origin")
assert.True(t, utils.IsValidOrigin("http://app.google.in"), "it should be valid origin")
assert.True(t, utils.IsValidOrigin("http://xyx.abc.com"), "it should be valid origin")
assert.True(t, utils.IsValidOrigin("http://xyx.abc.in"), "it should be valid origin")
assert.True(t, utils.IsValidOrigin("http://xyxabc.in"), "it should be valid origin")
assert.True(t, utils.IsValidOrigin("http://localhost:8080"), "it should be valid origin")
assert.False(t, validators.IsValidOrigin("http://myapp.com"), "it should be invalid origin")
assert.False(t, validators.IsValidOrigin("http://appgoogle.com"), "it should be invalid origin")
assert.True(t, validators.IsValidOrigin("http://app.google.com"), "it should be valid origin")
assert.False(t, validators.IsValidOrigin("http://app.google.ind"), "it should be invalid origin")
assert.True(t, validators.IsValidOrigin("http://app.google.in"), "it should be valid origin")
assert.True(t, validators.IsValidOrigin("http://xyx.abc.com"), "it should be valid origin")
assert.True(t, validators.IsValidOrigin("http://xyx.abc.in"), "it should be valid origin")
assert.True(t, validators.IsValidOrigin("http://xyxabc.in"), "it should be valid origin")
assert.True(t, validators.IsValidOrigin("http://localhost:8080"), "it should be valid origin")
memorystore.Provider.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyAllowedOrigins, []string{"*"})
}

View File

@ -17,6 +17,7 @@ import (
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
"github.com/authorizerdev/authorizer/server/utils"
)
@ -66,7 +67,7 @@ func CreateSessionToken(user models.User, nonce string, roles, scope []string) (
// CreateAuthToken creates a new auth token when userlogs in
func CreateAuthToken(gc *gin.Context, user models.User, roles, scope []string) (*Token, error) {
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
nonce := uuid.New().String()
_, fingerPrintHash, err := CreateSessionToken(user, nonce, roles, scope)
if err != nil {
@ -206,7 +207,7 @@ func ValidateAccessToken(gc *gin.Context, accessToken string) (map[string]interf
nonce := savedSessionSplit[0]
userID := savedSessionSplit[1]
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
res, err = ParseJWTToken(accessToken, hostname, nonce, userID)
if err != nil {
return res, err
@ -236,7 +237,7 @@ func ValidateRefreshToken(gc *gin.Context, refreshToken string) (map[string]inte
nonce := savedSessionSplit[0]
userID := savedSessionSplit[1]
hostname := utils.GetHost(gc)
hostname := parsers.GetHost(gc)
res, err = ParseJWTToken(refreshToken, hostname, nonce, userID)
if err != nil {
return res, err

View File

@ -1,22 +0,0 @@
package utils
import (
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// GetMeta helps in getting the meta data about the deployment from EnvData
func GetMetaInfo() model.Meta {
return model.Meta{
Version: constants.VERSION,
ClientID: memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID),
IsGoogleLoginEnabled: memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID) != "" && memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientSecret) != "",
IsGithubLoginEnabled: memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyGithubClientID) != "" && memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyGithubClientSecret) != "",
IsFacebookLoginEnabled: memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientID) != "" && memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientSecret) != "",
IsBasicAuthenticationEnabled: !memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication),
IsEmailVerificationEnabled: !memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification),
IsMagicLinkLoginEnabled: !memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin),
IsSignUpEnabled: !memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp),
}
}

View File

@ -1,120 +0,0 @@
package utils
import (
"net/mail"
"regexp"
"strings"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// IsValidEmail validates email
func IsValidEmail(email string) bool {
_, err := mail.ParseAddress(email)
return err == nil
}
// IsValidOrigin validates origin based on ALLOWED_ORIGINS
func IsValidOrigin(url string) bool {
allowedOrigins := memorystore.Provider.GetSliceStoreEnvVariable(constants.EnvKeyAllowedOrigins)
if len(allowedOrigins) == 1 && allowedOrigins[0] == "*" {
return true
}
hasValidURL := false
hostName, port := GetHostParts(url)
currentOrigin := hostName + ":" + port
for _, origin := range allowedOrigins {
replacedString := origin
// if has regex whitelisted domains
if strings.Contains(origin, "*") {
replacedString = strings.Replace(origin, ".", "\\.", -1)
replacedString = strings.Replace(replacedString, "*", ".*", -1)
if strings.HasPrefix(replacedString, ".*") {
replacedString += "\\b"
}
if strings.HasSuffix(replacedString, ".*") {
replacedString = "\\b" + replacedString
}
}
if matched, _ := regexp.MatchString(replacedString, currentOrigin); matched {
hasValidURL = true
break
}
}
return hasValidURL
}
// IsValidRoles validates roles
func IsValidRoles(userRoles []string, roles []string) bool {
valid := true
for _, userRole := range userRoles {
if !StringSliceContains(roles, userRole) {
valid = false
break
}
}
return valid
}
// IsValidVerificationIdentifier validates verification identifier that is used to identify
// the type of verification request
func IsValidVerificationIdentifier(identifier string) bool {
if identifier != constants.VerificationTypeBasicAuthSignup && identifier != constants.VerificationTypeForgotPassword && identifier != constants.VerificationTypeUpdateEmail {
return false
}
return true
}
// IsStringArrayEqual validates if string array are equal.
// This does check if the order is same
func IsStringArrayEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
// ValidatePassword to validate the password against the following policy
// min char length: 6
// max char length: 36
// at least one upper case letter
// at least one lower case letter
// at least one digit
// at least one special character
func IsValidPassword(password string) bool {
if len(password) < 6 || len(password) > 36 {
return false
}
hasUpperCase := false
hasLowerCase := false
hasDigit := false
hasSpecialChar := false
for _, char := range password {
if char >= 'A' && char <= 'Z' {
hasUpperCase = true
} else if char >= 'a' && char <= 'z' {
hasLowerCase = true
} else if char >= '0' && char <= '9' {
hasDigit = true
} else {
hasSpecialChar = true
}
}
return hasUpperCase && hasLowerCase && hasDigit && hasSpecialChar
}

View File

@ -0,0 +1,15 @@
package validators
// IsStringArrayEqual validates if string array are equal.
// This does check if the order is same
func IsStringArrayEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}

View File

@ -0,0 +1,9 @@
package validators
import "net/mail"
// IsValidEmail validates email
func IsValidEmail(email string) bool {
_, err := mail.ParseAddress(email)
return err == nil
}

View File

@ -0,0 +1,33 @@
package validators
// ValidatePassword to validate the password against the following policy
// min char length: 6
// max char length: 36
// at least one upper case letter
// at least one lower case letter
// at least one digit
// at least one special character
func IsValidPassword(password string) bool {
if len(password) < 6 || len(password) > 36 {
return false
}
hasUpperCase := false
hasLowerCase := false
hasDigit := false
hasSpecialChar := false
for _, char := range password {
if char >= 'A' && char <= 'Z' {
hasUpperCase = true
} else if char >= 'a' && char <= 'z' {
hasLowerCase = true
} else if char >= '0' && char <= '9' {
hasDigit = true
} else {
hasSpecialChar = true
}
}
return hasUpperCase && hasLowerCase && hasDigit && hasSpecialChar
}

View File

@ -0,0 +1,16 @@
package validators
import "github.com/authorizerdev/authorizer/server/utils"
// IsValidRoles validates roles
func IsValidRoles(userRoles []string, roles []string) bool {
valid := true
for _, userRole := range userRoles {
if !utils.StringSliceContains(roles, userRole) {
valid = false
break
}
}
return valid
}

49
server/validators/url.go Normal file
View File

@ -0,0 +1,49 @@
package validators
import (
"regexp"
"strings"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/parsers"
)
// IsValidOrigin validates origin based on ALLOWED_ORIGINS
func IsValidOrigin(url string) bool {
allowedOrigins, err := memorystore.Provider.GetSliceStoreEnvVariable(constants.EnvKeyAllowedOrigins)
if err != nil {
allowedOrigins = []string{"*"}
}
if len(allowedOrigins) == 1 && allowedOrigins[0] == "*" {
return true
}
hasValidURL := false
hostName, port := parsers.GetHostParts(url)
currentOrigin := hostName + ":" + port
for _, origin := range allowedOrigins {
replacedString := origin
// if has regex whitelisted domains
if strings.Contains(origin, "*") {
replacedString = strings.Replace(origin, ".", "\\.", -1)
replacedString = strings.Replace(replacedString, "*", ".*", -1)
if strings.HasPrefix(replacedString, ".*") {
replacedString += "\\b"
}
if strings.HasSuffix(replacedString, ".*") {
replacedString = "\\b" + replacedString
}
}
if matched, _ := regexp.MatchString(replacedString, currentOrigin); matched {
hasValidURL = true
break
}
}
return hasValidURL
}

View File

@ -0,0 +1,12 @@
package validators
import "github.com/authorizerdev/authorizer/server/constants"
// IsValidVerificationIdentifier validates verification identifier that is used to identify
// the type of verification request
func IsValidVerificationIdentifier(identifier string) bool {
if identifier != constants.VerificationTypeBasicAuthSignup && identifier != constants.VerificationTypeForgotPassword && identifier != constants.VerificationTypeUpdateEmail {
return false
}
return true
}