fix: bug with authorizer url
BIN
app/favicon_io/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
app/favicon_io/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
app/favicon_io/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
app/favicon_io/favicon-16x16.png
Normal file
After Width: | Height: | Size: 528 B |
BIN
app/favicon_io/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/favicon_io/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
dashboard/favicon_io/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
dashboard/favicon_io/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
dashboard/favicon_io/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
dashboard/favicon_io/favicon-16x16.png
Normal file
After Width: | Height: | Size: 528 B |
BIN
dashboard/favicon_io/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
dashboard/favicon_io/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
|
@ -64,6 +64,7 @@ export const UserDetailsQuery = `
|
|||
birthdate
|
||||
phone_number
|
||||
picture
|
||||
signup_methods
|
||||
roles
|
||||
created_at
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ interface userDataTypes {
|
|||
birthdate: string;
|
||||
phone_number: string;
|
||||
picture: string;
|
||||
signup_methods: string;
|
||||
roles: [string];
|
||||
created_at: number;
|
||||
}
|
||||
|
@ -167,6 +168,8 @@ export default function Users() {
|
|||
<Tr>
|
||||
<Th>Email</Th>
|
||||
<Th>Created At</Th>
|
||||
<Th>Signup Methods</Th>
|
||||
<Th>Roles</Th>
|
||||
<Th>Verified</Th>
|
||||
<Th>Actions</Th>
|
||||
</Tr>
|
||||
|
@ -177,7 +180,11 @@ export default function Users() {
|
|||
return (
|
||||
<Tr key={user.id} style={{ fontSize: 14 }}>
|
||||
<Td>{user.email}</Td>
|
||||
<Td>{dayjs(user.created_at).format('MMM DD, YYYY')}</Td>
|
||||
<Td>
|
||||
{dayjs(user.created_at * 1000).format('MMM DD, YYYY')}
|
||||
</Td>
|
||||
<Td>{user.signup_methods}</Td>
|
||||
<Td>{user.roles.join(', ')}</Td>
|
||||
<Td>
|
||||
<Tag
|
||||
size="sm"
|
||||
|
|
|
@ -51,7 +51,10 @@ export const getObjectDiff = (obj1: any, obj2: any) => {
|
|||
} else if (
|
||||
_.isEqual(obj1[key], obj2[key]) ||
|
||||
(obj1[key] === null && obj2[key] === '') ||
|
||||
(obj1[key] === [] && obj2[key] === null)
|
||||
(obj1[key] &&
|
||||
Array.isArray(obj1[key]) &&
|
||||
obj1[key].length === 0 &&
|
||||
obj2[key] === null)
|
||||
) {
|
||||
const resultKeyIndex = result.indexOf(key);
|
||||
result.splice(resultKeyIndex, 1);
|
||||
|
|
|
@ -16,6 +16,7 @@ const (
|
|||
// EnvKeyVersion key for build arg version
|
||||
EnvKeyVersion = "VERSION"
|
||||
// EnvKeyAuthorizerURL key for env variable AUTHORIZER_URL
|
||||
// TODO: remove support AUTHORIZER_URL env
|
||||
EnvKeyAuthorizerURL = "AUTHORIZER_URL"
|
||||
// EnvKeyPort key for env variable PORT
|
||||
EnvKeyPort = "PORT"
|
||||
|
|
|
@ -13,7 +13,8 @@ import (
|
|||
func SetAdminCookie(gc *gin.Context, token string) {
|
||||
secure := true
|
||||
httpOnly := true
|
||||
host, _ := utils.GetHostParts(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL))
|
||||
hostname := utils.GetHost(gc)
|
||||
host, _ := utils.GetHostParts(hostname)
|
||||
|
||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), token, 3600, "/", host, secure, httpOnly)
|
||||
}
|
||||
|
@ -38,7 +39,8 @@ func GetAdminCookie(gc *gin.Context) (string, error) {
|
|||
func DeleteAdminCookie(gc *gin.Context) {
|
||||
secure := true
|
||||
httpOnly := true
|
||||
host, _ := utils.GetHostParts(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL))
|
||||
hostname := utils.GetHost(gc)
|
||||
host, _ := utils.GetHostParts(hostname)
|
||||
|
||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), "", -1, "/", host, secure, httpOnly)
|
||||
}
|
||||
|
|
|
@ -19,8 +19,9 @@ import (
|
|||
func SetCookie(gc *gin.Context, accessToken, refreshToken, fingerprintHash string) {
|
||||
secure := true
|
||||
httpOnly := true
|
||||
host, _ := utils.GetHostParts(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL))
|
||||
domain := utils.GetDomainName(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL))
|
||||
hostname := utils.GetHost(gc)
|
||||
host, _ := utils.GetHostParts(hostname)
|
||||
domain := utils.GetDomainName(hostname)
|
||||
if domain != "localhost" {
|
||||
domain = "." + domain
|
||||
}
|
||||
|
@ -86,9 +87,9 @@ func GetFingerPrintCookie(gc *gin.Context) (string, error) {
|
|||
func DeleteCookie(gc *gin.Context) {
|
||||
secure := true
|
||||
httpOnly := true
|
||||
|
||||
host, _ := utils.GetHostParts(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL))
|
||||
domain := utils.GetDomainName(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL))
|
||||
hostname := utils.GetHost(gc)
|
||||
host, _ := utils.GetHostParts(hostname)
|
||||
domain := utils.GetDomainName(hostname)
|
||||
if domain != "localhost" {
|
||||
domain = "." + domain
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@ type Env struct {
|
|||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
||||
EnvData string `gorm:"type:text" json:"env" bson:"env"`
|
||||
Hash string `gorm:"type:text" json:"hash" bson:"hash"`
|
||||
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@ type Session struct {
|
|||
User User `json:"-" bson:"-"`
|
||||
UserAgent string `json:"user_agent" bson:"user_agent"`
|
||||
IP string `json:"ip" bson:"ip"`
|
||||
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ type User struct {
|
|||
PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at"`
|
||||
Picture *string `gorm:"type:text" json:"picture" bson:"picture"`
|
||||
Roles string `json:"roles" bson:"roles"`
|
||||
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
||||
}
|
||||
|
||||
func (user *User) AsAPIUser() *model.User {
|
||||
|
|
|
@ -9,8 +9,8 @@ type VerificationRequest struct {
|
|||
Token string `gorm:"type:text" json:"token" bson:"token"`
|
||||
Identifier string `gorm:"uniqueIndex:idx_email_identifier" json:"identifier" bson:"identifier"`
|
||||
ExpiresAt int64 `json:"expires_at" bson:"expires_at"`
|
||||
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
||||
Email string `gorm:"uniqueIndex:idx_email_identifier" json:"email" bson:"email"`
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,10 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
env.Key = env.ID
|
||||
result := p.db.Create(&env)
|
||||
env.CreatedAt = time.Now().Unix()
|
||||
env.UpdatedAt = time.Now().Unix()
|
||||
|
||||
result := p.db.Create(&env)
|
||||
if result.Error != nil {
|
||||
log.Println("error adding config:", result.Error)
|
||||
return env, result.Error
|
||||
|
|
|
@ -2,6 +2,7 @@ package sql
|
|||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/google/uuid"
|
||||
|
@ -15,6 +16,8 @@ func (p *provider) AddSession(session models.Session) error {
|
|||
}
|
||||
|
||||
session.Key = session.ID
|
||||
session.CreatedAt = time.Now().Unix()
|
||||
session.UpdatedAt = time.Now().Unix()
|
||||
res := p.db.Clauses(
|
||||
clause.OnConflict{
|
||||
DoNothing: true,
|
||||
|
|
|
@ -23,6 +23,8 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||
user.Roles = strings.Join(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
||||
}
|
||||
|
||||
user.CreatedAt = time.Now().Unix()
|
||||
user.UpdatedAt = time.Now().Unix()
|
||||
user.Key = user.ID
|
||||
result := p.db.Clauses(
|
||||
clause.OnConflict{
|
||||
|
|
|
@ -2,6 +2,7 @@ package sql
|
|||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
|
@ -16,6 +17,8 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||
}
|
||||
|
||||
verificationRequest.Key = verificationRequest.ID
|
||||
verificationRequest.CreatedAt = time.Now().Unix()
|
||||
verificationRequest.UpdatedAt = time.Now().Unix()
|
||||
result := p.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "email"}, {Name: "identifier"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"token", "expires_at"}),
|
||||
|
|
|
@ -6,10 +6,10 @@ import (
|
|||
)
|
||||
|
||||
// SendForgotPasswordMail to send forgot password email
|
||||
func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||
func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
||||
resetPasswordUrl := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
|
||||
if resetPasswordUrl == "" {
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyResetPasswordURL, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL)+"/app/reset-password")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyResetPasswordURL, hostname+"/app/reset-password")
|
||||
}
|
||||
|
||||
// The receiver needs to be in slice as the receive supports multiple receiver
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// SendVerificationMail to send verification email
|
||||
func SendVerificationMail(toEmail, token string) error {
|
||||
func SendVerificationMail(toEmail, token, hostname string) error {
|
||||
// The receiver needs to be in slice as the receive supports multiple receiver
|
||||
Receiver := []string{toEmail}
|
||||
|
||||
|
@ -99,7 +99,7 @@ func SendVerificationMail(toEmail, token string) error {
|
|||
data := make(map[string]interface{}, 3)
|
||||
data["org_logo"] = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
||||
data["org_name"] = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
||||
data["verification_url"] = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) + "/verify_email?token=" + token
|
||||
data["verification_url"] = hostname + "/verify_email?token=" + token
|
||||
message = addEmailTemplate(message, data, "verify_email.tmpl")
|
||||
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||
|
||||
|
|
5
server/env/env.go
vendored
|
@ -31,8 +31,6 @@ func InitEnv() {
|
|||
}
|
||||
}
|
||||
|
||||
// set authorizer url to empty string so that fresh url is obtained with every server start
|
||||
envData.StringEnv[constants.EnvKeyAuthorizerURL] = ""
|
||||
if envData.StringEnv[constants.EnvKeyAppURL] == "" {
|
||||
envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
|
||||
}
|
||||
|
@ -246,12 +244,11 @@ func InitEnv() {
|
|||
trimVal := strings.TrimSpace(val)
|
||||
if trimVal != "" {
|
||||
roles = append(roles, trimVal)
|
||||
}
|
||||
|
||||
if utils.StringSliceContains(defaultRoleSplit, trimVal) {
|
||||
defaultRoles = append(defaultRoles, trimVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRolesEnv) > 0 {
|
||||
panic(`Invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
||||
|
|
|
@ -6,7 +6,6 @@ require (
|
|||
github.com/99designs/gqlgen v0.14.0
|
||||
github.com/arangodb/go-driver v1.2.1
|
||||
github.com/coreos/go-oidc/v3 v3.1.0
|
||||
github.com/gin-contrib/location v0.0.2
|
||||
github.com/gin-gonic/gin v1.7.2
|
||||
github.com/go-playground/validator/v10 v10.8.0 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.0
|
||||
|
|
|
@ -82,11 +82,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/gin-contrib/location v0.0.2 h1:QZKh1+K/LLR4KG/61eIO3b7MLuKi8tytQhV6texLgP4=
|
||||
github.com/gin-contrib/location v0.0.2/go.mod h1:NGoidiRlf0BlA/VKSVp+g3cuSMeTmip/63PhEjRhUAc=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
|
||||
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
|
@ -100,7 +97,6 @@ github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8c
|
|||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.8.0 h1:1kAa0fCrnpv+QYdkdcRzrRM7AyYs5o8+jZdJCz9xj6k=
|
||||
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
|
||||
|
|
|
@ -54,7 +54,6 @@ type ComplexityRoot struct {
|
|||
AdminSecret func(childComplexity int) int
|
||||
AllowedOrigins func(childComplexity int) int
|
||||
AppURL func(childComplexity int) int
|
||||
AuthorizerURL func(childComplexity int) int
|
||||
CookieName func(childComplexity int) int
|
||||
CustomAccessTokenScript func(childComplexity int) int
|
||||
DatabaseName func(childComplexity int) int
|
||||
|
@ -280,13 +279,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
|
||||
return e.complexity.Env.AppURL(childComplexity), true
|
||||
|
||||
case "Env.AUTHORIZER_URL":
|
||||
if e.complexity.Env.AuthorizerURL == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Env.AuthorizerURL(childComplexity), true
|
||||
|
||||
case "Env.COOKIE_NAME":
|
||||
if e.complexity.Env.CookieName == nil {
|
||||
break
|
||||
|
@ -1215,7 +1207,6 @@ type Env {
|
|||
JWT_TYPE: String
|
||||
JWT_SECRET: String
|
||||
ALLOWED_ORIGINS: [String!]
|
||||
AUTHORIZER_URL: String
|
||||
APP_URL: String
|
||||
REDIS_URL: String
|
||||
COOKIE_NAME: String
|
||||
|
@ -1250,7 +1241,6 @@ input UpdateEnvInput {
|
|||
JWT_TYPE: String
|
||||
JWT_SECRET: String
|
||||
ALLOWED_ORIGINS: [String!]
|
||||
AUTHORIZER_URL: String
|
||||
APP_URL: String
|
||||
REDIS_URL: String
|
||||
COOKIE_NAME: String
|
||||
|
@ -2271,38 +2261,6 @@ func (ec *executionContext) _Env_ALLOWED_ORIGINS(ctx context.Context, field grap
|
|||
return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Env_AUTHORIZER_URL(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Env",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.AuthorizerURL, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Env_APP_URL(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
@ -7094,14 +7052,6 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
|
|||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "AUTHORIZER_URL":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("AUTHORIZER_URL"))
|
||||
it.AuthorizerURL, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "APP_URL":
|
||||
var err error
|
||||
|
||||
|
@ -7591,8 +7541,6 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
|
|||
out.Values[i] = ec._Env_JWT_SECRET(ctx, field, obj)
|
||||
case "ALLOWED_ORIGINS":
|
||||
out.Values[i] = ec._Env_ALLOWED_ORIGINS(ctx, field, obj)
|
||||
case "AUTHORIZER_URL":
|
||||
out.Values[i] = ec._Env_AUTHORIZER_URL(ctx, field, obj)
|
||||
case "APP_URL":
|
||||
out.Values[i] = ec._Env_APP_URL(ctx, field, obj)
|
||||
case "REDIS_URL":
|
||||
|
|
|
@ -35,7 +35,6 @@ type Env struct {
|
|||
JwtType *string `json:"JWT_TYPE"`
|
||||
JwtSecret *string `json:"JWT_SECRET"`
|
||||
AllowedOrigins []string `json:"ALLOWED_ORIGINS"`
|
||||
AuthorizerURL *string `json:"AUTHORIZER_URL"`
|
||||
AppURL *string `json:"APP_URL"`
|
||||
RedisURL *string `json:"REDIS_URL"`
|
||||
CookieName *string `json:"COOKIE_NAME"`
|
||||
|
@ -155,7 +154,6 @@ type UpdateEnvInput struct {
|
|||
JwtType *string `json:"JWT_TYPE"`
|
||||
JwtSecret *string `json:"JWT_SECRET"`
|
||||
AllowedOrigins []string `json:"ALLOWED_ORIGINS"`
|
||||
AuthorizerURL *string `json:"AUTHORIZER_URL"`
|
||||
AppURL *string `json:"APP_URL"`
|
||||
RedisURL *string `json:"REDIS_URL"`
|
||||
CookieName *string `json:"COOKIE_NAME"`
|
||||
|
|
|
@ -98,7 +98,6 @@ type Env {
|
|||
JWT_TYPE: String
|
||||
JWT_SECRET: String
|
||||
ALLOWED_ORIGINS: [String!]
|
||||
AUTHORIZER_URL: String
|
||||
APP_URL: String
|
||||
REDIS_URL: String
|
||||
COOKIE_NAME: String
|
||||
|
@ -133,7 +132,6 @@ input UpdateEnvInput {
|
|||
JWT_TYPE: String
|
||||
JWT_SECRET: String
|
||||
ALLOWED_ORIGINS: [String!]
|
||||
AUTHORIZER_URL: String
|
||||
APP_URL: String
|
||||
REDIS_URL: String
|
||||
COOKIE_NAME: String
|
||||
|
|
|
@ -22,6 +22,7 @@ type State struct {
|
|||
// AppHandler is the handler for the /app route
|
||||
func AppHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
hostname := utils.GetHost(c)
|
||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableLoginPage) {
|
||||
c.JSON(400, gin.H{"error": "login page is not enabled"})
|
||||
return
|
||||
|
@ -32,7 +33,8 @@ func AppHandler() gin.HandlerFunc {
|
|||
var stateObj State
|
||||
|
||||
if state == "" {
|
||||
stateObj.AuthorizerURL = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL)
|
||||
|
||||
stateObj.AuthorizerURL = hostname
|
||||
stateObj.RedirectURL = stateObj.AuthorizerURL + "/app"
|
||||
|
||||
} else {
|
||||
|
@ -62,7 +64,7 @@ func AppHandler() gin.HandlerFunc {
|
|||
}
|
||||
|
||||
// validate host and domain of authorizer url
|
||||
if strings.TrimSuffix(stateObj.AuthorizerURL, "/") != envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) {
|
||||
if strings.TrimSuffix(stateObj.AuthorizerURL, "/") != hostname {
|
||||
c.JSON(400, gin.H{"error": "invalid host url"})
|
||||
return
|
||||
}
|
||||
|
|
|
@ -99,6 +99,11 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
user.SignupMethods = signupMethod
|
||||
user.Password = existingUser.Password
|
||||
|
||||
if user.EmailVerifiedAt == nil {
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
// 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
|
||||
hostname := utils.GetHost(c)
|
||||
redirectURL := c.Query("redirectURL")
|
||||
roles := c.Query("roles")
|
||||
|
||||
|
@ -56,7 +56,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||
}
|
||||
sessionstore.SetSocailLoginState(oauthStateString, constants.SignupMethodGoogle)
|
||||
// during the init of OAuthProvider authorizer url might be empty
|
||||
oauth.OAuthProviders.GoogleConfig.RedirectURL = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) + "/oauth_callback/google"
|
||||
oauth.OAuthProviders.GoogleConfig.RedirectURL = hostname + "/oauth_callback/google"
|
||||
url := oauth.OAuthProviders.GoogleConfig.AuthCodeURL(oauthStateString)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
case constants.SignupMethodGithub:
|
||||
|
@ -65,7 +65,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||
break
|
||||
}
|
||||
sessionstore.SetSocailLoginState(oauthStateString, constants.SignupMethodGithub)
|
||||
oauth.OAuthProviders.GithubConfig.RedirectURL = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) + "/oauth_callback/github"
|
||||
oauth.OAuthProviders.GithubConfig.RedirectURL = hostname + "/oauth_callback/github"
|
||||
url := oauth.OAuthProviders.GithubConfig.AuthCodeURL(oauthStateString)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
case constants.SignupMethodFacebook:
|
||||
|
@ -74,7 +74,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||
break
|
||||
}
|
||||
sessionstore.SetSocailLoginState(oauthStateString, constants.SignupMethodFacebook)
|
||||
oauth.OAuthProviders.FacebookConfig.RedirectURL = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) + "/oauth_callback/facebook"
|
||||
oauth.OAuthProviders.FacebookConfig.RedirectURL = hostname + "/oauth_callback/facebook"
|
||||
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
default:
|
||||
|
|
|
@ -2,22 +2,13 @@ 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 envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) == "" {
|
||||
url := location.Get(c)
|
||||
log.Println("=> setting authorizer url to: " + url.Scheme + "://" + c.Request.Host)
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyAuthorizerURL, url.Scheme+"://"+c.Request.Host)
|
||||
}
|
||||
ctx := context.WithValue(c.Request.Context(), "GinContextKey", c)
|
||||
c.Request = c.Request.WithContext(ctx)
|
||||
c.Next()
|
||||
|
|
|
@ -43,7 +43,7 @@ func InitOAuth() {
|
|||
OAuthProviders.GoogleConfig = &oauth2.Config{
|
||||
ClientID: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID),
|
||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientSecret),
|
||||
RedirectURL: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) + "/oauth_callback/google",
|
||||
RedirectURL: "/oauth_callback/google",
|
||||
Endpoint: OIDCProviders.GoogleOIDC.Endpoint(),
|
||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ func InitOAuth() {
|
|||
OAuthProviders.GithubConfig = &oauth2.Config{
|
||||
ClientID: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientID),
|
||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientSecret),
|
||||
RedirectURL: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) + "/oauth_callback/github",
|
||||
RedirectURL: "/oauth_callback/github",
|
||||
Endpoint: githubOAuth2.Endpoint,
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func InitOAuth() {
|
|||
OAuthProviders.FacebookConfig = &oauth2.Config{
|
||||
ClientID: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientID),
|
||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientSecret),
|
||||
RedirectURL: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL) + "/oauth_callback/facebook",
|
||||
RedirectURL: "/oauth_callback/facebook",
|
||||
Endpoint: facebookOAuth2.Endpoint,
|
||||
Scopes: []string{"public_profile", "email"},
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
|||
jwtSecret := store.StringEnv[constants.EnvKeyJwtSecret]
|
||||
jwtRoleClaim := store.StringEnv[constants.EnvKeyJwtRoleClaim]
|
||||
allowedOrigins := store.SliceEnv[constants.EnvKeyAllowedOrigins]
|
||||
authorizerURL := store.StringEnv[constants.EnvKeyAuthorizerURL]
|
||||
appURL := store.StringEnv[constants.EnvKeyAppURL]
|
||||
redisURL := store.StringEnv[constants.EnvKeyRedisURL]
|
||||
cookieName := store.StringEnv[constants.EnvKeyCookieName]
|
||||
|
@ -77,7 +76,6 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
|||
JwtSecret: &jwtSecret,
|
||||
JwtRoleClaim: &jwtRoleClaim,
|
||||
AllowedOrigins: allowedOrigins,
|
||||
AuthorizerURL: &authorizerURL,
|
||||
AppURL: &appURL,
|
||||
RedisURL: &redisURL,
|
||||
CookieName: &cookieName,
|
||||
|
|
|
@ -27,7 +27,6 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||
}
|
||||
host := gc.Request.Host
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
|
||||
if !utils.IsValidEmail(params.Email) {
|
||||
|
@ -39,7 +38,8 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||
return res, fmt.Errorf(`user with this email not found`)
|
||||
}
|
||||
|
||||
verificationToken, err := token.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword)
|
||||
hostname := utils.GetHost(gc)
|
||||
verificationToken, err := token.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword, hostname)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
email.SendForgotPasswordMail(params.Email, verificationToken, host)
|
||||
email.SendForgotPasswordMail(params.Email, verificationToken, hostname)
|
||||
}()
|
||||
|
||||
res = &model.Response{
|
||||
|
|
|
@ -20,6 +20,10 @@ import (
|
|||
// MagicLinkLoginResolver is a resolver for magic link login mutation
|
||||
func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
|
||||
var res *model.Response
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
|
||||
return res, fmt.Errorf(`magic link login is disabled for this instance`)
|
||||
|
@ -102,10 +106,11 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||
}
|
||||
}
|
||||
|
||||
hostname := utils.GetHost(gc)
|
||||
if !envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
||||
// insert verification request
|
||||
verificationType := constants.VerificationTypeMagicLinkLogin
|
||||
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType)
|
||||
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
}
|
||||
|
@ -118,7 +123,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
email.SendVerificationMail(params.Email, verificationToken)
|
||||
email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ import (
|
|||
// ResendVerifyEmailResolver is a resolver for resend verify email mutation
|
||||
func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) {
|
||||
var res *model.Response
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
|
||||
if !utils.IsValidEmail(params.Email) {
|
||||
|
@ -39,7 +43,8 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
|||
log.Println("error deleting verification request:", err)
|
||||
}
|
||||
|
||||
verificationToken, err := token.CreateVerificationToken(params.Email, params.Identifier)
|
||||
hostname := utils.GetHost(gc)
|
||||
verificationToken, err := token.CreateVerificationToken(params.Email, params.Identifier, hostname)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
}
|
||||
|
@ -52,7 +57,7 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
email.SendVerificationMail(params.Email, verificationToken)
|
||||
email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||
}()
|
||||
|
||||
res = &model.Response{
|
||||
|
|
|
@ -119,10 +119,11 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
roles := strings.Split(user.Roles, ",")
|
||||
userToReturn := user.AsAPIUser()
|
||||
|
||||
hostname := utils.GetHost(gc)
|
||||
if !envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
||||
// insert verification request
|
||||
verificationType := constants.VerificationTypeBasicAuthSignup
|
||||
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType)
|
||||
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
}
|
||||
|
@ -135,7 +136,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
email.SendVerificationMail(params.Email, verificationToken)
|
||||
email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||
}()
|
||||
|
||||
res = &model.AuthResponse{
|
||||
|
|
|
@ -13,6 +13,8 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/envstore"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/oauth"
|
||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
)
|
||||
|
@ -115,6 +117,8 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||
|
||||
// Update local store
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvStore(updatedData)
|
||||
sessionstore.InitSession()
|
||||
oauth.InitOAuth()
|
||||
|
||||
// Fetch the current db store and update it
|
||||
env, err := db.Provider.GetEnv()
|
||||
|
|
|
@ -116,12 +116,13 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||
sessionstore.DeleteAllUserSession(fmt.Sprintf("%v", user.ID))
|
||||
cookie.DeleteCookie(gc)
|
||||
|
||||
hostname := utils.GetHost(gc)
|
||||
user.Email = newEmail
|
||||
user.EmailVerifiedAt = nil
|
||||
hasEmailChanged = true
|
||||
// insert verification request
|
||||
verificationType := constants.VerificationTypeUpdateEmail
|
||||
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType)
|
||||
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
}
|
||||
|
@ -134,7 +135,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
email.SendVerificationMail(newEmail, verificationToken)
|
||||
email.SendVerificationMail(newEmail, verificationToken, hostname)
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
@ -98,11 +98,12 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||
sessionstore.DeleteAllUserSession(fmt.Sprintf("%v", user.ID))
|
||||
cookie.DeleteCookie(gc)
|
||||
|
||||
hostname := utils.GetHost(gc)
|
||||
user.Email = newEmail
|
||||
user.EmailVerifiedAt = nil
|
||||
// insert verification request
|
||||
verificationType := constants.VerificationTypeUpdateEmail
|
||||
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType)
|
||||
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname)
|
||||
if err != nil {
|
||||
log.Println(`error generating token`, err)
|
||||
}
|
||||
|
@ -115,7 +116,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
email.SendVerificationMail(newEmail, verificationToken)
|
||||
email.SendVerificationMail(newEmail, verificationToken, hostname)
|
||||
}()
|
||||
}
|
||||
|
||||
|
@ -127,7 +128,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||
inputRoles = append(inputRoles, *item)
|
||||
}
|
||||
|
||||
if !utils.IsValidRoles(append([]string{}, append(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...), inputRoles) {
|
||||
if !utils.IsValidRoles(inputRoles, append([]string{}, append(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...)) {
|
||||
return res, fmt.Errorf("invalid list of roles")
|
||||
}
|
||||
|
||||
|
|
|
@ -3,14 +3,13 @@ package routes
|
|||
import (
|
||||
"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(location.Default())
|
||||
router.Use(middlewares.GinContextToContextMiddleware())
|
||||
router.Use(middlewares.CORSMiddleware())
|
||||
|
||||
|
@ -25,14 +24,16 @@ func InitRouter() *gin.Engine {
|
|||
// login page app related routes.
|
||||
app := router.Group("/app")
|
||||
{
|
||||
app.Static("/favicon_io", "app/favicon_io")
|
||||
app.Static("/build", "app/build")
|
||||
app.GET("/", handlers.AppHandler())
|
||||
app.GET("/reset-password", handlers.AppHandler())
|
||||
app.GET("/:page", handlers.AppHandler())
|
||||
}
|
||||
|
||||
// dashboard related routes
|
||||
dashboard := router.Group("/dashboard")
|
||||
{
|
||||
dashboard.Static("/favicon_io", "dashboard/favicon_io")
|
||||
dashboard.Static("/build", "dashboard/build")
|
||||
dashboard.GET("/", handlers.DashboardHandler())
|
||||
dashboard.GET("/:page", handlers.DashboardHandler())
|
||||
|
|
|
@ -7,13 +7,12 @@ import (
|
|||
"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(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run(`should complete admin login`, func(t *testing.T) {
|
||||
t.Run(`should complete admin signup`, func(t *testing.T) {
|
||||
_, ctx := createContext(s)
|
||||
_, err := resolvers.AdminSignupResolver(ctx, model.AdminSignupInput{
|
||||
AdminSecret: "admin",
|
||||
|
@ -24,7 +23,7 @@ func adminSignupTests(t *testing.T, s TestSetup) {
|
|||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyAdminSecret, "")
|
||||
|
||||
_, err = resolvers.AdminSignupResolver(ctx, model.AdminSignupInput{
|
||||
AdminSecret: uuid.New().String(),
|
||||
AdminSecret: "admin123",
|
||||
})
|
||||
|
||||
assert.Nil(t, err)
|
||||
|
|
|
@ -14,16 +14,13 @@ func TestEnvs(t *testing.T) {
|
|||
env.InitEnv()
|
||||
store := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
||||
|
||||
assert.Equal(t, store.StringEnv[constants.EnvKeyAdminSecret], "admin")
|
||||
assert.Equal(t, store.StringEnv[constants.EnvKeyEnv], "production")
|
||||
assert.False(t, store.BoolEnv[constants.EnvKeyDisableEmailVerification])
|
||||
assert.False(t, store.BoolEnv[constants.EnvKeyDisableMagicLinkLogin])
|
||||
assert.False(t, store.BoolEnv[constants.EnvKeyDisableBasicAuthentication])
|
||||
assert.Equal(t, store.StringEnv[constants.EnvKeyJwtType], "HS256")
|
||||
assert.Equal(t, store.StringEnv[constants.EnvKeyJwtSecret], "random_string")
|
||||
assert.Equal(t, store.StringEnv[constants.EnvKeyJwtRoleClaim], "role")
|
||||
assert.EqualValues(t, store.SliceEnv[constants.EnvKeyRoles], []string{"user"})
|
||||
assert.EqualValues(t, store.SliceEnv[constants.EnvKeyDefaultRoles], []string{"user"})
|
||||
assert.EqualValues(t, store.SliceEnv[constants.EnvKeyProtectedRoles], []string{"admin"})
|
||||
assert.EqualValues(t, store.SliceEnv[constants.EnvKeyAllowedOrigins], []string{"*"})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
|
@ -20,20 +21,20 @@ func TestResolvers(t *testing.T) {
|
|||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
|
||||
|
||||
env.InitEnv()
|
||||
s := testSetup()
|
||||
defer s.Server.Close()
|
||||
|
||||
db.InitDB()
|
||||
|
||||
// clean the persisted config for test to use fresh config
|
||||
envData, err := db.Provider.GetEnv()
|
||||
log.Println("=> envData:", envstore.EnvInMemoryStoreObj.GetEnvStoreClone())
|
||||
if err == nil {
|
||||
envData.EnvData = ""
|
||||
db.Provider.UpdateEnv(envData)
|
||||
}
|
||||
env.PersistEnv()
|
||||
|
||||
s := testSetup()
|
||||
defer s.Server.Close()
|
||||
|
||||
t.Run("should pass tests for "+dbType, func(t *testing.T) {
|
||||
// admin tests
|
||||
adminSignupTests(t, s)
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/handlers"
|
||||
"github.com/authorizerdev/authorizer/server/middlewares"
|
||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||
"github.com/gin-contrib/location"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
@ -73,13 +72,17 @@ func testSetup() TestSetup {
|
|||
}
|
||||
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, "../../.env.sample")
|
||||
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpHost, "smtp.yopmail.com")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPort, "2525")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpUsername, "lakhan@yopmail.com")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPassword, "test")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySenderEmail, "info@yopmail.com")
|
||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyProtectedRoles, []string{"admin"})
|
||||
env.InitEnv()
|
||||
sessionstore.InitSession()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, r := gin.CreateTestContext(w)
|
||||
r.Use(location.Default())
|
||||
r.Use(middlewares.GinContextToContextMiddleware())
|
||||
r.Use(middlewares.CORSMiddleware())
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ func updateUserTest(t *testing.T, s TestSetup) {
|
|||
})
|
||||
|
||||
user := *signupRes.User
|
||||
adminRole := "admin"
|
||||
adminRole := "supplier"
|
||||
userRole := "user"
|
||||
newRoles := []*string{&adminRole, &userRole}
|
||||
_, err := resolvers.UpdateUserResolver(ctx, model.UpdateUserInput{
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
)
|
||||
|
||||
func TestGetHostName(t *testing.T) {
|
||||
authorizer_url := "http://test.herokuapp.com:80"
|
||||
url := "http://test.herokuapp.com:80"
|
||||
|
||||
host, port := utils.GetHostParts(authorizer_url)
|
||||
host, port := utils.GetHostParts(url)
|
||||
expectedHost := "test.herokuapp.com"
|
||||
|
||||
assert.Equal(t, host, expectedHost, "hostname should be equal")
|
||||
|
@ -18,9 +18,9 @@ func TestGetHostName(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetDomainName(t *testing.T) {
|
||||
authorizer_url := "http://test.herokuapp.com"
|
||||
url := "http://test.herokuapp.com"
|
||||
|
||||
got := utils.GetDomainName(authorizer_url)
|
||||
got := utils.GetDomainName(url)
|
||||
want := "herokuapp.com"
|
||||
|
||||
assert.Equal(t, got, want, "domain name should be equal")
|
||||
|
|
|
@ -2,7 +2,6 @@ package token
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/cookie"
|
||||
|
@ -25,7 +24,7 @@ func GetAdminAuthToken(gc *gin.Context) (string, error) {
|
|||
}
|
||||
|
||||
err = bcrypt.CompareHashAndPassword([]byte(token), []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)))
|
||||
log.Println("error comparing hash:", err)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ type CustomClaim struct {
|
|||
}
|
||||
|
||||
// CreateVerificationToken creates a verification JWT token
|
||||
func CreateVerificationToken(email string, tokenType string) (string, error) {
|
||||
func CreateVerificationToken(email, tokenType, hostname string) (string, error) {
|
||||
t := jwt.New(jwt.GetSigningMethod(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)))
|
||||
|
||||
t.Claims = &CustomClaim{
|
||||
|
@ -31,7 +31,7 @@ func CreateVerificationToken(email string, tokenType string) (string, error) {
|
|||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
},
|
||||
tokenType,
|
||||
VerificationRequestToken{Email: email, Host: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL), RedirectURL: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL)},
|
||||
VerificationRequestToken{Email: email, Host: hostname, RedirectURL: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL)},
|
||||
}
|
||||
|
||||
return t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
|
||||
|
|
|
@ -34,3 +34,16 @@ func SaveSessionInDB(userId string, c *gin.Context) {
|
|||
log.Println("=> session saved in db:", sessionData)
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveDuplicateString removes duplicate strings from a string slice
|
||||
func RemoveDuplicateString(strSlice []string) []string {
|
||||
allKeys := make(map[string]bool)
|
||||
list := []string{}
|
||||
for _, item := range strSlice {
|
||||
if _, value := allKeys[item]; !value {
|
||||
allKeys[item] = true
|
||||
list = append(list, item)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
|
|
@ -1,10 +1,23 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetHost returns hostname from request context
|
||||
func GetHost(c *gin.Context) string {
|
||||
scheme := "http"
|
||||
if c.Request.TLS != nil {
|
||||
scheme = "https"
|
||||
}
|
||||
log.Println("=> url:", scheme+"://"+c.Request.Host)
|
||||
return scheme + "://" + c.Request.Host
|
||||
}
|
||||
|
||||
// GetHostName function returns hostname and port
|
||||
func GetHostParts(uri string) (string, string) {
|
||||
tempURI := uri
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>{{.data.organizationName}}</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/app/favicon_io/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/app/favicon_io/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/app/favicon_io/favicon-16x16.png">
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="/app/build/index.css">
|
||||
<script>
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Authorizer | Dashboard</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/dashboard/favicon_io/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/dashboard/favicon_io/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/dashboard/favicon_io/favicon-16x16.png">
|
||||
<title>Document</title>
|
||||
<script>
|
||||
window.__authorizer__ = {{.data}}
|
||||
|
|