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_TYPE=sqlite
|
||||
ADMIN_SECRET=admin
|
||||
DISABLE_EMAIL_VERIFICATION=true
|
||||
JWT_SECRET=random_string
|
||||
SENDER_EMAIL=username
|
||||
SENDER_PASSWORD=password
|
||||
SMTP_HOST=smtp.mailtrap.io
|
||||
SMTP_PORT=2525
|
||||
JWT_TYPE=HS256
|
||||
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
|
||||
}
|
||||
|
|
|
@ -26,8 +26,9 @@ type Manager interface {
|
|||
GetVerificationByToken(token string) (VerificationRequest, error)
|
||||
DeleteVerificationRequest(verificationRequest VerificationRequest) error
|
||||
GetVerificationRequests() ([]VerificationRequest, error)
|
||||
GetVerificationByEmail(email string) (VerificationRequest, error)
|
||||
GetVerificationByEmail(email string, identifier string) (VerificationRequest, error)
|
||||
AddSession(session Session) error
|
||||
DeleteUserSession(userId string) error
|
||||
}
|
||||
|
||||
type manager struct {
|
||||
|
@ -94,8 +95,8 @@ func InitDB() {
|
|||
|
||||
Mgr = &manager{
|
||||
sqlDB: nil,
|
||||
mongodb: nil,
|
||||
arangodb: arangodb,
|
||||
mongodb: nil,
|
||||
}
|
||||
|
||||
break
|
||||
|
|
|
@ -65,6 +65,13 @@ func initMongodb() (*mongo.Database, error) {
|
|||
}, options.CreateIndexes())
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
@ -12,7 +14,7 @@ import (
|
|||
type Session struct {
|
||||
Key string `json:"_key,omitempty" bson:"_key,omitempty"` // for arangodb
|
||||
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:"-"`
|
||||
UserAgent string `json:"user_agent" bson:"user_agent"`
|
||||
IP string `json:"ip" bson:"ip"`
|
||||
|
@ -63,3 +65,38 @@ func (mgr *manager) AddSession(session Session) error {
|
|||
|
||||
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"
|
||||
arangoDriver "github.com/arangodb/go-driver"
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
@ -41,6 +42,10 @@ func (mgr *manager) AddUser(user User) (User, error) {
|
|||
user.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
if user.Roles == "" {
|
||||
user.Roles = constants.DEFAULT_ROLES[0]
|
||||
}
|
||||
|
||||
if IsORMSupported {
|
||||
// copy id as value for fields required for mongodb & arangodb
|
||||
user.Key = user.ID
|
||||
|
@ -111,7 +116,7 @@ func (mgr *manager) UpdateUser(user User) (User, error) {
|
|||
|
||||
if IsMongoDB {
|
||||
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 {
|
||||
log.Println("error updating user:", err)
|
||||
return user, err
|
||||
|
@ -240,7 +245,7 @@ func (mgr *manager) GetUserByID(id string) (User, error) {
|
|||
}
|
||||
|
||||
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{}{
|
||||
"id": id,
|
||||
}
|
||||
|
@ -267,7 +272,7 @@ func (mgr *manager) GetUserByID(id string) (User, error) {
|
|||
|
||||
if IsMongoDB {
|
||||
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 {
|
||||
return user, err
|
||||
}
|
||||
|
@ -297,7 +302,7 @@ func (mgr *manager) DeleteUser(user User) error {
|
|||
|
||||
if IsMongoDB {
|
||||
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 {
|
||||
log.Println("error deleting user:", err)
|
||||
return err
|
||||
|
|
|
@ -179,10 +179,10 @@ func (mgr *manager) GetVerificationByToken(token string) (VerificationRequest, e
|
|||
return verification, nil
|
||||
}
|
||||
|
||||
func (mgr *manager) GetVerificationByEmail(email string) (VerificationRequest, error) {
|
||||
func (mgr *manager) GetVerificationByEmail(email string, identifier string) (VerificationRequest, error) {
|
||||
var verification VerificationRequest
|
||||
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 {
|
||||
log.Println(`error getting verification token:`, result.Error)
|
||||
|
@ -191,9 +191,10 @@ func (mgr *manager) GetVerificationByEmail(email string) (VerificationRequest, e
|
|||
}
|
||||
|
||||
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{}{
|
||||
"email": email,
|
||||
"identifier": identifier,
|
||||
}
|
||||
|
||||
cursor, err := mgr.arangodb.Query(nil, query, bindVars)
|
||||
|
@ -218,7 +219,7 @@ func (mgr *manager) GetVerificationByEmail(email string) (VerificationRequest, e
|
|||
|
||||
if IsMongoDB {
|
||||
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 {
|
||||
return verification, err
|
||||
}
|
||||
|
@ -248,7 +249,7 @@ func (mgr *manager) DeleteVerificationRequest(verificationRequest VerificationRe
|
|||
|
||||
if IsMongoDB {
|
||||
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 {
|
||||
log.Println("error deleting verification request::", err)
|
||||
return err
|
||||
|
|
15
server/env/env.go
vendored
15
server/env/env.go
vendored
|
@ -1,7 +1,6 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -25,13 +24,8 @@ func InitEnv() {
|
|||
if constants.ENV_PATH == "" {
|
||||
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 != "" {
|
||||
if ARG_ENV_FILE != nil && *ARG_ENV_FILE != "" {
|
||||
constants.ENV_PATH = *ARG_ENV_FILE
|
||||
}
|
||||
|
||||
|
@ -65,8 +59,9 @@ func InitEnv() {
|
|||
|
||||
if constants.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
|
||||
}
|
||||
|
||||
|
@ -78,7 +73,7 @@ func InitEnv() {
|
|||
if constants.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
|
||||
}
|
||||
|
||||
|
@ -129,7 +124,7 @@ func InitEnv() {
|
|||
if constants.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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ type ComplexityRoot struct {
|
|||
Query struct {
|
||||
Meta 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
|
||||
VerificationRequests func(childComplexity int) int
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ type MutationResolver interface {
|
|||
}
|
||||
type QueryResolver interface {
|
||||
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)
|
||||
Users(ctx context.Context) ([]*model.User, 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
|
||||
|
||||
case "Query.token":
|
||||
if e.complexity.Query.Token == nil {
|
||||
case "Query.session":
|
||||
if e.complexity.Query.Session == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Query_token_args(context.TODO(), rawArgs)
|
||||
args, err := ec.field_Query_session_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
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":
|
||||
if e.complexity.Query.Users == nil {
|
||||
|
@ -746,6 +746,7 @@ input VerifyEmailInput {
|
|||
|
||||
input ResendVerifyEmailInput {
|
||||
email: String!
|
||||
identifier: String!
|
||||
}
|
||||
|
||||
input UpdateProfileInput {
|
||||
|
@ -813,7 +814,7 @@ type Mutation {
|
|||
|
||||
type Query {
|
||||
meta: Meta!
|
||||
token(roles: [String!]): AuthResponse
|
||||
session(roles: [String!]): AuthResponse
|
||||
profile: User!
|
||||
# admin only apis
|
||||
_users: [User!]!
|
||||
|
@ -992,7 +993,7 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs
|
|||
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
|
||||
args := map[string]interface{}{}
|
||||
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)
|
||||
}
|
||||
|
||||
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() {
|
||||
if r := recover(); r != nil {
|
||||
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)
|
||||
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 {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
|
@ -2006,7 +2007,7 @@ func (ec *executionContext) _Query_token(ctx context.Context, field graphql.Coll
|
|||
fc.Args = args
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
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 {
|
||||
ec.Error(ctx, err)
|
||||
|
@ -4272,6 +4273,14 @@ func (ec *executionContext) unmarshalInputResendVerifyEmailInput(ctx context.Con
|
|||
if err != nil {
|
||||
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
|
||||
})
|
||||
case "token":
|
||||
case "session":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
|
@ -4913,7 +4922,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
|||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Query_token(ctx, field)
|
||||
res = ec._Query_session(ctx, field)
|
||||
return res
|
||||
})
|
||||
case "profile":
|
||||
|
|
|
@ -45,6 +45,7 @@ type Meta struct {
|
|||
|
||||
type ResendVerifyEmailInput struct {
|
||||
Email string `json:"email"`
|
||||
Identifier string `json:"identifier"`
|
||||
}
|
||||
|
||||
type ResetPasswordInput struct {
|
||||
|
|
|
@ -89,6 +89,7 @@ input VerifyEmailInput {
|
|||
|
||||
input ResendVerifyEmailInput {
|
||||
email: String!
|
||||
identifier: String!
|
||||
}
|
||||
|
||||
input UpdateProfileInput {
|
||||
|
@ -156,7 +157,7 @@ type Mutation {
|
|||
|
||||
type Query {
|
||||
meta: Meta!
|
||||
token(roles: [String!]): AuthResponse
|
||||
session(roles: [String!]): AuthResponse
|
||||
profile: User!
|
||||
# admin only apis
|
||||
_users: [User!]!
|
||||
|
|
|
@ -59,7 +59,7 @@ func (r *queryResolver) Meta(ctx context.Context) (*model.Meta, error) {
|
|||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -264,15 +264,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, inputRoles)
|
||||
utils.SetCookie(c, accessToken)
|
||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
||||
go func() {
|
||||
sessionData := db.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(c.Request),
|
||||
IP: utils.GetIP(c.Request),
|
||||
}
|
||||
|
||||
db.Mgr.AddSession(sessionData)
|
||||
}()
|
||||
utils.CreateSession(user.ID, c)
|
||||
|
||||
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -54,22 +53,13 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
// delete from verification table
|
||||
db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||
|
||||
userIdStr := fmt.Sprintf("%v", user.ID)
|
||||
roles := strings.Split(user.Roles, ",")
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
||||
|
||||
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||
|
||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
||||
go func() {
|
||||
sessionData := db.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(c.Request),
|
||||
IP: utils.GetIP(c.Request),
|
||||
}
|
||||
|
||||
db.Mgr.AddSession(sessionData)
|
||||
}()
|
||||
session.SetToken(user.ID, accessToken, refreshToken)
|
||||
utils.CreateSession(user.ID, c)
|
||||
utils.SetCookie(c, accessToken)
|
||||
c.Redirect(http.StatusTemporaryRedirect, claim.RedirectURL)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/env"
|
||||
|
@ -12,6 +14,12 @@ import (
|
|||
)
|
||||
|
||||
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()
|
||||
db.InitDB()
|
||||
session.InitSession()
|
||||
|
@ -20,7 +28,8 @@ func main() {
|
|||
|
||||
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/*")
|
||||
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)
|
||||
|
||||
session.SetToken(user.ID, accessToken, refreshToken)
|
||||
go func() {
|
||||
sessionData := db.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
}
|
||||
|
||||
db.Mgr.AddSession(sessionData)
|
||||
}()
|
||||
utils.CreateSession(user.ID, gc)
|
||||
|
||||
res = &model.AuthResponse{
|
||||
Message: `Logged in successfully`,
|
||||
|
|
|
@ -20,18 +20,28 @@ func ResendVerifyEmail(ctx context.Context, params model.ResendVerifyEmailInput)
|
|||
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 {
|
||||
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 {
|
||||
log.Println(`error generating token`, err)
|
||||
}
|
||||
db.Mgr.AddVerification(db.VerificationRequest{
|
||||
Token: token,
|
||||
Identifier: verificationRequest.Identifier,
|
||||
Identifier: params.Identifier,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
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)
|
||||
|
||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
||||
go func() {
|
||||
sessionData := db.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
}
|
||||
|
||||
db.Mgr.AddSession(sessionData)
|
||||
}()
|
||||
utils.CreateSession(user.ID, gc)
|
||||
res = &model.AuthResponse{
|
||||
Message: `Signed up successfully.`,
|
||||
AccessToken: &accessToken,
|
||||
|
|
|
@ -66,15 +66,7 @@ func Token(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
|||
session.DeleteVerificationRequest(userIdStr, token)
|
||||
token, expiresAt, _ = utils.CreateAuthToken(user, enum.AccessToken, claimRoles)
|
||||
session.SetToken(userIdStr, token, currentRefreshToken)
|
||||
go func() {
|
||||
sessionData := db.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
}
|
||||
|
||||
db.Mgr.AddSession(sessionData)
|
||||
}()
|
||||
utils.CreateSession(user.ID, gc)
|
||||
}
|
||||
|
||||
utils.SetCookie(gc, token)
|
||||
|
|
|
@ -43,22 +43,13 @@ func VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.Aut
|
|||
// delete from verification table
|
||||
db.Mgr.DeleteVerificationRequest(verificationRequest)
|
||||
|
||||
userIdStr := fmt.Sprintf("%v", user.ID)
|
||||
roles := strings.Split(user.Roles, ",")
|
||||
refreshToken, _, _ := utils.CreateAuthToken(user, enum.RefreshToken, roles)
|
||||
|
||||
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
|
||||
|
||||
session.SetToken(userIdStr, accessToken, refreshToken)
|
||||
go func() {
|
||||
sessionData := db.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
}
|
||||
|
||||
db.Mgr.AddSession(sessionData)
|
||||
}()
|
||||
session.SetToken(user.ID, accessToken, refreshToken)
|
||||
utils.CreateSession(user.ID, gc)
|
||||
|
||||
res = &model.AuthResponse{
|
||||
Message: `Email verified successfully.`,
|
||||
|
|
|
@ -2,44 +2,25 @@ package test
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"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"
|
||||
)
|
||||
|
||||
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
|
||||
notAllowedOrigin := "http://myapp.com"
|
||||
|
||||
server := httptest.NewServer(router)
|
||||
defer server.Close()
|
||||
|
||||
s := testSetup()
|
||||
defer s.Server.Close()
|
||||
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
|
||||
// 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.Equal(t, o, allowedOrigin, "Origins don't match")
|
||||
assert.Equal(t, o, allowedOrigin, "Origins do match")
|
||||
}
|
||||
|
|
|
@ -4,20 +4,16 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEnvs(t *testing.T) {
|
||||
constants.ENV_PATH = "../../.env.sample"
|
||||
// env.InitEnv()
|
||||
|
||||
assert.Equal(t, constants.ADMIN_SECRET, "admin")
|
||||
assert.Equal(t, constants.ENV, "production")
|
||||
assert.Equal(t, constants.DATABASE_URL, "../../data.db")
|
||||
assert.Equal(t, constants.DATABASE_TYPE, enum.Sqlite.String())
|
||||
assert.True(t, constants.DISABLE_EMAIL_VERIFICATION)
|
||||
assert.True(t, constants.DISABLE_MAGIC_LINK_LOGIN)
|
||||
assert.False(t, constants.DISABLE_EMAIL_VERIFICATION)
|
||||
assert.False(t, constants.DISABLE_MAGIC_LINK_LOGIN)
|
||||
assert.False(t, constants.DISABLE_BASIC_AUTHENTICATION)
|
||||
assert.Equal(t, constants.JWT_TYPE, "HS256")
|
||||
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
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http/httptest"
|
||||
"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/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSQLSignUp(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest("POST", "/graphql", nil)
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
ctx := context.WithValue(req.Context(), "GinContextKey", c)
|
||||
|
||||
res, err := resolvers.Signup(ctx, model.SignUpInput{
|
||||
Email: "test@yopmail.com",
|
||||
Password: "test",
|
||||
ConfirmPassword: "test",
|
||||
func commonSignupTest(s TestSetup, t *testing.T) {
|
||||
email := "signup." + s.TestInfo.Email
|
||||
res, err := resolvers.Signup(s.Ctx, model.SignUpInput{
|
||||
Email: email,
|
||||
Password: s.TestInfo.Password,
|
||||
ConfirmPassword: s.TestInfo.Password + "s",
|
||||
})
|
||||
log.Println("=> signup err:", err)
|
||||
log.Println("=> singup res:", res)
|
||||
assert.Equal(t, "success", "success")
|
||||
assert.NotNil(t, err, "invalid password errors")
|
||||
|
||||
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"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"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://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"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
@ -69,6 +70,13 @@ func IsValidRoles(userRoles []string, roles []string) bool {
|
|||
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 {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
|
|
|
@ -24,7 +24,6 @@ func CreateVerificationToken(email string, tokenType string) (string, error) {
|
|||
|
||||
t.Claims = &CustomClaim{
|
||||
&jwt.StandardClaims{
|
||||
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
},
|
||||
tokenType,
|
||||
|
|
Loading…
Reference in New Issue
Block a user