test-cases:
* completed test cases * tested for all dbs
This commit is contained in:
parent
80e8b3aaac
commit
96fdc38c3c
|
@ -267,6 +267,14 @@ func NewProvider() (*provider, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// add totp_secret and totp_verified on users table
|
||||||
|
totpTableAlterQuery := fmt.Sprintf(`ALTER TABLE %s.%s ADD (totp_verified boolean, totp_secret text, app_data text)`, KeySpace, models.Collections.User)
|
||||||
|
err = session.Query(totpTableAlterQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to alter table as column exists: ", err)
|
||||||
|
// return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: session,
|
db: session,
|
||||||
}, err
|
}, err
|
||||||
|
|
|
@ -39,6 +39,7 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
|
||||||
|
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
|
user.TotpVerified = false
|
||||||
|
|
||||||
bytes, err := json.Marshal(user)
|
bytes, err := json.Marshal(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -177,13 +178,19 @@ func (p *provider) ListUsers(ctx context.Context, pagination *model.Pagination)
|
||||||
// there is no offset in cassandra
|
// there is no offset in cassandra
|
||||||
// so we fetch till limit + offset
|
// so we fetch till limit + offset
|
||||||
// and return the results from offset to limit
|
// and return the results from offset to limit
|
||||||
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.User, pagination.Limit+pagination.Offset)
|
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, "+
|
||||||
|
"nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled,"+
|
||||||
|
" created_at, updated_at, totp_verified FROM %s LIMIT %d", KeySpace+"."+models.Collections.User,
|
||||||
|
pagination.Limit+pagination.Offset)
|
||||||
scanner := p.db.Query(query).Iter().Scanner()
|
scanner := p.db.Query(query).Iter().Scanner()
|
||||||
counter := int64(0)
|
counter := int64(0)
|
||||||
for scanner.Next() {
|
for scanner.Next() {
|
||||||
if counter >= pagination.Offset {
|
if counter >= pagination.Offset {
|
||||||
var user models.User
|
var user models.User
|
||||||
err := scanner.Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.IsMultiFactorAuthEnabled, &user.CreatedAt, &user.UpdatedAt)
|
err := scanner.Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods,
|
||||||
|
&user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber,
|
||||||
|
&user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.IsMultiFactorAuthEnabled,
|
||||||
|
&user.CreatedAt, &user.UpdatedAt, &user.TotpVerified)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -200,8 +207,8 @@ func (p *provider) ListUsers(ctx context.Context, pagination *model.Pagination)
|
||||||
// GetUserByEmail to get user information from database using email address
|
// GetUserByEmail to get user information from database using email address
|
||||||
func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.User, error) {
|
func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1 ALLOW FILTERING", KeySpace+"."+models.Collections.User, email)
|
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at, totp_secret, totp_verified, app_data FROM %s WHERE email = '%s' LIMIT 1 ALLOW FILTERING", KeySpace+"."+models.Collections.User, email)
|
||||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.IsMultiFactorAuthEnabled, &user.CreatedAt, &user.UpdatedAt)
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.IsMultiFactorAuthEnabled, &user.CreatedAt, &user.UpdatedAt, &user.TotpSecret, &user.TotpVerified, &user.AppData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -211,8 +218,8 @@ func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.Us
|
||||||
// GetUserByID to get user information from database using user ID
|
// GetUserByID to get user information from database using user ID
|
||||||
func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, error) {
|
func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, id)
|
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at, totp_secret, totp_verified, app_data FROM %s WHERE id = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, id)
|
||||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.IsMultiFactorAuthEnabled, &user.CreatedAt, &user.UpdatedAt)
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.IsMultiFactorAuthEnabled, &user.CreatedAt, &user.UpdatedAt, &user.TotpSecret, &user.TotpVerified, &user.AppData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ func (p *provider) ListUsers(ctx context.Context, pagination *model.Pagination)
|
||||||
// GetUserByEmail to get user information from database using email address
|
// GetUserByEmail to get user information from database using email address
|
||||||
func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.User, error) {
|
func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.User, error) {
|
||||||
var user *models.User
|
var user *models.User
|
||||||
query := fmt.Sprintf("SELECT _id, email, email_verified_at, `password`, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at FROM %s.%s WHERE email = $1 LIMIT 1", p.scopeName, models.Collections.User)
|
query := fmt.Sprintf("SELECT _id, email, email_verified_at, `password`, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at, totp_secret, totp_verified FROM %s.%s WHERE email = $1 LIMIT 1", p.scopeName, models.Collections.User)
|
||||||
q, err := p.db.Query(query, &gocb.QueryOptions{
|
q, err := p.db.Query(query, &gocb.QueryOptions{
|
||||||
ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
|
ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
|
@ -122,7 +122,7 @@ func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.Us
|
||||||
// GetUserByID to get user information from database using user ID
|
// GetUserByID to get user information from database using user ID
|
||||||
func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, error) {
|
func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, error) {
|
||||||
var user *models.User
|
var user *models.User
|
||||||
query := fmt.Sprintf("SELECT _id, email, email_verified_at, `password`, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at FROM %s.%s WHERE _id = $1 LIMIT 1", p.scopeName, models.Collections.User)
|
query := fmt.Sprintf("SELECT _id, email, email_verified_at, `password`, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, is_multi_factor_auth_enabled, created_at, updated_at, totp_secret, totp_verified FROM %s.%s WHERE _id = $1 LIMIT 1", p.scopeName, models.Collections.User)
|
||||||
q, err := p.db.Query(query, &gocb.QueryOptions{
|
q, err := p.db.Query(query, &gocb.QueryOptions{
|
||||||
ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
|
ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
|
|
|
@ -13,6 +13,7 @@ require (
|
||||||
github.com/go-playground/validator/v10 v10.11.1 // indirect
|
github.com/go-playground/validator/v10 v10.11.1 // indirect
|
||||||
github.com/goccy/go-json v0.9.11 // indirect
|
github.com/goccy/go-json v0.9.11 // indirect
|
||||||
github.com/gocql/gocql v1.2.0
|
github.com/gocql/gocql v1.2.0
|
||||||
|
github.com/gokyle/twofactor v1.0.1
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/google/go-cmp v0.5.6 // indirect
|
github.com/google/go-cmp v0.5.6 // indirect
|
||||||
|
@ -26,6 +27,7 @@ require (
|
||||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
|
github.com/tuotoo/qrcode v0.0.0-20220425170535-52ccc2bebf5d
|
||||||
github.com/twilio/twilio-go v1.7.2
|
github.com/twilio/twilio-go v1.7.2
|
||||||
github.com/vektah/gqlparser/v2 v2.5.1
|
github.com/vektah/gqlparser/v2 v2.5.1
|
||||||
go.mongodb.org/mongo-driver v1.8.1
|
go.mongodb.org/mongo-driver v1.8.1
|
||||||
|
|
|
@ -56,6 +56,8 @@ github.com/aws/aws-sdk-go v1.44.298/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8
|
||||||
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
||||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||||
|
github.com/bits-and-blooms/bitset v1.2.1 h1:M+/hrU9xlMp7t4TyTDQW97d3tRPVuKFC6zBEK16QnXY=
|
||||||
|
github.com/bits-and-blooms/bitset v1.2.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||||
|
@ -131,6 +133,8 @@ github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
|
||||||
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/gocql/gocql v1.2.0 h1:TZhsCd7fRuye4VyHr3WCvWwIQaZUmjsqnSIXK9FcVCE=
|
github.com/gocql/gocql v1.2.0 h1:TZhsCd7fRuye4VyHr3WCvWwIQaZUmjsqnSIXK9FcVCE=
|
||||||
github.com/gocql/gocql v1.2.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
|
github.com/gocql/gocql v1.2.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
|
||||||
|
github.com/gokyle/twofactor v1.0.1 h1:uRhvx0S4Hb82RPIDALnf7QxbmPL49LyyaCkJDpWx+Ek=
|
||||||
|
github.com/gokyle/twofactor v1.0.1/go.mod h1:4gxzH1eaE/F3Pct/sCDNOylP0ClofUO5j4XZN9tKtLE=
|
||||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
|
@ -256,6 +260,8 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic
|
||||||
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275 h1:IZycmTpoUtQK3PD60UYBwjaCUHUP7cML494ao9/O8+Q=
|
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275 h1:IZycmTpoUtQK3PD60UYBwjaCUHUP7cML494ao9/O8+Q=
|
||||||
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:zt6UU74K6Z6oMOYJbJzYpYucqdcQwSMPBEdSvGiaUMw=
|
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:zt6UU74K6Z6oMOYJbJzYpYucqdcQwSMPBEdSvGiaUMw=
|
||||||
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
|
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
|
||||||
|
github.com/maruel/rs v1.1.0 h1:dh4OceAF5yD06EASOrb+DS358LI4g0B90YApSdjCP6U=
|
||||||
|
github.com/maruel/rs v1.1.0/go.mod h1:vzwMjzSJJxLIXmU62qHj6O5QRn5kvCKxFrfaFCxBcUY=
|
||||||
github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk=
|
github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
@ -323,6 +329,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
|
github.com/tuotoo/qrcode v0.0.0-20220425170535-52ccc2bebf5d h1:4x1FeGJRB00cvxnKXnRJDT89fvG/Lzm2ecm0vlr/qDs=
|
||||||
|
github.com/tuotoo/qrcode v0.0.0-20220425170535-52ccc2bebf5d/go.mod h1:uSELzeIcTceNCgzbKdJuJa0ouCqqtkyzL+6bnA3rM+M=
|
||||||
github.com/twilio/twilio-go v1.7.2 h1:tX38DXbSuDWWIK+tKAE2AJSMR6d8i7lf9ksY8J29VLE=
|
github.com/twilio/twilio-go v1.7.2 h1:tX38DXbSuDWWIK+tKAE2AJSMR6d8i7lf9ksY8J29VLE=
|
||||||
github.com/twilio/twilio-go v1.7.2/go.mod h1:tdnfQ5TjbewoAu4lf9bMsGvfuJ/QU9gYuv9yx3TSIXU=
|
github.com/twilio/twilio-go v1.7.2/go.mod h1:tdnfQ5TjbewoAu4lf9bMsGvfuJ/QU9gYuv9yx3TSIXU=
|
||||||
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
|
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
|
||||||
|
@ -747,5 +755,7 @@ modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
modernc.org/z v1.6.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ=
|
modernc.org/z v1.6.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
|
||||||
|
rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
@ -272,6 +272,7 @@ type ComplexityRoot struct {
|
||||||
RevokedTimestamp func(childComplexity int) int
|
RevokedTimestamp func(childComplexity int) int
|
||||||
Roles func(childComplexity int) int
|
Roles func(childComplexity int) int
|
||||||
SignupMethods func(childComplexity int) int
|
SignupMethods func(childComplexity int) int
|
||||||
|
TotpVerified func(childComplexity int) int
|
||||||
UpdatedAt func(childComplexity int) int
|
UpdatedAt func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1900,6 +1901,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||||
|
|
||||||
return e.complexity.User.SignupMethods(childComplexity), true
|
return e.complexity.User.SignupMethods(childComplexity), true
|
||||||
|
|
||||||
|
case "User.totp_verified":
|
||||||
|
if e.complexity.User.TotpVerified == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.User.TotpVerified(childComplexity), true
|
||||||
|
|
||||||
case "User.updated_at":
|
case "User.updated_at":
|
||||||
if e.complexity.User.UpdatedAt == nil {
|
if e.complexity.User.UpdatedAt == nil {
|
||||||
break
|
break
|
||||||
|
@ -2317,6 +2325,7 @@ type User {
|
||||||
revoked_timestamp: Int64
|
revoked_timestamp: Int64
|
||||||
is_multi_factor_auth_enabled: Boolean
|
is_multi_factor_auth_enabled: Boolean
|
||||||
app_data: Map
|
app_data: Map
|
||||||
|
totp_verified: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Users {
|
type Users {
|
||||||
|
@ -4013,6 +4022,8 @@ func (ec *executionContext) fieldContext_AuthResponse_user(ctx context.Context,
|
||||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||||
case "app_data":
|
case "app_data":
|
||||||
return ec.fieldContext_User_app_data(ctx, field)
|
return ec.fieldContext_User_app_data(ctx, field)
|
||||||
|
case "totp_verified":
|
||||||
|
return ec.fieldContext_User_totp_verified(ctx, field)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||||
},
|
},
|
||||||
|
@ -7524,6 +7535,8 @@ func (ec *executionContext) fieldContext_InviteMembersResponse_Users(ctx context
|
||||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||||
case "app_data":
|
case "app_data":
|
||||||
return ec.fieldContext_User_app_data(ctx, field)
|
return ec.fieldContext_User_app_data(ctx, field)
|
||||||
|
case "totp_verified":
|
||||||
|
return ec.fieldContext_User_totp_verified(ctx, field)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||||
},
|
},
|
||||||
|
@ -9357,6 +9370,8 @@ func (ec *executionContext) fieldContext_Mutation__update_user(ctx context.Conte
|
||||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||||
case "app_data":
|
case "app_data":
|
||||||
return ec.fieldContext_User_app_data(ctx, field)
|
return ec.fieldContext_User_app_data(ctx, field)
|
||||||
|
case "totp_verified":
|
||||||
|
return ec.fieldContext_User_totp_verified(ctx, field)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||||
},
|
},
|
||||||
|
@ -10669,6 +10684,8 @@ func (ec *executionContext) fieldContext_Query_profile(ctx context.Context, fiel
|
||||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||||
case "app_data":
|
case "app_data":
|
||||||
return ec.fieldContext_User_app_data(ctx, field)
|
return ec.fieldContext_User_app_data(ctx, field)
|
||||||
|
case "totp_verified":
|
||||||
|
return ec.fieldContext_User_totp_verified(ctx, field)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||||
},
|
},
|
||||||
|
@ -10938,6 +10955,8 @@ func (ec *executionContext) fieldContext_Query__user(ctx context.Context, field
|
||||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||||
case "app_data":
|
case "app_data":
|
||||||
return ec.fieldContext_User_app_data(ctx, field)
|
return ec.fieldContext_User_app_data(ctx, field)
|
||||||
|
case "totp_verified":
|
||||||
|
return ec.fieldContext_User_totp_verified(ctx, field)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||||
},
|
},
|
||||||
|
@ -12846,6 +12865,47 @@ func (ec *executionContext) fieldContext_User_app_data(ctx context.Context, fiel
|
||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _User_totp_verified(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_User_totp_verified(ctx, field)
|
||||||
|
if err != nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.TotpVerified, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(*bool)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_User_totp_verified(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "User",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
return nil, errors.New("field of type Boolean does not have child fields")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Users_pagination(ctx context.Context, field graphql.CollectedField, obj *model.Users) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Users_pagination(ctx context.Context, field graphql.CollectedField, obj *model.Users) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_Users_pagination(ctx, field)
|
fc, err := ec.fieldContext_Users_pagination(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -12979,6 +13039,8 @@ func (ec *executionContext) fieldContext_Users_users(ctx context.Context, field
|
||||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||||
case "app_data":
|
case "app_data":
|
||||||
return ec.fieldContext_User_app_data(ctx, field)
|
return ec.fieldContext_User_app_data(ctx, field)
|
||||||
|
case "totp_verified":
|
||||||
|
return ec.fieldContext_User_totp_verified(ctx, field)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||||
},
|
},
|
||||||
|
@ -13194,6 +13256,8 @@ func (ec *executionContext) fieldContext_ValidateSessionResponse_user(ctx contex
|
||||||
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
return ec.fieldContext_User_is_multi_factor_auth_enabled(ctx, field)
|
||||||
case "app_data":
|
case "app_data":
|
||||||
return ec.fieldContext_User_app_data(ctx, field)
|
return ec.fieldContext_User_app_data(ctx, field)
|
||||||
|
case "totp_verified":
|
||||||
|
return ec.fieldContext_User_totp_verified(ctx, field)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||||
},
|
},
|
||||||
|
@ -20329,6 +20393,10 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj
|
||||||
|
|
||||||
out.Values[i] = ec._User_app_data(ctx, field, obj)
|
out.Values[i] = ec._User_app_data(ctx, field, obj)
|
||||||
|
|
||||||
|
case "totp_verified":
|
||||||
|
|
||||||
|
out.Values[i] = ec._User_totp_verified(ctx, field, obj)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("unknown field " + strconv.Quote(field.Name))
|
panic("unknown field " + strconv.Quote(field.Name))
|
||||||
}
|
}
|
||||||
|
|
|
@ -455,6 +455,7 @@ type User struct {
|
||||||
RevokedTimestamp *int64 `json:"revoked_timestamp"`
|
RevokedTimestamp *int64 `json:"revoked_timestamp"`
|
||||||
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
|
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"`
|
||||||
AppData map[string]interface{} `json:"app_data"`
|
AppData map[string]interface{} `json:"app_data"`
|
||||||
|
TotpVerified *bool `json:"totp_verified"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Users struct {
|
type Users struct {
|
||||||
|
|
|
@ -52,6 +52,7 @@ type User {
|
||||||
revoked_timestamp: Int64
|
revoked_timestamp: Int64
|
||||||
is_multi_factor_auth_enabled: Boolean
|
is_multi_factor_auth_enabled: Boolean
|
||||||
app_data: Map
|
app_data: Map
|
||||||
|
totp_verified: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Users {
|
type Users {
|
||||||
|
|
|
@ -54,6 +54,9 @@ func resendOTPTest(t *testing.T, s TestSetup) {
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, updateRes)
|
assert.NotNil(t, updateRes)
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMailOTPLogin, false)
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableTOTPLogin, true)
|
||||||
|
|
||||||
// Resend otp should return error as no initial opt is being sent
|
// Resend otp should return error as no initial opt is being sent
|
||||||
resendOtpRes, err := resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{
|
resendOtpRes, err := resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{
|
||||||
Email: refs.NewStringRef(email),
|
Email: refs.NewStringRef(email),
|
||||||
|
|
|
@ -28,6 +28,8 @@ func revokeAccessTest(t *testing.T, s TestSetup) {
|
||||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||||
Token: verificationRequest.Token,
|
Token: verificationRequest.Token,
|
||||||
})
|
})
|
||||||
|
fmt.Println("\n", verifyRes)
|
||||||
|
fmt.Println("\n", err)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, verifyRes.AccessToken)
|
assert.NotNil(t, verifyRes.AccessToken)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ func verificationRequestsTest(t *testing.T, s TestSetup) {
|
||||||
Password: s.TestInfo.Password,
|
Password: s.TestInfo.Password,
|
||||||
ConfirmPassword: s.TestInfo.Password,
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
})
|
})
|
||||||
|
fmt.Println("res", res)
|
||||||
|
fmt.Println("err", err)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, res)
|
assert.NotNil(t, res)
|
||||||
limit := int64(10)
|
limit := int64(10)
|
||||||
|
|
|
@ -54,6 +54,8 @@ func verifyOTPTest(t *testing.T, s TestSetup) {
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, updateProfileRes.Message)
|
assert.NotEmpty(t, updateProfileRes.Message)
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMailOTPLogin, false)
|
||||||
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableTOTPLogin, true)
|
||||||
|
|
||||||
// Login should not return error but access token should be empty as otp should have been sent
|
// Login should not return error but access token should be empty as otp should have been sent
|
||||||
loginRes, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
loginRes, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
||||||
|
|
|
@ -1,18 +1,30 @@
|
||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
|
"github.com/gokyle/twofactor"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/tuotoo/qrcode"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func verifyTOTPTest(t *testing.T, s TestSetup) {
|
func verifyTOTPTest(t *testing.T, s TestSetup) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
t.Run(`should verify totp`, func(t *testing.T) {
|
t.Run(`should verify totp`, func(t *testing.T) {
|
||||||
_, ctx := createContext(s)
|
req, ctx := createContext(s)
|
||||||
email := "verify_otp." + s.TestInfo.Email
|
email := "verify_totp." + s.TestInfo.Email
|
||||||
|
cleanData(email)
|
||||||
res, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
res, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||||
Email: email,
|
Email: email,
|
||||||
Password: s.TestInfo.Password,
|
Password: s.TestInfo.Password,
|
||||||
|
@ -28,54 +40,108 @@ func verifyTOTPTest(t *testing.T, s TestSetup) {
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, loginRes)
|
assert.Nil(t, loginRes)
|
||||||
_, err = db.Provider.GenerateTotp(ctx, loginRes.User.ID)
|
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
//assert.Equal(t, ??, string)
|
assert.Equal(t, email, verificationRequest.Email)
|
||||||
// verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||||
// Token: verificationRequest.Token,
|
Token: verificationRequest.Token,
|
||||||
// })
|
})
|
||||||
// assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
// assert.NotEqual(t, verifyRes.AccessToken, "", "access token should not be empty")
|
assert.NotEqual(t, verifyRes.AccessToken, "", "access token should not be empty")
|
||||||
//
|
|
||||||
// // Using access token update profile
|
// Using access token update profile
|
||||||
// s.GinContext.Request.Header.Set("Authorization", "Bearer "+refs.StringValue(verifyRes.AccessToken))
|
s.GinContext.Request.Header.Set("Authorization", "Bearer "+refs.StringValue(verifyRes.AccessToken))
|
||||||
// ctx = context.WithValue(req.Context(), "GinContextKey", s.GinContext)
|
ctx = context.WithValue(req.Context(), "GinContextKey", s.GinContext)
|
||||||
// updateProfileRes, err := resolvers.UpdateProfileResolver(ctx, model.UpdateProfileInput{
|
updateProfileRes, err := resolvers.UpdateProfileResolver(ctx, model.UpdateProfileInput{
|
||||||
// IsMultiFactorAuthEnabled: refs.NewBoolRef(true),
|
IsMultiFactorAuthEnabled: refs.NewBoolRef(true),
|
||||||
// })
|
})
|
||||||
// assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// assert.NotEmpty(t, updateProfileRes.Message)
|
assert.NotEmpty(t, updateProfileRes.Message)
|
||||||
//
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableTOTPLogin, false)
|
||||||
// // Login should not return error but access token should be empty as otp should have been sent
|
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMailOTPLogin, true)
|
||||||
// loginRes, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
|
||||||
// Email: email,
|
// Login should not return error but access token should be empty
|
||||||
// Password: s.TestInfo.Password,
|
loginRes, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
||||||
// })
|
Email: email,
|
||||||
// assert.NoError(t, err)
|
Password: s.TestInfo.Password,
|
||||||
// assert.NotNil(t, loginRes)
|
})
|
||||||
// assert.Nil(t, loginRes.AccessToken)
|
assert.NoError(t, err)
|
||||||
//
|
assert.NotNil(t, loginRes)
|
||||||
// // Get otp from db
|
assert.NotNil(t, loginRes.TotpBase64url)
|
||||||
// otp, err := db.Provider.GetOTPByEmail(ctx, email)
|
assert.NotNil(t, loginRes.TokenTotp)
|
||||||
// assert.NoError(t, err)
|
assert.Nil(t, loginRes.AccessToken)
|
||||||
// assert.NotEmpty(t, otp.Otp)
|
assert.Equal(t, loginRes.Message, `Proceed to totp screen`)
|
||||||
// // Get user by email
|
|
||||||
// user, err := db.Provider.GetUserByEmail(ctx, email)
|
// get totp url for validation
|
||||||
// assert.NoError(t, err)
|
pngBytes, err := base64.StdEncoding.DecodeString(*loginRes.TotpBase64url)
|
||||||
// assert.NotNil(t, user)
|
assert.NoError(t, err)
|
||||||
// // Set mfa cookie session
|
qrmatrix, err := qrcode.Decode(bytes.NewReader(pngBytes))
|
||||||
// mfaSession := uuid.NewString()
|
assert.NoError(t, err)
|
||||||
// memorystore.Provider.SetMfaSession(user.ID, mfaSession, time.Now().Add(1*time.Minute).Unix())
|
tf, label, err := twofactor.FromURL(qrmatrix.Content)
|
||||||
// cookie := fmt.Sprintf("%s=%s;", constants.MfaCookieName+"_session", mfaSession)
|
data := strings.Split(label, ":")
|
||||||
// cookie = strings.TrimSuffix(cookie, ";")
|
assert.NoError(t, err)
|
||||||
// req.Header.Set("Cookie", cookie)
|
assert.Equal(t, email, data[1])
|
||||||
// verifyOtpRes, err := resolvers.VerifyOtpResolver(ctx, model.VerifyOTPRequest{
|
assert.NotNil(t, tf)
|
||||||
// Email: &email,
|
|
||||||
// Otp: otp.Otp,
|
code := tf.OTP()
|
||||||
// })
|
|
||||||
// assert.Nil(t, err)
|
assert.NotEmpty(t, code)
|
||||||
// assert.NotEqual(t, verifyOtpRes.AccessToken, "", "access token should not be empty")
|
|
||||||
// cleanData(email)
|
valid, err := resolvers.VerifyTotpResolver(ctx, model.VerifyTOTPRequest{
|
||||||
//})
|
Otp: code,
|
||||||
|
Token: *loginRes.TokenTotp,
|
||||||
|
})
|
||||||
|
|
||||||
|
accessToken := *valid.AccessToken
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, accessToken)
|
||||||
|
assert.Equal(t, `Logged in successfully`, valid.Message)
|
||||||
|
|
||||||
|
assert.NotEmpty(t, accessToken)
|
||||||
|
claims, err := token.ParseJWTToken(accessToken)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, claims)
|
||||||
|
loginMethod := claims["login_method"]
|
||||||
|
sessionKey := verifyRes.User.ID
|
||||||
|
if loginMethod != nil && loginMethod != "" {
|
||||||
|
sessionKey = loginMethod.(string) + ":" + verifyRes.User.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionToken, err := memorystore.Provider.GetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+claims["nonce"].(string))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, sessionToken)
|
||||||
|
|
||||||
|
cookie := fmt.Sprintf("%s=%s;", constants.AppCookieName+"_session", sessionToken)
|
||||||
|
cookie = strings.TrimSuffix(cookie, ";")
|
||||||
|
|
||||||
|
req.Header.Set("Cookie", cookie)
|
||||||
|
//logged out
|
||||||
|
logout, err := resolvers.LogoutResolver(ctx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, logout.Message, `Logged out successfully`)
|
||||||
|
|
||||||
|
loginRes, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
||||||
|
Email: email,
|
||||||
|
Password: s.TestInfo.Password,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, loginRes)
|
||||||
|
assert.NotNil(t, loginRes.TokenTotp)
|
||||||
|
assert.Nil(t, loginRes.TotpBase64url)
|
||||||
|
assert.Nil(t, loginRes.AccessToken)
|
||||||
|
assert.Equal(t, loginRes.Message, `Proceed to totp screen`)
|
||||||
|
|
||||||
|
code = tf.OTP()
|
||||||
|
assert.NotEmpty(t, code)
|
||||||
|
|
||||||
|
valid, err = resolvers.VerifyTotpResolver(ctx, model.VerifyTOTPRequest{
|
||||||
|
Otp: code,
|
||||||
|
Token: *loginRes.TokenTotp,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, *valid.AccessToken)
|
||||||
|
assert.Equal(t, `Logged in successfully`, valid.Message)
|
||||||
|
|
||||||
|
cleanData(email)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user