implement login resolver
This commit is contained in:
parent
bd7ba50766
commit
ca55ae6b25
|
@ -9,8 +9,9 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
DB_TYPE = enum.Postgres
|
||||
DB_URL = "postgresql://localhost:5432/postgres"
|
||||
ENV = ""
|
||||
DB_TYPE = ""
|
||||
DB_URL = ""
|
||||
SMTP_HOST = ""
|
||||
SMTP_PORT = ""
|
||||
SENDER_EMAIL = ""
|
||||
|
@ -20,6 +21,8 @@ var (
|
|||
FRONTEND_URL = ""
|
||||
PORT = "8080"
|
||||
REDIS_URL = ""
|
||||
IS_PROD = false
|
||||
COOKIE_NAME = ""
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -28,6 +31,9 @@ func init() {
|
|||
log.Println("Error loading .env file")
|
||||
}
|
||||
|
||||
ENV = os.Getenv("ENV")
|
||||
DB_TYPE = os.Getenv("DB_TYPE")
|
||||
DB_URL = os.Getenv("DB_URL")
|
||||
SMTP_HOST = os.Getenv("SMTP_HOST")
|
||||
SMTP_PORT = os.Getenv("SMTP_PORT")
|
||||
SENDER_EMAIL = os.Getenv("SENDER_EMAIL")
|
||||
|
@ -37,8 +43,31 @@ func init() {
|
|||
FRONTEND_URL = os.Getenv("FRONTEND_URL")
|
||||
PORT = os.Getenv("PORT")
|
||||
REDIS_URL = os.Getenv("REDIS_URL")
|
||||
COOKIE_NAME = os.Getenv("COOKIE_NAME")
|
||||
|
||||
if ENV == "" {
|
||||
ENV = "production"
|
||||
}
|
||||
|
||||
if ENV == "production" {
|
||||
IS_PROD = true
|
||||
} else {
|
||||
IS_PROD = false
|
||||
}
|
||||
|
||||
if DB_TYPE == "" {
|
||||
DB_TYPE = enum.Postgres.String()
|
||||
}
|
||||
|
||||
if DB_URL == "" {
|
||||
DB_TYPE = "postgresql://localhost:5432/postgres"
|
||||
}
|
||||
|
||||
if JWT_TYPE == "" {
|
||||
JWT_TYPE = "HS256"
|
||||
}
|
||||
|
||||
if COOKIE_NAME == "" {
|
||||
COOKIE_NAME = "yauth"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,13 +36,13 @@ func init() {
|
|||
TablePrefix: "yauth_",
|
||||
},
|
||||
}
|
||||
if constants.DB_TYPE == enum.Postgres {
|
||||
if constants.DB_TYPE == enum.Postgres.String() {
|
||||
db, err = gorm.Open(postgres.Open(constants.DB_URL), ormConfig)
|
||||
}
|
||||
if constants.DB_TYPE == enum.Mysql {
|
||||
if constants.DB_TYPE == enum.Mysql.String() {
|
||||
db, err = gorm.Open(mysql.Open(constants.DB_URL), ormConfig)
|
||||
}
|
||||
if constants.DB_TYPE == enum.Sqlite {
|
||||
if constants.DB_TYPE == enum.Sqlite.String() {
|
||||
db, err = gorm.Open(sqlite.Open(constants.DB_URL), ormConfig)
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ type User struct {
|
|||
|
||||
func (user *User) BeforeSave(tx *gorm.DB) error {
|
||||
// Modify current operation through tx.Statement, e.g:
|
||||
if pw, err := bcrypt.GenerateFromPassword([]byte(user.Password), 0); err == nil {
|
||||
if pw, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost); err == nil {
|
||||
tx.Statement.SetColumn("Password", pw)
|
||||
}
|
||||
|
||||
|
|
15
server/enum/tokenType.go
Normal file
15
server/enum/tokenType.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package enum
|
||||
|
||||
type TokenType int
|
||||
|
||||
const (
|
||||
RefreshToken TokenType = iota
|
||||
AccessToken
|
||||
)
|
||||
|
||||
func (d TokenType) String() string {
|
||||
return [...]string{
|
||||
"refresh_token",
|
||||
"access_token",
|
||||
}[d]
|
||||
}
|
|
@ -10,6 +10,7 @@ require (
|
|||
github.com/jackc/pgproto3/v2 v2.1.0 // indirect
|
||||
github.com/joho/godotenv v1.3.0 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.7 // indirect
|
||||
github.com/rs/cors v1.8.0 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.1.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
|
|
|
@ -71,6 +71,7 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
|
|||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
||||
github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
|
||||
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
|
@ -81,8 +82,10 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
|||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
||||
|
@ -243,6 +246,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
|
@ -351,6 +355,8 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn
|
|||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so=
|
||||
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
|
@ -442,6 +448,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
|||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -529,12 +536,14 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=
|
||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,20 +2,6 @@
|
|||
|
||||
package model
|
||||
|
||||
type BasicAuthLoginInput struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type BasicAuthLoginResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Errors []*Error `json:"errors"`
|
||||
StatusCode int `json:"statusCode"`
|
||||
RefreshToken *string `json:"refreshToken"`
|
||||
User *User `json:"user"`
|
||||
}
|
||||
|
||||
type BasicAuthSignupInput struct {
|
||||
FirstName *string `json:"firstName"`
|
||||
LastName *string `json:"lastName"`
|
||||
|
@ -26,11 +12,8 @@ type BasicAuthSignupInput struct {
|
|||
}
|
||||
|
||||
type BasicAuthSignupResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Errors []*Error `json:"errors"`
|
||||
StatusCode int `json:"statusCode"`
|
||||
User *User `json:"user"`
|
||||
Message string `json:"message"`
|
||||
User *User `json:"user"`
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
|
@ -38,11 +21,19 @@ type Error struct {
|
|||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
type LoginInput struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type LoginResponse struct {
|
||||
Message string `json:"message"`
|
||||
AccessToken *string `json:"accessToken"`
|
||||
User *User `json:"user"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Errors []*Error `json:"errors"`
|
||||
StatusCode int `json:"statusCode"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
|
|
|
@ -32,33 +32,20 @@ type Error {
|
|||
}
|
||||
|
||||
type Response {
|
||||
success: Boolean!
|
||||
message: String!
|
||||
errors: [Error!]
|
||||
statusCode: Int!
|
||||
}
|
||||
|
||||
type BasicAuthLoginResponse {
|
||||
success: Boolean!
|
||||
type LoginResponse {
|
||||
message: String!
|
||||
errors: [Error!]
|
||||
statusCode: Int!
|
||||
refreshToken: String
|
||||
accessToken: String
|
||||
user: User
|
||||
}
|
||||
|
||||
type BasicAuthSignupResponse {
|
||||
success: Boolean!
|
||||
message: String!
|
||||
errors: [Error!]
|
||||
statusCode: Int!
|
||||
user: User
|
||||
}
|
||||
|
||||
type Query {
|
||||
users: [User!]!
|
||||
}
|
||||
|
||||
input BasicAuthSignupInput {
|
||||
firstName: String
|
||||
lastName: String
|
||||
|
@ -68,7 +55,7 @@ input BasicAuthSignupInput {
|
|||
image: String
|
||||
}
|
||||
|
||||
input BasicAuthLoginInput {
|
||||
input LoginInput {
|
||||
email: String!
|
||||
password: String!
|
||||
}
|
||||
|
@ -80,5 +67,10 @@ input VerifySignupTokenInput {
|
|||
type Mutation {
|
||||
verifySignupToken(params: VerifySignupTokenInput!): Response!
|
||||
basicAuthSignUp(params: BasicAuthSignupInput!): BasicAuthSignupResponse!
|
||||
login(params: BasicAuthLoginInput!): BasicAuthLoginResponse!
|
||||
login(params: LoginInput!): LoginResponse!
|
||||
}
|
||||
|
||||
type Query {
|
||||
users: [User!]!
|
||||
updateToken: LoginResponse
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ package graph
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
@ -14,7 +15,9 @@ import (
|
|||
"github.com/yauthdev/yauth/server/enum"
|
||||
"github.com/yauthdev/yauth/server/graph/generated"
|
||||
"github.com/yauthdev/yauth/server/graph/model"
|
||||
"github.com/yauthdev/yauth/server/session"
|
||||
"github.com/yauthdev/yauth/server/utils"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func (r *mutationResolver) VerifySignupToken(ctx context.Context, params model.VerifySignupTokenInput) (*model.Response, error) {
|
||||
|
@ -22,73 +25,36 @@ func (r *mutationResolver) VerifySignupToken(ctx context.Context, params model.V
|
|||
var res *model.Response
|
||||
_, err := db.Mgr.GetVerificationByToken(params.Token)
|
||||
if err != nil {
|
||||
res = &model.Response{
|
||||
Success: false,
|
||||
Message: `Invalid token`,
|
||||
StatusCode: 400,
|
||||
Errors: []*model.Error{&model.Error{
|
||||
Message: `Invalid token`,
|
||||
Reason: `invalid token`,
|
||||
}},
|
||||
}
|
||||
} else {
|
||||
|
||||
// verify if token exists in db
|
||||
claim, err := utils.VerifyVerificationToken(params.Token)
|
||||
if err != nil {
|
||||
res = &model.Response{
|
||||
Success: false,
|
||||
Message: `Invalid token`,
|
||||
StatusCode: 400,
|
||||
Errors: []*model.Error{&model.Error{
|
||||
Message: `Invalid token`,
|
||||
Reason: `invalid token`,
|
||||
}},
|
||||
}
|
||||
} else {
|
||||
res = &model.Response{
|
||||
Success: true,
|
||||
Message: `Email verified successfully. Login to access the system.`,
|
||||
StatusCode: 200,
|
||||
}
|
||||
|
||||
// update email_verified_at in users table
|
||||
db.Mgr.UpdateVerificationTime(time.Now().Unix(), claim.Email)
|
||||
// delete from verification table
|
||||
db.Mgr.DeleteToken(claim.Email)
|
||||
}
|
||||
|
||||
return res, errors.New(`Invalid token`)
|
||||
}
|
||||
|
||||
// verify if token exists in db
|
||||
claim, err := utils.VerifyVerificationToken(params.Token)
|
||||
if err != nil {
|
||||
return res, errors.New(`Invalid token`)
|
||||
}
|
||||
res = &model.Response{
|
||||
Message: `Email verified successfully. Login to access the system.`,
|
||||
}
|
||||
|
||||
// update email_verified_at in users table
|
||||
db.Mgr.UpdateVerificationTime(time.Now().Unix(), claim.Email)
|
||||
// delete from verification table
|
||||
db.Mgr.DeleteToken(claim.Email)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) BasicAuthSignUp(ctx context.Context, params model.BasicAuthSignupInput) (*model.BasicAuthSignupResponse, error) {
|
||||
var res *model.BasicAuthSignupResponse
|
||||
if params.CofirmPassword != params.Password {
|
||||
res = &model.BasicAuthSignupResponse{
|
||||
Success: false,
|
||||
Message: `Passowrd and Confirm Password does not match`,
|
||||
StatusCode: 400,
|
||||
Errors: []*model.Error{&model.Error{
|
||||
Message: `Passowrd and Confirm Password does not match`,
|
||||
Reason: `password and confirm_password fields should match`,
|
||||
}},
|
||||
}
|
||||
return res, errors.New(`Passowrd and Confirm Password does not match`)
|
||||
}
|
||||
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
|
||||
if !utils.IsValidEmail(params.Email) {
|
||||
res = &model.BasicAuthSignupResponse{
|
||||
Success: false,
|
||||
Message: `Invalid email address`,
|
||||
StatusCode: 400,
|
||||
Errors: []*model.Error{&model.Error{
|
||||
Message: `Invalid email address`,
|
||||
Reason: `invalid email address`,
|
||||
}},
|
||||
}
|
||||
return res, errors.New(`Invalid email address`)
|
||||
}
|
||||
|
||||
// find user with email
|
||||
|
@ -99,65 +65,107 @@ func (r *mutationResolver) BasicAuthSignUp(ctx context.Context, params model.Bas
|
|||
|
||||
if existingUser.EmailVerifiedAt > 0 {
|
||||
// email is verified
|
||||
res = &model.BasicAuthSignupResponse{
|
||||
Success: false,
|
||||
Message: `You have already signed up. Please login`,
|
||||
StatusCode: 400,
|
||||
Errors: []*model.Error{&model.Error{
|
||||
Message: `Already signed up`,
|
||||
Reason: `already signed up`,
|
||||
}},
|
||||
}
|
||||
} else {
|
||||
user := db.User{
|
||||
Email: params.Email,
|
||||
Password: params.Password,
|
||||
}
|
||||
return res, errors.New(`You have already signed up. Please login`)
|
||||
}
|
||||
user := db.User{
|
||||
Email: params.Email,
|
||||
Password: params.Password,
|
||||
}
|
||||
|
||||
if params.FirstName != nil {
|
||||
user.FirstName = *params.FirstName
|
||||
}
|
||||
if params.FirstName != nil {
|
||||
user.FirstName = *params.FirstName
|
||||
}
|
||||
|
||||
if params.LastName != nil {
|
||||
user.LastName = *params.LastName
|
||||
}
|
||||
if params.LastName != nil {
|
||||
user.LastName = *params.LastName
|
||||
}
|
||||
|
||||
user.SignUpMethod = enum.BasicAuth.String()
|
||||
_, err = db.Mgr.AddUser(user)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
user.SignUpMethod = enum.BasicAuth.String()
|
||||
_, err = db.Mgr.AddUser(user)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// insert verification request
|
||||
verificationType := enum.BasicAuth.String()
|
||||
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
||||
if err != nil {
|
||||
log.Println(`Error generating token`, err)
|
||||
}
|
||||
db.Mgr.AddVerification(db.Verification{
|
||||
Token: token,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
Email: params.Email,
|
||||
})
|
||||
// insert verification request
|
||||
verificationType := enum.BasicAuth.String()
|
||||
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
||||
if err != nil {
|
||||
log.Println(`Error generating token`, err)
|
||||
}
|
||||
db.Mgr.AddVerification(db.Verification{
|
||||
Token: token,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
Email: params.Email,
|
||||
})
|
||||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendVerificationMail(params.Email, token)
|
||||
}()
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendVerificationMail(params.Email, token)
|
||||
}()
|
||||
|
||||
res = &model.BasicAuthSignupResponse{
|
||||
Success: true,
|
||||
Message: `Verification email sent successfully. Please check your inbox`,
|
||||
StatusCode: 200,
|
||||
}
|
||||
res = &model.BasicAuthSignupResponse{
|
||||
Message: `Verification email sent successfully. Please check your inbox`,
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) Login(ctx context.Context, params model.BasicAuthLoginInput) (*model.BasicAuthLoginResponse, error) {
|
||||
panic(fmt.Errorf("not implemented"))
|
||||
func (r *mutationResolver) Login(ctx context.Context, params model.LoginInput) (*model.LoginResponse, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.LoginResponse
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
user, err := db.Mgr.GetUserByEmail(params.Email)
|
||||
if err != nil {
|
||||
return res, errors.New(`User with this email not found`)
|
||||
}
|
||||
|
||||
if user.SignUpMethod != enum.BasicAuth.String() {
|
||||
return res, errors.New(`User has not signed up email & password`)
|
||||
}
|
||||
|
||||
if user.EmailVerifiedAt <= 0 {
|
||||
return res, errors.New(`Email not verified`)
|
||||
}
|
||||
// match password
|
||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(params.Password))
|
||||
if err != nil {
|
||||
return res, errors.New(`Invalid Password`)
|
||||
}
|
||||
userIdStr := fmt.Sprintf("%d", user.ID)
|
||||
log.Println("session object init -> ", session.GetToken(userIdStr))
|
||||
refreshToken, _ := utils.CreateAuthToken(utils.UserAuthInfo{
|
||||
ID: userIdStr,
|
||||
Email: user.Email,
|
||||
}, enum.RefreshToken)
|
||||
|
||||
accessToken, _ := utils.CreateAuthToken(utils.UserAuthInfo{
|
||||
ID: userIdStr,
|
||||
Email: user.Email,
|
||||
}, enum.AccessToken)
|
||||
|
||||
session.SetToken(userIdStr, refreshToken)
|
||||
log.Println("session object -> ", session.GetToken(userIdStr))
|
||||
|
||||
res = &model.LoginResponse{
|
||||
Message: `Logged in successfully`,
|
||||
AccessToken: &accessToken,
|
||||
User: &model.User{
|
||||
ID: userIdStr,
|
||||
Email: user.Email,
|
||||
Image: &user.Image,
|
||||
FirstName: &user.FirstName,
|
||||
LastName: &user.LastName,
|
||||
},
|
||||
}
|
||||
|
||||
utils.SetCookie(gc, accessToken)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) {
|
||||
|
@ -182,6 +190,10 @@ func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) {
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) UpdateToken(ctx context.Context) (*model.LoginResponse, error) {
|
||||
panic(fmt.Errorf("not implemented"))
|
||||
}
|
||||
|
||||
// Mutation returns generated.MutationResolver implementation.
|
||||
func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ type SessionStore struct {
|
|||
|
||||
var SessionStoreObj SessionStore
|
||||
|
||||
func setToken(userId, token string) {
|
||||
func SetToken(userId, token string) {
|
||||
if SessionStoreObj.redisMemoryStoreObj != nil {
|
||||
SessionStoreObj.redisMemoryStoreObj.AddToken(userId, token)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func setToken(userId, token string) {
|
|||
}
|
||||
}
|
||||
|
||||
func deleteToken(userId string) {
|
||||
func DeleteToken(userId string) {
|
||||
if SessionStoreObj.redisMemoryStoreObj != nil {
|
||||
SessionStoreObj.redisMemoryStoreObj.DeleteToken(userId)
|
||||
}
|
||||
|
@ -33,16 +33,18 @@ func deleteToken(userId string) {
|
|||
}
|
||||
}
|
||||
|
||||
func getToken(userId string) {
|
||||
func GetToken(userId string) string {
|
||||
if SessionStoreObj.redisMemoryStoreObj != nil {
|
||||
SessionStoreObj.redisMemoryStoreObj.GetToken(userId)
|
||||
return SessionStoreObj.redisMemoryStoreObj.GetToken(userId)
|
||||
}
|
||||
if SessionStoreObj.inMemoryStoreObj != nil {
|
||||
SessionStoreObj.inMemoryStoreObj.GetToken(userId)
|
||||
return SessionStoreObj.inMemoryStoreObj.GetToken(userId)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func clearStore() {
|
||||
func ClearStore() {
|
||||
if SessionStoreObj.redisMemoryStoreObj != nil {
|
||||
SessionStoreObj.redisMemoryStoreObj.ClearStore()
|
||||
}
|
||||
|
|
39
server/utils/authToken.go
Normal file
39
server/utils/authToken.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/yauthdev/yauth/server/constants"
|
||||
"github.com/yauthdev/yauth/server/enum"
|
||||
)
|
||||
|
||||
type UserAuthInfo struct {
|
||||
Email string `json:"email"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type UserAuthClaim struct {
|
||||
*jwt.StandardClaims
|
||||
TokenType string `json:"token_type"`
|
||||
UserAuthInfo
|
||||
}
|
||||
|
||||
func CreateAuthToken(user UserAuthInfo, tokenType enum.TokenType) (string, error) {
|
||||
t := jwt.New(jwt.GetSigningMethod(constants.JWT_TYPE))
|
||||
expiryBound := time.Hour
|
||||
if tokenType == enum.RefreshToken {
|
||||
// expires in 90 days
|
||||
expiryBound = time.Hour * 2160
|
||||
}
|
||||
|
||||
t.Claims = &UserAuthClaim{
|
||||
&jwt.StandardClaims{
|
||||
ExpiresAt: time.Now().Add(expiryBound).Unix(),
|
||||
},
|
||||
tokenType.String(),
|
||||
user,
|
||||
}
|
||||
|
||||
return t.SignedString([]byte(constants.JWT_SECRET))
|
||||
}
|
17
server/utils/cookie.go
Normal file
17
server/utils/cookie.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yauthdev/yauth/server/constants"
|
||||
)
|
||||
|
||||
func SetCookie(gc *gin.Context, token string) {
|
||||
secure := true
|
||||
httpOnly := true
|
||||
|
||||
if !constants.IS_PROD {
|
||||
secure = false
|
||||
}
|
||||
|
||||
gc.SetCookie(constants.COOKIE_NAME, token, 3600, "/", GetFrontendHost(), secure, httpOnly)
|
||||
}
|
16
server/utils/urls.go
Normal file
16
server/utils/urls.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/yauthdev/yauth/server/constants"
|
||||
)
|
||||
|
||||
func GetFrontendHost() string {
|
||||
u, err := url.Parse(constants.FRONTEND_URL)
|
||||
if err != nil {
|
||||
return `localhost`
|
||||
}
|
||||
|
||||
return u.Hostname()
|
||||
}
|
Loading…
Reference in New Issue
Block a user