feat: add integration tests for signup, login, reset_password, forgot_password, verify_email
This commit is contained in:
parent
969395ccdb
commit
beae4502d4
|
@ -2,8 +2,11 @@ ENV=production
|
||||||
DATABASE_URL=data.db
|
DATABASE_URL=data.db
|
||||||
DATABASE_TYPE=sqlite
|
DATABASE_TYPE=sqlite
|
||||||
ADMIN_SECRET=admin
|
ADMIN_SECRET=admin
|
||||||
DISABLE_EMAIL_VERIFICATION=true
|
|
||||||
JWT_SECRET=random_string
|
JWT_SECRET=random_string
|
||||||
|
SENDER_EMAIL=username
|
||||||
|
SENDER_PASSWORD=password
|
||||||
|
SMTP_HOST=smtp.mailtrap.io
|
||||||
|
SMTP_PORT=2525
|
||||||
JWT_TYPE=HS256
|
JWT_TYPE=HS256
|
||||||
ROLES=user
|
ROLES=user
|
||||||
DEFAULT_ROLES=user
|
DEFAULT_ROLES=user
|
||||||
|
|
|
@ -95,5 +95,10 @@ func initArangodb() (arangoDriver.Database, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionCollection, _ := arangodb.Collection(nil, Collections.Session)
|
||||||
|
sessionCollection.EnsureHashIndex(ctx, []string{"user_id"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
|
||||||
return arangodb, err
|
return arangodb, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,9 @@ type Manager interface {
|
||||||
GetVerificationByToken(token string) (VerificationRequest, error)
|
GetVerificationByToken(token string) (VerificationRequest, error)
|
||||||
DeleteVerificationRequest(verificationRequest VerificationRequest) error
|
DeleteVerificationRequest(verificationRequest VerificationRequest) error
|
||||||
GetVerificationRequests() ([]VerificationRequest, error)
|
GetVerificationRequests() ([]VerificationRequest, error)
|
||||||
GetVerificationByEmail(email string) (VerificationRequest, error)
|
GetVerificationByEmail(email string, identifier string) (VerificationRequest, error)
|
||||||
AddSession(session Session) error
|
AddSession(session Session) error
|
||||||
|
DeleteUserSession(userId string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type manager struct {
|
type manager struct {
|
||||||
|
@ -94,8 +95,8 @@ func InitDB() {
|
||||||
|
|
||||||
Mgr = &manager{
|
Mgr = &manager{
|
||||||
sqlDB: nil,
|
sqlDB: nil,
|
||||||
mongodb: nil,
|
|
||||||
arangodb: arangodb,
|
arangodb: arangodb,
|
||||||
|
mongodb: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
|
@ -65,6 +65,13 @@ func initMongodb() (*mongo.Database, error) {
|
||||||
}, options.CreateIndexes())
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
mongodb.CreateCollection(ctx, Collections.Session, options.CreateCollection())
|
mongodb.CreateCollection(ctx, Collections.Session, options.CreateCollection())
|
||||||
|
sessionCollection := mongodb.Collection(Collections.Session, options.Collection())
|
||||||
|
sessionCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
mongo.IndexModel{
|
||||||
|
Keys: bson.M{"user_id": 1},
|
||||||
|
Options: options.Index().SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
return mongodb, nil
|
return mongodb, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
)
|
)
|
||||||
|
@ -12,7 +14,7 @@ import (
|
||||||
type Session struct {
|
type Session struct {
|
||||||
Key string `json:"_key,omitempty" bson:"_key,omitempty"` // for arangodb
|
Key string `json:"_key,omitempty" bson:"_key,omitempty"` // for arangodb
|
||||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
||||||
UserID string `gorm:"type:char(36)" json:"user_id" bson:"user_id"`
|
UserID string `gorm:"type:char(36),index:" json:"user_id" bson:"user_id"`
|
||||||
User User `json:"-" bson:"-"`
|
User User `json:"-" bson:"-"`
|
||||||
UserAgent string `json:"user_agent" bson:"user_agent"`
|
UserAgent string `json:"user_agent" bson:"user_agent"`
|
||||||
IP string `json:"ip" bson:"ip"`
|
IP string `json:"ip" bson:"ip"`
|
||||||
|
@ -63,3 +65,38 @@ func (mgr *manager) AddSession(session Session) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mgr *manager) DeleteUserSession(userId string) error {
|
||||||
|
if IsORMSupported {
|
||||||
|
result := mgr.sqlDB.Where("user_id = ?", userId).Delete(&Session{})
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
log.Println(`error deleting session:`, result.Error)
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsArangoDB {
|
||||||
|
query := fmt.Sprintf(`FOR d IN %s FILTER d.user_id == @userId REMOVE { _key: d._key } IN %s`, Collections.Session, Collections.Session)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"userId": userId,
|
||||||
|
}
|
||||||
|
cursor, err := mgr.arangodb.Query(nil, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("=> error deleting arangodb session:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsMongoDB {
|
||||||
|
sessionCollection := mgr.mongodb.Collection(Collections.Session, options.Collection())
|
||||||
|
_, err := sessionCollection.DeleteMany(nil, bson.M{"user_id": userId}, options.Delete())
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error deleting session:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
arangoDriver "github.com/arangodb/go-driver"
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
@ -41,6 +42,10 @@ func (mgr *manager) AddUser(user User) (User, error) {
|
||||||
user.ID = uuid.New().String()
|
user.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if user.Roles == "" {
|
||||||
|
user.Roles = constants.DEFAULT_ROLES[0]
|
||||||
|
}
|
||||||
|
|
||||||
if IsORMSupported {
|
if IsORMSupported {
|
||||||
// copy id as value for fields required for mongodb & arangodb
|
// copy id as value for fields required for mongodb & arangodb
|
||||||
user.Key = user.ID
|
user.Key = user.ID
|
||||||
|
@ -111,7 +116,7 @@ func (mgr *manager) UpdateUser(user User) (User, error) {
|
||||||
|
|
||||||
if IsMongoDB {
|
if IsMongoDB {
|
||||||
userCollection := mgr.mongodb.Collection(Collections.User, options.Collection())
|
userCollection := mgr.mongodb.Collection(Collections.User, options.Collection())
|
||||||
_, err := userCollection.UpdateOne(nil, bson.M{"id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
|
_, err := userCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
log.Println("error updating user:", err)
|
||||||
return user, err
|
return user, err
|
||||||
|
@ -240,7 +245,7 @@ func (mgr *manager) GetUserByID(id string) (User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsArangoDB {
|
if IsArangoDB {
|
||||||
query := fmt.Sprintf("FOR d in %s FILTER d.id == @id LIMIT 1 RETURN d", Collections.User)
|
query := fmt.Sprintf("FOR d in %s FILTER d._id == @id LIMIT 1 RETURN d", Collections.User)
|
||||||
bindVars := map[string]interface{}{
|
bindVars := map[string]interface{}{
|
||||||
"id": id,
|
"id": id,
|
||||||
}
|
}
|
||||||
|
@ -267,7 +272,7 @@ func (mgr *manager) GetUserByID(id string) (User, error) {
|
||||||
|
|
||||||
if IsMongoDB {
|
if IsMongoDB {
|
||||||
userCollection := mgr.mongodb.Collection(Collections.User, options.Collection())
|
userCollection := mgr.mongodb.Collection(Collections.User, options.Collection())
|
||||||
err := userCollection.FindOne(nil, bson.M{"id": id}).Decode(&user)
|
err := userCollection.FindOne(nil, bson.M{"_id": id}).Decode(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
@ -297,7 +302,7 @@ func (mgr *manager) DeleteUser(user User) error {
|
||||||
|
|
||||||
if IsMongoDB {
|
if IsMongoDB {
|
||||||
userCollection := mgr.mongodb.Collection(Collections.User, options.Collection())
|
userCollection := mgr.mongodb.Collection(Collections.User, options.Collection())
|
||||||
_, err := userCollection.DeleteOne(nil, bson.M{"id": user.ID}, options.Delete())
|
_, err := userCollection.DeleteOne(nil, bson.M{"_id": user.ID}, options.Delete())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting user:", err)
|
log.Println("error deleting user:", err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -179,10 +179,10 @@ func (mgr *manager) GetVerificationByToken(token string) (VerificationRequest, e
|
||||||
return verification, nil
|
return verification, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mgr *manager) GetVerificationByEmail(email string) (VerificationRequest, error) {
|
func (mgr *manager) GetVerificationByEmail(email string, identifier string) (VerificationRequest, error) {
|
||||||
var verification VerificationRequest
|
var verification VerificationRequest
|
||||||
if IsORMSupported {
|
if IsORMSupported {
|
||||||
result := mgr.sqlDB.Where("email = ?", email).First(&verification)
|
result := mgr.sqlDB.Where("email = ? AND identifier = ?", email, identifier).First(&verification)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error getting verification token:`, result.Error)
|
log.Println(`error getting verification token:`, result.Error)
|
||||||
|
@ -191,9 +191,10 @@ func (mgr *manager) GetVerificationByEmail(email string) (VerificationRequest, e
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsArangoDB {
|
if IsArangoDB {
|
||||||
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email LIMIT 1 RETURN d", Collections.VerificationRequest)
|
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email FILTER d.identifier == @identifier LIMIT 1 RETURN d", Collections.VerificationRequest)
|
||||||
bindVars := map[string]interface{}{
|
bindVars := map[string]interface{}{
|
||||||
"email": email,
|
"email": email,
|
||||||
|
"identifier": identifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor, err := mgr.arangodb.Query(nil, query, bindVars)
|
cursor, err := mgr.arangodb.Query(nil, query, bindVars)
|
||||||
|
@ -218,7 +219,7 @@ func (mgr *manager) GetVerificationByEmail(email string) (VerificationRequest, e
|
||||||
|
|
||||||
if IsMongoDB {
|
if IsMongoDB {
|
||||||
verificationRequestCollection := mgr.mongodb.Collection(Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := mgr.mongodb.Collection(Collections.VerificationRequest, options.Collection())
|
||||||
err := verificationRequestCollection.FindOne(nil, bson.M{"email": email}).Decode(&verification)
|
err := verificationRequestCollection.FindOne(nil, bson.M{"email": email, "identifier": identifier}).Decode(&verification)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return verification, err
|
return verification, err
|
||||||
}
|
}
|
||||||
|
@ -248,7 +249,7 @@ func (mgr *manager) DeleteVerificationRequest(verificationRequest VerificationRe
|
||||||
|
|
||||||
if IsMongoDB {
|
if IsMongoDB {
|
||||||
verificationRequestCollection := mgr.mongodb.Collection(Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := mgr.mongodb.Collection(Collections.VerificationRequest, options.Collection())
|
||||||
_, err := verificationRequestCollection.DeleteOne(nil, bson.M{"id": verificationRequest.ID}, options.Delete())
|
_, err := verificationRequestCollection.DeleteOne(nil, bson.M{"_id": verificationRequest.ID}, options.Delete())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting verification request::", err)
|
log.Println("error deleting verification request::", err)
|
||||||
return err
|
return err
|
||||||
|
|
15
server/env/env.go
vendored
15
server/env/env.go
vendored
|
@ -1,7 +1,6 @@
|
||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -25,13 +24,8 @@ func InitEnv() {
|
||||||
if constants.ENV_PATH == "" {
|
if constants.ENV_PATH == "" {
|
||||||
constants.ENV_PATH = `.env`
|
constants.ENV_PATH = `.env`
|
||||||
}
|
}
|
||||||
ARG_DB_URL = flag.String("database_url", "", "Database connection string")
|
|
||||||
ARG_DB_TYPE = flag.String("database_type", "", "Database type, possible values are postgres,mysql,sqlite")
|
|
||||||
ARG_AUTHORIZER_URL = flag.String("authorizer_url", "", "URL for authorizer instance, eg: https://xyz.herokuapp.com")
|
|
||||||
ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
|
|
||||||
|
|
||||||
flag.Parse()
|
if ARG_ENV_FILE != nil && *ARG_ENV_FILE != "" {
|
||||||
if *ARG_ENV_FILE != "" {
|
|
||||||
constants.ENV_PATH = *ARG_ENV_FILE
|
constants.ENV_PATH = *ARG_ENV_FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +59,9 @@ func InitEnv() {
|
||||||
|
|
||||||
if constants.DATABASE_TYPE == "" {
|
if constants.DATABASE_TYPE == "" {
|
||||||
constants.DATABASE_TYPE = os.Getenv("DATABASE_TYPE")
|
constants.DATABASE_TYPE = os.Getenv("DATABASE_TYPE")
|
||||||
|
log.Println(constants.DATABASE_TYPE)
|
||||||
|
|
||||||
if *ARG_DB_TYPE != "" {
|
if ARG_DB_TYPE != nil && *ARG_DB_TYPE != "" {
|
||||||
constants.DATABASE_TYPE = *ARG_DB_TYPE
|
constants.DATABASE_TYPE = *ARG_DB_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +73,7 @@ func InitEnv() {
|
||||||
if constants.DATABASE_URL == "" {
|
if constants.DATABASE_URL == "" {
|
||||||
constants.DATABASE_URL = os.Getenv("DATABASE_URL")
|
constants.DATABASE_URL = os.Getenv("DATABASE_URL")
|
||||||
|
|
||||||
if *ARG_DB_URL != "" {
|
if ARG_DB_URL != nil && *ARG_DB_URL != "" {
|
||||||
constants.DATABASE_URL = *ARG_DB_URL
|
constants.DATABASE_URL = *ARG_DB_URL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +124,7 @@ func InitEnv() {
|
||||||
if constants.AUTHORIZER_URL == "" {
|
if constants.AUTHORIZER_URL == "" {
|
||||||
constants.AUTHORIZER_URL = strings.TrimSuffix(os.Getenv("AUTHORIZER_URL"), "/")
|
constants.AUTHORIZER_URL = strings.TrimSuffix(os.Getenv("AUTHORIZER_URL"), "/")
|
||||||
|
|
||||||
if *ARG_AUTHORIZER_URL != "" {
|
if ARG_AUTHORIZER_URL != nil && *ARG_AUTHORIZER_URL != "" {
|
||||||
constants.AUTHORIZER_URL = *ARG_AUTHORIZER_URL
|
constants.AUTHORIZER_URL = *ARG_AUTHORIZER_URL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ type ComplexityRoot struct {
|
||||||
Query struct {
|
Query struct {
|
||||||
Meta func(childComplexity int) int
|
Meta func(childComplexity int) int
|
||||||
Profile func(childComplexity int) int
|
Profile func(childComplexity int) int
|
||||||
Token func(childComplexity int, roles []string) int
|
Session func(childComplexity int, roles []string) int
|
||||||
Users func(childComplexity int) int
|
Users func(childComplexity int) int
|
||||||
VerificationRequests func(childComplexity int) int
|
VerificationRequests func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ type MutationResolver interface {
|
||||||
}
|
}
|
||||||
type QueryResolver interface {
|
type QueryResolver interface {
|
||||||
Meta(ctx context.Context) (*model.Meta, error)
|
Meta(ctx context.Context) (*model.Meta, error)
|
||||||
Token(ctx context.Context, roles []string) (*model.AuthResponse, error)
|
Session(ctx context.Context, roles []string) (*model.AuthResponse, error)
|
||||||
Profile(ctx context.Context) (*model.User, error)
|
Profile(ctx context.Context) (*model.User, error)
|
||||||
Users(ctx context.Context) ([]*model.User, error)
|
Users(ctx context.Context) ([]*model.User, error)
|
||||||
VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error)
|
VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error)
|
||||||
|
@ -390,17 +390,17 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||||
|
|
||||||
return e.complexity.Query.Profile(childComplexity), true
|
return e.complexity.Query.Profile(childComplexity), true
|
||||||
|
|
||||||
case "Query.token":
|
case "Query.session":
|
||||||
if e.complexity.Query.Token == nil {
|
if e.complexity.Query.Session == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
args, err := ec.field_Query_token_args(context.TODO(), rawArgs)
|
args, err := ec.field_Query_session_args(context.TODO(), rawArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.complexity.Query.Token(childComplexity, args["roles"].([]string)), true
|
return e.complexity.Query.Session(childComplexity, args["roles"].([]string)), true
|
||||||
|
|
||||||
case "Query._users":
|
case "Query._users":
|
||||||
if e.complexity.Query.Users == nil {
|
if e.complexity.Query.Users == nil {
|
||||||
|
@ -746,6 +746,7 @@ input VerifyEmailInput {
|
||||||
|
|
||||||
input ResendVerifyEmailInput {
|
input ResendVerifyEmailInput {
|
||||||
email: String!
|
email: String!
|
||||||
|
identifier: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
input UpdateProfileInput {
|
input UpdateProfileInput {
|
||||||
|
@ -813,7 +814,7 @@ type Mutation {
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
meta: Meta!
|
meta: Meta!
|
||||||
token(roles: [String!]): AuthResponse
|
session(roles: [String!]): AuthResponse
|
||||||
profile: User!
|
profile: User!
|
||||||
# admin only apis
|
# admin only apis
|
||||||
_users: [User!]!
|
_users: [User!]!
|
||||||
|
@ -992,7 +993,7 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs
|
||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) field_Query_token_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
func (ec *executionContext) field_Query_session_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
var err error
|
var err error
|
||||||
args := map[string]interface{}{}
|
args := map[string]interface{}{}
|
||||||
var arg0 []string
|
var arg0 []string
|
||||||
|
@ -1981,7 +1982,7 @@ func (ec *executionContext) _Query_meta(ctx context.Context, field graphql.Colle
|
||||||
return ec.marshalNMeta2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐMeta(ctx, field.Selections, res)
|
return ec.marshalNMeta2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐMeta(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Query_token(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Query_session(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
@ -1998,7 +1999,7 @@ func (ec *executionContext) _Query_token(ctx context.Context, field graphql.Coll
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
rawArgs := field.ArgumentMap(ec.Variables)
|
rawArgs := field.ArgumentMap(ec.Variables)
|
||||||
args, err := ec.field_Query_token_args(ctx, rawArgs)
|
args, err := ec.field_Query_session_args(ctx, rawArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
|
@ -2006,7 +2007,7 @@ func (ec *executionContext) _Query_token(ctx context.Context, field graphql.Coll
|
||||||
fc.Args = args
|
fc.Args = args
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
ctx = rctx // use context from middleware stack in children
|
ctx = rctx // use context from middleware stack in children
|
||||||
return ec.resolvers.Query().Token(rctx, args["roles"].([]string))
|
return ec.resolvers.Query().Session(rctx, args["roles"].([]string))
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
|
@ -4272,6 +4273,14 @@ func (ec *executionContext) unmarshalInputResendVerifyEmailInput(ctx context.Con
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
|
case "identifier":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("identifier"))
|
||||||
|
it.Identifier, err = ec.unmarshalNString2string(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4905,7 +4914,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
case "token":
|
case "session":
|
||||||
field := field
|
field := field
|
||||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -4913,7 +4922,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
res = ec._Query_token(ctx, field)
|
res = ec._Query_session(ctx, field)
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
case "profile":
|
case "profile":
|
||||||
|
|
|
@ -45,6 +45,7 @@ type Meta struct {
|
||||||
|
|
||||||
type ResendVerifyEmailInput struct {
|
type ResendVerifyEmailInput struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
|
Identifier string `json:"identifier"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResetPasswordInput struct {
|
type ResetPasswordInput struct {
|
||||||
|
|
|
@ -89,6 +89,7 @@ input VerifyEmailInput {
|
||||||
|
|
||||||
input ResendVerifyEmailInput {
|
input ResendVerifyEmailInput {
|
||||||
email: String!
|
email: String!
|
||||||
|
identifier: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
input UpdateProfileInput {
|
input UpdateProfileInput {
|
||||||
|
@ -156,7 +157,7 @@ type Mutation {
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
meta: Meta!
|
meta: Meta!
|
||||||
token(roles: [String!]): AuthResponse
|
session(roles: [String!]): AuthResponse
|
||||||
profile: User!
|
profile: User!
|
||||||
# admin only apis
|
# admin only apis
|
||||||
_users: [User!]!
|
_users: [User!]!
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (r *queryResolver) Meta(ctx context.Context) (*model.Meta, error) {
|
||||||
return resolvers.Meta(ctx)
|
return resolvers.Meta(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Token(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
func (r *queryResolver) Session(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
||||||
return resolvers.Token(ctx, roles)
|
return resolvers.Token(ctx, roles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,15 +264,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||||
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, inputRoles)
|
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, inputRoles)
|
||||||
utils.SetCookie(c, accessToken)
|
utils.SetCookie(c, accessToken)
|
||||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
session.SetToken(userIdStr, accessToken, refreshToken)
|
||||||
go func() {
|
utils.CreateSession(user.ID, c)
|
||||||
sessionData := db.Session{
|
|
||||||
UserID: user.ID,
|
|
||||||
UserAgent: utils.GetUserAgent(c.Request),
|
|
||||||
IP: utils.GetIP(c.Request),
|
|
||||||
}
|
|
||||||
|
|
||||||
db.Mgr.AddSession(sessionData)
|
|
||||||
}()
|
|
||||||
|
|
||||||
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -54,22 +53,13 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
||||||
// delete from verification table
|
// delete from verification table
|
||||||
db.Mgr.DeleteVerificationRequest(verificationRequest)
|
db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||||
|
|
||||||
userIdStr := fmt.Sprintf("%v", user.ID)
|
|
||||||
roles := strings.Split(user.Roles, ",")
|
roles := strings.Split(user.Roles, ",")
|
||||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
||||||
|
|
||||||
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||||
|
|
||||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
session.SetToken(user.ID, accessToken, refreshToken)
|
||||||
go func() {
|
utils.CreateSession(user.ID, c)
|
||||||
sessionData := db.Session{
|
|
||||||
UserID: user.ID,
|
|
||||||
UserAgent: utils.GetUserAgent(c.Request),
|
|
||||||
IP: utils.GetIP(c.Request),
|
|
||||||
}
|
|
||||||
|
|
||||||
db.Mgr.AddSession(sessionData)
|
|
||||||
}()
|
|
||||||
utils.SetCookie(c, accessToken)
|
utils.SetCookie(c, accessToken)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, claim.RedirectURL)
|
c.Redirect(http.StatusTemporaryRedirect, claim.RedirectURL)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/env"
|
"github.com/authorizerdev/authorizer/server/env"
|
||||||
|
@ -12,6 +14,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
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()
|
||||||
|
|
||||||
env.InitEnv()
|
env.InitEnv()
|
||||||
db.InitDB()
|
db.InitDB()
|
||||||
session.InitSession()
|
session.InitSession()
|
||||||
|
@ -20,7 +28,8 @@ func main() {
|
||||||
|
|
||||||
router := router.InitRouter()
|
router := router.InitRouter()
|
||||||
|
|
||||||
// login wall app related routes
|
// login wall app related routes.
|
||||||
|
// if we put them in router file then tests would fail as templates or build path will be different
|
||||||
router.LoadHTMLGlob("templates/*")
|
router.LoadHTMLGlob("templates/*")
|
||||||
app := router.Group("/app")
|
app := router.Group("/app")
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,15 +60,7 @@ func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, e
|
||||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||||
|
|
||||||
session.SetToken(user.ID, accessToken, refreshToken)
|
session.SetToken(user.ID, accessToken, refreshToken)
|
||||||
go func() {
|
utils.CreateSession(user.ID, gc)
|
||||||
sessionData := db.Session{
|
|
||||||
UserID: user.ID,
|
|
||||||
UserAgent: utils.GetUserAgent(gc.Request),
|
|
||||||
IP: utils.GetIP(gc.Request),
|
|
||||||
}
|
|
||||||
|
|
||||||
db.Mgr.AddSession(sessionData)
|
|
||||||
}()
|
|
||||||
|
|
||||||
res = &model.AuthResponse{
|
res = &model.AuthResponse{
|
||||||
Message: `Logged in successfully`,
|
Message: `Logged in successfully`,
|
||||||
|
|
|
@ -20,18 +20,28 @@ func ResendVerifyEmail(ctx context.Context, params model.ResendVerifyEmailInput)
|
||||||
return res, fmt.Errorf("invalid email")
|
return res, fmt.Errorf("invalid email")
|
||||||
}
|
}
|
||||||
|
|
||||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(params.Email)
|
if !utils.IsValidVerificationIdentifier(params.Identifier) {
|
||||||
|
return res, fmt.Errorf("invalid identifier")
|
||||||
|
}
|
||||||
|
|
||||||
|
verificationRequest, err := db.Mgr.GetVerificationByEmail(params.Email, params.Identifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, fmt.Errorf(`verification request not found`)
|
return res, fmt.Errorf(`verification request not found`)
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := utils.CreateVerificationToken(params.Email, verificationRequest.Identifier)
|
// delete current verification and create new one
|
||||||
|
err = db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error deleting verification request:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := utils.CreateVerificationToken(params.Email, params.Identifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Println(`error generating token`, err)
|
||||||
}
|
}
|
||||||
db.Mgr.AddVerification(db.VerificationRequest{
|
db.Mgr.AddVerification(db.VerificationRequest{
|
||||||
Token: token,
|
Token: token,
|
||||||
Identifier: verificationRequest.Identifier,
|
Identifier: params.Identifier,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
Email: params.Email,
|
Email: params.Email,
|
||||||
})
|
})
|
||||||
|
|
|
@ -145,15 +145,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
||||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||||
|
|
||||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
session.SetToken(userIdStr, accessToken, refreshToken)
|
||||||
go func() {
|
utils.CreateSession(user.ID, gc)
|
||||||
sessionData := db.Session{
|
|
||||||
UserID: user.ID,
|
|
||||||
UserAgent: utils.GetUserAgent(gc.Request),
|
|
||||||
IP: utils.GetIP(gc.Request),
|
|
||||||
}
|
|
||||||
|
|
||||||
db.Mgr.AddSession(sessionData)
|
|
||||||
}()
|
|
||||||
res = &model.AuthResponse{
|
res = &model.AuthResponse{
|
||||||
Message: `Signed up successfully.`,
|
Message: `Signed up successfully.`,
|
||||||
AccessToken: &accessToken,
|
AccessToken: &accessToken,
|
||||||
|
|
|
@ -66,15 +66,7 @@ func Token(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
||||||
session.DeleteVerificationRequest(userIdStr, token)
|
session.DeleteVerificationRequest(userIdStr, token)
|
||||||
token, expiresAt, _ = utils.CreateAuthToken(user, enum.AccessToken, claimRoles)
|
token, expiresAt, _ = utils.CreateAuthToken(user, enum.AccessToken, claimRoles)
|
||||||
session.SetToken(userIdStr, token, currentRefreshToken)
|
session.SetToken(userIdStr, token, currentRefreshToken)
|
||||||
go func() {
|
utils.CreateSession(user.ID, gc)
|
||||||
sessionData := db.Session{
|
|
||||||
UserID: user.ID,
|
|
||||||
UserAgent: utils.GetUserAgent(gc.Request),
|
|
||||||
IP: utils.GetIP(gc.Request),
|
|
||||||
}
|
|
||||||
|
|
||||||
db.Mgr.AddSession(sessionData)
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.SetCookie(gc, token)
|
utils.SetCookie(gc, token)
|
||||||
|
|
|
@ -43,22 +43,13 @@ func VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.Aut
|
||||||
// delete from verification table
|
// delete from verification table
|
||||||
db.Mgr.DeleteVerificationRequest(verificationRequest)
|
db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||||
|
|
||||||
userIdStr := fmt.Sprintf("%v", user.ID)
|
|
||||||
roles := strings.Split(user.Roles, ",")
|
roles := strings.Split(user.Roles, ",")
|
||||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
||||||
|
|
||||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||||
|
|
||||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
session.SetToken(user.ID, accessToken, refreshToken)
|
||||||
go func() {
|
utils.CreateSession(user.ID, gc)
|
||||||
sessionData := db.Session{
|
|
||||||
UserID: user.ID,
|
|
||||||
UserAgent: utils.GetUserAgent(gc.Request),
|
|
||||||
IP: utils.GetIP(gc.Request),
|
|
||||||
}
|
|
||||||
|
|
||||||
db.Mgr.AddSession(sessionData)
|
|
||||||
}()
|
|
||||||
|
|
||||||
res = &model.AuthResponse{
|
res = &model.AuthResponse{
|
||||||
Message: `Email verified successfully.`,
|
Message: `Email verified successfully.`,
|
||||||
|
|
|
@ -2,44 +2,25 @@ package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
|
||||||
"github.com/authorizerdev/authorizer/server/env"
|
|
||||||
"github.com/authorizerdev/authorizer/server/router"
|
|
||||||
"github.com/authorizerdev/authorizer/server/session"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCors(t *testing.T) {
|
func TestCors(t *testing.T) {
|
||||||
constants.ENV_PATH = "../../.env.sample"
|
|
||||||
constants.DATABASE_URL = "../../data.db"
|
|
||||||
env.InitEnv()
|
|
||||||
db.InitDB()
|
|
||||||
session.InitSession()
|
|
||||||
router := router.InitRouter()
|
|
||||||
|
|
||||||
allowedOrigin := "http://localhost:8080" // The allowed origin that you want to check
|
allowedOrigin := "http://localhost:8080" // The allowed origin that you want to check
|
||||||
notAllowedOrigin := "http://myapp.com"
|
notAllowedOrigin := "http://myapp.com"
|
||||||
|
|
||||||
server := httptest.NewServer(router)
|
s := testSetup()
|
||||||
defer server.Close()
|
defer s.Server.Close()
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
req, _ := http.NewRequest(
|
|
||||||
"GET",
|
|
||||||
"http://"+server.Listener.Addr().String()+"/graphql",
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
req.Header.Add("Origin", allowedOrigin)
|
|
||||||
|
|
||||||
get, _ := client.Do(req)
|
s.Req.Header.Add("Origin", allowedOrigin)
|
||||||
|
res, _ := client.Do(s.Req)
|
||||||
|
|
||||||
// You should get your origin (or a * depending on your config) if the
|
// You should get your origin (or a * depending on your config) if the
|
||||||
// passed origin is allowed.
|
// passed origin is allowed.
|
||||||
o := get.Header.Get("Access-Control-Allow-Origin")
|
o := res.Header.Get("Access-Control-Allow-Origin")
|
||||||
assert.NotEqual(t, o, notAllowedOrigin, "Origins should not match")
|
assert.NotEqual(t, o, notAllowedOrigin, "Origins should not match")
|
||||||
assert.Equal(t, o, allowedOrigin, "Origins don't match")
|
assert.Equal(t, o, allowedOrigin, "Origins do match")
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,20 +4,16 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/enum"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEnvs(t *testing.T) {
|
func TestEnvs(t *testing.T) {
|
||||||
constants.ENV_PATH = "../../.env.sample"
|
constants.ENV_PATH = "../../.env.sample"
|
||||||
// env.InitEnv()
|
|
||||||
|
|
||||||
assert.Equal(t, constants.ADMIN_SECRET, "admin")
|
assert.Equal(t, constants.ADMIN_SECRET, "admin")
|
||||||
assert.Equal(t, constants.ENV, "production")
|
assert.Equal(t, constants.ENV, "production")
|
||||||
assert.Equal(t, constants.DATABASE_URL, "../../data.db")
|
assert.False(t, constants.DISABLE_EMAIL_VERIFICATION)
|
||||||
assert.Equal(t, constants.DATABASE_TYPE, enum.Sqlite.String())
|
assert.False(t, constants.DISABLE_MAGIC_LINK_LOGIN)
|
||||||
assert.True(t, constants.DISABLE_EMAIL_VERIFICATION)
|
|
||||||
assert.True(t, constants.DISABLE_MAGIC_LINK_LOGIN)
|
|
||||||
assert.False(t, constants.DISABLE_BASIC_AUTHENTICATION)
|
assert.False(t, constants.DISABLE_BASIC_AUTHENTICATION)
|
||||||
assert.Equal(t, constants.JWT_TYPE, "HS256")
|
assert.Equal(t, constants.JWT_TYPE, "HS256")
|
||||||
assert.Equal(t, constants.JWT_SECRET, "random_string")
|
assert.Equal(t, constants.JWT_SECRET, "random_string")
|
||||||
|
|
65
server/test/forgot_password_test.go
Normal file
65
server/test/forgot_password_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/enum"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func commonForgotPasswordTest(s TestSetup, t *testing.T) {
|
||||||
|
email := "forgot_password." + s.TestInfo.Email
|
||||||
|
_, err := resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = resolvers.ForgotPassword(s.Ctx, model.ForgotPasswordInput{
|
||||||
|
Email: email,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err, "no errors for forgot password")
|
||||||
|
|
||||||
|
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.ForgotPassword.String())
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, verificationRequest.Identifier, enum.ForgotPassword.String())
|
||||||
|
|
||||||
|
cleanData(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestForgotPassword(t *testing.T) {
|
||||||
|
s := testSetup()
|
||||||
|
defer s.Server.Close()
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForSQL {
|
||||||
|
t.Run("forgot password for sql dbs should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.SQL
|
||||||
|
constants.DATABASE_TYPE = enum.Sqlite.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonForgotPasswordTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForArango {
|
||||||
|
t.Run("forgot password for arangodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.ArangoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Arangodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonForgotPasswordTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForMongo {
|
||||||
|
t.Run("forgot password for mongodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.MongoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Mongodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonForgotPasswordTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
90
server/test/login_test.go
Normal file
90
server/test/login_test.go
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
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/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func commonLoginTest(s TestSetup, t *testing.T) {
|
||||||
|
email := "login." + s.TestInfo.Email
|
||||||
|
_, err := resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = resolvers.Login(s.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(s.Ctx, model.VerifyEmailInput{
|
||||||
|
Token: verificationRequest.Token,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = resolvers.Login(s.Ctx, model.LoginInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
Roles: []string{"test"},
|
||||||
|
})
|
||||||
|
assert.NotNil(t, err, "invalid roles")
|
||||||
|
|
||||||
|
_, err = resolvers.Login(s.Ctx, model.LoginInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password + "s",
|
||||||
|
})
|
||||||
|
assert.NotNil(t, err, "invalid password")
|
||||||
|
|
||||||
|
loginRes, err := resolvers.Login(s.Ctx, model.LoginInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
log.Println("=> access token:", loginRes.AccessToken)
|
||||||
|
assert.Nil(t, err, "login successful")
|
||||||
|
assert.NotNil(t, loginRes.AccessToken, "access token should not be empty")
|
||||||
|
|
||||||
|
cleanData(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogin(t *testing.T) {
|
||||||
|
s := testSetup()
|
||||||
|
defer s.Server.Close()
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForSQL {
|
||||||
|
t.Run("login for sql dbs should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.SQL
|
||||||
|
constants.DATABASE_TYPE = enum.Sqlite.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonLoginTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForArango {
|
||||||
|
t.Run("login for arangodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.ArangoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Arangodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonLoginTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForMongo {
|
||||||
|
t.Run("login for mongodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.MongoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Mongodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonLoginTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
62
server/test/resend_verify_email_test.go
Normal file
62
server/test/resend_verify_email_test.go
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
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 commonResendVerifyEmailTest(s TestSetup, t *testing.T) {
|
||||||
|
email := "resend_verify_email." + s.TestInfo.Email
|
||||||
|
_, err := resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = resolvers.ResendVerifyEmail(s.Ctx, model.ResendVerifyEmailInput{
|
||||||
|
Email: email,
|
||||||
|
Identifier: enum.BasicAuthSignup.String(),
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
cleanData(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResendVerifyEmail(t *testing.T) {
|
||||||
|
s := testSetup()
|
||||||
|
defer s.Server.Close()
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForSQL {
|
||||||
|
t.Run("resend verify email for sql dbs should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.SQL
|
||||||
|
constants.DATABASE_TYPE = enum.Sqlite.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonResendVerifyEmailTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForArango {
|
||||||
|
t.Run("resend verify email for arangodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.ArangoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Arangodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonResendVerifyEmailTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForMongo {
|
||||||
|
t.Run("resend verify email for mongodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.MongoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Mongodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonResendVerifyEmailTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
79
server/test/reset_password_test.go
Normal file
79
server/test/reset_password_test.go
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
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 commonResetPasswordTest(s TestSetup, t *testing.T) {
|
||||||
|
email := "reset_password." + s.TestInfo.Email
|
||||||
|
_, err := resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = resolvers.ForgotPassword(s.Ctx, model.ForgotPasswordInput{
|
||||||
|
Email: email,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err, "no errors for forgot password")
|
||||||
|
|
||||||
|
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.ForgotPassword.String())
|
||||||
|
assert.Nil(t, err, "should get forgot password request")
|
||||||
|
|
||||||
|
_, err = resolvers.ResetPassword(s.Ctx, model.ResetPasswordInput{
|
||||||
|
Token: verificationRequest.Token,
|
||||||
|
Password: "test1",
|
||||||
|
ConfirmPassword: "test",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NotNil(t, err, "passowrds don't match")
|
||||||
|
|
||||||
|
_, err = resolvers.ResetPassword(s.Ctx, model.ResetPasswordInput{
|
||||||
|
Token: verificationRequest.Token,
|
||||||
|
Password: "test1",
|
||||||
|
ConfirmPassword: "test1",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Nil(t, err, "password changed successfully")
|
||||||
|
|
||||||
|
cleanData(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPassword(t *testing.T) {
|
||||||
|
s := testSetup()
|
||||||
|
defer s.Server.Close()
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForSQL {
|
||||||
|
t.Run("reset password for sql dbs should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.SQL
|
||||||
|
constants.DATABASE_TYPE = enum.Sqlite.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonResetPasswordTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForArango {
|
||||||
|
t.Run("reset password for arangodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.ArangoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Arangodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonResetPasswordTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForMongo {
|
||||||
|
t.Run("reset password for mongodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.MongoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Mongodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonResetPasswordTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +1,77 @@
|
||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
"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/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSQLSignUp(t *testing.T) {
|
func commonSignupTest(s TestSetup, t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
email := "signup." + s.TestInfo.Email
|
||||||
req := httptest.NewRequest("POST", "/graphql", nil)
|
res, err := resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||||
c, _ := gin.CreateTestContext(w)
|
Email: email,
|
||||||
ctx := context.WithValue(req.Context(), "GinContextKey", c)
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password + "s",
|
||||||
res, err := resolvers.Signup(ctx, model.SignUpInput{
|
|
||||||
Email: "test@yopmail.com",
|
|
||||||
Password: "test",
|
|
||||||
ConfirmPassword: "test",
|
|
||||||
})
|
})
|
||||||
log.Println("=> signup err:", err)
|
assert.NotNil(t, err, "invalid password errors")
|
||||||
log.Println("=> singup res:", res)
|
|
||||||
assert.Equal(t, "success", "success")
|
res, err = resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
user := *res.User
|
||||||
|
assert.Equal(t, email, user.Email)
|
||||||
|
assert.Nil(t, res.AccessToken, "access token should be nil")
|
||||||
|
|
||||||
|
res, err = resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NotNil(t, err, "should throw duplicate email error")
|
||||||
|
|
||||||
|
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, email, verificationRequest.Email)
|
||||||
|
cleanData(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignUp(t *testing.T) {
|
||||||
|
s := testSetup()
|
||||||
|
defer s.Server.Close()
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForSQL {
|
||||||
|
t.Run("signup for sql dbs should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.SQL
|
||||||
|
constants.DATABASE_TYPE = enum.Sqlite.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonSignupTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForArango {
|
||||||
|
t.Run("signup for arangodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.ArangoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Arangodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonSignupTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForMongo {
|
||||||
|
t.Run("signup for mongodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.MongoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Mongodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonSignupTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
117
server/test/test.go
Normal file
117
server/test/test.go
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
|
||||||
|
"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/handlers"
|
||||||
|
"github.com/authorizerdev/authorizer/server/middlewares"
|
||||||
|
"github.com/authorizerdev/authorizer/server/session"
|
||||||
|
"github.com/gin-contrib/location"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// common user data to share across tests
|
||||||
|
type TestData struct {
|
||||||
|
Email string
|
||||||
|
Password string
|
||||||
|
SQL string
|
||||||
|
MongoDB string
|
||||||
|
ArangoDB string
|
||||||
|
ShouldExecuteForSQL bool
|
||||||
|
ShouldExecuteForArango bool
|
||||||
|
ShouldExecuteForMongo bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestSetup struct {
|
||||||
|
GinEngine *gin.Engine
|
||||||
|
GinContext *gin.Context
|
||||||
|
Ctx context.Context
|
||||||
|
Server *httptest.Server
|
||||||
|
Req *http.Request
|
||||||
|
TestInfo TestData
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetup() TestSetup {
|
||||||
|
testData := TestData{
|
||||||
|
Email: "authorizer_tester@yopmail.com",
|
||||||
|
Password: "test",
|
||||||
|
SQL: "../../data.db",
|
||||||
|
ArangoDB: "http://root:root@localhost:8529",
|
||||||
|
MongoDB: "mongodb://localhost:27017",
|
||||||
|
ShouldExecuteForSQL: true,
|
||||||
|
ShouldExecuteForArango: true,
|
||||||
|
ShouldExecuteForMongo: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
constants.ENV_PATH = "../../.env.sample"
|
||||||
|
constants.DATABASE_URL = testData.SQL
|
||||||
|
env.InitEnv()
|
||||||
|
session.InitSession()
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, r := gin.CreateTestContext(w)
|
||||||
|
r.Use(location.Default())
|
||||||
|
r.Use(middlewares.GinContextToContextMiddleware())
|
||||||
|
r.Use(middlewares.CORSMiddleware())
|
||||||
|
|
||||||
|
r.POST("/graphql", handlers.GraphqlHandler())
|
||||||
|
|
||||||
|
server := httptest.NewServer(r)
|
||||||
|
|
||||||
|
req, _ := http.NewRequest(
|
||||||
|
"POST",
|
||||||
|
"http://"+server.Listener.Addr().String()+"/graphql",
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
req.Header.Add("x-authorizer-admin-secret", constants.ADMIN_SECRET)
|
||||||
|
c.Request = req
|
||||||
|
ctx := context.WithValue(req.Context(), "GinContextKey", c)
|
||||||
|
|
||||||
|
return TestSetup{
|
||||||
|
GinEngine: r,
|
||||||
|
GinContext: c,
|
||||||
|
Ctx: ctx,
|
||||||
|
Server: server,
|
||||||
|
Req: req,
|
||||||
|
TestInfo: testData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanData(email string) {
|
||||||
|
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||||
|
if err == nil {
|
||||||
|
err = db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
verificationRequest, err = db.Mgr.GetVerificationByEmail(email, enum.ForgotPassword.String())
|
||||||
|
if err == nil {
|
||||||
|
err = db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
verificationRequest, err = db.Mgr.GetVerificationByEmail(email, enum.UpdateEmail.String())
|
||||||
|
if err == nil {
|
||||||
|
err = db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUser, err := db.Mgr.GetUserByEmail(email)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error getting user:", err)
|
||||||
|
} else {
|
||||||
|
err = db.Mgr.DeleteUser(dbUser)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error deleting user:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.Mgr.DeleteUserSession(dbUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error deleting user session:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/enum"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -33,3 +34,10 @@ func TestIsValidOrigin(t *testing.T) {
|
||||||
assert.True(t, utils.IsValidOrigin("http://xyxabc.in"), "it should be valid origin")
|
assert.True(t, utils.IsValidOrigin("http://xyxabc.in"), "it should be valid origin")
|
||||||
assert.True(t, utils.IsValidOrigin("http://localhost:8080"), "it should be valid origin")
|
assert.True(t, utils.IsValidOrigin("http://localhost:8080"), "it should be valid origin")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsValidIdentifier(t *testing.T) {
|
||||||
|
assert.False(t, utils.IsValidVerificationIdentifier("test"), "it should be invalid identifier")
|
||||||
|
assert.True(t, utils.IsValidVerificationIdentifier(enum.BasicAuthSignup.String()), "it should be valid identifier")
|
||||||
|
assert.True(t, utils.IsValidVerificationIdentifier(enum.UpdateEmail.String()), "it should be valid identifier")
|
||||||
|
assert.True(t, utils.IsValidVerificationIdentifier(enum.ForgotPassword.String()), "it should be valid identifier")
|
||||||
|
}
|
||||||
|
|
68
server/test/verify_email_test.go
Normal file
68
server/test/verify_email_test.go
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
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 commonVerifyEmailTest(s TestSetup, t *testing.T) {
|
||||||
|
email := "verify_email." + s.TestInfo.Email
|
||||||
|
res, err := resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
user := *res.User
|
||||||
|
assert.Equal(t, email, user.Email)
|
||||||
|
assert.Nil(t, res.AccessToken, "access token should be nil")
|
||||||
|
verificationRequest, err := db.Mgr.GetVerificationByEmail(email, enum.BasicAuthSignup.String())
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, email, verificationRequest.Email)
|
||||||
|
|
||||||
|
verifyRes, err := resolvers.VerifyEmail(s.Ctx, model.VerifyEmailInput{
|
||||||
|
Token: verificationRequest.Token,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotEqual(t, verifyRes.AccessToken, "", "access token should not be empty")
|
||||||
|
|
||||||
|
cleanData(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerifyEmail(t *testing.T) {
|
||||||
|
s := testSetup()
|
||||||
|
defer s.Server.Close()
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForSQL {
|
||||||
|
t.Run("verify email for sql dbs should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.SQL
|
||||||
|
constants.DATABASE_TYPE = enum.Sqlite.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonVerifyEmailTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForArango {
|
||||||
|
t.Run("verify email for arangodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.ArangoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Arangodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonVerifyEmailTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.TestInfo.ShouldExecuteForMongo {
|
||||||
|
t.Run("verify email for mongodb should pass", func(t *testing.T) {
|
||||||
|
constants.DATABASE_URL = s.TestInfo.MongoDB
|
||||||
|
constants.DATABASE_TYPE = enum.Mongodb.String()
|
||||||
|
db.InitDB()
|
||||||
|
commonVerifyEmailTest(s, t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
16
server/utils/create_session.go
Normal file
16
server/utils/create_session.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateSession(userId string, c *gin.Context) {
|
||||||
|
sessionData := db.Session{
|
||||||
|
UserID: userId,
|
||||||
|
UserAgent: GetUserAgent(c.Request),
|
||||||
|
IP: GetIP(c.Request),
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Mgr.AddSession(sessionData)
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/enum"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -69,6 +70,13 @@ func IsValidRoles(userRoles []string, roles []string) bool {
|
||||||
return valid
|
return valid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsValidVerificationIdentifier(identifier string) bool {
|
||||||
|
if identifier != enum.BasicAuthSignup.String() && identifier != enum.ForgotPassword.String() && identifier != enum.UpdateEmail.String() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func IsStringArrayEqual(a, b []string) bool {
|
func IsStringArrayEqual(a, b []string) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -24,7 +24,6 @@ func CreateVerificationToken(email string, tokenType string) (string, error) {
|
||||||
|
|
||||||
t.Claims = &CustomClaim{
|
t.Claims = &CustomClaim{
|
||||||
&jwt.StandardClaims{
|
&jwt.StandardClaims{
|
||||||
|
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
},
|
},
|
||||||
tokenType,
|
tokenType,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user