Feat/dashboard (#105)
This commit is contained in:
parent
7ce96367a3
commit
f1b4141367
4
.github/CONTRIBUTING.md
vendored
4
.github/CONTRIBUTING.md
vendored
|
@ -70,7 +70,11 @@ docker run --name arangodb -d -p 8529:8529 -e ARANGO_NO_AUTH=1 arangodb/arangodb
|
|||
If you are adding new resolver,
|
||||
|
||||
1. create new resolver test file [here](https://github.com/authorizerdev/authorizer/tree/main/server/__test__)
|
||||
<<<<<<< HEAD
|
||||
Naming convention filename: `resolver_name_test.go` function name: `resolverNameTest(t *testing.T, s TestSetup)`
|
||||
=======
|
||||
Naming convention filename: `resolver_name_test.go` function name: `resolverNameTest(s TestSetup, t *testing.T)`
|
||||
>>>>>>> main
|
||||
2. Add your tests [here](https://github.com/authorizerdev/authorizer/blob/main/server/__test__/resolvers_test.go#L38)
|
||||
|
||||
**Command to run tests:**
|
||||
|
|
2
Makefile
2
Makefile
|
@ -10,4 +10,4 @@ build-dashboard:
|
|||
clean:
|
||||
rm -rf build
|
||||
test:
|
||||
cd server && go clean --testcache && go test -v ./__test__
|
||||
cd server && go clean --testcache && go test -v ./test
|
||||
|
|
|
@ -42,7 +42,11 @@ export default function App() {
|
|||
<BrowserRouter>
|
||||
<AuthorizerProvider
|
||||
config={{
|
||||
<<<<<<< HEAD
|
||||
authorizerURL: window.location.origin,
|
||||
=======
|
||||
authorizerURL: globalState.authorizerURL,
|
||||
>>>>>>> main
|
||||
redirectURL: globalState.redirectURL,
|
||||
}}
|
||||
>
|
||||
|
|
3360
dashboard/package-lock.json
generated
3360
dashboard/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
0
dashboard/src/Router.tsx
Normal file
0
dashboard/src/Router.tsx
Normal file
5
dashboard/src/components/layouts/AuthLayout.tsx
Normal file
5
dashboard/src/components/layouts/AuthLayout.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
export default function AuthLayout() {
|
||||
return <h1>Auth Layout</h1>;
|
||||
}
|
5
dashboard/src/components/layouts/DefaultLayout.tsx
Normal file
5
dashboard/src/components/layouts/DefaultLayout.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
export default function DefaultLayout() {
|
||||
return <h1>Default Layout</h1>;
|
||||
}
|
0
dashboard/src/contexts/AuthContext.tsx
Normal file
0
dashboard/src/contexts/AuthContext.tsx
Normal file
|
@ -1,26 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func adminLogoutTests(s TestSetup, t *testing.T) {
|
||||
t.Run(`should get admin session`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
_, err := resolvers.AdminLogout(ctx)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
h, err := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.ADMIN_COOKIE_NAME, h))
|
||||
_, err = resolvers.AdminLogout(ctx)
|
||||
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func adminSessionTests(s TestSetup, t *testing.T) {
|
||||
t.Run(`should get admin session`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
_, err := resolvers.AdminSession(ctx)
|
||||
log.Println("error:", err)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
h, err := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.ADMIN_COOKIE_NAME, h))
|
||||
_, err = resolvers.AdminSession(ctx)
|
||||
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEnvs(t *testing.T) {
|
||||
constants.EnvData.ENV_PATH = "../../.env.sample"
|
||||
|
||||
assert.Equal(t, constants.EnvData.ADMIN_SECRET, "admin")
|
||||
assert.Equal(t, constants.EnvData.ENV, "production")
|
||||
assert.False(t, constants.EnvData.DISABLE_EMAIL_VERIFICATION)
|
||||
assert.False(t, constants.EnvData.DISABLE_MAGIC_LINK_LOGIN)
|
||||
assert.False(t, constants.EnvData.DISABLE_BASIC_AUTHENTICATION)
|
||||
assert.Equal(t, constants.EnvData.JWT_TYPE, "HS256")
|
||||
assert.Equal(t, constants.EnvData.JWT_SECRET, "random_string")
|
||||
assert.Equal(t, constants.EnvData.JWT_ROLE_CLAIM, "role")
|
||||
assert.EqualValues(t, constants.EnvData.ROLES, []string{"user"})
|
||||
assert.EqualValues(t, constants.EnvData.DEFAULT_ROLES, []string{"user"})
|
||||
assert.EqualValues(t, constants.EnvData.PROTECTED_ROLES, []string{"admin"})
|
||||
assert.EqualValues(t, constants.EnvData.ALLOWED_ORIGINS, []string{"*"})
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/env"
|
||||
)
|
||||
|
||||
func TestResolvers(t *testing.T) {
|
||||
databases := map[string]string{
|
||||
enum.Sqlite.String(): "../../data.db",
|
||||
enum.Arangodb.String(): "http://localhost:8529",
|
||||
enum.Mongodb.String(): "mongodb://localhost:27017",
|
||||
}
|
||||
|
||||
for dbType, dbURL := range databases {
|
||||
constants.EnvData.DATABASE_URL = dbURL
|
||||
constants.EnvData.DATABASE_TYPE = dbType
|
||||
db.InitDB()
|
||||
|
||||
// clean the persisted config for test to use fresh config
|
||||
config, err := db.Mgr.GetConfig()
|
||||
if err == nil {
|
||||
config.Config = []byte{}
|
||||
db.Mgr.UpdateConfig(config)
|
||||
}
|
||||
env.PersistEnv()
|
||||
|
||||
s := testSetup()
|
||||
defer s.Server.Close()
|
||||
|
||||
log.Println("EnvData:", constants.EnvData)
|
||||
t.Run("should pass tests for "+dbType, func(t *testing.T) {
|
||||
// admin tests
|
||||
adminSignupTests(s, t)
|
||||
verificationRequestsTest(s, t)
|
||||
usersTest(s, t)
|
||||
deleteUserTest(s, t)
|
||||
updateUserTest(s, t)
|
||||
adminLoginTests(s, t)
|
||||
adminLogoutTests(s, t)
|
||||
adminSessionTests(s, t)
|
||||
updateConfigTests(s, t)
|
||||
configTests(s, t)
|
||||
|
||||
// user tests
|
||||
loginTests(s, t)
|
||||
signupTests(s, t)
|
||||
forgotPasswordTest(s, t)
|
||||
resendVerifyEmailTests(s, t)
|
||||
resetPasswordTest(s, t)
|
||||
verifyEmailTest(s, t)
|
||||
sessionTests(s, t)
|
||||
profileTests(s, t)
|
||||
updateProfileTests(s, t)
|
||||
magicLinkLoginTests(s, t)
|
||||
logoutTests(s, t)
|
||||
metaTests(s, t)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package constants
|
||||
|
||||
type EnvConst struct {
|
||||
ADMIN_SECRET string
|
||||
ENV string
|
||||
ENV_PATH string
|
||||
VERSION string
|
||||
DATABASE_TYPE string
|
||||
DATABASE_URL string
|
||||
DATABASE_NAME string
|
||||
SMTP_HOST string
|
||||
SMTP_PORT string
|
||||
SMTP_PASSWORD string
|
||||
SMTP_USERNAME string
|
||||
SENDER_EMAIL string
|
||||
JWT_TYPE string
|
||||
JWT_SECRET string
|
||||
ALLOWED_ORIGINS []string
|
||||
AUTHORIZER_URL string
|
||||
APP_URL string
|
||||
PORT string
|
||||
REDIS_URL string
|
||||
COOKIE_NAME string
|
||||
ADMIN_COOKIE_NAME string
|
||||
RESET_PASSWORD_URL string
|
||||
ENCRYPTION_KEY string `json:"-"`
|
||||
IS_PROD bool
|
||||
DISABLE_EMAIL_VERIFICATION bool
|
||||
DISABLE_BASIC_AUTHENTICATION bool
|
||||
DISABLE_MAGIC_LINK_LOGIN bool
|
||||
DISABLE_LOGIN_PAGE bool
|
||||
|
||||
// ROLES
|
||||
ROLES []string
|
||||
PROTECTED_ROLES []string
|
||||
DEFAULT_ROLES []string
|
||||
JWT_ROLE_CLAIM string
|
||||
|
||||
// OAuth login
|
||||
GOOGLE_CLIENT_ID string
|
||||
GOOGLE_CLIENT_SECRET string
|
||||
GITHUB_CLIENT_ID string
|
||||
GITHUB_CLIENT_SECRET string
|
||||
FACEBOOK_CLIENT_ID string
|
||||
FACEBOOK_CLIENT_SECRET string
|
||||
|
||||
// Org envs
|
||||
ORGANIZATION_NAME string
|
||||
ORGANIZATION_LOGO string
|
||||
}
|
||||
|
||||
var EnvData = EnvConst{
|
||||
ADMIN_COOKIE_NAME: "authorizer-admin",
|
||||
JWT_ROLE_CLAIM: "role",
|
||||
ORGANIZATION_NAME: "Authorizer",
|
||||
ORGANIZATION_LOGO: "https://authorizer.dev/images/logo.png",
|
||||
DISABLE_EMAIL_VERIFICATION: false,
|
||||
DISABLE_BASIC_AUTHENTICATION: false,
|
||||
DISABLE_MAGIC_LINK_LOGIN: false,
|
||||
DISABLE_LOGIN_PAGE: false,
|
||||
IS_PROD: false,
|
||||
}
|
16
server/constants/db_types.go
Normal file
16
server/constants/db_types.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package constants
|
||||
|
||||
const (
|
||||
// DbTypePostgres is the postgres database type
|
||||
DbTypePostgres = "postgres"
|
||||
// DbTypeSqlite is the sqlite database type
|
||||
DbTypeSqlite = "sqlite"
|
||||
// DbTypeMysql is the mysql database type
|
||||
DbTypeMysql = "mysql"
|
||||
// DbTypeSqlserver is the sqlserver database type
|
||||
DbTypeSqlserver = "sqlserver"
|
||||
// DbTypeArangodb is the arangodb database type
|
||||
DbTypeArangodb = "arangodb"
|
||||
// DbTypeMongodb is the mongodb database type
|
||||
DbTypeMongodb = "mongodb"
|
||||
)
|
87
server/constants/env.go
Normal file
87
server/constants/env.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
package constants
|
||||
|
||||
const (
|
||||
// EnvKeyEnv key for env variable ENV
|
||||
EnvKeyEnv = "ENV"
|
||||
// EnvKeyEnvPath key for cli arg variable ENV_PATH
|
||||
EnvKeyEnvPath = "ENV_PATH"
|
||||
// EnvKeyVersion key for build arg version
|
||||
EnvKeyVersion = "VERSION"
|
||||
// EnvKeyAuthorizerURL key for env variable AUTHORIZER_URL
|
||||
EnvKeyAuthorizerURL = "AUTHORIZER_URL"
|
||||
// EnvKeyPort key for env variable PORT
|
||||
EnvKeyPort = "PORT"
|
||||
|
||||
// EnvKeyAdminSecret key for env variable ADMIN_SECRET
|
||||
EnvKeyAdminSecret = "ADMIN_SECRET"
|
||||
// EnvKeyDatabaseType key for env variable DATABASE_TYPE
|
||||
EnvKeyDatabaseType = "DATABASE_TYPE"
|
||||
// EnvKeyDatabaseURL key for env variable DATABASE_URL
|
||||
EnvKeyDatabaseURL = "DATABASE_URL"
|
||||
// EnvKeyDatabaseName key for env variable DATABASE_NAME
|
||||
EnvKeyDatabaseName = "DATABASE_NAME"
|
||||
// EnvKeySmtpHost key for env variable SMTP_HOST
|
||||
EnvKeySmtpHost = "SMTP_HOST"
|
||||
// EnvKeySmtpPort key for env variable SMTP_PORT
|
||||
EnvKeySmtpPort = "SMTP_PORT"
|
||||
// EnvKeySmtpUsername key for env variable SMTP_USERNAME
|
||||
EnvKeySmtpUsername = "SMTP_USERNAME"
|
||||
// EnvKeySmtpPassword key for env variable SMTP_PASSWORD
|
||||
EnvKeySmtpPassword = "SMTP_PASSWORD"
|
||||
// EnvKeySenderEmail key for env variable SENDER_EMAIL
|
||||
EnvKeySenderEmail = "SENDER_EMAIL"
|
||||
// EnvKeyJwtType key for env variable JWT_TYPE
|
||||
EnvKeyJwtType = "JWT_TYPE"
|
||||
// EnvKeyJwtSecret key for env variable JWT_SECRET
|
||||
EnvKeyJwtSecret = "JWT_SECRET"
|
||||
// EnvKeyAllowedOrigins key for env variable ALLOWED_ORIGINS
|
||||
EnvKeyAllowedOrigins = "ALLOWED_ORIGINS"
|
||||
// EnvKeyAppURL key for env variable APP_URL
|
||||
EnvKeyAppURL = "APP_URL"
|
||||
// EnvKeyRedisURL key for env variable REDIS_URL
|
||||
EnvKeyRedisURL = "REDIS_URL"
|
||||
// EnvKeyCookieName key for env variable COOKIE_NAME
|
||||
EnvKeyCookieName = "COOKIE_NAME"
|
||||
// EnvKeyAdminCookieName key for env variable ADMIN_COOKIE_NAME
|
||||
EnvKeyAdminCookieName = "ADMIN_COOKIE_NAME"
|
||||
// EnvKeyResetPasswordURL key for env variable RESET_PASSWORD_URL
|
||||
EnvKeyResetPasswordURL = "RESET_PASSWORD_URL"
|
||||
// EnvKeyEncryptionKey key for env variable ENCRYPTION_KEY
|
||||
EnvKeyEncryptionKey = "ENCRYPTION_KEY"
|
||||
// EnvKeyDisableEmailVerification key for env variable DISABLE_EMAIL_VERIFICATION
|
||||
EnvKeyDisableEmailVerification = "DISABLE_EMAIL_VERIFICATION"
|
||||
// EnvKeyDisableBasicAuthentication key for env variable DISABLE_BASIC_AUTH
|
||||
EnvKeyDisableBasicAuthentication = "DISABLE_BASIC_AUTHENTICATION"
|
||||
// EnvKeyDisableMagicLinkLogin key for env variable DISABLE_MAGIC_LINK_LOGIN
|
||||
EnvKeyDisableMagicLinkLogin = "DISABLE_MAGIC_LINK_LOGIN"
|
||||
// EnvKeyDisableLoginPage key for env variable DISABLE_LOGIN_PAGE
|
||||
EnvKeyDisableLoginPage = "DISABLE_LOGIN_PAGE"
|
||||
// EnvKeyRoles key for env variable ROLES
|
||||
EnvKeyRoles = "ROLES"
|
||||
// EnvKeyProtectedRoles key for env variable PROTECTED_ROLES
|
||||
EnvKeyProtectedRoles = "PROTECTED_ROLES"
|
||||
// EnvKeyDefaultRoles key for env variable DEFAULT_ROLES
|
||||
EnvKeyDefaultRoles = "DEFAULT_ROLES"
|
||||
// EnvKeyJwtRoleClaim key for env variable JWT_ROLE_CLAIM
|
||||
EnvKeyJwtRoleClaim = "JWT_ROLE_CLAIM"
|
||||
// EnvKeyGoogleClientID key for env variable GOOGLE_CLIENT_ID
|
||||
EnvKeyGoogleClientID = "GOOGLE_CLIENT_ID"
|
||||
// EnvKeyGoogleClientSecret key for env variable GOOGLE_CLIENT_SECRET
|
||||
EnvKeyGoogleClientSecret = "GOOGLE_CLIENT_SECRET"
|
||||
// EnvKeyGithubClientID key for env variable GITHUB_CLIENT_ID
|
||||
EnvKeyGithubClientID = "GITHUB_CLIENT_ID"
|
||||
// EnvKeyGithubClientSecret key for env variable GITHUB_CLIENT_SECRET
|
||||
EnvKeyGithubClientSecret = "GITHUB_CLIENT_SECRET"
|
||||
// EnvKeyFacebookClientID key for env variable FACEBOOK_CLIENT_ID
|
||||
EnvKeyFacebookClientID = "FACEBOOK_CLIENT_ID"
|
||||
// EnvKeyFacebookClientSecret key for env variable FACEBOOK_CLIENT_SECRET
|
||||
EnvKeyFacebookClientSecret = "FACEBOOK_CLIENT_SECRET"
|
||||
// EnvKeyOrganizationName key for env variable ORGANIZATION_NAME
|
||||
EnvKeyOrganizationName = "ORGANIZATION_NAME"
|
||||
// EnvKeyOrganizationLogo key for env variable ORGANIZATION_LOGO
|
||||
EnvKeyOrganizationLogo = "ORGANIZATION_LOGO"
|
||||
// EnvKeyIsProd key for env variable IS_PROD
|
||||
EnvKeyIsProd = "IS_PROD"
|
||||
// EnvKeyCustomAccessTokenScript key for env variable CUSTOM_ACCESS_TOKEN_SCRIPT
|
||||
EnvKeyCustomAccessTokenScript = "CUSTOM_ACCESS_TOKEN_SCRIPT"
|
||||
)
|
|
@ -1,6 +1,6 @@
|
|||
package constants
|
||||
|
||||
var (
|
||||
const (
|
||||
// Ref: https://github.com/qor/auth/blob/master/providers/google/google.go
|
||||
// deprecated and not used. instead we follow open id approach for google login
|
||||
GoogleUserInfoURL = "https://www.googleapis.com/oauth2/v3/userinfo"
|
||||
|
|
14
server/constants/signup_methods.go
Normal file
14
server/constants/signup_methods.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package constants
|
||||
|
||||
const (
|
||||
// SignupMethodBasicAuth is the basic_auth signup method
|
||||
SignupMethodBasicAuth = "basic_auth"
|
||||
// SignupMethodMagicLinkLogin is the magic_link_login signup method
|
||||
SignupMethodMagicLinkLogin = "magic_link_login"
|
||||
// SignupMethodGoogle is the google signup method
|
||||
SignupMethodGoogle = "google"
|
||||
// SignupMethodGithub is the github signup method
|
||||
SignupMethodGithub = "github"
|
||||
// SignupMethodFacebook is the facebook signup method
|
||||
SignupMethodFacebook = "facebook"
|
||||
)
|
8
server/constants/token_types.go
Normal file
8
server/constants/token_types.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package constants
|
||||
|
||||
const (
|
||||
// TokenTypeRefreshToken is the refresh_token token type
|
||||
TokenTypeRefreshToken = "refresh_token"
|
||||
// TokenTypeAccessToken is the access_token token type
|
||||
TokenTypeAccessToken = "access_token"
|
||||
)
|
12
server/constants/verification_types.go
Normal file
12
server/constants/verification_types.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package constants
|
||||
|
||||
const (
|
||||
// VerificationTypeBasicAuthSignup is the basic_auth_signup verification type
|
||||
VerificationTypeBasicAuthSignup = "basic_auth_signup"
|
||||
// VerificationTypeMagicLinkLogin is the magic_link_login verification type
|
||||
VerificationTypeMagicLinkLogin = "magic_link_login"
|
||||
// VerificationTypeUpdateEmail is the update_email verification type
|
||||
VerificationTypeUpdateEmail = "update_email"
|
||||
// VerificationTypeForgotPassword is the forgot_password verification type
|
||||
VerificationTypeForgotPassword = "forgot_password"
|
||||
)
|
|
@ -8,6 +8,7 @@ import (
|
|||
arangoDriver "github.com/arangodb/go-driver"
|
||||
"github.com/arangodb/go-driver/http"
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
)
|
||||
|
||||
// for this we need arangodb instance up and running
|
||||
|
@ -17,7 +18,7 @@ import (
|
|||
func initArangodb() (arangoDriver.Database, error) {
|
||||
ctx := context.Background()
|
||||
conn, err := http.NewConnection(http.ConnectionConfig{
|
||||
Endpoints: []string{constants.EnvData.DATABASE_URL},
|
||||
Endpoints: []string{envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseURL).(string)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -32,16 +33,16 @@ func initArangodb() (arangoDriver.Database, error) {
|
|||
|
||||
var arangodb driver.Database
|
||||
|
||||
arangodb_exists, err := arangoClient.DatabaseExists(nil, constants.EnvData.DATABASE_NAME)
|
||||
arangodb_exists, err := arangoClient.DatabaseExists(nil, envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseName).(string))
|
||||
|
||||
if arangodb_exists {
|
||||
log.Println(constants.EnvData.DATABASE_NAME + " db exists already")
|
||||
arangodb, err = arangoClient.Database(nil, constants.EnvData.DATABASE_NAME)
|
||||
log.Println(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseName).(string) + " db exists already")
|
||||
arangodb, err = arangoClient.Database(nil, envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseName).(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
arangodb, err = arangoClient.CreateDatabase(nil, constants.EnvData.DATABASE_NAME, nil)
|
||||
arangodb, err = arangoClient.CreateDatabase(nil, envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseName).(string), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
arangoDriver "github.com/arangodb/go-driver"
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/driver/postgres"
|
||||
|
@ -66,9 +66,9 @@ func InitDB() {
|
|||
var sqlDB *gorm.DB
|
||||
var err error
|
||||
|
||||
IsORMSupported = constants.EnvData.DATABASE_TYPE != enum.Arangodb.String() && constants.EnvData.DATABASE_TYPE != enum.Mongodb.String()
|
||||
IsArangoDB = constants.EnvData.DATABASE_TYPE == enum.Arangodb.String()
|
||||
IsMongoDB = constants.EnvData.DATABASE_TYPE == enum.Mongodb.String()
|
||||
IsORMSupported = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseType).(string) != constants.DbTypeArangodb && envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseType).(string) != constants.DbTypeMongodb
|
||||
IsArangoDB = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseType).(string) == constants.DbTypeArangodb
|
||||
IsMongoDB = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseType).(string) == constants.DbTypeMongodb
|
||||
|
||||
// sql db orm config
|
||||
ormConfig := &gorm.Config{
|
||||
|
@ -77,22 +77,22 @@ func InitDB() {
|
|||
},
|
||||
}
|
||||
|
||||
log.Println("db type:", constants.EnvData.DATABASE_TYPE)
|
||||
log.Println("db type:", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseType).(string))
|
||||
|
||||
switch constants.EnvData.DATABASE_TYPE {
|
||||
case enum.Postgres.String():
|
||||
sqlDB, err = gorm.Open(postgres.Open(constants.EnvData.DATABASE_URL), ormConfig)
|
||||
switch envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseType).(string) {
|
||||
case constants.DbTypePostgres:
|
||||
sqlDB, err = gorm.Open(postgres.Open(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseURL).(string)), ormConfig)
|
||||
break
|
||||
case enum.Sqlite.String():
|
||||
sqlDB, err = gorm.Open(sqlite.Open(constants.EnvData.DATABASE_URL), ormConfig)
|
||||
case constants.DbTypeSqlite:
|
||||
sqlDB, err = gorm.Open(sqlite.Open(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseURL).(string)), ormConfig)
|
||||
break
|
||||
case enum.Mysql.String():
|
||||
sqlDB, err = gorm.Open(mysql.Open(constants.EnvData.DATABASE_URL), ormConfig)
|
||||
case constants.DbTypeMysql:
|
||||
sqlDB, err = gorm.Open(mysql.Open(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseURL).(string)), ormConfig)
|
||||
break
|
||||
case enum.SQLServer.String():
|
||||
sqlDB, err = gorm.Open(sqlserver.Open(constants.EnvData.DATABASE_URL), ormConfig)
|
||||
case constants.DbTypeSqlserver:
|
||||
sqlDB, err = gorm.Open(sqlserver.Open(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseURL).(string)), ormConfig)
|
||||
break
|
||||
case enum.Arangodb.String():
|
||||
case constants.DbTypeArangodb:
|
||||
arangodb, err := initArangodb()
|
||||
if err != nil {
|
||||
log.Fatal("error initializing arangodb:", err)
|
||||
|
@ -105,7 +105,7 @@ func InitDB() {
|
|||
}
|
||||
|
||||
break
|
||||
case enum.Mongodb.String():
|
||||
case constants.DbTypeMongodb:
|
||||
mongodb, err := initMongodb()
|
||||
if err != nil {
|
||||
log.Fatal("error initializing mongodb connection:", err)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
@ -12,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
func initMongodb() (*mongo.Database, error) {
|
||||
mongodbOptions := options.Client().ApplyURI(constants.EnvData.DATABASE_URL)
|
||||
mongodbOptions := options.Client().ApplyURI(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseURL).(string))
|
||||
maxWait := time.Duration(5 * time.Second)
|
||||
mongodbOptions.ConnectTimeout = &maxWait
|
||||
mongoClient, err := mongo.NewClient(mongodbOptions)
|
||||
|
@ -30,7 +31,7 @@ func initMongodb() (*mongo.Database, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
mongodb := mongoClient.Database(constants.EnvData.DATABASE_NAME, options.Database())
|
||||
mongodb := mongoClient.Database(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDatabaseName).(string), options.Database())
|
||||
|
||||
mongodb.CreateCollection(ctx, Collections.User, options.CreateCollection())
|
||||
userCollection := mongodb.Collection(Collections.User, options.Collection())
|
||||
|
|
|
@ -3,11 +3,13 @@ package db
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
arangoDriver "github.com/arangodb/go-driver"
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
@ -43,7 +45,7 @@ func (mgr *manager) AddUser(user User) (User, error) {
|
|||
}
|
||||
|
||||
if user.Roles == "" {
|
||||
user.Roles = constants.EnvData.DEFAULT_ROLES[0]
|
||||
user.Roles = strings.Join(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDefaultRoles).([]string), ",")
|
||||
}
|
||||
|
||||
if IsORMSupported {
|
||||
|
@ -185,6 +187,7 @@ func (mgr *manager) GetUsers() ([]User, error) {
|
|||
return users, nil
|
||||
}
|
||||
|
||||
// GetUserByEmail function to get user by email
|
||||
func (mgr *manager) GetUserByEmail(email string) (User, error) {
|
||||
var user User
|
||||
|
||||
|
@ -233,6 +236,7 @@ func (mgr *manager) GetUserByEmail(email string) (User, error) {
|
|||
return user, nil
|
||||
}
|
||||
|
||||
// GetUserByID function to get user by ID
|
||||
func (mgr *manager) GetUserByID(id string) (User, error) {
|
||||
var user User
|
||||
|
||||
|
@ -281,6 +285,7 @@ func (mgr *manager) GetUserByID(id string) (User, error) {
|
|||
return user, nil
|
||||
}
|
||||
|
||||
// DeleteUser function to delete user
|
||||
func (mgr *manager) DeleteUser(user User) error {
|
||||
if IsORMSupported {
|
||||
result := mgr.sqlDB.Delete(&user)
|
||||
|
|
|
@ -1,23 +1,44 @@
|
|||
package email
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"strconv"
|
||||
"text/template"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
gomail "gopkg.in/mail.v2"
|
||||
)
|
||||
|
||||
// addEmailTemplate is used to add html template in email body
|
||||
func addEmailTemplate(a string, b map[string]interface{}, templateName string) string {
|
||||
tmpl, err := template.New(templateName).Parse(a)
|
||||
if err != nil {
|
||||
output, _ := json.Marshal(b)
|
||||
return string(output)
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
err = tmpl.Execute(buf, b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
s := buf.String()
|
||||
return s
|
||||
}
|
||||
|
||||
// SendMail function to send mail
|
||||
func SendMail(to []string, Subject, bodyMessage string) error {
|
||||
m := gomail.NewMessage()
|
||||
m.SetHeader("From", constants.EnvData.SENDER_EMAIL)
|
||||
m.SetHeader("From", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeySenderEmail).(string))
|
||||
m.SetHeader("To", to...)
|
||||
m.SetHeader("Subject", Subject)
|
||||
m.SetBody("text/html", bodyMessage)
|
||||
port, _ := strconv.Atoi(constants.EnvData.SMTP_PORT)
|
||||
d := gomail.NewDialer(constants.EnvData.SMTP_HOST, port, constants.EnvData.SMTP_USERNAME, constants.EnvData.SMTP_PASSWORD)
|
||||
if constants.EnvData.ENV == "development" {
|
||||
port, _ := strconv.Atoi(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeySmtpPort).(string))
|
||||
d := gomail.NewDialer(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeySmtpHost).(string), port, envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeySmtpUsername).(string), envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeySmtpPassword).(string))
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyEnv).(string) == "development" {
|
||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
if err := d.DialAndSend(m); err != nil {
|
||||
|
|
112
server/email/forgot_password_email.go
Normal file
112
server/email/forgot_password_email.go
Normal file
|
@ -0,0 +1,112 @@
|
|||
package email
|
||||
|
||||
import (
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
)
|
||||
|
||||
// SendForgotPasswordMail to send forgot password email
|
||||
func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||
resetPasswordUrl := envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyResetPasswordURL).(string)
|
||||
if resetPasswordUrl == "" {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyResetPasswordURL, envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string)+"/app/reset-password")
|
||||
}
|
||||
|
||||
// The receiver needs to be in slice as the receive supports multiple receiver
|
||||
Receiver := []string{toEmail}
|
||||
|
||||
Subject := "Reset Password"
|
||||
|
||||
message := `
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<meta name="x-apple-disable-message-reformatting">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<title></title>
|
||||
<!--[if (mso 16)]>
|
||||
<style type="text/css">
|
||||
a {}
|
||||
</style>
|
||||
<![endif]-->
|
||||
<!--[if gte mso 9]><style>sup { font-size: 100%% !important; }</style><![endif]-->
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG></o:AllowPNG>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body style="font-family: sans-serif;">
|
||||
<div class="es-wrapper-color">
|
||||
<!--[if gte mso 9]>
|
||||
<v:background xmlns:v="urn:schemas-microsoft-com:vml" fill="t">
|
||||
<v:fill type="tile" color="#ffffff"></v:fill>
|
||||
</v:background>
|
||||
<![endif]-->
|
||||
<table class="es-wrapper" width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-email-paddings" valign="top">
|
||||
<table class="es-content esd-footer-popover" cellspacing="0" cellpadding="0" align="center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-stripe" align="center">
|
||||
<table class="es-content-body" style="border-left:1px solid transparent;border-right:1px solid transparent;border-top:1px solid transparent;border-bottom:1px solid transparent;padding:20px 0px;" width="600" cellspacing="0" cellpadding="0" bgcolor="#ffffff" align="center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-structure es-p20t es-p40b es-p40r es-p40l" esd-custom-block-id="8537" align="left">
|
||||
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-container-frame" width="518" align="left">
|
||||
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.org_logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
|
||||
</tr>
|
||||
|
||||
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
||||
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
||||
<p>Hey there 👋</p>
|
||||
<p>We have received a request to reset password for email: <b>{{.org_name}}</b>. If this is correct, please reset the password clicking the button below.</p> <br/>
|
||||
<a clicktracking="off" href="{{.verification_url}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Reset Password</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
data := make(map[string]interface{}, 3)
|
||||
data["org_logo"] = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyOrganizationLogo).(string)
|
||||
data["org_name"] = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyOrganizationName).(string)
|
||||
data["verification_url"] = resetPasswordUrl + "?token=" + token
|
||||
message = addEmailTemplate(message, data, "reset_password_email.tmpl")
|
||||
|
||||
return SendMail(Receiver, Subject, message)
|
||||
}
|
107
server/email/verification_email.go
Normal file
107
server/email/verification_email.go
Normal file
|
@ -0,0 +1,107 @@
|
|||
package email
|
||||
|
||||
import (
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
)
|
||||
|
||||
// SendVerificationMail to send verification email
|
||||
func SendVerificationMail(toEmail, token string) error {
|
||||
// The receiver needs to be in slice as the receive supports multiple receiver
|
||||
Receiver := []string{toEmail}
|
||||
|
||||
Subject := "Please verify your email"
|
||||
message := `
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<meta name="x-apple-disable-message-reformatting">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<title></title>
|
||||
<!--[if (mso 16)]>
|
||||
<style type="text/css">
|
||||
a {}
|
||||
</style>
|
||||
<![endif]-->
|
||||
<!--[if gte mso 9]><style>sup { font-size: 100%% !important; }</style><![endif]-->
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG></o:AllowPNG>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body style="font-family: sans-serif;">
|
||||
<div class="es-wrapper-color">
|
||||
<!--[if gte mso 9]>
|
||||
<v:background xmlns:v="urn:schemas-microsoft-com:vml" fill="t">
|
||||
<v:fill type="tile" color="#ffffff"></v:fill>
|
||||
</v:background>
|
||||
<![endif]-->
|
||||
<table class="es-wrapper" width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-email-paddings" valign="top">
|
||||
<table class="es-content esd-footer-popover" cellspacing="0" cellpadding="0" align="center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-stripe" align="center">
|
||||
<table class="es-content-body" style="border-left:1px solid transparent;border-right:1px solid transparent;border-top:1px solid transparent;border-bottom:1px solid transparent;padding:20px 0px;" width="600" cellspacing="0" cellpadding="0" bgcolor="#ffffff" align="center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-structure es-p20t es-p40b es-p40r es-p40l" esd-custom-block-id="8537" align="left">
|
||||
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-container-frame" width="518" align="left">
|
||||
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.org_logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
|
||||
</tr>
|
||||
|
||||
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
||||
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
||||
<p>Hey there 👋</p>
|
||||
<p>We have received request to verify email for <b>{{.org_name}}</b>. If this is correct, please confirm your email address by clicking the button below.</p> <br/>
|
||||
<a
|
||||
clicktracking="off" href="{{.verification_url}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Confirm Email</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
data := make(map[string]interface{}, 3)
|
||||
data["org_logo"] = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyOrganizationLogo).(string)
|
||||
data["org_name"] = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyOrganizationName).(string)
|
||||
data["verification_url"] = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) + "/verify_email?token=" + token
|
||||
message = addEmailTemplate(message, data, "verify_email.tmpl")
|
||||
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||
|
||||
return SendMail(Receiver, Subject, message)
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package enum
|
||||
|
||||
type DbType int
|
||||
|
||||
const (
|
||||
Postgres DbType = iota
|
||||
Sqlite
|
||||
Mysql
|
||||
SQLServer
|
||||
Arangodb
|
||||
Mongodb
|
||||
)
|
||||
|
||||
func (d DbType) String() string {
|
||||
return [...]string{
|
||||
"postgres",
|
||||
"sqlite",
|
||||
"mysql",
|
||||
"sqlserver",
|
||||
"arangodb",
|
||||
"mongodb",
|
||||
}[d]
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package enum
|
||||
|
||||
type OAuthProvider int
|
||||
|
||||
const (
|
||||
GoogleProvider OAuthProvider = iota
|
||||
GithubProvider
|
||||
)
|
||||
|
||||
func (d OAuthProvider) String() string {
|
||||
return [...]string{
|
||||
"google_provider",
|
||||
"github_provider",
|
||||
}[d]
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package enum
|
||||
|
||||
type SignupMethod int
|
||||
|
||||
const (
|
||||
BasicAuth SignupMethod = iota
|
||||
MagicLinkLogin
|
||||
Google
|
||||
Github
|
||||
Facebook
|
||||
)
|
||||
|
||||
func (d SignupMethod) String() string {
|
||||
return [...]string{
|
||||
"basic_auth",
|
||||
"magic_link_login",
|
||||
"google",
|
||||
"github",
|
||||
"facebook",
|
||||
}[d]
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package enum
|
||||
|
||||
type TokenType int
|
||||
|
||||
const (
|
||||
RefreshToken TokenType = iota
|
||||
AccessToken
|
||||
)
|
||||
|
||||
func (d TokenType) String() string {
|
||||
return [...]string{
|
||||
"refresh_token",
|
||||
"access_token",
|
||||
}[d]
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package enum
|
||||
|
||||
type VerificationType int
|
||||
|
||||
const (
|
||||
BasicAuthSignup VerificationType = iota
|
||||
UpdateEmail
|
||||
ForgotPassword
|
||||
)
|
||||
|
||||
func (d VerificationType) String() string {
|
||||
return [...]string{
|
||||
"basic_auth_signup",
|
||||
"update_email",
|
||||
"forgot_password",
|
||||
}[d]
|
||||
}
|
255
server/env/env.go
vendored
255
server/env/env.go
vendored
|
@ -6,188 +6,197 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/google/uuid"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
// build variables
|
||||
// TODO move this to env store
|
||||
var (
|
||||
ARG_DB_URL *string
|
||||
ARG_DB_TYPE *string
|
||||
ARG_AUTHORIZER_URL *string
|
||||
ARG_ENV_FILE *string
|
||||
// ARG_DB_URL is the cli arg variable for the database url
|
||||
ARG_DB_URL *string
|
||||
// ARG_DB_TYPE is the cli arg variable for the database type
|
||||
ARG_DB_TYPE *string
|
||||
// ARG_ENV_FILE is the cli arg variable for the env file
|
||||
ARG_ENV_FILE *string
|
||||
)
|
||||
|
||||
// InitEnv -> to initialize env and through error if required env are not present
|
||||
// InitEnv to initialize EnvData and through error if required env are not present
|
||||
func InitEnv() {
|
||||
if constants.EnvData.ENV_PATH == "" {
|
||||
constants.EnvData.ENV_PATH = `.env`
|
||||
// get clone of current store
|
||||
envData := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
||||
|
||||
if envData[constants.EnvKeyEnv] == nil || envData[constants.EnvKeyEnv] == "" {
|
||||
envData[constants.EnvKeyEnv] = os.Getenv("ENV")
|
||||
if envData[constants.EnvKeyEnv] == "" {
|
||||
envData[constants.EnvKeyEnv] = "production"
|
||||
}
|
||||
|
||||
if envData[constants.EnvKeyEnv] == "production" {
|
||||
envData[constants.EnvKeyIsProd] = true
|
||||
os.Setenv("GIN_MODE", "release")
|
||||
} else {
|
||||
envData[constants.EnvKeyIsProd] = false
|
||||
}
|
||||
}
|
||||
|
||||
// set authorizer url to empty string so that fresh url is obtained with every server start
|
||||
envData[constants.EnvKeyAuthorizerURL] = ""
|
||||
if envData[constants.EnvKeyAppURL] == nil || envData[constants.EnvKeyAppURL] == "" {
|
||||
envData[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
|
||||
}
|
||||
|
||||
if envData[constants.EnvKeyEnvPath] == nil || envData[constants.EnvKeyEnvPath].(string) == "" {
|
||||
envData[constants.EnvKeyEnvPath] = `.env`
|
||||
}
|
||||
|
||||
if ARG_ENV_FILE != nil && *ARG_ENV_FILE != "" {
|
||||
constants.EnvData.ENV_PATH = *ARG_ENV_FILE
|
||||
envData[constants.EnvKeyEnvPath] = *ARG_ENV_FILE
|
||||
}
|
||||
|
||||
err := godotenv.Load(constants.EnvData.ENV_PATH)
|
||||
err := godotenv.Load(envData[constants.EnvKeyEnvPath].(string))
|
||||
if err != nil {
|
||||
log.Printf("error loading %s file", constants.EnvData.ENV_PATH)
|
||||
log.Printf("error loading %s file", envData[constants.EnvKeyEnvPath])
|
||||
}
|
||||
|
||||
if constants.EnvData.ADMIN_SECRET == "" {
|
||||
constants.EnvData.ADMIN_SECRET = os.Getenv("ADMIN_SECRET")
|
||||
if envData[constants.EnvKeyPort] == nil || envData[constants.EnvKeyPort].(string) == "" {
|
||||
envData[constants.EnvKeyPort] = os.Getenv("PORT")
|
||||
if envData[constants.EnvKeyPort].(string) == "" {
|
||||
envData[constants.EnvKeyPort] = "8080"
|
||||
}
|
||||
}
|
||||
|
||||
if constants.EnvData.DATABASE_TYPE == "" {
|
||||
constants.EnvData.DATABASE_TYPE = os.Getenv("DATABASE_TYPE")
|
||||
log.Println(constants.EnvData.DATABASE_TYPE)
|
||||
if envData[constants.EnvKeyAdminSecret] == nil || envData[constants.EnvKeyAdminSecret].(string) == "" {
|
||||
envData[constants.EnvKeyAdminSecret] = os.Getenv("ADMIN_SECRET")
|
||||
}
|
||||
|
||||
if envData[constants.EnvKeyDatabaseType] == nil || envData[constants.EnvKeyDatabaseType].(string) == "" {
|
||||
envData[constants.EnvKeyDatabaseType] = os.Getenv("DATABASE_TYPE")
|
||||
log.Println(envData[constants.EnvKeyDatabaseType].(string))
|
||||
|
||||
if ARG_DB_TYPE != nil && *ARG_DB_TYPE != "" {
|
||||
constants.EnvData.DATABASE_TYPE = *ARG_DB_TYPE
|
||||
envData[constants.EnvKeyDatabaseType] = *ARG_DB_TYPE
|
||||
}
|
||||
|
||||
if constants.EnvData.DATABASE_TYPE == "" {
|
||||
if envData[constants.EnvKeyDatabaseType].(string) == "" {
|
||||
panic("DATABASE_TYPE is required")
|
||||
}
|
||||
}
|
||||
|
||||
if constants.EnvData.DATABASE_URL == "" {
|
||||
constants.EnvData.DATABASE_URL = os.Getenv("DATABASE_URL")
|
||||
if envData[constants.EnvKeyDatabaseURL] == nil || envData[constants.EnvKeyDatabaseURL].(string) == "" {
|
||||
envData[constants.EnvKeyDatabaseURL] = os.Getenv("DATABASE_URL")
|
||||
|
||||
if ARG_DB_URL != nil && *ARG_DB_URL != "" {
|
||||
constants.EnvData.DATABASE_URL = *ARG_DB_URL
|
||||
envData[constants.EnvKeyDatabaseURL] = *ARG_DB_URL
|
||||
}
|
||||
|
||||
if constants.EnvData.DATABASE_URL == "" {
|
||||
if envData[constants.EnvKeyDatabaseURL] == "" {
|
||||
panic("DATABASE_URL is required")
|
||||
}
|
||||
}
|
||||
|
||||
if constants.EnvData.DATABASE_NAME == "" {
|
||||
constants.EnvData.DATABASE_NAME = os.Getenv("DATABASE_NAME")
|
||||
if constants.EnvData.DATABASE_NAME == "" {
|
||||
constants.EnvData.DATABASE_NAME = "authorizer"
|
||||
if envData[constants.EnvKeyDatabaseName] == nil || envData[constants.EnvKeyDatabaseName].(string) == "" {
|
||||
envData[constants.EnvKeyDatabaseName] = os.Getenv("DATABASE_NAME")
|
||||
if envData[constants.EnvKeyDatabaseName].(string) == "" {
|
||||
envData[constants.EnvKeyDatabaseName] = "authorizer"
|
||||
}
|
||||
}
|
||||
|
||||
if constants.EnvData.ENV == "" {
|
||||
constants.EnvData.ENV = os.Getenv("ENV")
|
||||
if constants.EnvData.ENV == "" {
|
||||
constants.EnvData.ENV = "production"
|
||||
}
|
||||
if envData[constants.EnvKeySmtpHost] == nil || envData[constants.EnvKeySmtpHost].(string) == "" {
|
||||
envData[constants.EnvKeySmtpHost] = os.Getenv("SMTP_HOST")
|
||||
}
|
||||
|
||||
if constants.EnvData.ENV == "production" {
|
||||
constants.EnvData.IS_PROD = true
|
||||
os.Setenv("GIN_MODE", "release")
|
||||
} else {
|
||||
constants.EnvData.IS_PROD = false
|
||||
if envData[constants.EnvKeySmtpPort] == nil || envData[constants.EnvKeySmtpPort].(string) == "" {
|
||||
envData[constants.EnvKeySmtpPort] = os.Getenv("SMTP_PORT")
|
||||
}
|
||||
|
||||
if envData[constants.EnvKeySmtpUsername] == nil || envData[constants.EnvKeySmtpUsername].(string) == "" {
|
||||
envData[constants.EnvKeySmtpUsername] = os.Getenv("SMTP_USERNAME")
|
||||
}
|
||||
|
||||
if envData[constants.EnvKeySmtpPassword] == nil || envData[constants.EnvKeySmtpPassword].(string) == "" {
|
||||
envData[constants.EnvKeySmtpPassword] = os.Getenv("SMTP_PASSWORD")
|
||||
}
|
||||
|
||||
if envData[constants.EnvKeySenderEmail] == nil || envData[constants.EnvKeySenderEmail].(string) == "" {
|
||||
envData[constants.EnvKeySenderEmail] = os.Getenv("SENDER_EMAIL")
|
||||
}
|
||||
|
||||
if envData[constants.EnvKeyJwtSecret] == nil || envData[constants.EnvKeyJwtSecret].(string) == "" {
|
||||
envData[constants.EnvKeyJwtSecret] = os.Getenv("JWT_SECRET")
|
||||
if envData[constants.EnvKeyJwtSecret].(string) == "" {
|
||||
envData[constants.EnvKeyJwtSecret] = uuid.New().String()
|
||||
}
|
||||
}
|
||||
|
||||
if constants.EnvData.SMTP_HOST == "" {
|
||||
constants.EnvData.SMTP_HOST = os.Getenv("SMTP_HOST")
|
||||
}
|
||||
|
||||
if constants.EnvData.SMTP_PORT == "" {
|
||||
constants.EnvData.SMTP_PORT = os.Getenv("SMTP_PORT")
|
||||
}
|
||||
|
||||
if constants.EnvData.SMTP_USERNAME == "" {
|
||||
constants.EnvData.SMTP_USERNAME = os.Getenv("SMTP_USERNAME")
|
||||
}
|
||||
|
||||
if constants.EnvData.SMTP_PASSWORD == "" {
|
||||
constants.EnvData.SMTP_PASSWORD = os.Getenv("SMTP_PASSWORD")
|
||||
}
|
||||
|
||||
if constants.EnvData.SENDER_EMAIL == "" {
|
||||
constants.EnvData.SENDER_EMAIL = os.Getenv("SENDER_EMAIL")
|
||||
}
|
||||
|
||||
if constants.EnvData.JWT_SECRET == "" {
|
||||
constants.EnvData.JWT_SECRET = os.Getenv("JWT_SECRET")
|
||||
if constants.EnvData.JWT_SECRET == "" {
|
||||
constants.EnvData.JWT_SECRET = uuid.New().String()
|
||||
if envData[constants.EnvKeyJwtType] == nil || envData[constants.EnvKeyJwtType].(string) == "" {
|
||||
envData[constants.EnvKeyJwtType] = os.Getenv("JWT_TYPE")
|
||||
if envData[constants.EnvKeyJwtType].(string) == "" {
|
||||
envData[constants.EnvKeyJwtType] = "HS256"
|
||||
}
|
||||
}
|
||||
|
||||
if constants.EnvData.JWT_TYPE == "" {
|
||||
constants.EnvData.JWT_TYPE = os.Getenv("JWT_TYPE")
|
||||
if constants.EnvData.JWT_TYPE == "" {
|
||||
constants.EnvData.JWT_TYPE = "HS256"
|
||||
if envData[constants.EnvKeyJwtRoleClaim] == nil || envData[constants.EnvKeyJwtRoleClaim].(string) == "" {
|
||||
envData[constants.EnvKeyJwtRoleClaim] = os.Getenv("JWT_ROLE_CLAIM")
|
||||
|
||||
if envData[constants.EnvKeyJwtRoleClaim].(string) == "" {
|
||||
envData[constants.EnvKeyJwtRoleClaim] = "role"
|
||||
}
|
||||
}
|
||||
|
||||
if constants.EnvData.JWT_ROLE_CLAIM == "" {
|
||||
constants.EnvData.JWT_ROLE_CLAIM = os.Getenv("JWT_ROLE_CLAIM")
|
||||
if envData[constants.EnvKeyRedisURL] == nil || envData[constants.EnvKeyRedisURL].(string) == "" {
|
||||
envData[constants.EnvKeyRedisURL] = os.Getenv("REDIS_URL")
|
||||
}
|
||||
|
||||
if constants.EnvData.JWT_ROLE_CLAIM == "" {
|
||||
constants.EnvData.JWT_ROLE_CLAIM = "role"
|
||||
if envData[constants.EnvKeyCookieName] == nil || envData[constants.EnvKeyCookieName].(string) == "" {
|
||||
envData[constants.EnvKeyCookieName] = os.Getenv("COOKIE_NAME")
|
||||
if envData[constants.EnvKeyCookieName].(string) == "" {
|
||||
envData[constants.EnvKeyCookieName] = "authorizer"
|
||||
}
|
||||
}
|
||||
|
||||
if constants.EnvData.AUTHORIZER_URL == "" {
|
||||
constants.EnvData.AUTHORIZER_URL = strings.TrimSuffix(os.Getenv("AUTHORIZER_URL"), "/")
|
||||
|
||||
if ARG_AUTHORIZER_URL != nil && *ARG_AUTHORIZER_URL != "" {
|
||||
constants.EnvData.AUTHORIZER_URL = *ARG_AUTHORIZER_URL
|
||||
}
|
||||
if envData[constants.EnvKeyGoogleClientID] == nil || envData[constants.EnvKeyGoogleClientID].(string) == "" {
|
||||
envData[constants.EnvKeyGoogleClientID] = os.Getenv("GOOGLE_CLIENT_ID")
|
||||
}
|
||||
|
||||
if constants.EnvData.PORT == "" {
|
||||
constants.EnvData.PORT = os.Getenv("PORT")
|
||||
if constants.EnvData.PORT == "" {
|
||||
constants.EnvData.PORT = "8080"
|
||||
}
|
||||
if envData[constants.EnvKeyGoogleClientSecret] == nil || envData[constants.EnvKeyGoogleClientSecret].(string) == "" {
|
||||
envData[constants.EnvKeyGoogleClientSecret] = os.Getenv("GOOGLE_CLIENT_SECRET")
|
||||
}
|
||||
|
||||
if constants.EnvData.REDIS_URL == "" {
|
||||
constants.EnvData.REDIS_URL = os.Getenv("REDIS_URL")
|
||||
if envData[constants.EnvKeyGithubClientID] == nil || envData[constants.EnvKeyGithubClientID].(string) == "" {
|
||||
envData[constants.EnvKeyGithubClientID] = os.Getenv("GITHUB_CLIENT_ID")
|
||||
}
|
||||
|
||||
if constants.EnvData.COOKIE_NAME == "" {
|
||||
constants.EnvData.COOKIE_NAME = os.Getenv("COOKIE_NAME")
|
||||
if constants.EnvData.COOKIE_NAME == "" {
|
||||
constants.EnvData.COOKIE_NAME = "authorizer"
|
||||
}
|
||||
if envData[constants.EnvKeyGithubClientSecret] == nil || envData[constants.EnvKeyGithubClientSecret].(string) == "" {
|
||||
envData[constants.EnvKeyGithubClientSecret] = os.Getenv("GITHUB_CLIENT_SECRET")
|
||||
}
|
||||
|
||||
if constants.EnvData.GOOGLE_CLIENT_ID == "" {
|
||||
constants.EnvData.GOOGLE_CLIENT_ID = os.Getenv("GOOGLE_CLIENT_ID")
|
||||
if envData[constants.EnvKeyFacebookClientID] == nil || envData[constants.EnvKeyFacebookClientID].(string) == "" {
|
||||
envData[constants.EnvKeyFacebookClientID] = os.Getenv("FACEBOOK_CLIENT_ID")
|
||||
}
|
||||
|
||||
if constants.EnvData.GOOGLE_CLIENT_SECRET == "" {
|
||||
constants.EnvData.GOOGLE_CLIENT_SECRET = os.Getenv("GOOGLE_CLIENT_SECRET")
|
||||
if envData[constants.EnvKeyFacebookClientSecret] == nil || envData[constants.EnvKeyFacebookClientSecret].(string) == "" {
|
||||
envData[constants.EnvKeyFacebookClientSecret] = os.Getenv("FACEBOOK_CLIENT_SECRET")
|
||||
}
|
||||
|
||||
if constants.EnvData.GITHUB_CLIENT_ID == "" {
|
||||
constants.EnvData.GITHUB_CLIENT_ID = os.Getenv("GITHUB_CLIENT_ID")
|
||||
if envData[constants.EnvKeyResetPasswordURL] == nil || envData[constants.EnvKeyResetPasswordURL].(string) == "" {
|
||||
envData[constants.EnvKeyResetPasswordURL] = strings.TrimPrefix(os.Getenv("RESET_PASSWORD_URL"), "/")
|
||||
}
|
||||
|
||||
if constants.EnvData.GITHUB_CLIENT_SECRET == "" {
|
||||
constants.EnvData.GITHUB_CLIENT_SECRET = os.Getenv("GITHUB_CLIENT_SECRET")
|
||||
envData[constants.EnvKeyDisableBasicAuthentication] = os.Getenv("DISABLE_BASIC_AUTHENTICATION") == "true"
|
||||
envData[constants.EnvKeyDisableEmailVerification] = os.Getenv("DISABLE_EMAIL_VERIFICATION") == "true"
|
||||
envData[constants.EnvKeyDisableMagicLinkLogin] = os.Getenv("DISABLE_MAGIC_LINK_LOGIN") == "true"
|
||||
envData[constants.EnvKeyDisableLoginPage] = os.Getenv("DISABLE_LOGIN_PAGE") == "true"
|
||||
|
||||
// no need to add nil check as its already done above
|
||||
if envData[constants.EnvKeySmtpHost].(string) == "" || envData[constants.EnvKeySmtpUsername].(string) == "" || envData[constants.EnvKeySmtpPassword].(string) == "" || envData[constants.EnvKeySenderEmail].(string) == "" {
|
||||
envData[constants.EnvKeyDisableEmailVerification] = true
|
||||
envData[constants.EnvKeyDisableMagicLinkLogin] = true
|
||||
}
|
||||
|
||||
if constants.EnvData.FACEBOOK_CLIENT_ID == "" {
|
||||
constants.EnvData.FACEBOOK_CLIENT_ID = os.Getenv("FACEBOOK_CLIENT_ID")
|
||||
}
|
||||
|
||||
if constants.EnvData.FACEBOOK_CLIENT_SECRET == "" {
|
||||
constants.EnvData.FACEBOOK_CLIENT_SECRET = os.Getenv("FACEBOOK_CLIENT_SECRET")
|
||||
}
|
||||
|
||||
if constants.EnvData.RESET_PASSWORD_URL == "" {
|
||||
constants.EnvData.RESET_PASSWORD_URL = strings.TrimPrefix(os.Getenv("RESET_PASSWORD_URL"), "/")
|
||||
}
|
||||
|
||||
constants.EnvData.DISABLE_BASIC_AUTHENTICATION = os.Getenv("DISABLE_BASIC_AUTHENTICATION") == "true"
|
||||
constants.EnvData.DISABLE_EMAIL_VERIFICATION = os.Getenv("DISABLE_EMAIL_VERIFICATION") == "true"
|
||||
constants.EnvData.DISABLE_MAGIC_LINK_LOGIN = os.Getenv("DISABLE_MAGIC_LINK_LOGIN") == "true"
|
||||
constants.EnvData.DISABLE_LOGIN_PAGE = os.Getenv("DISABLE_LOGIN_PAGE") == "true"
|
||||
|
||||
if constants.EnvData.SMTP_HOST == "" || constants.EnvData.SMTP_USERNAME == "" || constants.EnvData.SMTP_PASSWORD == "" || constants.EnvData.SENDER_EMAIL == "" {
|
||||
constants.EnvData.DISABLE_EMAIL_VERIFICATION = true
|
||||
constants.EnvData.DISABLE_MAGIC_LINK_LOGIN = true
|
||||
if envData[constants.EnvKeyDisableEmailVerification].(bool) {
|
||||
envData[constants.EnvKeyDisableMagicLinkLogin] = true
|
||||
}
|
||||
|
||||
allowedOriginsSplit := strings.Split(os.Getenv("ALLOWED_ORIGINS"), ",")
|
||||
|
@ -216,11 +225,7 @@ func InitEnv() {
|
|||
allowedOrigins = []string{"*"}
|
||||
}
|
||||
|
||||
constants.EnvData.ALLOWED_ORIGINS = allowedOrigins
|
||||
|
||||
if constants.EnvData.DISABLE_EMAIL_VERIFICATION {
|
||||
constants.EnvData.DISABLE_MAGIC_LINK_LOGIN = true
|
||||
}
|
||||
envData[constants.EnvKeyAllowedOrigins] = allowedOrigins
|
||||
|
||||
rolesEnv := strings.TrimSpace(os.Getenv("ROLES"))
|
||||
rolesSplit := strings.Split(rolesEnv, ",")
|
||||
|
@ -263,15 +268,17 @@ func InitEnv() {
|
|||
panic(`Invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
||||
}
|
||||
|
||||
constants.EnvData.ROLES = roles
|
||||
constants.EnvData.DEFAULT_ROLES = defaultRoles
|
||||
constants.EnvData.PROTECTED_ROLES = protectedRoles
|
||||
envData[constants.EnvKeyRoles] = roles
|
||||
envData[constants.EnvKeyDefaultRoles] = defaultRoles
|
||||
envData[constants.EnvKeyProtectedRoles] = protectedRoles
|
||||
|
||||
if os.Getenv("ORGANIZATION_NAME") != "" {
|
||||
constants.EnvData.ORGANIZATION_NAME = os.Getenv("ORGANIZATION_NAME")
|
||||
envData[constants.EnvKeyOrganizationName] = os.Getenv("ORGANIZATION_NAME")
|
||||
}
|
||||
|
||||
if os.Getenv("ORGANIZATION_LOGO") != "" {
|
||||
constants.EnvData.ORGANIZATION_LOGO = os.Getenv("ORGANIZATION_LOGO")
|
||||
envData[constants.EnvKeyOrganizationLogo] = os.Getenv("ORGANIZATION_LOGO")
|
||||
}
|
||||
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvStore(envData)
|
||||
}
|
||||
|
|
11
server/env/persist_env.go
vendored
11
server/env/persist_env.go
vendored
|
@ -9,20 +9,22 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// PersistEnv persists the environment variables to the database
|
||||
func PersistEnv() error {
|
||||
config, err := db.Mgr.GetConfig()
|
||||
// config not found in db
|
||||
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]
|
||||
constants.EnvData.ENCRYPTION_KEY = hash
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyEncryptionKey, hash)
|
||||
encodedHash := utils.EncryptB64(hash)
|
||||
|
||||
configData, err := json.Marshal(constants.EnvData)
|
||||
configData, err := json.Marshal(envstore.EnvInMemoryStoreObj.GetEnvStoreClone())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -45,7 +47,8 @@ func PersistEnv() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
constants.EnvData.ENCRYPTION_KEY = decryptedEncryptionKey
|
||||
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
||||
decryptedConfigs, err := utils.DecryptAES(config.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -119,7 +122,7 @@ func PersistEnv() error {
|
|||
}
|
||||
|
||||
if hasChanged {
|
||||
encryptedConfig, err := utils.EncryptConfig(jsonData)
|
||||
encryptedConfig, err := utils.EncryptEnvData(jsonData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
65
server/envstore/store.go
Normal file
65
server/envstore/store.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
package envstore
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
)
|
||||
|
||||
// EnvInMemoryStore struct
|
||||
type EnvInMemoryStore struct {
|
||||
mutex sync.Mutex
|
||||
store map[string]interface{}
|
||||
}
|
||||
|
||||
// EnvInMemoryStoreObj global variable for EnvInMemoryStore
|
||||
var EnvInMemoryStoreObj = &EnvInMemoryStore{
|
||||
store: map[string]interface{}{
|
||||
constants.EnvKeyAdminCookieName: "authorizer-admin",
|
||||
constants.EnvKeyJwtRoleClaim: "role",
|
||||
constants.EnvKeyOrganizationName: "Authorizer",
|
||||
constants.EnvKeyOrganizationLogo: "https://www.authorizer.io/images/logo.png",
|
||||
constants.EnvKeyDisableBasicAuthentication: false,
|
||||
constants.EnvKeyDisableMagicLinkLogin: false,
|
||||
constants.EnvKeyDisableEmailVerification: false,
|
||||
constants.EnvKeyDisableLoginPage: false,
|
||||
},
|
||||
}
|
||||
|
||||
// UpdateEnvStore to update the whole env store object
|
||||
func (e *EnvInMemoryStore) UpdateEnvStore(data map[string]interface{}) {
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
// just override the keys + new keys
|
||||
for key, value := range data {
|
||||
e.store[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateEnvVariable to update the particular env variable
|
||||
func (e *EnvInMemoryStore) UpdateEnvVariable(key string, value interface{}) map[string]interface{} {
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
e.store[key] = value
|
||||
return e.store
|
||||
}
|
||||
|
||||
// GetEnvStore to get the env variable from env store object
|
||||
func (e *EnvInMemoryStore) GetEnvVariable(key string) interface{} {
|
||||
// e.mutex.Lock()
|
||||
// defer e.mutex.Unlock()
|
||||
return e.store[key]
|
||||
}
|
||||
|
||||
// GetEnvStoreClone to get clone of current env store object
|
||||
func (e *EnvInMemoryStore) GetEnvStoreClone() map[string]interface{} {
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
|
||||
result := make(map[string]interface{})
|
||||
for key, value := range e.store {
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
|
@ -1182,6 +1182,7 @@ input UpdateProfileInput {
|
|||
input UpdateUserInput {
|
||||
id: ID!
|
||||
email: String
|
||||
email_verified: Boolean
|
||||
given_name: String
|
||||
family_name: String
|
||||
middle_name: String
|
||||
|
@ -6646,6 +6647,14 @@ func (ec *executionContext) unmarshalInputUpdateUserInput(ctx context.Context, o
|
|||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "email_verified":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email_verified"))
|
||||
it.EmailVerified, err = ec.unmarshalOBoolean2ᚖbool(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "given_name":
|
||||
var err error
|
||||
|
||||
|
|
|
@ -168,17 +168,18 @@ type UpdateProfileInput struct {
|
|||
}
|
||||
|
||||
type UpdateUserInput struct {
|
||||
ID string `json:"id"`
|
||||
Email *string `json:"email"`
|
||||
GivenName *string `json:"given_name"`
|
||||
FamilyName *string `json:"family_name"`
|
||||
MiddleName *string `json:"middle_name"`
|
||||
Nickname *string `json:"nickname"`
|
||||
Gender *string `json:"gender"`
|
||||
Birthdate *string `json:"birthdate"`
|
||||
PhoneNumber *string `json:"phone_number"`
|
||||
Picture *string `json:"picture"`
|
||||
Roles []*string `json:"roles"`
|
||||
ID string `json:"id"`
|
||||
Email *string `json:"email"`
|
||||
EmailVerified *bool `json:"email_verified"`
|
||||
GivenName *string `json:"given_name"`
|
||||
FamilyName *string `json:"family_name"`
|
||||
MiddleName *string `json:"middle_name"`
|
||||
Nickname *string `json:"nickname"`
|
||||
Gender *string `json:"gender"`
|
||||
Birthdate *string `json:"birthdate"`
|
||||
PhoneNumber *string `json:"phone_number"`
|
||||
Picture *string `json:"picture"`
|
||||
Roles []*string `json:"roles"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
|
|
|
@ -189,6 +189,7 @@ input UpdateProfileInput {
|
|||
input UpdateUserInput {
|
||||
id: ID!
|
||||
email: String
|
||||
email_verified: Boolean
|
||||
given_name: String
|
||||
family_name: String
|
||||
middle_name: String
|
||||
|
|
|
@ -12,47 +12,47 @@ import (
|
|||
)
|
||||
|
||||
func (r *mutationResolver) Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) {
|
||||
return resolvers.Signup(ctx, params)
|
||||
return resolvers.SignupResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error) {
|
||||
return resolvers.Login(ctx, params)
|
||||
return resolvers.LoginResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
|
||||
return resolvers.MagicLinkLogin(ctx, params)
|
||||
return resolvers.MagicLinkLoginResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) Logout(ctx context.Context) (*model.Response, error) {
|
||||
return resolvers.Logout(ctx)
|
||||
return resolvers.LogoutResolver(ctx)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) {
|
||||
return resolvers.UpdateProfile(ctx, params)
|
||||
return resolvers.UpdateProfileResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.AuthResponse, error) {
|
||||
return resolvers.VerifyEmail(ctx, params)
|
||||
return resolvers.VerifyEmailResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) ResendVerifyEmail(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) {
|
||||
return resolvers.ResendVerifyEmail(ctx, params)
|
||||
return resolvers.ResendVerifyEmailResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) ForgotPassword(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) {
|
||||
return resolvers.ForgotPassword(ctx, params)
|
||||
return resolvers.ForgotPasswordResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) ResetPassword(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
||||
return resolvers.ResetPassword(ctx, params)
|
||||
return resolvers.ResetPasswordResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
|
||||
return resolvers.DeleteUser(ctx, params)
|
||||
return resolvers.DeleteUserResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User, error) {
|
||||
return resolvers.UpdateUser(ctx, params)
|
||||
return resolvers.UpdateUserResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) AdminSignup(ctx context.Context, params model.AdminSignupInput) (*model.Response, error) {
|
||||
|
@ -64,7 +64,7 @@ func (r *mutationResolver) AdminLogin(ctx context.Context, params model.AdminLog
|
|||
}
|
||||
|
||||
func (r *mutationResolver) AdminLogout(ctx context.Context) (*model.Response, error) {
|
||||
return resolvers.AdminLogout(ctx)
|
||||
return resolvers.AdminLogoutResolver(ctx)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) UpdateConfig(ctx context.Context, params model.UpdateConfigInput) (*model.Response, error) {
|
||||
|
@ -72,27 +72,27 @@ func (r *mutationResolver) UpdateConfig(ctx context.Context, params model.Update
|
|||
}
|
||||
|
||||
func (r *queryResolver) Meta(ctx context.Context) (*model.Meta, error) {
|
||||
return resolvers.Meta(ctx)
|
||||
return resolvers.MetaResolver(ctx)
|
||||
}
|
||||
|
||||
func (r *queryResolver) Session(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
||||
return resolvers.Session(ctx, roles)
|
||||
return resolvers.SessionResolver(ctx, roles)
|
||||
}
|
||||
|
||||
func (r *queryResolver) Profile(ctx context.Context) (*model.User, error) {
|
||||
return resolvers.Profile(ctx)
|
||||
return resolvers.ProfileResolver(ctx)
|
||||
}
|
||||
|
||||
func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) {
|
||||
return resolvers.Users(ctx)
|
||||
return resolvers.UsersResolver(ctx)
|
||||
}
|
||||
|
||||
func (r *queryResolver) VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error) {
|
||||
return resolvers.VerificationRequests(ctx)
|
||||
return resolvers.VerificationRequestsResolver(ctx)
|
||||
}
|
||||
|
||||
func (r *queryResolver) AdminSession(ctx context.Context) (*model.Response, error) {
|
||||
return resolvers.AdminSession(ctx)
|
||||
return resolvers.AdminSessionResolver(ctx)
|
||||
}
|
||||
|
||||
func (r *queryResolver) Config(ctx context.Context) (*model.Config, error) {
|
||||
|
@ -105,5 +105,7 @@ func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResol
|
|||
// Query returns generated.QueryResolver implementation.
|
||||
func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
|
||||
|
||||
type mutationResolver struct{ *Resolver }
|
||||
type queryResolver struct{ *Resolver }
|
||||
type (
|
||||
mutationResolver struct{ *Resolver }
|
||||
queryResolver struct{ *Resolver }
|
||||
)
|
||||
|
|
|
@ -7,15 +7,19 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// State is the struct that holds authorizer url and redirect url
|
||||
// They are provided via query string in the request
|
||||
type State struct {
|
||||
AuthorizerURL string `json:"authorizerURL"`
|
||||
RedirectURL string `json:"redirectURL"`
|
||||
}
|
||||
|
||||
// AppHandler is the handler for the /app route
|
||||
func AppHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
state := c.Query("state")
|
||||
|
@ -23,14 +27,8 @@ func AppHandler() gin.HandlerFunc {
|
|||
var stateObj State
|
||||
|
||||
if state == "" {
|
||||
// cookie, err := utils.GetAuthToken(c)
|
||||
// if err != nil {
|
||||
// c.JSON(400, gin.H{"error": "invalid state"})
|
||||
// return
|
||||
// }
|
||||
|
||||
stateObj.AuthorizerURL = constants.EnvData.AUTHORIZER_URL
|
||||
stateObj.RedirectURL = constants.EnvData.AUTHORIZER_URL + "/app"
|
||||
stateObj.AuthorizerURL = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string)
|
||||
stateObj.RedirectURL = stateObj.AuthorizerURL + "/app"
|
||||
|
||||
} else {
|
||||
decodedState, err := utils.DecryptB64(state)
|
||||
|
@ -59,7 +57,7 @@ func AppHandler() gin.HandlerFunc {
|
|||
}
|
||||
|
||||
// validate host and domain of authorizer url
|
||||
if strings.TrimSuffix(stateObj.AuthorizerURL, "/") != constants.EnvData.AUTHORIZER_URL {
|
||||
if strings.TrimSuffix(stateObj.AuthorizerURL, "/") != envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) {
|
||||
c.JSON(400, gin.H{"error": "invalid host url"})
|
||||
return
|
||||
}
|
||||
|
@ -76,8 +74,8 @@ func AppHandler() gin.HandlerFunc {
|
|||
"data": map[string]string{
|
||||
"authorizerURL": stateObj.AuthorizerURL,
|
||||
"redirectURL": stateObj.RedirectURL,
|
||||
"organizationName": constants.EnvData.ORGANIZATION_NAME,
|
||||
"organizationLogo": constants.EnvData.ORGANIZATION_LOGO,
|
||||
"organizationName": envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyOrganizationName).(string),
|
||||
"organizationLogo": envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyOrganizationLogo).(string),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,14 +4,16 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// DashboardHandler is the handler for the /dashboard route
|
||||
func DashboardHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
isOnboardingCompleted := false
|
||||
|
||||
if constants.EnvData.ADMIN_SECRET != "" {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret) != nil && envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string) != "" {
|
||||
isOnboardingCompleted = true
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Defining the Graphql handler
|
||||
// GraphqlHandler is the main handler that handels all the graphql requests
|
||||
func GraphqlHandler() gin.HandlerFunc {
|
||||
// NewExecutableSchema and Config are in the generated.go file
|
||||
// Resolver is in the resolver.go file
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/oauth"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
|
@ -21,6 +21,131 @@ import (
|
|||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// OAuthCallbackHandler handles the OAuth callback for various oauth providers
|
||||
func OAuthCallbackHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
provider := c.Param("oauth_provider")
|
||||
state := c.Request.FormValue("state")
|
||||
|
||||
sessionState := session.GetSocailLoginState(state)
|
||||
if sessionState == "" {
|
||||
c.JSON(400, gin.H{"error": "invalid oauth state"})
|
||||
}
|
||||
session.RemoveSocialLoginState(state)
|
||||
// contains random token, redirect url, role
|
||||
sessionSplit := strings.Split(state, "___")
|
||||
|
||||
// TODO validate redirect url
|
||||
if len(sessionSplit) < 2 {
|
||||
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
||||
return
|
||||
}
|
||||
|
||||
inputRoles := strings.Split(sessionSplit[2], ",")
|
||||
redirectURL := sessionSplit[1]
|
||||
|
||||
var err error
|
||||
user := db.User{}
|
||||
code := c.Request.FormValue("code")
|
||||
switch provider {
|
||||
case constants.SignupMethodGoogle:
|
||||
user, err = processGoogleUserInfo(code)
|
||||
case constants.SignupMethodGithub:
|
||||
user, err = processGithubUserInfo(code)
|
||||
case constants.SignupMethodFacebook:
|
||||
user, err = processFacebookUserInfo(code)
|
||||
default:
|
||||
err = fmt.Errorf(`invalid oauth provider`)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
existingUser, err := db.Mgr.GetUserByEmail(user.Email)
|
||||
|
||||
if err != nil {
|
||||
// user not registered, register user and generate session token
|
||||
user.SignupMethods = provider
|
||||
// make sure inputRoles don't include protected roles
|
||||
hasProtectedRole := false
|
||||
for _, ir := range inputRoles {
|
||||
if utils.StringSliceContains(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyProtectedRoles).([]string), ir) {
|
||||
hasProtectedRole = true
|
||||
}
|
||||
}
|
||||
|
||||
if hasProtectedRole {
|
||||
c.JSON(400, gin.H{"error": "invalid role"})
|
||||
return
|
||||
}
|
||||
|
||||
user.Roles = strings.Join(inputRoles, ",")
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
user, _ = db.Mgr.AddUser(user)
|
||||
} else {
|
||||
// user exists in db, check if method was google
|
||||
// if not append google to existing signup method and save it
|
||||
|
||||
signupMethod := existingUser.SignupMethods
|
||||
if !strings.Contains(signupMethod, provider) {
|
||||
signupMethod = signupMethod + "," + provider
|
||||
}
|
||||
user.SignupMethods = signupMethod
|
||||
user.Password = existingUser.Password
|
||||
|
||||
// There multiple scenarios with roles here in social login
|
||||
// 1. user has access to protected roles + roles and trying to login
|
||||
// 2. user has not signed up for one of the available role but trying to signup.
|
||||
// Need to modify roles in this case
|
||||
|
||||
// find the unassigned roles
|
||||
existingRoles := strings.Split(existingUser.Roles, ",")
|
||||
unasignedRoles := []string{}
|
||||
for _, ir := range inputRoles {
|
||||
if !utils.StringSliceContains(existingRoles, ir) {
|
||||
unasignedRoles = append(unasignedRoles, ir)
|
||||
}
|
||||
}
|
||||
|
||||
if len(unasignedRoles) > 0 {
|
||||
// check if it contains protected unassigned role
|
||||
hasProtectedRole := false
|
||||
for _, ur := range unasignedRoles {
|
||||
if utils.StringSliceContains(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyProtectedRoles).([]string), ur) {
|
||||
hasProtectedRole = true
|
||||
}
|
||||
}
|
||||
|
||||
if hasProtectedRole {
|
||||
c.JSON(400, gin.H{"error": "invalid role"})
|
||||
return
|
||||
} else {
|
||||
user.Roles = existingUser.Roles + "," + strings.Join(unasignedRoles, ",")
|
||||
}
|
||||
} else {
|
||||
user.Roles = existingUser.Roles
|
||||
}
|
||||
user.Key = existingUser.Key
|
||||
user.ID = existingUser.ID
|
||||
user, err = db.Mgr.UpdateUser(user)
|
||||
}
|
||||
|
||||
user, _ = db.Mgr.GetUserByEmail(user.Email)
|
||||
userIdStr := fmt.Sprintf("%v", user.ID)
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, constants.TokenTypeRefreshToken, inputRoles)
|
||||
|
||||
accessToken, _, _ := utils.CreateAuthToken(user, constants.TokenTypeAccessToken, inputRoles)
|
||||
utils.SetCookie(c, accessToken)
|
||||
session.SetUserSession(userIdStr, accessToken, refreshToken)
|
||||
utils.SaveSessionInDB(user.ID, c)
|
||||
|
||||
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||
}
|
||||
}
|
||||
|
||||
func processGoogleUserInfo(code string) (db.User, error) {
|
||||
user := db.User{}
|
||||
ctx := context.Background()
|
||||
|
@ -145,127 +270,3 @@ func processFacebookUserInfo(code string) (db.User, error) {
|
|||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func OAuthCallbackHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
provider := c.Param("oauth_provider")
|
||||
state := c.Request.FormValue("state")
|
||||
|
||||
sessionState := session.GetSocailLoginState(state)
|
||||
if sessionState == "" {
|
||||
c.JSON(400, gin.H{"error": "invalid oauth state"})
|
||||
}
|
||||
session.RemoveSocialLoginState(state)
|
||||
// contains random token, redirect url, role
|
||||
sessionSplit := strings.Split(state, "___")
|
||||
|
||||
// TODO validate redirect url
|
||||
if len(sessionSplit) < 2 {
|
||||
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
||||
return
|
||||
}
|
||||
|
||||
inputRoles := strings.Split(sessionSplit[2], ",")
|
||||
redirectURL := sessionSplit[1]
|
||||
|
||||
var err error
|
||||
user := db.User{}
|
||||
code := c.Request.FormValue("code")
|
||||
switch provider {
|
||||
case enum.Google.String():
|
||||
user, err = processGoogleUserInfo(code)
|
||||
case enum.Github.String():
|
||||
user, err = processGithubUserInfo(code)
|
||||
case enum.Facebook.String():
|
||||
user, err = processFacebookUserInfo(code)
|
||||
default:
|
||||
err = fmt.Errorf(`invalid oauth provider`)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
existingUser, err := db.Mgr.GetUserByEmail(user.Email)
|
||||
|
||||
if err != nil {
|
||||
// user not registered, register user and generate session token
|
||||
user.SignupMethods = provider
|
||||
// make sure inputRoles don't include protected roles
|
||||
hasProtectedRole := false
|
||||
for _, ir := range inputRoles {
|
||||
if utils.StringSliceContains(constants.EnvData.PROTECTED_ROLES, ir) {
|
||||
hasProtectedRole = true
|
||||
}
|
||||
}
|
||||
|
||||
if hasProtectedRole {
|
||||
c.JSON(400, gin.H{"error": "invalid role"})
|
||||
return
|
||||
}
|
||||
|
||||
user.Roles = strings.Join(inputRoles, ",")
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
user, _ = db.Mgr.AddUser(user)
|
||||
} else {
|
||||
// user exists in db, check if method was google
|
||||
// if not append google to existing signup method and save it
|
||||
|
||||
signupMethod := existingUser.SignupMethods
|
||||
if !strings.Contains(signupMethod, provider) {
|
||||
signupMethod = signupMethod + "," + provider
|
||||
}
|
||||
user.SignupMethods = signupMethod
|
||||
user.Password = existingUser.Password
|
||||
|
||||
// There multiple scenarios with roles here in social login
|
||||
// 1. user has access to protected roles + roles and trying to login
|
||||
// 2. user has not signed up for one of the available role but trying to signup.
|
||||
// Need to modify roles in this case
|
||||
|
||||
// find the unassigned roles
|
||||
existingRoles := strings.Split(existingUser.Roles, ",")
|
||||
unasignedRoles := []string{}
|
||||
for _, ir := range inputRoles {
|
||||
if !utils.StringSliceContains(existingRoles, ir) {
|
||||
unasignedRoles = append(unasignedRoles, ir)
|
||||
}
|
||||
}
|
||||
|
||||
if len(unasignedRoles) > 0 {
|
||||
// check if it contains protected unassigned role
|
||||
hasProtectedRole := false
|
||||
for _, ur := range unasignedRoles {
|
||||
if utils.StringSliceContains(constants.EnvData.PROTECTED_ROLES, ur) {
|
||||
hasProtectedRole = true
|
||||
}
|
||||
}
|
||||
|
||||
if hasProtectedRole {
|
||||
c.JSON(400, gin.H{"error": "invalid role"})
|
||||
return
|
||||
} else {
|
||||
user.Roles = existingUser.Roles + "," + strings.Join(unasignedRoles, ",")
|
||||
}
|
||||
} else {
|
||||
user.Roles = existingUser.Roles
|
||||
}
|
||||
user.Key = existingUser.Key
|
||||
user.ID = existingUser.ID
|
||||
user, err = db.Mgr.UpdateUser(user)
|
||||
}
|
||||
|
||||
user, _ = db.Mgr.GetUserByEmail(user.Email)
|
||||
userIdStr := fmt.Sprintf("%v", user.ID)
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, inputRoles)
|
||||
|
||||
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, inputRoles)
|
||||
utils.SetCookie(c, accessToken)
|
||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
||||
utils.CreateSession(user.ID, c)
|
||||
|
||||
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/oauth"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
|
@ -13,8 +13,7 @@ import (
|
|||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// set host in the oauth state that is useful for redirecting
|
||||
|
||||
// OAuthLoginHandler set host in the oauth state that is useful for redirecting to oauth_callback
|
||||
func OAuthLoginHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// TODO validate redirect URL
|
||||
|
@ -34,14 +33,14 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||
|
||||
// use protected roles verification for admin login only.
|
||||
// though if not associated with user, it will be rejected from oauth_callback
|
||||
if !utils.IsValidRoles(append([]string{}, append(constants.EnvData.ROLES, constants.EnvData.PROTECTED_ROLES...)...), rolesSplit) {
|
||||
if !utils.IsValidRoles(append([]string{}, append(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyRoles).([]string), envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyProtectedRoles).([]string)...)...), rolesSplit) {
|
||||
c.JSON(400, gin.H{
|
||||
"error": "invalid role",
|
||||
})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
roles = strings.Join(constants.EnvData.DEFAULT_ROLES, ",")
|
||||
roles = strings.Join(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDefaultRoles).([]string), ",")
|
||||
}
|
||||
|
||||
uuid := uuid.New()
|
||||
|
@ -50,32 +49,32 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||
provider := c.Param("oauth_provider")
|
||||
isProviderConfigured := true
|
||||
switch provider {
|
||||
case enum.Google.String():
|
||||
case constants.SignupMethodGoogle:
|
||||
if oauth.OAuthProviders.GoogleConfig == nil {
|
||||
isProviderConfigured = false
|
||||
break
|
||||
}
|
||||
session.SetSocailLoginState(oauthStateString, enum.Google.String())
|
||||
session.SetSocailLoginState(oauthStateString, constants.SignupMethodGoogle)
|
||||
// during the init of OAuthProvider authorizer url might be empty
|
||||
oauth.OAuthProviders.GoogleConfig.RedirectURL = constants.EnvData.AUTHORIZER_URL + "/oauth_callback/google"
|
||||
oauth.OAuthProviders.GoogleConfig.RedirectURL = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) + "/oauth_callback/google"
|
||||
url := oauth.OAuthProviders.GoogleConfig.AuthCodeURL(oauthStateString)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
case enum.Github.String():
|
||||
case constants.SignupMethodGithub:
|
||||
if oauth.OAuthProviders.GithubConfig == nil {
|
||||
isProviderConfigured = false
|
||||
break
|
||||
}
|
||||
session.SetSocailLoginState(oauthStateString, enum.Github.String())
|
||||
oauth.OAuthProviders.GithubConfig.RedirectURL = constants.EnvData.AUTHORIZER_URL + "/oauth_callback/github"
|
||||
session.SetSocailLoginState(oauthStateString, constants.SignupMethodGithub)
|
||||
oauth.OAuthProviders.GithubConfig.RedirectURL = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) + "/oauth_callback/github"
|
||||
url := oauth.OAuthProviders.GithubConfig.AuthCodeURL(oauthStateString)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
case enum.Facebook.String():
|
||||
case constants.SignupMethodFacebook:
|
||||
if oauth.OAuthProviders.FacebookConfig == nil {
|
||||
isProviderConfigured = false
|
||||
break
|
||||
}
|
||||
session.SetSocailLoginState(oauthStateString, enum.Facebook.String())
|
||||
oauth.OAuthProviders.FacebookConfig.RedirectURL = constants.EnvData.AUTHORIZER_URL + "/oauth_callback/facebook"
|
||||
session.SetSocailLoginState(oauthStateString, constants.SignupMethodFacebook)
|
||||
oauth.OAuthProviders.FacebookConfig.RedirectURL = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) + "/oauth_callback/facebook"
|
||||
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
default:
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// PlaygroundHandler is the handler for the /playground route
|
||||
func PlaygroundHandler() gin.HandlerFunc {
|
||||
h := playground.Handler("GraphQL", "/graphql")
|
||||
|
||||
|
|
14
server/handlers/root.go
Normal file
14
server/handlers/root.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// RootHandler is the handler for / root route.
|
||||
func RootHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Redirect(http.StatusTemporaryRedirect, "/dashboard")
|
||||
}
|
||||
}
|
|
@ -5,13 +5,15 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// VerifyEmailHandler handles the verify email route.
|
||||
// It verifies email based on JWT token in query string
|
||||
func VerifyEmailHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
errorRes := gin.H{
|
||||
|
@ -54,12 +56,12 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||
|
||||
roles := strings.Split(user.Roles, ",")
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, constants.TokenTypeRefreshToken, roles)
|
||||
|
||||
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||
accessToken, _, _ := utils.CreateAuthToken(user, constants.TokenTypeAccessToken, roles)
|
||||
|
||||
session.SetToken(user.ID, accessToken, refreshToken)
|
||||
utils.CreateSession(user.ID, c)
|
||||
session.SetUserSession(user.ID, accessToken, refreshToken)
|
||||
utils.SaveSessionInDB(user.ID, c)
|
||||
utils.SetCookie(c, accessToken)
|
||||
c.Redirect(http.StatusTemporaryRedirect, claim.RedirectURL)
|
||||
}
|
||||
|
|
|
@ -6,11 +6,10 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/env"
|
||||
"github.com/authorizerdev/authorizer/server/handlers"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/oauth"
|
||||
"github.com/authorizerdev/authorizer/server/router"
|
||||
"github.com/authorizerdev/authorizer/server/routes"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
var VERSION string
|
||||
|
@ -18,11 +17,10 @@ var VERSION string
|
|||
func main() {
|
||||
env.ARG_DB_URL = flag.String("database_url", "", "Database connection string")
|
||||
env.ARG_DB_TYPE = flag.String("database_type", "", "Database type, possible values are postgres,mysql,sqlite")
|
||||
env.ARG_AUTHORIZER_URL = flag.String("authorizer_url", "", "URL for authorizer instance, eg: https://xyz.herokuapp.com")
|
||||
env.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
|
||||
flag.Parse()
|
||||
|
||||
constants.EnvData.VERSION = VERSION
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyVersion, VERSION)
|
||||
|
||||
env.InitEnv()
|
||||
db.InitDB()
|
||||
|
@ -30,27 +28,8 @@ func main() {
|
|||
|
||||
session.InitSession()
|
||||
oauth.InitOAuth()
|
||||
utils.InitServer()
|
||||
|
||||
router := router.InitRouter()
|
||||
router := routes.InitRouter()
|
||||
|
||||
router.LoadHTMLGlob("templates/*")
|
||||
// login page app related routes.
|
||||
// if we put them in router file then tests would fail as templates or build path will be different
|
||||
if !constants.EnvData.DISABLE_LOGIN_PAGE {
|
||||
app := router.Group("/app")
|
||||
{
|
||||
app.Static("/build", "app/build")
|
||||
app.GET("/", handlers.AppHandler())
|
||||
app.GET("/reset-password", handlers.AppHandler())
|
||||
}
|
||||
}
|
||||
|
||||
app := router.Group("/dashboard")
|
||||
{
|
||||
app.Static("/build", "dashboard/build")
|
||||
app.GET("/", handlers.DashboardHandler())
|
||||
}
|
||||
|
||||
router.Run(":" + constants.EnvData.PORT)
|
||||
router.Run(":" + envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyPort).(string))
|
||||
}
|
||||
|
|
|
@ -2,19 +2,19 @@ package middlewares
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/gin-contrib/location"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GinContextToContextMiddleware is a middleware to add gin context in context
|
||||
func GinContextToContextMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if constants.EnvData.AUTHORIZER_URL == "" {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) == "" {
|
||||
url := location.Get(c)
|
||||
constants.EnvData.AUTHORIZER_URL = url.Scheme + "://" + c.Request.Host
|
||||
log.Println("authorizer url:", constants.EnvData.AUTHORIZER_URL)
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyAuthorizerURL, url.Scheme+"://"+c.Request.Host)
|
||||
}
|
||||
ctx := context.WithValue(c.Request.Context(), "GinContextKey", c)
|
||||
c.Request = c.Request.WithContext(ctx)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// CORSMiddleware is a middleware to add cors headers
|
||||
func CORSMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
origin := c.Request.Header.Get("Origin")
|
||||
|
|
|
@ -5,56 +5,62 @@ import (
|
|||
"log"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"golang.org/x/oauth2"
|
||||
facebookOAuth2 "golang.org/x/oauth2/facebook"
|
||||
githubOAuth2 "golang.org/x/oauth2/github"
|
||||
)
|
||||
|
||||
// OAuthProviders is a struct that contains reference all the OAuth providers
|
||||
type OAuthProvider struct {
|
||||
GoogleConfig *oauth2.Config
|
||||
GithubConfig *oauth2.Config
|
||||
FacebookConfig *oauth2.Config
|
||||
}
|
||||
|
||||
// OIDCProviders is a struct that contains reference all the OpenID providers
|
||||
type OIDCProvider struct {
|
||||
GoogleOIDC *oidc.Provider
|
||||
}
|
||||
|
||||
var (
|
||||
// OAuthProviders is a global variable that contains instance for all enabled the OAuth providers
|
||||
OAuthProviders OAuthProvider
|
||||
OIDCProviders OIDCProvider
|
||||
// OIDCProviders is a global variable that contains instance for all enabled the OpenID providers
|
||||
OIDCProviders OIDCProvider
|
||||
)
|
||||
|
||||
// InitOAuth initializes the OAuth providers based on EnvData
|
||||
func InitOAuth() {
|
||||
ctx := context.Background()
|
||||
if constants.EnvData.GOOGLE_CLIENT_ID != "" && constants.EnvData.GOOGLE_CLIENT_SECRET != "" {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGoogleClientID).(string) != "" && envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGoogleClientSecret).(string) != "" {
|
||||
p, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
||||
if err != nil {
|
||||
log.Fatalln("error creating oidc provider for google:", err)
|
||||
}
|
||||
OIDCProviders.GoogleOIDC = p
|
||||
OAuthProviders.GoogleConfig = &oauth2.Config{
|
||||
ClientID: constants.EnvData.GOOGLE_CLIENT_ID,
|
||||
ClientSecret: constants.EnvData.GOOGLE_CLIENT_SECRET,
|
||||
RedirectURL: constants.EnvData.AUTHORIZER_URL + "/oauth_callback/google",
|
||||
ClientID: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGoogleClientID).(string),
|
||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGoogleClientSecret).(string),
|
||||
RedirectURL: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) + "/oauth_callback/google",
|
||||
Endpoint: OIDCProviders.GoogleOIDC.Endpoint(),
|
||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||
}
|
||||
}
|
||||
if constants.EnvData.GITHUB_CLIENT_ID != "" && constants.EnvData.GITHUB_CLIENT_SECRET != "" {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGithubClientID).(string) != "" && envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGithubClientSecret).(string) != "" {
|
||||
OAuthProviders.GithubConfig = &oauth2.Config{
|
||||
ClientID: constants.EnvData.GITHUB_CLIENT_ID,
|
||||
ClientSecret: constants.EnvData.GITHUB_CLIENT_SECRET,
|
||||
RedirectURL: constants.EnvData.AUTHORIZER_URL + "/oauth_callback/github",
|
||||
ClientID: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGithubClientID).(string),
|
||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGithubClientSecret).(string),
|
||||
RedirectURL: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) + "/oauth_callback/github",
|
||||
Endpoint: githubOAuth2.Endpoint,
|
||||
}
|
||||
}
|
||||
if constants.EnvData.FACEBOOK_CLIENT_ID != "" && constants.EnvData.FACEBOOK_CLIENT_SECRET != "" {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyFacebookClientID).(string) != "" && envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyGoogleClientID).(string) != "" {
|
||||
OAuthProviders.FacebookConfig = &oauth2.Config{
|
||||
ClientID: constants.EnvData.FACEBOOK_CLIENT_ID,
|
||||
ClientSecret: constants.EnvData.FACEBOOK_CLIENT_SECRET,
|
||||
RedirectURL: constants.EnvData.AUTHORIZER_URL + "/oauth_callback/facebook",
|
||||
ClientID: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyFacebookClientID).(string),
|
||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyFacebookClientSecret).(string),
|
||||
RedirectURL: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAuthorizerURL).(string) + "/oauth_callback/facebook",
|
||||
Endpoint: facebookOAuth2.Endpoint,
|
||||
Scopes: []string{"public_profile", "email"},
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
// AdminLoginResolver is a resolver for admin login mutation
|
||||
func AdminLoginResolver(ctx context.Context, params model.AdminLoginInput) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
|
@ -17,11 +19,12 @@ func AdminLoginResolver(ctx context.Context, params model.AdminLoginInput) (*mod
|
|||
return res, err
|
||||
}
|
||||
|
||||
if params.AdminSecret != constants.EnvData.ADMIN_SECRET {
|
||||
adminSecret := envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string)
|
||||
if params.AdminSecret != adminSecret {
|
||||
return res, fmt.Errorf(`invalid admin secret`)
|
||||
}
|
||||
|
||||
hashedKey, err := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
hashedKey, err := utils.EncryptPassword(adminSecret)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func AdminLogout(ctx context.Context) (*model.Response, error) {
|
||||
// AdminLogoutResolver is a resolver for admin logout mutation
|
||||
func AdminLogoutResolver(ctx context.Context) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
|
||||
|
|
|
@ -5,11 +5,13 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func AdminSession(ctx context.Context) (*model.Response, error) {
|
||||
// AdminSessionResolver is a resolver for admin session query
|
||||
func AdminSessionResolver(ctx context.Context) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
|
||||
|
@ -21,7 +23,7 @@ func AdminSession(ctx context.Context) (*model.Response, error) {
|
|||
return res, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
hashedKey, err := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
hashedKey, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
|
|
@ -8,10 +8,12 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
// AdminSignupResolver is a resolver for admin signup mutation
|
||||
func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
|
@ -30,17 +32,18 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||
return res, err
|
||||
}
|
||||
|
||||
if constants.EnvData.ADMIN_SECRET != "" {
|
||||
adminSecret := envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string)
|
||||
|
||||
if adminSecret != "" {
|
||||
err = fmt.Errorf("admin sign up already completed")
|
||||
return res, err
|
||||
}
|
||||
|
||||
constants.EnvData.ADMIN_SECRET = params.AdminSecret
|
||||
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyAdminSecret, params.AdminSecret)
|
||||
// consvert EnvData to JSON
|
||||
var jsonData map[string]interface{}
|
||||
|
||||
jsonBytes, err := json.Marshal(constants.EnvData)
|
||||
jsonBytes, err := json.Marshal(envstore.EnvInMemoryStoreObj.GetEnvStoreClone())
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@ -54,7 +57,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||
return res, err
|
||||
}
|
||||
|
||||
configData, err := utils.EncryptConfig(jsonData)
|
||||
configData, err := utils.EncryptEnvData(jsonData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@ -64,7 +67,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||
return res, err
|
||||
}
|
||||
|
||||
hashedKey, err := utils.HashPassword(params.AdminSecret)
|
||||
hashedKey, err := utils.EncryptPassword(params.AdminSecret)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
|
|
@ -5,10 +5,15 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
// TODO rename to env_data
|
||||
|
||||
// ConfigResolver is a resolver for config query
|
||||
// This is admin only query
|
||||
func ConfigResolver(ctx context.Context) (*model.Config, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Config
|
||||
|
@ -21,40 +26,76 @@ func ConfigResolver(ctx context.Context) (*model.Config, error) {
|
|||
return res, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
// get clone of store
|
||||
store := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
||||
adminSecret := store[constants.EnvKeyAdminSecret].(string)
|
||||
databaseType := store[constants.EnvKeyDatabaseType].(string)
|
||||
databaseURL := store[constants.EnvKeyDatabaseURL].(string)
|
||||
databaseName := store[constants.EnvKeyDatabaseName].(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)
|
||||
allowedOrigins := store[constants.EnvKeyAllowedOrigins].([]string)
|
||||
authorizerURL := store[constants.EnvKeyAuthorizerURL].(string)
|
||||
appURL := store[constants.EnvKeyAppURL].(string)
|
||||
redisURL := store[constants.EnvKeyRedisURL].(string)
|
||||
cookieName := store[constants.EnvKeyCookieName].(string)
|
||||
resetPasswordURL := store[constants.EnvKeyResetPasswordURL].(string)
|
||||
disableEmailVerification := store[constants.EnvKeyDisableEmailVerification].(bool)
|
||||
disableBasicAuthentication := store[constants.EnvKeyDisableBasicAuthentication].(bool)
|
||||
disableMagicLinkLogin := store[constants.EnvKeyDisableMagicLinkLogin].(bool)
|
||||
disableLoginPage := store[constants.EnvKeyDisableLoginPage].(bool)
|
||||
roles := store[constants.EnvKeyRoles].([]string)
|
||||
defaultRoles := store[constants.EnvKeyDefaultRoles].([]string)
|
||||
protectedRoles := store[constants.EnvKeyProtectedRoles].([]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)
|
||||
|
||||
res = &model.Config{
|
||||
AdminSecret: &constants.EnvData.ADMIN_SECRET,
|
||||
DatabaseType: &constants.EnvData.DATABASE_TYPE,
|
||||
DatabaseURL: &constants.EnvData.DATABASE_URL,
|
||||
DatabaseName: &constants.EnvData.DATABASE_NAME,
|
||||
SMTPHost: &constants.EnvData.SMTP_HOST,
|
||||
SMTPPort: &constants.EnvData.SMTP_PORT,
|
||||
SMTPPassword: &constants.EnvData.SMTP_PASSWORD,
|
||||
SMTPUsername: &constants.EnvData.SMTP_USERNAME,
|
||||
SenderEmail: &constants.EnvData.SENDER_EMAIL,
|
||||
JwtType: &constants.EnvData.JWT_TYPE,
|
||||
JwtSecret: &constants.EnvData.JWT_SECRET,
|
||||
AllowedOrigins: constants.EnvData.ALLOWED_ORIGINS,
|
||||
AuthorizerURL: &constants.EnvData.AUTHORIZER_URL,
|
||||
AppURL: &constants.EnvData.APP_URL,
|
||||
RedisURL: &constants.EnvData.REDIS_URL,
|
||||
CookieName: &constants.EnvData.COOKIE_NAME,
|
||||
ResetPasswordURL: &constants.EnvData.RESET_PASSWORD_URL,
|
||||
DisableEmailVerification: &constants.EnvData.DISABLE_EMAIL_VERIFICATION,
|
||||
DisableBasicAuthentication: &constants.EnvData.DISABLE_BASIC_AUTHENTICATION,
|
||||
DisableMagicLinkLogin: &constants.EnvData.DISABLE_MAGIC_LINK_LOGIN,
|
||||
DisableLoginPage: &constants.EnvData.DISABLE_LOGIN_PAGE,
|
||||
Roles: constants.EnvData.ROLES,
|
||||
ProtectedRoles: constants.EnvData.PROTECTED_ROLES,
|
||||
DefaultRoles: constants.EnvData.DEFAULT_ROLES,
|
||||
JwtRoleClaim: &constants.EnvData.JWT_ROLE_CLAIM,
|
||||
GoogleClientID: &constants.EnvData.GOOGLE_CLIENT_ID,
|
||||
GoogleClientSecret: &constants.EnvData.GOOGLE_CLIENT_SECRET,
|
||||
GithubClientID: &constants.EnvData.GITHUB_CLIENT_ID,
|
||||
GithubClientSecret: &constants.EnvData.GITHUB_CLIENT_SECRET,
|
||||
FacebookClientID: &constants.EnvData.FACEBOOK_CLIENT_ID,
|
||||
FacebookClientSecret: &constants.EnvData.FACEBOOK_CLIENT_SECRET,
|
||||
OrganizationName: &constants.EnvData.ORGANIZATION_NAME,
|
||||
OrganizationLogo: &constants.EnvData.ORGANIZATION_LOGO,
|
||||
AdminSecret: &adminSecret,
|
||||
DatabaseType: &databaseType,
|
||||
DatabaseURL: &databaseURL,
|
||||
DatabaseName: &databaseName,
|
||||
SMTPHost: &smtpHost,
|
||||
SMTPPort: &smtpPort,
|
||||
SMTPPassword: &smtpPassword,
|
||||
SMTPUsername: &smtpUsername,
|
||||
SenderEmail: &senderEmail,
|
||||
JwtType: &jwtType,
|
||||
JwtSecret: &jwtSecret,
|
||||
JwtRoleClaim: &jwtRoleClaim,
|
||||
AllowedOrigins: allowedOrigins,
|
||||
AuthorizerURL: &authorizerURL,
|
||||
AppURL: &appURL,
|
||||
RedisURL: &redisURL,
|
||||
CookieName: &cookieName,
|
||||
ResetPasswordURL: &resetPasswordURL,
|
||||
DisableEmailVerification: &disableEmailVerification,
|
||||
DisableBasicAuthentication: &disableBasicAuthentication,
|
||||
DisableMagicLinkLogin: &disableMagicLinkLogin,
|
||||
DisableLoginPage: &disableLoginPage,
|
||||
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
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
|
||||
// DeleteUserResolver is a resolver for delete user mutation
|
||||
func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
if err != nil {
|
||||
|
@ -27,7 +28,7 @@ func DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Respo
|
|||
return res, err
|
||||
}
|
||||
|
||||
session.DeleteUserSession(fmt.Sprintf("%x", user.ID))
|
||||
session.DeleteAllUserSession(fmt.Sprintf("%x", user.ID))
|
||||
|
||||
err = db.Mgr.DeleteUser(user)
|
||||
if err != nil {
|
||||
|
|
|
@ -9,18 +9,20 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/email"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func ForgotPassword(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) {
|
||||
// ForgotPasswordResolver is a resolver for forgot password mutation
|
||||
func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if constants.EnvData.DISABLE_BASIC_AUTHENTICATION {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableBasicAuthentication).(bool) {
|
||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||
}
|
||||
host := gc.Request.Host
|
||||
|
@ -35,20 +37,20 @@ func ForgotPassword(ctx context.Context, params model.ForgotPasswordInput) (*mod
|
|||
return res, fmt.Errorf(`user with this email not found`)
|
||||
}
|
||||
|
||||
token, err := utils.CreateVerificationToken(params.Email, enum.ForgotPassword.String())
|
||||
token, err := utils.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
}
|
||||
db.Mgr.AddVerification(db.VerificationRequest{
|
||||
Token: token,
|
||||
Identifier: enum.ForgotPassword.String(),
|
||||
Identifier: constants.VerificationTypeForgotPassword,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
Email: params.Email,
|
||||
})
|
||||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendForgotPasswordMail(params.Email, token, host)
|
||||
email.SendForgotPasswordMail(params.Email, token, host)
|
||||
}()
|
||||
|
||||
res = &model.Response{
|
||||
|
|
|
@ -8,21 +8,22 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error) {
|
||||
// LoginResolver is a resolver for login mutation
|
||||
func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.AuthResponse
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if constants.EnvData.DISABLE_BASIC_AUTHENTICATION {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableBasicAuthentication).(bool) {
|
||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||
}
|
||||
|
||||
|
@ -32,7 +33,7 @@ func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, e
|
|||
return res, fmt.Errorf(`user with this email not found`)
|
||||
}
|
||||
|
||||
if !strings.Contains(user.SignupMethods, enum.BasicAuth.String()) {
|
||||
if !strings.Contains(user.SignupMethods, constants.SignupMethodBasicAuth) {
|
||||
return res, fmt.Errorf(`user has not signed up email & password`)
|
||||
}
|
||||
|
||||
|
@ -46,7 +47,7 @@ func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, e
|
|||
log.Println("compare password error:", err)
|
||||
return res, fmt.Errorf(`invalid password`)
|
||||
}
|
||||
roles := constants.EnvData.DEFAULT_ROLES
|
||||
roles := envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDefaultRoles).([]string)
|
||||
currentRoles := strings.Split(user.Roles, ",")
|
||||
if len(params.Roles) > 0 {
|
||||
if !utils.IsValidRoles(currentRoles, params.Roles) {
|
||||
|
@ -55,12 +56,12 @@ func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, e
|
|||
|
||||
roles = params.Roles
|
||||
}
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, constants.TokenTypeRefreshToken, roles)
|
||||
|
||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, constants.TokenTypeAccessToken, roles)
|
||||
|
||||
session.SetToken(user.ID, accessToken, refreshToken)
|
||||
utils.CreateSession(user.ID, gc)
|
||||
session.SetUserSession(user.ID, accessToken, refreshToken)
|
||||
utils.SaveSessionInDB(user.ID, gc)
|
||||
|
||||
res = &model.AuthResponse{
|
||||
Message: `Logged in successfully`,
|
||||
|
|
|
@ -9,7 +9,8 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func Logout(ctx context.Context) (*model.Response, error) {
|
||||
// LogoutResolver is a resolver for logout mutation
|
||||
func LogoutResolver(ctx context.Context) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
if err != nil {
|
||||
|
@ -27,7 +28,7 @@ func Logout(ctx context.Context) (*model.Response, error) {
|
|||
}
|
||||
|
||||
userId := fmt.Sprintf("%v", claim["id"])
|
||||
session.DeleteVerificationRequest(userId, token)
|
||||
session.DeleteUserSession(userId, token)
|
||||
res = &model.Response{
|
||||
Message: "Logged out successfully",
|
||||
}
|
||||
|
|
|
@ -9,15 +9,17 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/email"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
|
||||
// MagicLinkLoginResolver is a resolver for magic link login mutation
|
||||
func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
|
||||
var res *model.Response
|
||||
|
||||
if constants.EnvData.DISABLE_MAGIC_LINK_LOGIN {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableMagicLinkLogin).(bool) {
|
||||
return res, fmt.Errorf(`magic link login is disabled for this instance`)
|
||||
}
|
||||
|
||||
|
@ -37,17 +39,17 @@ func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*mod
|
|||
existingUser, err := db.Mgr.GetUserByEmail(params.Email)
|
||||
|
||||
if err != nil {
|
||||
user.SignupMethods = enum.MagicLinkLogin.String()
|
||||
user.SignupMethods = constants.SignupMethodMagicLinkLogin
|
||||
// define roles for new user
|
||||
if len(params.Roles) > 0 {
|
||||
// check if roles exists
|
||||
if !utils.IsValidRoles(constants.EnvData.ROLES, params.Roles) {
|
||||
if !utils.IsValidRoles(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyRoles).([]string), params.Roles) {
|
||||
return res, fmt.Errorf(`invalid roles`)
|
||||
} else {
|
||||
inputRoles = params.Roles
|
||||
}
|
||||
} else {
|
||||
inputRoles = constants.EnvData.DEFAULT_ROLES
|
||||
inputRoles = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDefaultRoles).([]string)
|
||||
}
|
||||
|
||||
user.Roles = strings.Join(inputRoles, ",")
|
||||
|
@ -72,7 +74,7 @@ func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*mod
|
|||
// check if it contains protected unassigned role
|
||||
hasProtectedRole := false
|
||||
for _, ur := range unasignedRoles {
|
||||
if utils.StringSliceContains(constants.EnvData.PROTECTED_ROLES, ur) {
|
||||
if utils.StringSliceContains(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyProtectedRoles).([]string), ur) {
|
||||
hasProtectedRole = true
|
||||
}
|
||||
}
|
||||
|
@ -87,8 +89,8 @@ func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*mod
|
|||
}
|
||||
|
||||
signupMethod := existingUser.SignupMethods
|
||||
if !strings.Contains(signupMethod, enum.MagicLinkLogin.String()) {
|
||||
signupMethod = signupMethod + "," + enum.MagicLinkLogin.String()
|
||||
if !strings.Contains(signupMethod, constants.SignupMethodMagicLinkLogin) {
|
||||
signupMethod = signupMethod + "," + constants.SignupMethodMagicLinkLogin
|
||||
}
|
||||
|
||||
user.SignupMethods = signupMethod
|
||||
|
@ -98,9 +100,9 @@ func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*mod
|
|||
}
|
||||
}
|
||||
|
||||
if !constants.EnvData.DISABLE_EMAIL_VERIFICATION {
|
||||
if !envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableEmailVerification).(bool) {
|
||||
// insert verification request
|
||||
verificationType := enum.MagicLinkLogin.String()
|
||||
verificationType := constants.VerificationTypeMagicLinkLogin
|
||||
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
|
@ -114,7 +116,7 @@ func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*mod
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendVerificationMail(params.Email, token)
|
||||
email.SendVerificationMail(params.Email, token)
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func Meta(ctx context.Context) (*model.Meta, error) {
|
||||
// MetaResolver is a resolver for meta query
|
||||
func MetaResolver(ctx context.Context) (*model.Meta, error) {
|
||||
metaInfo := utils.GetMetaInfo()
|
||||
return &metaInfo, nil
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func Profile(ctx context.Context) (*model.User, error) {
|
||||
// ProfileResolver is a resolver for profile query
|
||||
func ProfileResolver(ctx context.Context) (*model.User, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.User
|
||||
if err != nil {
|
||||
|
@ -29,7 +30,7 @@ func Profile(ctx context.Context) (*model.User, error) {
|
|||
|
||||
userID := fmt.Sprintf("%v", claim["id"])
|
||||
email := fmt.Sprintf("%v", claim["email"])
|
||||
sessionToken := session.GetToken(userID, token)
|
||||
sessionToken := session.GetUserSession(userID, token)
|
||||
|
||||
if sessionToken == "" {
|
||||
return res, fmt.Errorf(`unauthorized`)
|
||||
|
|
|
@ -8,11 +8,13 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/email"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func ResendVerifyEmail(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) {
|
||||
// ResendVerifyEmailResolver is a resolver for resend verify email mutation
|
||||
func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) {
|
||||
var res *model.Response
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
|
||||
|
@ -48,7 +50,7 @@ func ResendVerifyEmail(ctx context.Context, params model.ResendVerifyEmailInput)
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendVerificationMail(params.Email, token)
|
||||
email.SendVerificationMail(params.Email, token)
|
||||
}()
|
||||
|
||||
res = &model.Response{
|
||||
|
|
|
@ -8,14 +8,15 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func ResetPassword(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
||||
// ResetPasswordResolver is a resolver for reset password mutation
|
||||
func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
||||
var res *model.Response
|
||||
if constants.EnvData.DISABLE_BASIC_AUTHENTICATION {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableBasicAuthentication).(bool) {
|
||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||
}
|
||||
|
||||
|
@ -39,12 +40,12 @@ func ResetPassword(ctx context.Context, params model.ResetPasswordInput) (*model
|
|||
return res, err
|
||||
}
|
||||
|
||||
password, _ := utils.HashPassword(params.Password)
|
||||
password, _ := utils.EncryptPassword(params.Password)
|
||||
user.Password = &password
|
||||
|
||||
signupMethod := user.SignupMethods
|
||||
if !strings.Contains(signupMethod, enum.BasicAuth.String()) {
|
||||
signupMethod = signupMethod + "," + enum.BasicAuth.String()
|
||||
if !strings.Contains(signupMethod, constants.SignupMethodBasicAuth) {
|
||||
signupMethod = signupMethod + "," + constants.SignupMethodBasicAuth
|
||||
}
|
||||
user.SignupMethods = signupMethod
|
||||
|
||||
|
|
|
@ -7,13 +7,14 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func Session(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
||||
// SessionResolver is a resolver for session query
|
||||
func SessionResolver(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
||||
var res *model.AuthResponse
|
||||
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
|
@ -36,7 +37,7 @@ func Session(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
|||
|
||||
userIdStr := fmt.Sprintf("%v", user.ID)
|
||||
|
||||
sessionToken := session.GetToken(userIdStr, token)
|
||||
sessionToken := session.GetUserSession(userIdStr, token)
|
||||
|
||||
if sessionToken == "" {
|
||||
return res, fmt.Errorf(`unauthorized`)
|
||||
|
@ -45,7 +46,7 @@ func Session(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
|||
expiresTimeObj := time.Unix(expiresAt, 0)
|
||||
currentTimeObj := time.Now()
|
||||
|
||||
claimRoleInterface := claim[constants.EnvData.JWT_ROLE_CLAIM].([]interface{})
|
||||
claimRoleInterface := claim[envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyJwtRoleClaim).(string)].([]interface{})
|
||||
claimRoles := make([]string, len(claimRoleInterface))
|
||||
for i, v := range claimRoleInterface {
|
||||
claimRoles[i] = v.(string)
|
||||
|
@ -59,14 +60,15 @@ func Session(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO change this logic to make it more secure
|
||||
if accessTokenErr != nil || expiresTimeObj.Sub(currentTimeObj).Minutes() <= 5 {
|
||||
// if access token has expired and refresh/session token is valid
|
||||
// generate new accessToken
|
||||
currentRefreshToken := session.GetToken(userIdStr, token)
|
||||
session.DeleteVerificationRequest(userIdStr, token)
|
||||
token, expiresAt, _ = utils.CreateAuthToken(user, enum.AccessToken, claimRoles)
|
||||
session.SetToken(userIdStr, token, currentRefreshToken)
|
||||
utils.CreateSession(user.ID, gc)
|
||||
currentRefreshToken := session.GetUserSession(userIdStr, token)
|
||||
session.DeleteUserSession(userIdStr, token)
|
||||
token, expiresAt, _ = utils.CreateAuthToken(user, constants.TokenTypeAccessToken, claimRoles)
|
||||
session.SetUserSession(userIdStr, token, currentRefreshToken)
|
||||
utils.SaveSessionInDB(user.ID, gc)
|
||||
}
|
||||
|
||||
utils.SetCookie(gc, token)
|
||||
|
|
|
@ -9,20 +9,23 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/email"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) {
|
||||
// SignupResolver is a resolver for signup mutation
|
||||
func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) {
|
||||
log.Println(envstore.EnvInMemoryStoreObj.GetEnvStoreClone())
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.AuthResponse
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if constants.EnvData.DISABLE_BASIC_AUTHENTICATION {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableBasicAuthentication).(bool) {
|
||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||
}
|
||||
if params.ConfirmPassword != params.Password {
|
||||
|
@ -52,13 +55,13 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
|||
|
||||
if len(params.Roles) > 0 {
|
||||
// check if roles exists
|
||||
if !utils.IsValidRoles(constants.EnvData.ROLES, params.Roles) {
|
||||
if !utils.IsValidRoles(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyRoles).([]string), params.Roles) {
|
||||
return res, fmt.Errorf(`invalid roles`)
|
||||
} else {
|
||||
inputRoles = params.Roles
|
||||
}
|
||||
} else {
|
||||
inputRoles = constants.EnvData.DEFAULT_ROLES
|
||||
inputRoles = envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDefaultRoles).([]string)
|
||||
}
|
||||
|
||||
user := db.User{
|
||||
|
@ -67,7 +70,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
|||
|
||||
user.Roles = strings.Join(inputRoles, ",")
|
||||
|
||||
password, _ := utils.HashPassword(params.Password)
|
||||
password, _ := utils.EncryptPassword(params.Password)
|
||||
user.Password = &password
|
||||
|
||||
if params.GivenName != nil {
|
||||
|
@ -102,8 +105,8 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
|||
user.Picture = params.Picture
|
||||
}
|
||||
|
||||
user.SignupMethods = enum.BasicAuth.String()
|
||||
if constants.EnvData.DISABLE_EMAIL_VERIFICATION {
|
||||
user.SignupMethods = constants.SignupMethodBasicAuth
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableEmailVerification).(bool) {
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
}
|
||||
|
@ -115,9 +118,9 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
|||
roles := strings.Split(user.Roles, ",")
|
||||
userToReturn := utils.GetResponseUserData(user)
|
||||
|
||||
if !constants.EnvData.DISABLE_EMAIL_VERIFICATION {
|
||||
if !envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableEmailVerification).(bool) {
|
||||
// insert verification request
|
||||
verificationType := enum.BasicAuthSignup.String()
|
||||
verificationType := constants.VerificationTypeBasicAuthSignup
|
||||
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
|
@ -131,7 +134,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendVerificationMail(params.Email, token)
|
||||
email.SendVerificationMail(params.Email, token)
|
||||
}()
|
||||
|
||||
res = &model.AuthResponse{
|
||||
|
@ -140,12 +143,12 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
|||
}
|
||||
} else {
|
||||
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, constants.TokenTypeRefreshToken, roles)
|
||||
|
||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, constants.TokenTypeAccessToken, roles)
|
||||
|
||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
||||
utils.CreateSession(user.ID, gc)
|
||||
session.SetUserSession(userIdStr, accessToken, refreshToken)
|
||||
utils.SaveSessionInDB(user.ID, gc)
|
||||
res = &model.AuthResponse{
|
||||
Message: `Signed up successfully.`,
|
||||
AccessToken: &accessToken,
|
||||
|
|
|
@ -9,10 +9,15 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
// TODO rename to UpdateEnvDataResolver
|
||||
|
||||
// UpdateConfigResolver is a resolver for update config mutation
|
||||
// This is admin only mutation
|
||||
func UpdateConfigResolver(ctx context.Context, params model.UpdateConfigInput) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
|
@ -57,13 +62,13 @@ func UpdateConfigResolver(ctx context.Context, params model.UpdateConfigInput) (
|
|||
|
||||
// handle derivative cases like disabling email verification & magic login
|
||||
// in case SMTP is off but env is set to true
|
||||
if updatedData["SMTP_HOST"] == "" || updatedData["SENDER_EMAIL"] == "" || updatedData["SENDER_PASSWORD"] == "" {
|
||||
if !updatedData["DISABLE_EMAIL_VERIFICATION"].(bool) {
|
||||
updatedData["DISABLE_EMAIL_VERIFICATION"] = true
|
||||
if updatedData[constants.EnvKeySmtpHost] == "" || updatedData[constants.EnvKeySenderEmail] == "" || updatedData[constants.EnvKeySmtpPort] == "" || updatedData[constants.EnvKeySmtpUsername] == "" || updatedData[constants.EnvKeySmtpPassword] == "" {
|
||||
if !updatedData[constants.EnvKeyDisableEmailVerification].(bool) {
|
||||
updatedData[constants.EnvKeyDisableEmailVerification] = true
|
||||
}
|
||||
|
||||
if !updatedData["DISABLE_MAGIC_LINK_LOGIN"].(bool) {
|
||||
updatedData["DISABLE_MAGIC_LINK_LOGIN"] = true
|
||||
if !updatedData[constants.EnvKeyDisableMagicLinkLogin].(bool) {
|
||||
updatedData[constants.EnvKeyDisableMagicLinkLogin] = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +77,9 @@ func UpdateConfigResolver(ctx context.Context, params model.UpdateConfigInput) (
|
|||
return res, err
|
||||
}
|
||||
|
||||
encryptedConfig, err := utils.EncryptConfig(updatedData)
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvStore(updatedData)
|
||||
|
||||
encryptedConfig, err := utils.EncryptEnvData(updatedData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@ -84,7 +91,7 @@ func UpdateConfigResolver(ctx context.Context, params model.UpdateConfigInput) (
|
|||
|
||||
// in case of admin secret change update the cookie with new hash
|
||||
if params.AdminSecret != nil {
|
||||
hashedKey, err := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
hashedKey, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
|
|
@ -7,15 +7,17 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/email"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) {
|
||||
// UpdateProfileResolver is resolver for update profile mutation
|
||||
func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
if err != nil {
|
||||
|
@ -33,7 +35,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
|
|||
}
|
||||
|
||||
id := fmt.Sprintf("%v", claim["id"])
|
||||
sessionToken := session.GetToken(id, token)
|
||||
sessionToken := session.GetUserSession(id, token)
|
||||
|
||||
if sessionToken == "" {
|
||||
return res, fmt.Errorf(`unauthorized`)
|
||||
|
@ -44,8 +46,8 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
|
|||
return res, fmt.Errorf("please enter atleast one param to update")
|
||||
}
|
||||
|
||||
email := fmt.Sprintf("%v", claim["email"])
|
||||
user, err := db.Mgr.GetUserByEmail(email)
|
||||
userEmail := fmt.Sprintf("%v", claim["email"])
|
||||
user, err := db.Mgr.GetUserByEmail(userEmail)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@ -99,7 +101,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
|
|||
return res, fmt.Errorf(`password and confirm password does not match`)
|
||||
}
|
||||
|
||||
password, _ := utils.HashPassword(*params.NewPassword)
|
||||
password, _ := utils.EncryptPassword(*params.NewPassword)
|
||||
|
||||
user.Password = &password
|
||||
}
|
||||
|
@ -120,14 +122,14 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
|
|||
return res, fmt.Errorf("user with this email address already exists")
|
||||
}
|
||||
|
||||
session.DeleteUserSession(fmt.Sprintf("%v", user.ID))
|
||||
session.DeleteAllUserSession(fmt.Sprintf("%v", user.ID))
|
||||
utils.DeleteCookie(gc)
|
||||
|
||||
user.Email = newEmail
|
||||
user.EmailVerifiedAt = nil
|
||||
hasEmailChanged = true
|
||||
// insert verification request
|
||||
verificationType := enum.UpdateEmail.String()
|
||||
verificationType := constants.VerificationTypeUpdateEmail
|
||||
token, err := utils.CreateVerificationToken(newEmail, verificationType)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
|
@ -141,7 +143,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendVerificationMail(newEmail, token)
|
||||
email.SendVerificationMail(newEmail, token)
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
@ -9,13 +9,16 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/email"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User, error) {
|
||||
// UpdateUserResolver is a resolver for update user mutation
|
||||
// This is admin only mutation
|
||||
func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*model.User, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.User
|
||||
if err != nil {
|
||||
|
@ -67,6 +70,15 @@ func UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User,
|
|||
user.Picture = params.Picture
|
||||
}
|
||||
|
||||
if params.EmailVerified != nil {
|
||||
if *params.EmailVerified {
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
} else {
|
||||
user.EmailVerifiedAt = nil
|
||||
}
|
||||
}
|
||||
|
||||
if params.Email != nil && user.Email != *params.Email {
|
||||
// check if valid email
|
||||
if !utils.IsValidEmail(*params.Email) {
|
||||
|
@ -80,13 +92,13 @@ func UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User,
|
|||
return res, fmt.Errorf("user with this email address already exists")
|
||||
}
|
||||
|
||||
session.DeleteUserSession(fmt.Sprintf("%v", user.ID))
|
||||
session.DeleteAllUserSession(fmt.Sprintf("%v", user.ID))
|
||||
utils.DeleteCookie(gc)
|
||||
|
||||
user.Email = newEmail
|
||||
user.EmailVerifiedAt = nil
|
||||
// insert verification request
|
||||
verificationType := enum.UpdateEmail.String()
|
||||
verificationType := constants.VerificationTypeUpdateEmail
|
||||
token, err := utils.CreateVerificationToken(newEmail, verificationType)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
|
@ -100,7 +112,7 @@ func UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User,
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendVerificationMail(newEmail, token)
|
||||
email.SendVerificationMail(newEmail, token)
|
||||
}()
|
||||
}
|
||||
|
||||
|
@ -112,7 +124,7 @@ func UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User,
|
|||
inputRoles = append(inputRoles, *item)
|
||||
}
|
||||
|
||||
if !utils.IsValidRoles(append([]string{}, append(constants.EnvData.ROLES, constants.EnvData.PROTECTED_ROLES...)...), inputRoles) {
|
||||
if !utils.IsValidRoles(append([]string{}, append(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyRoles).([]string), envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyProtectedRoles).([]string)...)...), inputRoles) {
|
||||
return res, fmt.Errorf("invalid list of roles")
|
||||
}
|
||||
|
||||
|
@ -120,7 +132,7 @@ func UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User,
|
|||
rolesToSave = strings.Join(inputRoles, ",")
|
||||
}
|
||||
|
||||
session.DeleteUserSession(fmt.Sprintf("%v", user.ID))
|
||||
session.DeleteAllUserSession(fmt.Sprintf("%v", user.ID))
|
||||
utils.DeleteCookie(gc)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func Users(ctx context.Context) ([]*model.User, error) {
|
||||
// UsersResolver is a resolver for users query
|
||||
// This is admin only query
|
||||
func UsersResolver(ctx context.Context) ([]*model.User, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res []*model.User
|
||||
if err != nil {
|
||||
|
|
|
@ -9,7 +9,9 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error) {
|
||||
// VerificationRequestsResolver is a resolver for verification requests query
|
||||
// This is admin only query
|
||||
func VerificationRequestsResolver(ctx context.Context) ([]*model.VerificationRequest, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res []*model.VerificationRequest
|
||||
if err != nil {
|
||||
|
|
|
@ -6,14 +6,15 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
||||
func VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.AuthResponse, error) {
|
||||
// VerifyEmailResolver is a resolver for verify email mutation
|
||||
func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*model.AuthResponse, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.AuthResponse
|
||||
if err != nil {
|
||||
|
@ -44,12 +45,11 @@ func VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.Aut
|
|||
db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||
|
||||
roles := strings.Split(user.Roles, ",")
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, constants.TokenTypeRefreshToken, roles)
|
||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, constants.TokenTypeAccessToken, roles)
|
||||
|
||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||
|
||||
session.SetToken(user.ID, accessToken, refreshToken)
|
||||
utils.CreateSession(user.ID, gc)
|
||||
session.SetUserSession(user.ID, accessToken, refreshToken)
|
||||
utils.SaveSessionInDB(user.ID, gc)
|
||||
|
||||
res = &model.AuthResponse{
|
||||
Message: `Email verified successfully.`,
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"github.com/authorizerdev/authorizer/server/handlers"
|
||||
"github.com/authorizerdev/authorizer/server/middlewares"
|
||||
"github.com/gin-contrib/location"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitRouter() *gin.Engine {
|
||||
router := gin.Default()
|
||||
router.Use(location.Default())
|
||||
router.Use(middlewares.GinContextToContextMiddleware())
|
||||
router.Use(middlewares.CORSMiddleware())
|
||||
|
||||
router.GET("/", handlers.PlaygroundHandler())
|
||||
router.POST("/graphql", handlers.GraphqlHandler())
|
||||
router.GET("/verify_email", handlers.VerifyEmailHandler())
|
||||
router.GET("/oauth_login/:oauth_provider", handlers.OAuthLoginHandler())
|
||||
router.GET("/oauth_callback/:oauth_provider", handlers.OAuthCallbackHandler())
|
||||
|
||||
return router
|
||||
}
|
44
server/routes/routes.go
Normal file
44
server/routes/routes.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/handlers"
|
||||
"github.com/authorizerdev/authorizer/server/middlewares"
|
||||
"github.com/gin-contrib/location"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// InitRouter initializes gin router
|
||||
func InitRouter() *gin.Engine {
|
||||
router := gin.Default()
|
||||
router.Use(location.Default())
|
||||
router.Use(middlewares.GinContextToContextMiddleware())
|
||||
router.Use(middlewares.CORSMiddleware())
|
||||
|
||||
router.GET("/", handlers.RootHandler())
|
||||
router.POST("/graphql", handlers.GraphqlHandler())
|
||||
router.GET("/playground", handlers.PlaygroundHandler())
|
||||
router.GET("/oauth_login/:oauth_provider", handlers.OAuthLoginHandler())
|
||||
router.GET("/oauth_callback/:oauth_provider", handlers.OAuthCallbackHandler())
|
||||
router.GET("/verify_email", handlers.VerifyEmailHandler())
|
||||
|
||||
router.LoadHTMLGlob("templates/*")
|
||||
// login page app related routes.
|
||||
if !envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyDisableLoginPage).(bool) {
|
||||
app := router.Group("/app")
|
||||
{
|
||||
app.Static("/build", "app/build")
|
||||
app.GET("/", handlers.AppHandler())
|
||||
app.GET("/reset-password", handlers.AppHandler())
|
||||
}
|
||||
}
|
||||
|
||||
// dashboard related routes
|
||||
app := router.Group("/dashboard")
|
||||
{
|
||||
app.Static("/build", "dashboard/build")
|
||||
app.GET("/", handlers.DashboardHandler())
|
||||
}
|
||||
return router
|
||||
}
|
|
@ -4,14 +4,17 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
// InMemoryStore is a simple in-memory store for sessions.
|
||||
type InMemoryStore struct {
|
||||
mu sync.Mutex
|
||||
mutex sync.Mutex
|
||||
store map[string]map[string]string
|
||||
socialLoginState map[string]string
|
||||
}
|
||||
|
||||
func (c *InMemoryStore) AddToken(userId, accessToken, refreshToken string) {
|
||||
c.mu.Lock()
|
||||
// AddUserSession adds a user session to the in-memory store.
|
||||
func (c *InMemoryStore) AddUserSession(userId, accessToken, refreshToken string) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
// delete sessions > 500 // not recommended for production
|
||||
if len(c.store) >= 500 {
|
||||
c.store = map[string]map[string]string{}
|
||||
|
@ -28,48 +31,57 @@ func (c *InMemoryStore) AddToken(userId, accessToken, refreshToken string) {
|
|||
}
|
||||
c.store[userId] = tempMap
|
||||
}
|
||||
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *InMemoryStore) DeleteUserSession(userId string) {
|
||||
c.mu.Lock()
|
||||
// DeleteAllUserSession deletes all the user sessions from in-memory store.
|
||||
func (c *InMemoryStore) DeleteAllUserSession(userId string) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
delete(c.store, userId)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *InMemoryStore) DeleteVerificationRequest(userId, accessToken string) {
|
||||
c.mu.Lock()
|
||||
// DeleteUserSession deletes the particular user session from in-memory store.
|
||||
func (c *InMemoryStore) DeleteUserSession(userId, accessToken string) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
delete(c.store[userId], accessToken)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// ClearStore clears the in-memory store.
|
||||
func (c *InMemoryStore) ClearStore() {
|
||||
c.mu.Lock()
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
c.store = map[string]map[string]string{}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *InMemoryStore) GetToken(userId, accessToken string) string {
|
||||
// GetUserSession returns the user session token from the in-memory store.
|
||||
func (c *InMemoryStore) GetUserSession(userId, accessToken string) string {
|
||||
// c.mutex.Lock()
|
||||
// defer c.mutex.Unlock()
|
||||
|
||||
token := ""
|
||||
c.mu.Lock()
|
||||
if sessionMap, ok := c.store[userId]; ok {
|
||||
if val, ok := sessionMap[accessToken]; ok {
|
||||
token = val
|
||||
}
|
||||
}
|
||||
c.mu.Unlock()
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
// SetSocialLoginState sets the social login state in the in-memory store.
|
||||
func (c *InMemoryStore) SetSocialLoginState(key, state string) {
|
||||
c.mu.Lock()
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
c.socialLoginState[key] = state
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// GetSocialLoginState gets the social login state from the in-memory store.
|
||||
func (c *InMemoryStore) GetSocialLoginState(key string) string {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
state := ""
|
||||
if stateVal, ok := c.socialLoginState[key]; ok {
|
||||
state = stateVal
|
||||
|
@ -78,8 +90,10 @@ func (c *InMemoryStore) GetSocialLoginState(key string) string {
|
|||
return state
|
||||
}
|
||||
|
||||
// RemoveSocialLoginState removes the social login state from the in-memory store.
|
||||
func (c *InMemoryStore) RemoveSocialLoginState(key string) {
|
||||
c.mu.Lock()
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
delete(c.socialLoginState, key)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ type RedisStore struct {
|
|||
store *redis.Client
|
||||
}
|
||||
|
||||
func (c *RedisStore) AddToken(userId, accessToken, refreshToken string) {
|
||||
// AddUserSession adds the user session to redis
|
||||
func (c *RedisStore) AddUserSession(userId, accessToken, refreshToken string) {
|
||||
err := c.store.HMSet(c.ctx, "authorizer_"+userId, map[string]string{
|
||||
accessToken: refreshToken,
|
||||
}).Err()
|
||||
|
@ -22,20 +23,23 @@ func (c *RedisStore) AddToken(userId, accessToken, refreshToken string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *RedisStore) DeleteUserSession(userId string) {
|
||||
// DeleteAllUserSession deletes all the user session from redis
|
||||
func (c *RedisStore) DeleteAllUserSession(userId string) {
|
||||
err := c.store.Del(c.ctx, "authorizer_"+userId).Err()
|
||||
if err != nil {
|
||||
log.Fatalln("Error deleting redis token:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RedisStore) DeleteVerificationRequest(userId, accessToken string) {
|
||||
// DeleteUserSession deletes the particular user session from redis
|
||||
func (c *RedisStore) DeleteUserSession(userId, accessToken string) {
|
||||
err := c.store.HDel(c.ctx, "authorizer_"+userId, accessToken).Err()
|
||||
if err != nil {
|
||||
log.Fatalln("Error deleting redis token:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ClearStore clears the redis store for authorizer related tokens
|
||||
func (c *RedisStore) ClearStore() {
|
||||
err := c.store.Del(c.ctx, "authorizer_*").Err()
|
||||
if err != nil {
|
||||
|
@ -43,7 +47,8 @@ func (c *RedisStore) ClearStore() {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *RedisStore) GetToken(userId, accessToken string) string {
|
||||
// GetUserSession returns the user session token from the redis store.
|
||||
func (c *RedisStore) GetUserSession(userId, accessToken string) string {
|
||||
token := ""
|
||||
res, err := c.store.HMGet(c.ctx, "authorizer_"+userId, accessToken).Result()
|
||||
if err != nil {
|
||||
|
@ -55,6 +60,7 @@ func (c *RedisStore) GetToken(userId, accessToken string) string {
|
|||
return token
|
||||
}
|
||||
|
||||
// SetSocialLoginState sets the social login state in redis store.
|
||||
func (c *RedisStore) SetSocialLoginState(key, state string) {
|
||||
err := c.store.Set(c.ctx, key, state, 0).Err()
|
||||
if err != nil {
|
||||
|
@ -62,6 +68,7 @@ func (c *RedisStore) SetSocialLoginState(key, state string) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetSocialLoginState gets the social login state from redis store.
|
||||
func (c *RedisStore) GetSocialLoginState(key string) string {
|
||||
state := ""
|
||||
state, err := c.store.Get(c.ctx, key).Result()
|
||||
|
@ -72,6 +79,7 @@ func (c *RedisStore) GetSocialLoginState(key string) string {
|
|||
return state
|
||||
}
|
||||
|
||||
// RemoveSocialLoginState removes the social login state from redis store.
|
||||
func (c *RedisStore) RemoveSocialLoginState(key string) {
|
||||
err := c.store.Del(c.ctx, key).Err()
|
||||
if err != nil {
|
||||
|
|
|
@ -5,57 +5,65 @@ import (
|
|||
"log"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
|
||||
// SessionStore is a struct that defines available session stores
|
||||
// If redis store is available, higher preference is given to that store.
|
||||
// Else in memory store is used.
|
||||
type SessionStore struct {
|
||||
InMemoryStoreObj *InMemoryStore
|
||||
RedisMemoryStoreObj *RedisStore
|
||||
}
|
||||
|
||||
// SessionStoreObj is a global variable that holds the
|
||||
// reference to various session store instances
|
||||
var SessionStoreObj SessionStore
|
||||
|
||||
func SetToken(userId, accessToken, refreshToken string) {
|
||||
// TODO: Set session information in db for all the sessions that gets generated
|
||||
// it should async go function
|
||||
|
||||
// SetUserSession sets the user session in the session store
|
||||
func SetUserSession(userId, accessToken, refreshToken string) {
|
||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||
SessionStoreObj.RedisMemoryStoreObj.AddToken(userId, accessToken, refreshToken)
|
||||
SessionStoreObj.RedisMemoryStoreObj.AddUserSession(userId, accessToken, refreshToken)
|
||||
}
|
||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
||||
SessionStoreObj.InMemoryStoreObj.AddToken(userId, accessToken, refreshToken)
|
||||
SessionStoreObj.InMemoryStoreObj.AddUserSession(userId, accessToken, refreshToken)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteVerificationRequest(userId, accessToken string) {
|
||||
// DeleteUserSession deletes the particular user session from the session store
|
||||
func DeleteUserSession(userId, accessToken string) {
|
||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||
SessionStoreObj.RedisMemoryStoreObj.DeleteVerificationRequest(userId, accessToken)
|
||||
SessionStoreObj.RedisMemoryStoreObj.DeleteUserSession(userId, accessToken)
|
||||
}
|
||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
||||
SessionStoreObj.InMemoryStoreObj.DeleteVerificationRequest(userId, accessToken)
|
||||
SessionStoreObj.InMemoryStoreObj.DeleteUserSession(userId, accessToken)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteUserSession(userId string) {
|
||||
// DeleteAllSessions deletes all the sessions from the session store
|
||||
func DeleteAllUserSession(userId string) {
|
||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||
SessionStoreObj.RedisMemoryStoreObj.DeleteUserSession(userId)
|
||||
SessionStoreObj.RedisMemoryStoreObj.DeleteAllUserSession(userId)
|
||||
}
|
||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
||||
SessionStoreObj.InMemoryStoreObj.DeleteUserSession(userId)
|
||||
SessionStoreObj.InMemoryStoreObj.DeleteAllUserSession(userId)
|
||||
}
|
||||
}
|
||||
|
||||
func GetToken(userId, accessToken string) string {
|
||||
// GetUserSession returns the user session from the session store
|
||||
func GetUserSession(userId, accessToken string) string {
|
||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||
return SessionStoreObj.RedisMemoryStoreObj.GetToken(userId, accessToken)
|
||||
return SessionStoreObj.RedisMemoryStoreObj.GetUserSession(userId, accessToken)
|
||||
}
|
||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
||||
return SessionStoreObj.InMemoryStoreObj.GetToken(userId, accessToken)
|
||||
return SessionStoreObj.InMemoryStoreObj.GetUserSession(userId, accessToken)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// ClearStore clears the session store for authorizer tokens
|
||||
func ClearStore() {
|
||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||
SessionStoreObj.RedisMemoryStoreObj.ClearStore()
|
||||
|
@ -65,6 +73,7 @@ func ClearStore() {
|
|||
}
|
||||
}
|
||||
|
||||
// SetSocialLoginState sets the social login state in the session store
|
||||
func SetSocailLoginState(key, state string) {
|
||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||
SessionStoreObj.RedisMemoryStoreObj.SetSocialLoginState(key, state)
|
||||
|
@ -74,6 +83,7 @@ func SetSocailLoginState(key, state string) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetSocialLoginState returns the social login state from the session store
|
||||
func GetSocailLoginState(key string) string {
|
||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||
return SessionStoreObj.RedisMemoryStoreObj.GetSocialLoginState(key)
|
||||
|
@ -85,6 +95,7 @@ func GetSocailLoginState(key string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// RemoveSocialLoginState removes the social login state from the session store
|
||||
func RemoveSocialLoginState(key string) {
|
||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||
SessionStoreObj.RedisMemoryStoreObj.RemoveSocialLoginState(key)
|
||||
|
@ -94,10 +105,11 @@ func RemoveSocialLoginState(key string) {
|
|||
}
|
||||
}
|
||||
|
||||
// InitializeSessionStore initializes the SessionStoreObj based on environment variables
|
||||
func InitSession() {
|
||||
if constants.EnvData.REDIS_URL != "" {
|
||||
if envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyRedisURL).(string) != "" {
|
||||
log.Println("using redis store to save sessions")
|
||||
opt, err := redis.ParseURL(constants.EnvData.REDIS_URL)
|
||||
opt, err := redis.ParseURL(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyRedisURL).(string))
|
||||
if err != nil {
|
||||
log.Fatalln("Error parsing redis url:", err)
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func adminLoginTests(s TestSetup, t *testing.T) {
|
||||
func adminLoginTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should complete admin login`, func(t *testing.T) {
|
||||
_, ctx := createContext(s)
|
||||
_, err := resolvers.AdminLoginResolver(ctx, model.AdminLoginInput{
|
||||
|
@ -19,7 +21,7 @@ func adminLoginTests(s TestSetup, t *testing.T) {
|
|||
assert.NotNil(t, err)
|
||||
|
||||
_, err = resolvers.AdminLoginResolver(ctx, model.AdminLoginInput{
|
||||
AdminSecret: constants.EnvData.ADMIN_SECRET,
|
||||
AdminSecret: envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string),
|
||||
})
|
||||
|
||||
assert.Nil(t, err)
|
28
server/test/admin_logout_test.go
Normal file
28
server/test/admin_logout_test.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func adminLogoutTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should get admin session`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
_, err := resolvers.AdminLogoutResolver(ctx)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminCookieName).(string), h))
|
||||
_, err = resolvers.AdminLogoutResolver(ctx)
|
||||
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
}
|
30
server/test/admin_session_test.go
Normal file
30
server/test/admin_session_test.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func adminSessionTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should get admin session`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
_, err := resolvers.AdminSessionResolver(ctx)
|
||||
log.Println("error:", err)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminCookieName).(string), h))
|
||||
_, err = resolvers.AdminSessionResolver(ctx)
|
||||
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
}
|
|
@ -1,26 +1,27 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func adminSignupTests(s TestSetup, t *testing.T) {
|
||||
func adminSignupTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should complete admin login`, func(t *testing.T) {
|
||||
_, ctx := createContext(s)
|
||||
_, err := resolvers.AdminSignupResolver(ctx, model.AdminSignupInput{
|
||||
AdminSecret: "admin",
|
||||
})
|
||||
log.Println("err", err)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
// reset env for test to pass
|
||||
constants.EnvData.ADMIN_SECRET = ""
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyAdminSecret, "")
|
||||
|
||||
_, err = resolvers.AdminSignupResolver(ctx, model.AdminSignupInput{
|
||||
AdminSecret: uuid.New().String(),
|
|
@ -6,24 +6,26 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func configTests(s TestSetup, t *testing.T) {
|
||||
func configTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should get config`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
_, err := resolvers.ConfigResolver(ctx)
|
||||
log.Println("error:", err)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
h, err := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.ADMIN_COOKIE_NAME, h))
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminCookieName).(string), h))
|
||||
res, err := resolvers.ConfigResolver(ctx)
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, *res.AdminSecret, constants.EnvData.ADMIN_SECRET)
|
||||
assert.Equal(t, *res.AdminSecret, envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
})
|
||||
}
|
|
@ -5,32 +5,34 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func deleteUserTest(s TestSetup, t *testing.T) {
|
||||
func deleteUserTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should delete users with admin secret only`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
email := "delete_user." + s.TestInfo.Email
|
||||
resolvers.Signup(ctx, model.SignUpInput{
|
||||
resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
_, err := resolvers.DeleteUser(ctx, model.DeleteUserInput{
|
||||
_, err := resolvers.DeleteUserResolver(ctx, model.DeleteUserInput{
|
||||
Email: email,
|
||||
})
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
h, err := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.ADMIN_COOKIE_NAME, h))
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminCookieName).(string), h))
|
||||
|
||||
_, err = resolvers.DeleteUser(ctx, model.DeleteUserInput{
|
||||
_, err = resolvers.DeleteUserResolver(ctx, model.DeleteUserInput{
|
||||
Email: email,
|
||||
})
|
||||
assert.Nil(t, err)
|
29
server/test/env_test.go
Normal file
29
server/test/env_test.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/env"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEnvs(t *testing.T) {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyEnvPath, "../../.env.sample")
|
||||
env.InitEnv()
|
||||
store := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
||||
|
||||
assert.Equal(t, store[constants.EnvKeyAdminSecret].(string), "admin")
|
||||
assert.Equal(t, store[constants.EnvKeyEnv].(string), "production")
|
||||
assert.False(t, store[constants.EnvKeyDisableEmailVerification].(bool))
|
||||
assert.False(t, store[constants.EnvKeyDisableMagicLinkLogin].(bool))
|
||||
assert.False(t, store[constants.EnvKeyDisableBasicAuthentication].(bool))
|
||||
assert.Equal(t, store[constants.EnvKeyJwtType].(string), "HS256")
|
||||
assert.Equal(t, store[constants.EnvKeyJwtSecret].(string), "random_string")
|
||||
assert.Equal(t, store[constants.EnvKeyJwtRoleClaim].(string), "role")
|
||||
assert.EqualValues(t, store[constants.EnvKeyRoles].([]string), []string{"user"})
|
||||
assert.EqualValues(t, store[constants.EnvKeyDefaultRoles].([]string), []string{"user"})
|
||||
assert.EqualValues(t, store[constants.EnvKeyProtectedRoles].([]string), []string{"admin"})
|
||||
assert.EqualValues(t, store[constants.EnvKeyAllowedOrigins].([]string), []string{"*"})
|
||||
}
|
|
@ -3,32 +3,33 @@ package test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func forgotPasswordTest(s TestSetup, t *testing.T) {
|
||||
func forgotPasswordTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should run forgot password`, func(t *testing.T) {
|
||||
_, ctx := createContext(s)
|
||||
email := "forgot_password." + s.TestInfo.Email
|
||||
_, err := resolvers.Signup(ctx, model.SignUpInput{
|
||||
_, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
_, err = resolvers.ForgotPassword(ctx, model.ForgotPasswordInput{
|
||||
_, err = resolvers.ForgotPasswordResolver(ctx, model.ForgotPasswordInput{
|
||||
Email: email,
|
||||
})
|
||||
assert.Nil(t, err, "no errors for forgot password")
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.ForgotPassword.String())
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeForgotPassword)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, verificationRequest.Identifier, enum.ForgotPassword.String())
|
||||
assert.Equal(t, verificationRequest.Identifier, constants.VerificationTypeForgotPassword)
|
||||
|
||||
cleanData(email)
|
||||
})
|
|
@ -3,49 +3,50 @@ package test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func loginTests(s TestSetup, t *testing.T) {
|
||||
func loginTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should login`, func(t *testing.T) {
|
||||
_, ctx := createContext(s)
|
||||
email := "login." + s.TestInfo.Email
|
||||
_, err := resolvers.Signup(ctx, model.SignUpInput{
|
||||
_, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
_, err = resolvers.Login(ctx, model.LoginInput{
|
||||
_, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
assert.NotNil(t, err, "should fail because email is not verified")
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||
resolvers.VerifyEmail(ctx, model.VerifyEmailInput{
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
||||
_, err = resolvers.Login(ctx, model.LoginInput{
|
||||
_, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
Roles: []string{"test"},
|
||||
})
|
||||
assert.NotNil(t, err, "invalid roles")
|
||||
|
||||
_, err = resolvers.Login(ctx, model.LoginInput{
|
||||
_, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password + "s",
|
||||
})
|
||||
assert.NotNil(t, err, "invalid password")
|
||||
|
||||
loginRes, err := resolvers.Login(ctx, model.LoginInput{
|
||||
loginRes, err := resolvers.LoginResolver(ctx, model.LoginInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
})
|
|
@ -6,31 +6,32 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func logoutTests(s TestSetup, t *testing.T) {
|
||||
func logoutTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should logout user`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
email := "logout." + s.TestInfo.Email
|
||||
|
||||
_, err := resolvers.MagicLinkLogin(ctx, model.MagicLinkLoginInput{
|
||||
_, err := resolvers.MagicLinkLoginResolver(ctx, model.MagicLinkLoginInput{
|
||||
Email: email,
|
||||
})
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.MagicLinkLogin.String())
|
||||
verifyRes, err := resolvers.VerifyEmail(ctx, model.VerifyEmailInput{
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeMagicLinkLogin)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
||||
token := *verifyRes.AccessToken
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.COOKIE_NAME, token))
|
||||
_, err = resolvers.Logout(ctx)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyCookieName).(string), token))
|
||||
_, err = resolvers.LogoutResolver(ctx)
|
||||
assert.Nil(t, err)
|
||||
_, err = resolvers.Profile(ctx)
|
||||
_, err = resolvers.ProfileResolver(ctx)
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
cleanData(email)
|
||||
})
|
|
@ -6,30 +6,31 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func magicLinkLoginTests(s TestSetup, t *testing.T) {
|
||||
func magicLinkLoginTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should login with magic link`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
email := "magic_link_login." + s.TestInfo.Email
|
||||
|
||||
_, err := resolvers.MagicLinkLogin(ctx, model.MagicLinkLoginInput{
|
||||
_, err := resolvers.MagicLinkLoginResolver(ctx, model.MagicLinkLoginInput{
|
||||
Email: email,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.MagicLinkLogin.String())
|
||||
verifyRes, err := resolvers.VerifyEmail(ctx, model.VerifyEmailInput{
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeMagicLinkLogin)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
||||
token := *verifyRes.AccessToken
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.COOKIE_NAME, token))
|
||||
_, err = resolvers.Profile(ctx)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyCookieName).(string), token))
|
||||
_, err = resolvers.ProfileResolver(ctx)
|
||||
assert.Nil(t, err)
|
||||
|
||||
cleanData(email)
|
|
@ -2,18 +2,17 @@ package test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func metaTests(s TestSetup, t *testing.T) {
|
||||
func metaTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should get meta information`, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
meta, err := resolvers.Meta(ctx)
|
||||
log.Println("=> meta:", meta)
|
||||
meta, err := resolvers.MetaResolver(ctx)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, meta.IsFacebookLoginEnabled)
|
||||
assert.False(t, meta.IsGoogleLoginEnabled)
|
|
@ -6,34 +6,35 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func profileTests(s TestSetup, t *testing.T) {
|
||||
func profileTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should get profile only with token`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
email := "profile." + s.TestInfo.Email
|
||||
|
||||
resolvers.Signup(ctx, model.SignUpInput{
|
||||
resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
_, err := resolvers.Profile(ctx)
|
||||
_, err := resolvers.ProfileResolver(ctx)
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||
verifyRes, err := resolvers.VerifyEmail(ctx, model.VerifyEmailInput{
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
||||
token := *verifyRes.AccessToken
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.COOKIE_NAME, token))
|
||||
profileRes, err := resolvers.Profile(ctx)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyCookieName).(string), token))
|
||||
profileRes, err := resolvers.ProfileResolver(ctx)
|
||||
assert.Nil(t, err)
|
||||
|
||||
newEmail := *&profileRes.Email
|
|
@ -3,25 +3,26 @@ package test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func resendVerifyEmailTests(s TestSetup, t *testing.T) {
|
||||
func resendVerifyEmailTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should resend verification email`, func(t *testing.T) {
|
||||
_, ctx := createContext(s)
|
||||
email := "resend_verify_email." + s.TestInfo.Email
|
||||
_, err := resolvers.Signup(ctx, model.SignUpInput{
|
||||
_, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
_, err = resolvers.ResendVerifyEmail(ctx, model.ResendVerifyEmailInput{
|
||||
_, err = resolvers.ResendVerifyEmailResolver(ctx, model.ResendVerifyEmailInput{
|
||||
Email: email,
|
||||
Identifier: enum.BasicAuthSignup.String(),
|
||||
Identifier: constants.VerificationTypeBasicAuthSignup,
|
||||
})
|
||||
|
||||
assert.Nil(t, err)
|
|
@ -3,32 +3,33 @@ package test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func resetPasswordTest(s TestSetup, t *testing.T) {
|
||||
func resetPasswordTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should reset password`, func(t *testing.T) {
|
||||
email := "reset_password." + s.TestInfo.Email
|
||||
_, ctx := createContext(s)
|
||||
_, err := resolvers.Signup(ctx, model.SignUpInput{
|
||||
_, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
_, err = resolvers.ForgotPassword(ctx, model.ForgotPasswordInput{
|
||||
_, err = resolvers.ForgotPasswordResolver(ctx, model.ForgotPasswordInput{
|
||||
Email: email,
|
||||
})
|
||||
assert.Nil(t, err, "no errors for forgot password")
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.ForgotPassword.String())
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeForgotPassword)
|
||||
assert.Nil(t, err, "should get forgot password request")
|
||||
|
||||
_, err = resolvers.ResetPassword(ctx, model.ResetPasswordInput{
|
||||
_, err = resolvers.ResetPasswordResolver(ctx, model.ResetPasswordInput{
|
||||
Token: verificationRequest.Token,
|
||||
Password: "test1",
|
||||
ConfirmPassword: "test",
|
||||
|
@ -36,7 +37,7 @@ func resetPasswordTest(s TestSetup, t *testing.T) {
|
|||
|
||||
assert.NotNil(t, err, "passowrds don't match")
|
||||
|
||||
_, err = resolvers.ResetPassword(ctx, model.ResetPasswordInput{
|
||||
_, err = resolvers.ResetPasswordResolver(ctx, model.ResetPasswordInput{
|
||||
Token: verificationRequest.Token,
|
||||
Password: "test1",
|
||||
ConfirmPassword: "test1",
|
65
server/test/resolvers_test.go
Normal file
65
server/test/resolvers_test.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/env"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
)
|
||||
|
||||
func TestResolvers(t *testing.T) {
|
||||
databases := map[string]string{
|
||||
constants.DbTypeSqlite: "../../data.db",
|
||||
// constants.DbTypeArangodb: "http://localhost:8529",
|
||||
// constants.DbTypeMongodb: "mongodb://localhost:27017",
|
||||
}
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyVersion, "test")
|
||||
for dbType, dbURL := range databases {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyDatabaseURL, dbURL)
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyDatabaseType, dbType)
|
||||
|
||||
env.InitEnv()
|
||||
db.InitDB()
|
||||
|
||||
// clean the persisted config for test to use fresh config
|
||||
config, err := db.Mgr.GetConfig()
|
||||
if err == nil {
|
||||
config.Config = []byte{}
|
||||
db.Mgr.UpdateConfig(config)
|
||||
}
|
||||
env.PersistEnv()
|
||||
|
||||
s := testSetup()
|
||||
defer s.Server.Close()
|
||||
|
||||
t.Run("should pass tests for "+dbType, func(t *testing.T) {
|
||||
// admin tests
|
||||
adminSignupTests(t, s)
|
||||
verificationRequestsTest(t, s)
|
||||
usersTest(t, s)
|
||||
deleteUserTest(t, s)
|
||||
updateUserTest(t, s)
|
||||
adminLoginTests(t, s)
|
||||
adminLogoutTests(t, s)
|
||||
adminSessionTests(t, s)
|
||||
updateConfigTests(t, s)
|
||||
configTests(t, s)
|
||||
|
||||
// user tests
|
||||
loginTests(t, s)
|
||||
signupTests(t, s)
|
||||
forgotPasswordTest(t, s)
|
||||
resendVerifyEmailTests(t, s)
|
||||
resetPasswordTest(t, s)
|
||||
verifyEmailTest(t, s)
|
||||
sessionTests(t, s)
|
||||
profileTests(t, s)
|
||||
updateProfileTests(t, s)
|
||||
magicLinkLoginTests(t, s)
|
||||
logoutTests(t, s)
|
||||
metaTests(t, s)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -6,35 +6,36 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func sessionTests(s TestSetup, t *testing.T) {
|
||||
func sessionTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should allow access to profile with session only`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
email := "session." + s.TestInfo.Email
|
||||
|
||||
resolvers.Signup(ctx, model.SignUpInput{
|
||||
resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
_, err := resolvers.Session(ctx, []string{})
|
||||
_, err := resolvers.SessionResolver(ctx, []string{})
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||
verifyRes, err := resolvers.VerifyEmail(ctx, model.VerifyEmailInput{
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
||||
token := *verifyRes.AccessToken
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.COOKIE_NAME, token))
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyCookieName).(string), token))
|
||||
|
||||
sessionRes, err := resolvers.Session(ctx, []string{})
|
||||
sessionRes, err := resolvers.SessionResolver(ctx, []string{})
|
||||
assert.Nil(t, err)
|
||||
|
||||
newToken := *sessionRes.AccessToken
|
|
@ -3,25 +3,26 @@ package test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func signupTests(s TestSetup, t *testing.T) {
|
||||
func signupTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should complete the signup and check duplicates`, func(t *testing.T) {
|
||||
_, ctx := createContext(s)
|
||||
email := "signup." + s.TestInfo.Email
|
||||
res, err := resolvers.Signup(ctx, model.SignUpInput{
|
||||
res, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password + "s",
|
||||
})
|
||||
assert.NotNil(t, err, "invalid password errors")
|
||||
|
||||
res, err = resolvers.Signup(ctx, model.SignUpInput{
|
||||
res, err = resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
|
@ -31,7 +32,7 @@ func signupTests(s TestSetup, t *testing.T) {
|
|||
assert.Equal(t, email, user.Email)
|
||||
assert.Nil(t, res.AccessToken, "access token should be nil")
|
||||
|
||||
res, err = resolvers.Signup(ctx, model.SignUpInput{
|
||||
res, err = resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
|
@ -39,7 +40,7 @@ func signupTests(s TestSetup, t *testing.T) {
|
|||
|
||||
assert.NotNil(t, err, "should throw duplicate email error")
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, email, verificationRequest.Email)
|
||||
cleanData(email)
|
|
@ -9,8 +9,8 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/env"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/handlers"
|
||||
"github.com/authorizerdev/authorizer/server/middlewares"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
|
@ -32,17 +32,17 @@ type TestSetup struct {
|
|||
}
|
||||
|
||||
func cleanData(email string) {
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
if err == nil {
|
||||
err = db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||
}
|
||||
|
||||
verificationRequest, err = db.Mgr.GetVerificationByEmail(email, enum.ForgotPassword.String())
|
||||
verificationRequest, err = db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeForgotPassword)
|
||||
if err == nil {
|
||||
err = db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||
}
|
||||
|
||||
verificationRequest, err = db.Mgr.GetVerificationByEmail(email, enum.UpdateEmail.String())
|
||||
verificationRequest, err = db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeUpdateEmail)
|
||||
if err == nil {
|
||||
err = db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||
}
|
||||
|
@ -72,8 +72,7 @@ func testSetup() TestSetup {
|
|||
Password: "test",
|
||||
}
|
||||
|
||||
constants.EnvData.ENV_PATH = "../../.env.sample"
|
||||
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.EnvKeyEnvPath, "../../.env.sample")
|
||||
env.InitEnv()
|
||||
session.InitSession()
|
||||
|
|
@ -6,26 +6,27 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func updateConfigTests(s TestSetup, t *testing.T) {
|
||||
func updateConfigTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should update configs`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
originalAppURL := constants.EnvData.APP_URL
|
||||
log.Println("=> originalAppURL:", constants.EnvData.APP_URL)
|
||||
originalAppURL := envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAppURL).(string)
|
||||
|
||||
data := model.UpdateConfigInput{}
|
||||
_, err := resolvers.UpdateConfigResolver(ctx, data)
|
||||
log.Println("error:", err)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
h, _ := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.ADMIN_COOKIE_NAME, h))
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.ADMIN_COOKIE_NAME, h))
|
||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminCookieName).(string), h))
|
||||
newURL := "https://test.com"
|
||||
data = model.UpdateConfigInput{
|
||||
AppURL: &newURL,
|
||||
|
@ -33,8 +34,7 @@ func updateConfigTests(s TestSetup, t *testing.T) {
|
|||
_, err = resolvers.UpdateConfigResolver(ctx, data)
|
||||
log.Println("error:", err)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, constants.EnvData.APP_URL, newURL)
|
||||
assert.NotEqual(t, constants.EnvData.APP_URL, originalAppURL)
|
||||
assert.Equal(t, envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAppURL).(string), newURL)
|
||||
data = model.UpdateConfigInput{
|
||||
AppURL: &originalAppURL,
|
||||
}
|
|
@ -6,47 +6,48 @@ import (
|
|||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func updateProfileTests(s TestSetup, t *testing.T) {
|
||||
func updateProfileTests(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should update the profile with access token only`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
email := "update_profile." + s.TestInfo.Email
|
||||
|
||||
resolvers.Signup(ctx, model.SignUpInput{
|
||||
resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
})
|
||||
|
||||
fName := "samani"
|
||||
_, err := resolvers.UpdateProfile(ctx, model.UpdateProfileInput{
|
||||
_, err := resolvers.UpdateProfileResolver(ctx, model.UpdateProfileInput{
|
||||
FamilyName: &fName,
|
||||
})
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||
verifyRes, err := resolvers.VerifyEmail(ctx, model.VerifyEmailInput{
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
||||
token := *verifyRes.AccessToken
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.COOKIE_NAME, token))
|
||||
_, err = resolvers.UpdateProfile(ctx, model.UpdateProfileInput{
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyCookieName).(string), token))
|
||||
_, err = resolvers.UpdateProfileResolver(ctx, model.UpdateProfileInput{
|
||||
FamilyName: &fName,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
newEmail := "new_" + email
|
||||
_, err = resolvers.UpdateProfile(ctx, model.UpdateProfileInput{
|
||||
_, err = resolvers.UpdateProfileResolver(ctx, model.UpdateProfileInput{
|
||||
Email: &newEmail,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
_, err = resolvers.Profile(ctx)
|
||||
_, err = resolvers.ProfileResolver(ctx)
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
cleanData(newEmail)
|
|
@ -5,17 +5,19 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func updateUserTest(s TestSetup, t *testing.T) {
|
||||
func updateUserTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should update the user with admin secret only`, func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
email := "update_user." + s.TestInfo.Email
|
||||
signupRes, _ := resolvers.Signup(ctx, model.SignUpInput{
|
||||
signupRes, _ := resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password,
|
||||
|
@ -25,16 +27,16 @@ func updateUserTest(s TestSetup, t *testing.T) {
|
|||
adminRole := "admin"
|
||||
userRole := "user"
|
||||
newRoles := []*string{&adminRole, &userRole}
|
||||
_, err := resolvers.UpdateUser(ctx, model.UpdateUserInput{
|
||||
_, err := resolvers.UpdateUserResolver(ctx, model.UpdateUserInput{
|
||||
ID: user.ID,
|
||||
Roles: newRoles,
|
||||
})
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
h, err := utils.HashPassword(constants.EnvData.ADMIN_SECRET)
|
||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminSecret).(string))
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.EnvData.ADMIN_COOKIE_NAME, h))
|
||||
_, err = resolvers.UpdateUser(ctx, model.UpdateUserInput{
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetEnvVariable(constants.EnvKeyAdminCookieName).(string), h))
|
||||
_, err = resolvers.UpdateUserResolver(ctx, model.UpdateUserInput{
|
||||
ID: user.ID,
|
||||
Roles: newRoles,
|
||||
})
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user