Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 37 additions & 11 deletions recipe/emailverification/api/emailverify.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ package api
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"reflect"

"github.com/supertokens/supertokens-golang/recipe/emailverification/schema"
)

func EmailVerify(apiImplementation schema.APIInterface, options schema.APIOptions) error {
var result map[string]string
func EmailVerify(apiImplementation schema.APIImplementation, options schema.APIOptions) error {
var result map[string]interface{}
if options.Req.Method == http.MethodPost {

if apiImplementation.VerifyEmailPOST == nil {
options.OtherHandler(options.Res, options.Req)
return nil
}

body, err := ioutil.ReadAll(options.Req.Response.Body)
if err != nil {
return err
Expand All @@ -30,20 +37,39 @@ func EmailVerify(apiImplementation schema.APIInterface, options schema.APIOption
return errors.New("The email verification token must be a string")
}

response := apiImplementation.VerifyEmailPOST(token.(string), options)
if response["status"] == "OK" {
result["status"] = "OK"
response, err := apiImplementation.VerifyEmailPOST(token.(string), options)
if err != nil {
return err
}

if response.OK != nil {
result = map[string]interface{}{
"status": "OK",
}
} else {
for k, v := range response {
result[k] = v.(string)
result = map[string]interface{}{
"status": "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR",
}
}
} else {
response := apiImplementation.IsEmailVerifiedGET(options)
for k, v := range response {
result[k] = v.(string)
if apiImplementation.IsEmailVerifiedGET == nil {
options.OtherHandler(options.Res, options.Req)
return nil
}

response, err := apiImplementation.IsEmailVerifiedGET(options)
if err != nil {
return err
}

result = map[string]interface{}{
"status": "OK",
"isVerified": response,
}

}
// todo: send200Response(options.res, result);

// TODO: send200Response(options.res, result);
fmt.Printf("", result)
return nil
}
36 changes: 29 additions & 7 deletions recipe/emailverification/api/generateEmailVerifyToken.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
package api

import "github.com/supertokens/supertokens-golang/recipe/emailverification/schema"
import (
"fmt"

func GenerateEmailVerifyToken(apiImplementation schema.APIInterface, options schema.APIOptions) {
var result map[string]string
"github.com/supertokens/supertokens-golang/recipe/emailverification/schema"
)

response := apiImplementation.GenerateEmailVerifyTokenPOST(options)
for k, v := range response {
result[k] = v.(string)
func GenerateEmailVerifyToken(apiImplementation schema.APIImplementation, options schema.APIOptions) error {
var result map[string]interface{}

if apiImplementation.GenerateEmailVerifyTokenPOST == nil {
options.OtherHandler(options.Res, options.Req)
return nil
}

response, err := apiImplementation.GenerateEmailVerifyTokenPOST(options)
if err != nil {
return err
}
// todo: send200Response(options.res, result);

if response.OK {
result = map[string]interface{}{
"status": "OK",
}
} else {
result = map[string]interface{}{
"status": "EMAIL_ALREADY_VERIFIED_ERROR",
}
}

// TODO: send200Response(options.res, result);
fmt.Printf("", result)
return nil
}
53 changes: 37 additions & 16 deletions recipe/emailverification/api/implementation.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
package api

import "github.com/supertokens/supertokens-golang/recipe/emailverification/schema"
import (
"github.com/supertokens/supertokens-golang/recipe/emailverification/schema"
)

type APIImplementation struct{}
func MakeAPIImplementation() schema.APIImplementation {
return schema.APIImplementation{
VerifyEmailPOST: func(token string, options schema.APIOptions) (*schema.VerifyEmailUsingTokenResponse, error) {
return options.RecipeImplementation.VerifyEmailUsingToken((token))
},

// Implementing APIInterface below
IsEmailVerifiedGET: func(options schema.APIOptions) (bool, error) {
// TODO: session management
userId := "TODO"
email := "TODO"
return options.RecipeImplementation.IsEmailVerified(userId, email)
},

func NewAPIImplementation() *APIImplementation {
return &APIImplementation{}
}
GenerateEmailVerifyTokenPOST: func(options schema.APIOptions) (*schema.CreateEmailVerificationTokenAPIResponse, error) {
// TODO: session management
userId := "TODO"
email := "TODO"
response, err := options.RecipeImplementation.CreateEmailVerificationToken(userId, email)

func (a *APIImplementation) VerifyEmailPOST(token string, options schema.APIOptions) map[string]interface{} {
return options.RecipeImplementation.VerifyEmailUsingToken(token)
}
if err != nil {
return nil, err
}

func (a *APIImplementation) IsEmailVerifiedGET(options schema.APIOptions) map[string]interface{} {
// todo
return nil
}
if response.EmailAlreadyVerifiedError == true {
return &schema.CreateEmailVerificationTokenAPIResponse{
EmailAlreadyVerifiedError: true,
}, nil
}

emailVerifyLink := options.Config.GetEmailVerificationURL(schema.User{ID: userId, Email: email}) +
"?token=" + response.OK.Token + "&rid=" + options.RecipeID

options.Config.CreateAndSendCustomEmail(schema.User{ID: userId, Email: email}, emailVerifyLink)

func (a *APIImplementation) GenerateEmailVerifyTokenPOST(options schema.APIOptions) map[string]interface{} {
// todo
return nil
return &schema.CreateEmailVerificationTokenAPIResponse{
OK: true,
}, nil
},
}
}
9 changes: 3 additions & 6 deletions recipe/emailverification/emailverificationfunctions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@ package emailverification
import (
"bytes"
"encoding/json"
"fmt"
"net/http"

"github.com/supertokens/supertokens-golang/recipe/emailverification/schema"
"github.com/supertokens/supertokens-golang/supertokens"
)

func GetEmailVerificationURL(appInfo supertokens.NormalisedAppinfo) func(schema.User) string {
return func(userId schema.User) string {
func DefaultGetEmailVerificationURL(appInfo supertokens.NormalisedAppinfo) func(schema.User) string {
return func(user schema.User) string {
return appInfo.WebsiteDomain.GetAsStringDangerous() + appInfo.WebsiteBasePath.GetAsStringDangerous() + "/verify-email"
}
}

func CreateAndSendCustomEmail(appInfo supertokens.NormalisedAppinfo) func(user schema.User, emailVerifyURLWithToken string) {
func DefaultCreateAndSendCustomEmail(appInfo supertokens.NormalisedAppinfo) func(user schema.User, emailVerifyURLWithToken string) {
return func(user schema.User, emailVerifyURLWithToken string) {
const url = "https://api.supertokens.io/0/st/auth/email/verify"

Expand All @@ -27,12 +26,10 @@ func CreateAndSendCustomEmail(appInfo supertokens.NormalisedAppinfo) func(user s
}
jsonData, err := json.Marshal(data)
if err != nil {
fmt.Println(err) // todo: handle error
return
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println(err) // todo: handle error
return
}

Expand Down
110 changes: 57 additions & 53 deletions recipe/emailverification/recipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,80 +12,80 @@ import (
const RECIPE_ID = "emailverification"

type Recipe struct {
RecipeModule *supertokens.RecipeModule
instance *Recipe
Config schema.TypeNormalisedInput
RecipeInterfaceImpl schema.RecipeInterface
APIImpl schema.APIInterface
RecipeModule supertokens.RecipeModule
Config schema.TypeNormalisedInput
RecipeImpl schema.RecipeImplementation
APIImpl schema.APIImplementation
}

var r Recipe
var r *Recipe = nil

func NewRecipe(recipeId string, appInfo supertokens.NormalisedAppinfo, config schema.TypeInput) *Recipe {
q := supertokens.Querier{}
instance, _ := q.GetNewInstanceOrThrowError(recipeId)
recipeModuleInstance := supertokens.NewRecipeModule(recipeId, appInfo)
recipeModuleInstance.GetAPIsHandled = func() []supertokens.APIHandled {
return GetAPIsHandled()
}
recipeModuleInstance.HandleAPIRequest = func(id string, req *http.Request, w http.ResponseWriter, path supertokens.NormalisedURLPath, method string) {
HandleAPIRequest(id, req, w, path, method)
}
recipeModuleInstance.GetAllCORSHeaders = func() []string {
return GetAllCORSHeaders()
}
func MakeRecipe(recipeId string, appInfo supertokens.NormalisedAppinfo, config schema.TypeInput) Recipe {
querierInstance, _ := supertokens.GetNewQuerierInstanceOrThrowError(recipeId)
recipeModuleInstance := supertokens.MakeRecipeModule(recipeId, appInfo, HandleAPIRequest, GetAllCORSHeaders, GetAPIsHandled)
verifiedConfig := ValidateAndNormaliseUserInput(appInfo, config)
recipeInterface := NewRecipeImplementation(*instance)
return &Recipe{
RecipeModule: recipeModuleInstance,
Config: verifiedConfig,
RecipeInterfaceImpl: verifiedConfig.Override.Functions(recipeInterface),
APIImpl: verifiedConfig.Override.APIs(api.NewAPIImplementation()),
recipeImplementation := MakeRecipeImplementation(*querierInstance)

return Recipe{
RecipeModule: recipeModuleInstance,
Config: verifiedConfig,
RecipeImpl: verifiedConfig.Override.Functions(recipeImplementation),
APIImpl: verifiedConfig.Override.APIs(api.MakeAPIImplementation()),
}
}

func GetInstanceOrThrowError() (*Recipe, error) {
if r.instance != nil {
return r.instance, nil
if r != nil {
return r, nil
}
return nil, errors.New("Initialisation not done. Did you forget to call the SuperTokens.init function?")
}

func RecipeInit(config schema.TypeInput) supertokens.RecipeListFunction {
return func(appInfo supertokens.NormalisedAppinfo) *supertokens.RecipeModule {
if r.instance == nil {
r.instance = NewRecipe(RECIPE_ID, appInfo, config)
return r.RecipeModule
return func(appInfo supertokens.NormalisedAppinfo) (*supertokens.RecipeModule, error) {
if r == nil {
recipe := MakeRecipe(RECIPE_ID, appInfo, config)
r = &recipe
return &r.RecipeModule, nil
}
// handle errors.New("Emailverification recipe has already been initialised. Please check your code for bugs.")
return nil
return nil, errors.New("Emailverification recipe has already been initialised. Please check your code for bugs.")
}
}

func (r *Recipe) CreateEmailVerificationToken(userID, email string) string {
response := r.RecipeInterfaceImpl.CreateEmailVerificationToken(userID, email)
if response["status"] == "OK" {
return response["token"].(string)
func (r *Recipe) CreateEmailVerificationToken(userID, email string) (string, error) {
response, err := r.RecipeImpl.CreateEmailVerificationToken(userID, email)
if err != nil {
return "", err
}
// todo : error("Email already verified")
return ""
if response.OK != nil {
return response.OK.Token, nil
}
return "", errors.New("Email has already been verified")
}

func (r *Recipe) VerifyEmailUsingToken(token string) schema.User {
response := r.RecipeInterfaceImpl.VerifyEmailUsingToken(token)
if response["status"] == "OK" {
return response["user"].(schema.User)
func (r *Recipe) VerifyEmailUsingToken(token string) (*schema.User, error) {
response, err := r.RecipeImpl.VerifyEmailUsingToken(token)
if err != nil {
return nil, err
}
if response.OK != nil {
return &response.OK.User, nil
}
// todo : error("Invalid token")
return schema.User{}
return nil, errors.New("Invalid email verification token")
}

// implement RecipeModule

func GetAPIsHandled() []supertokens.APIHandled {
generateEmailVerifyTokenAPI, _ := supertokens.NewNormalisedURLPath(GenerateEmailVerifyTokenAPI)
emailVerifyAPI, _ := supertokens.NewNormalisedURLPath(EmailVerifyAPI)
return []supertokens.APIHandled{{
func GetAPIsHandled() (*[]supertokens.APIHandled, error) {
generateEmailVerifyTokenAPI, err := supertokens.NewNormalisedURLPath(GenerateEmailVerifyTokenAPI)
if err != nil {
return nil, err
}
emailVerifyAPI, err := supertokens.NewNormalisedURLPath(EmailVerifyAPI)
if err != nil {
return nil, err
}
return &[]supertokens.APIHandled{{
Method: "post",
PathWithoutAPIBasePath: *generateEmailVerifyTokenAPI,
ID: GenerateEmailVerifyTokenAPI,
Expand All @@ -100,20 +100,24 @@ func GetAPIsHandled() []supertokens.APIHandled {
PathWithoutAPIBasePath: *emailVerifyAPI,
ID: EmailVerifyAPI,
Disabled: r.APIImpl.IsEmailVerifiedGET == nil,
}}
}}, nil
}

func HandleAPIRequest(id string, req *http.Request, w http.ResponseWriter, path supertokens.NormalisedURLPath, method string) {
func HandleAPIRequest(id string, req *http.Request, w http.ResponseWriter, path supertokens.NormalisedURLPath, method string) error {
options := schema.APIOptions{
Config: r.Config,
RecipeID: r.RecipeModule.GetRecipeID(),
RecipeImplementation: r.RecipeInterfaceImpl,
RecipeImplementation: r.RecipeImpl,
Req: req,
Res: w,
}
var err error = nil
if id == GenerateEmailVerifyTokenAPI {
api.GenerateEmailVerifyToken(r.APIImpl, options)
err = api.GenerateEmailVerifyToken(r.APIImpl, options)
} else {
err = api.EmailVerify(r.APIImpl, options)
}
return err
}

func GetAllCORSHeaders() []string {
Expand Down
Loading