Add query for verification requests

Resolves #28
This commit is contained in:
Lakhan Samani 2021-07-18 09:52:54 +05:30
parent c6cbcd2e66
commit e2fc610762
14 changed files with 187 additions and 18 deletions

View File

@ -18,9 +18,10 @@ type Manager interface {
GetUsers() ([]User, error) GetUsers() ([]User, error)
GetUserByEmail(email string) (User, error) GetUserByEmail(email string) (User, error)
UpdateVerificationTime(verifiedAt int64, id uint) error UpdateVerificationTime(verifiedAt int64, id uint) error
AddVerification(verification Verification) (Verification, error) AddVerification(verification VerificationRequest) (VerificationRequest, error)
GetVerificationByToken(token string) (Verification, error) GetVerificationByToken(token string) (VerificationRequest, error)
DeleteToken(email string) error DeleteToken(email string) error
GetVerificationRequests() ([]VerificationRequest, error)
} }
type manager struct { type manager struct {
@ -50,7 +51,7 @@ func init() {
if err != nil { if err != nil {
log.Fatal("Failed to init db:", err) log.Fatal("Failed to init db:", err)
} else { } else {
db.AutoMigrate(&User{}, &Verification{}) db.AutoMigrate(&User{}, &VerificationRequest{})
} }
Mgr = &manager{db: db} Mgr = &manager{db: db}

View File

@ -6,7 +6,7 @@ import (
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
) )
type Verification struct { type VerificationRequest struct {
ID uint `gorm:"primaryKey"` ID uint `gorm:"primaryKey"`
Token string `gorm:"index"` Token string `gorm:"index"`
Identifier string Identifier string
@ -17,7 +17,7 @@ type Verification struct {
} }
// AddVerification function to add verification record // AddVerification function to add verification record
func (mgr *manager) AddVerification(verification Verification) (Verification, error) { func (mgr *manager) AddVerification(verification VerificationRequest) (VerificationRequest, error) {
result := mgr.db.Clauses(clause.OnConflict{ result := mgr.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "email"}}, Columns: []clause.Column{{Name: "email"}},
DoUpdates: clause.AssignmentColumns([]string{"token", "identifier", "expires_at"}), DoUpdates: clause.AssignmentColumns([]string{"token", "identifier", "expires_at"}),
@ -29,8 +29,8 @@ func (mgr *manager) AddVerification(verification Verification) (Verification, er
return verification, nil return verification, nil
} }
func (mgr *manager) GetVerificationByToken(token string) (Verification, error) { func (mgr *manager) GetVerificationByToken(token string) (VerificationRequest, error) {
var verification Verification var verification VerificationRequest
result := mgr.db.Where("token = ?", token).First(&verification) result := mgr.db.Where("token = ?", token).First(&verification)
if result.Error != nil { if result.Error != nil {
@ -42,7 +42,7 @@ func (mgr *manager) GetVerificationByToken(token string) (Verification, error) {
} }
func (mgr *manager) DeleteToken(email string) error { func (mgr *manager) DeleteToken(email string) error {
var verification Verification var verification VerificationRequest
result := mgr.db.Where("email = ?", email).Delete(&verification) result := mgr.db.Where("email = ?", email).Delete(&verification)
if result.Error != nil { if result.Error != nil {
@ -52,3 +52,14 @@ func (mgr *manager) DeleteToken(email string) error {
return nil return nil
} }
// GetUsers function to get all users
func (mgr *manager) GetVerificationRequests() ([]VerificationRequest, error) {
var verificationRequests []VerificationRequest
result := mgr.db.Find(&verificationRequests)
if result.Error != nil {
log.Println(result.Error)
return verificationRequests, result.Error
}
return verificationRequests, nil
}

View File

@ -67,6 +67,7 @@ type ComplexityRoot struct {
Profile func(childComplexity int) int Profile func(childComplexity int) int
Token func(childComplexity int) int Token func(childComplexity int) int
Users func(childComplexity int) int Users func(childComplexity int) int
VerificationRequests func(childComplexity int) int
} }
Response struct { Response struct {
@ -108,6 +109,7 @@ type QueryResolver interface {
Users(ctx context.Context) ([]*model.User, error) Users(ctx context.Context) ([]*model.User, error)
Token(ctx context.Context) (*model.LoginResponse, error) Token(ctx context.Context) (*model.LoginResponse, error)
Profile(ctx context.Context) (*model.User, error) Profile(ctx context.Context) (*model.User, error)
VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error)
} }
type executableSchema struct { type executableSchema struct {
@ -243,6 +245,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Query.Users(childComplexity), true return e.complexity.Query.Users(childComplexity), true
case "Query.verificationRequests":
if e.complexity.Query.VerificationRequests == nil {
break
}
return e.complexity.Query.VerificationRequests(childComplexity), true
case "Response.message": case "Response.message":
if e.complexity.Response.Message == nil { if e.complexity.Response.Message == nil {
break break
@ -517,6 +526,7 @@ type Query {
users: [User!]! users: [User!]!
token: LoginResponse token: LoginResponse
profile: User! profile: User!
verificationRequests: [VerificationRequest!]!
} }
`, BuiltIn: false}, `, BuiltIn: false},
} }
@ -1145,6 +1155,41 @@ func (ec *executionContext) _Query_profile(ctx context.Context, field graphql.Co
return ec.marshalNUser2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) return ec.marshalNUser2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐUser(ctx, field.Selections, res)
} }
func (ec *executionContext) _Query_verificationRequests(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Query",
Field: field,
Args: nil,
IsMethod: true,
IsResolver: true,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Query().VerificationRequests(rctx)
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.([]*model.VerificationRequest)
fc.Result = res
return ec.marshalNVerificationRequest2ᚕᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerificationRequestᚄ(ctx, field.Selections, res)
}
func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
@ -3248,6 +3293,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
} }
return res return res
}) })
case "verificationRequests":
field := field
out.Concurrently(i, func() (res graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._Query_verificationRequests(ctx, field)
if res == graphql.Null {
atomic.AddUint32(&invalids, 1)
}
return res
})
case "__type": case "__type":
out.Values[i] = ec._Query___type(ctx, field) out.Values[i] = ec._Query___type(ctx, field)
case "__schema": case "__schema":
@ -3764,6 +3823,53 @@ func (ec *executionContext) marshalNUser2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋse
return ec._User(ctx, sel, v) return ec._User(ctx, sel, v)
} }
func (ec *executionContext) marshalNVerificationRequest2ᚕᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerificationRequestᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.VerificationRequest) graphql.Marshaler {
ret := make(graphql.Array, len(v))
var wg sync.WaitGroup
isLen1 := len(v) == 1
if !isLen1 {
wg.Add(len(v))
}
for i := range v {
i := i
fc := &graphql.FieldContext{
Index: &i,
Result: &v[i],
}
ctx := graphql.WithFieldContext(ctx, fc)
f := func(i int) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = nil
}
}()
if !isLen1 {
defer wg.Done()
}
ret[i] = ec.marshalNVerificationRequest2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerificationRequest(ctx, sel, v[i])
}
if isLen1 {
f(i)
} else {
go f(i)
}
}
wg.Wait()
return ret
}
func (ec *executionContext) marshalNVerificationRequest2ᚖgithubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerificationRequest(ctx context.Context, sel ast.SelectionSet, v *model.VerificationRequest) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
return ec._VerificationRequest(ctx, sel, v)
}
func (ec *executionContext) unmarshalNVerifyEmailInput2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerifyEmailInput(ctx context.Context, v interface{}) (model.VerifyEmailInput, error) { func (ec *executionContext) unmarshalNVerifyEmailInput2githubᚗcomᚋyauthdevᚋyauthᚋserverᚋgraphᚋmodelᚐVerifyEmailInput(ctx context.Context, v interface{}) (model.VerifyEmailInput, error) {
res, err := ec.unmarshalInputVerifyEmailInput(ctx, v) res, err := ec.unmarshalInputVerifyEmailInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err) return res, graphql.ErrorOnPath(ctx, err)

View File

@ -82,4 +82,5 @@ type Query {
users: [User!]! users: [User!]!
token: LoginResponse token: LoginResponse
profile: User! profile: User!
verificationRequests: [VerificationRequest!]!
} }

View File

@ -43,6 +43,10 @@ func (r *queryResolver) Profile(ctx context.Context) (*model.User, error) {
return resolvers.Profile(ctx) return resolvers.Profile(ctx)
} }
func (r *queryResolver) VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error) {
return resolvers.VerificationRequests(ctx)
}
// Mutation returns generated.MutationResolver implementation. // Mutation returns generated.MutationResolver implementation.
func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} } func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }

View File

@ -34,9 +34,7 @@ func Login(ctx context.Context, params model.LoginInput) (*model.LoginResponse,
if user.EmailVerifiedAt <= 0 { if user.EmailVerifiedAt <= 0 {
return res, fmt.Errorf(`email not verified`) return res, fmt.Errorf(`email not verified`)
} }
// match password
cost, err := bcrypt.Cost([]byte(user.Password))
log.Println(cost, err)
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(params.Password)) err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(params.Password))
if err != nil { if err != nil {
@ -68,6 +66,8 @@ func Login(ctx context.Context, params model.LoginInput) (*model.LoginResponse,
LastName: &user.LastName, LastName: &user.LastName,
SignupMethod: user.SignupMethod, SignupMethod: user.SignupMethod,
EmailVerifiedAt: &user.EmailVerifiedAt, EmailVerifiedAt: &user.EmailVerifiedAt,
CreatedAt: &user.CreatedAt,
UpdatedAt: &user.UpdatedAt,
}, },
} }

View File

@ -48,6 +48,8 @@ func Profile(ctx context.Context) (*model.User, error) {
LastName: &user.LastName, LastName: &user.LastName,
SignupMethod: user.SignupMethod, SignupMethod: user.SignupMethod,
EmailVerifiedAt: &user.EmailVerifiedAt, EmailVerifiedAt: &user.EmailVerifiedAt,
CreatedAt: &user.CreatedAt,
UpdatedAt: &user.UpdatedAt,
} }
return res, nil return res, nil

View File

@ -62,7 +62,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.Response, err
if err != nil { if err != nil {
log.Println(`Error generating token`, err) log.Println(`Error generating token`, err)
} }
db.Mgr.AddVerification(db.Verification{ db.Mgr.AddVerification(db.VerificationRequest{
Token: token, Token: token,
Identifier: verificationType, Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),

View File

@ -58,6 +58,8 @@ func Token(ctx context.Context) (*model.LoginResponse, error) {
Image: &user.Image, Image: &user.Image,
FirstName: &user.FirstName, FirstName: &user.FirstName,
LastName: &user.LastName, LastName: &user.LastName,
CreatedAt: &user.CreatedAt,
UpdatedAt: &user.UpdatedAt,
}, },
} }
return res, nil return res, nil

View File

@ -109,7 +109,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
if err != nil { if err != nil {
log.Println(`Error generating token`, err) log.Println(`Error generating token`, err)
} }
db.Mgr.AddVerification(db.Verification{ db.Mgr.AddVerification(db.VerificationRequest{
Token: token, Token: token,
Identifier: verificationType, Identifier: verificationType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),

View File

@ -34,6 +34,8 @@ func Users(ctx context.Context) ([]*model.User, error) {
LastName: &user.LastName, LastName: &user.LastName,
Password: &user.Password, Password: &user.Password,
EmailVerifiedAt: &user.EmailVerifiedAt, EmailVerifiedAt: &user.EmailVerifiedAt,
CreatedAt: &user.CreatedAt,
UpdatedAt: &user.UpdatedAt,
}) })
} }

View File

@ -0,0 +1,40 @@
package resolvers
import (
"context"
"fmt"
"github.com/yauthdev/yauth/server/db"
"github.com/yauthdev/yauth/server/graph/model"
"github.com/yauthdev/yauth/server/utils"
)
func VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error) {
gc, err := utils.GinContextFromContext(ctx)
var res []*model.VerificationRequest
if err != nil {
return res, err
}
if !utils.IsSuperAdmin(gc) {
return res, fmt.Errorf("unauthorized")
}
verificationRequests, err := db.Mgr.GetVerificationRequests()
if err != nil {
return res, err
}
for _, verificationRequest := range verificationRequests {
res = append(res, &model.VerificationRequest{
ID: fmt.Sprintf("%d", verificationRequest.ID),
Email: &verificationRequest.Email,
Token: &verificationRequest.Token,
Expires: &verificationRequest.ExpiresAt,
CreatedAt: &verificationRequest.CreatedAt,
UpdatedAt: &verificationRequest.UpdatedAt,
})
}
return res, nil
}

View File

@ -65,6 +65,8 @@ func VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.Log
LastName: &user.LastName, LastName: &user.LastName,
SignupMethod: user.SignupMethod, SignupMethod: user.SignupMethod,
EmailVerifiedAt: &user.EmailVerifiedAt, EmailVerifiedAt: &user.EmailVerifiedAt,
CreatedAt: &user.CreatedAt,
UpdatedAt: &user.UpdatedAt,
}, },
} }

View File

@ -2,7 +2,6 @@ package main
import ( import (
"context" "context"
"log"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/yauthdev/yauth/server/enum" "github.com/yauthdev/yauth/server/enum"
@ -27,7 +26,6 @@ func main() {
r.GET("/login/google", handlers.HandleOAuthLogin(enum.GoogleProvider)) r.GET("/login/google", handlers.HandleOAuthLogin(enum.GoogleProvider))
r.GET("/callback/google", handlers.HandleOAuthCallback(enum.GoogleProvider)) r.GET("/callback/google", handlers.HandleOAuthCallback(enum.GoogleProvider))
} }
log.Println(oauth.OAuthProvider.GithubConfig)
if oauth.OAuthProvider.GithubConfig != nil { if oauth.OAuthProvider.GithubConfig != nil {
r.GET("/login/github", handlers.HandleOAuthLogin(enum.GithubProvider)) r.GET("/login/github", handlers.HandleOAuthLogin(enum.GithubProvider))
r.GET("/callback/github", handlers.HandleOAuthCallback(enum.GithubProvider)) r.GET("/callback/github", handlers.HandleOAuthCallback(enum.GithubProvider))