Skip to content

Commit

Permalink
Introduce solana auth integration
Browse files Browse the repository at this point in the history
  • Loading branch information
thisisommore committed Sep 15, 2022
1 parent dd681e2 commit 6db7092
Show file tree
Hide file tree
Showing 19 changed files with 1,695 additions and 196 deletions.
7 changes: 7 additions & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This configuration file was automatically generated by Gitpod.
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
# and commit this file to your remote git repository to share the goodness with others.

tasks:
- init: go get && go build ./...

77 changes: 44 additions & 33 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,76 @@ package app

import (
"fmt"
"net/http"
"os"
"time"
"log"

_ "github.com/lib/pq"
"gorm.io/gorm"

"collection/config/envconfig"
"collection/domain"
"collection/dto"
"collection/logger"
"collection/service"
"github.com/jmoiron/sqlx"


"gorm.io/driver/postgres"

"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/gorilla/mux"
"github.com/joho/godotenv"
)

func Start(){
err := godotenv.Load("local.env")
if err != nil {
log.Fatalf("Some error occured. Err: %s", err)
}
func Start() {
envconfig.InitEnvVars()

r :=mux.NewRouter()
r := mux.NewRouter()

dbClient := getDbClient()
//wiring
newRepositoryDb := domain.NewUserRepositoryDb(dbClient)
newRepositoryDb := domain.NewUserRepositoryDb(dbClient.Model(&dto.User{}))
us := UserHandler{service.NewUserService(newRepositoryDb)}

r.HandleFunc("/collections",us.CreateCollection).Methods("Post")

address := os.Getenv("SERVER_ADDRESS")
port := os.Getenv("SERVER_PORT")
log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%s", address, port), r))

r.HandleFunc("/collections", us.CreateCollection).Methods("Post")
ginApp := gin.Default()

corsM := cors.New(cors.Config{AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"},
AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "Authorization"},
AllowCredentials: false,
MaxAge: 12 * time.Hour,
AllowOrigins: envconfig.EnvVars.ALLOWED_ORIGIN})
ginApp.Use(corsM)
// api.ApplyRoutes(ginApp)
port := envconfig.EnvVars.APP_PORT
err := ginApp.Run(fmt.Sprintf(":%d", port))
if err != nil {
logger.Fatalf("failed to serve app on port %s: %s", port, err)
}

}

func getDbClient() *sqlx.DB{
func getDbClient() *gorm.DB {
dbUser := os.Getenv("DB_USER")
dbPasswd := os.Getenv("DB_PASSWD")
dbAddr := os.Getenv("DB_ADDR")
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_NAME")
db:= os.Getenv("DB")

dataSource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?sslmode=disable", dbUser, dbPasswd, dbAddr, dbPort, dbName)
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable port=%s",
dbHost, dbUser, dbPasswd, dbName, dbPort)
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
logger.Fatalf("failed to connect to database: %s", err)
}

client, err := sqlx.Open(db, dataSource)
// Get underlying sql database to ping it
sqlDb, err := db.DB()
if err != nil {
panic(err)
logger.Fatalf("failed to ping database: %s", err)
}

// If ping fails then log error and exit
if err = sqlDb.Ping(); err != nil {
logger.Fatalf("failed to ping database: %s", err)
}
// See "Important settings" section.
client.SetConnMaxLifetime(time.Minute * 10)
client.SetMaxOpenConns(10)
client.SetMaxIdleConns(10)

logger.Info("Database is Connected")
return client
return db
}


52 changes: 52 additions & 0 deletions app/authenticate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package app

import (
"collection/dto/dtoapis"
"collection/internal/pkg/errorso"
"collection/logger"
"collection/service"
"errors"
"net/http"

"github.com/TheLazarusNetwork/go-helpers/httpo"
"github.com/gin-gonic/gin"
// "github.com/gorilla/mux"
)

func (u FlowIdHandler) Authenticate(c *gin.Context) {
var req dtoapis.AuthenticateRequest
err := c.BindJSON(&req)
if err != nil {
httpo.NewErrorResponse(http.StatusBadRequest, "failed to validate body").
Send(c, http.StatusBadRequest)
return
}

pasetoToken, err := u.service.VerifySignAndGetPaseto(req.Signature, req.FlowId)
if err != nil {
logger.Errorf("failed to get paseto: %s", err)

// If signature denied
if errors.Is(err, service.ErrSignDenied) {
httpo.NewErrorResponse(httpo.SignatureDenied, "signature denied").
Send(c, http.StatusUnauthorized)
return
}

if errors.Is(err, errorso.ErrRecordNotFound) {
httpo.NewErrorResponse(httpo.FlowIdNotFound, "flow id not found").
Send(c, http.StatusNotFound)
return
}

// If unexpected error
httpo.NewErrorResponse(500, "failed to verify and get paseto").Send(c, 500)
return
} else {
payload := dtoapis.AuthenticatePayload{
Token: pasetoToken,
}
httpo.NewSuccessResponse(http.StatusOK, "Token generated successfully", payload).
Send(c, http.StatusOK)
}
}
47 changes: 47 additions & 0 deletions app/flowid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package app

import (
"collection/config/envconfig"
"collection/dto/dtoapis"
"collection/logger"
"collection/service"
"net/http"

"github.com/TheLazarusNetwork/go-helpers/httpo"
"github.com/gin-gonic/gin"
"github.com/streamingfast/solana-go"
// "github.com/gorilla/mux"
)

type FlowIdHandler struct {
service service.DefaultFlowIdService
}

func (u FlowIdHandler) GetFlowId(c *gin.Context) {
walletAddress := c.Query("walletAddress")

if walletAddress == "" {
httpo.NewErrorResponse(http.StatusBadRequest, "wallet address (walletAddress) is required").
Send(c, http.StatusBadRequest)
return
}
_, err := solana.PublicKeyFromBase58(walletAddress)
if err != nil {
logger.Errorf("failed to get pubkey from wallet address (base58) %s: %s", walletAddress, err)
httpo.NewErrorResponse(httpo.WalletAddressInvalid, "failed to parse wallet address (walletAddress)").Send(c, http.StatusBadRequest)
return
}

flowId, err := u.service.CreateFlowId(walletAddress)
if err != nil {
logger.Errorf("failed to generate flow id: %s", err)
httpo.NewErrorResponse(http.StatusInternalServerError, "Unexpected error occured").Send(c, http.StatusInternalServerError)
return
}
userAuthEULA := envconfig.EnvVars.AUTH_EULA
payload := dtoapis.GetFlowIdPayload{
FlowId: flowId,
Eula: userAuthEULA,
}
httpo.NewSuccessResponse(http.StatusOK, "Flowid successfully generated", payload).Send(c, http.StatusOK)
}
34 changes: 34 additions & 0 deletions config/envconfig/envconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package envconfig

import (
"log"
"time"

"github.com/caarlos0/env/v6"
_ "github.com/joho/godotenv/autoload"
)

type config struct {
PASETO_PRIVATE_KEY string `env:"PASETO_PRIVATE_KEY,required"`
PASETO_EXPIRATION time.Duration `env:"PASETO_EXPIRATION,required"`

APP_PORT int `env:"APP_PORT,required"`
AUTH_EULA string `env:"AUTH_EULA,required"`
GIN_MODE string `env:"GIN_MODE,required"`
DB_HOST string `env:"DB_HOST,required"`
DB_USERNAME string `env:"DB_USERNAME,required"`
DB_PASSWORD string `env:"DB_PASSWORD,required"`
DB_NAME string `env:"DB_NAME,required"`
DB_PORT int `env:"DB_PORT,required"`
ALLOWED_ORIGIN []string `env:"ALLOWED_ORIGIN,required" envSeparator:","`
SIGNED_BY string `env:"SIGNED_BY,required"`
COLLECTION_PATH string `env:"COLLECTION_PATH,required"`
}

var EnvVars config = config{}

func InitEnvVars() {
if err := env.Parse(&EnvVars); err != nil {
log.Fatalf("failed to parse EnvVars: %s", err)
}
}
55 changes: 55 additions & 0 deletions domain/FlowIdRespository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package domain

import (
"collection/dto"
"collection/internal/pkg/errorso"

_ "github.com/lib/pq"
"gorm.io/gorm"
// _ "github.com/go-sql-driver/mysql"
)

type FlowIdRepositoryDb struct {
client *gorm.DB
}

func (i *FlowIdRepositoryDb) GetFlowId(flowId string) (*dto.FlowId, error) {
db := i.client
var userFlowId dto.FlowId
res := db.Find(&userFlowId, &dto.FlowId{
FlowId: flowId,
})

if err := res.Error; err != nil {
return nil, err
}

if res.RowsAffected == 0 {
return nil, errorso.ErrRecordNotFound
}
return &userFlowId, nil
}

// Adds flow id into database for given wallet Address
func (i *FlowIdRepositoryDb) AddFlowId(walletAddr string, flowId string) error {
db := i.client
err := db.Create(&dto.FlowId{
WalletAddress: walletAddr,
FlowId: flowId,
}).Error

return err
}

func (i *FlowIdRepositoryDb) DeleteFlowId(flowId string) error {
db := i.client
err := db.Delete(&dto.FlowId{
FlowId: flowId,
}).Error

return err
}

func NewFlowIdRepositoryDb(dbCLient *gorm.DB) FlowIdRepositoryDb {
return FlowIdRepositoryDb{dbCLient}
}
48 changes: 20 additions & 28 deletions domain/UserRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,44 @@ package domain
import (
"collection/errs"
"collection/logger"
"strconv"

"collection/dto"

_ "github.com/lib/pq"

"gorm.io/gorm"
// _ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)

type UserRepositoryDb struct{
client *sqlx.DB
type UserRepositoryDb struct {
client *gorm.DB
}




func (d UserRepositoryDb)AddUser(c Collection,add []dto.Address)(*errs.AppError){
sqlInsert := `INSERT INTO "Collection"(user_id,name,symbol,description,total_supply,seller_fee,mint_price,game_resource,live_mint_start)values($,$,$,$,$,$,$,$,$)`
result,err := d.client.Exec(sqlInsert,c.User_id,c.Name,c.Symbol,c.Description,c.Total_supply,c.Seller_fee,c.Mint_price,c.Game_resource,c.Live_mint_start)
if err!=nil{
logger.Error("Error While creating new account for collection "+err.Error())
// return errs.NewUnexpectedError("Unexpected error from database")
return nil
}

id,err:=result.LastInsertId()
if err!=nil{
logger.Error("Error While getting last insert id"+err.Error())
func (d UserRepositoryDb) AddUser(c Collection, add []dto.Address) *errs.AppError {
collectionDb := d.client.Model(&Collection{})
err := collectionDb.Create(&c).Error
if err != nil {
logger.Error("Error While creating new account for collection " + err.Error())
// return errs.NewUnexpectedError("Unexpected error from database")
return nil
}

userId := strconv.FormatInt(id,10)
addInsert := "INSERT INTO Seller(user_id,address,share)values($,$,$)"
for _,v := range add{
_,err := d.client.Exec(addInsert,userId,v.Address,v.Share)
if err!=nil{
logger.Error("Error While creating new account"+err.Error())
sellerDb := d.client.Model(&Seller{})
for _, v := range add {
newSeller := Seller{
User_id: c.User_id,
Address: v.Address,
Share: v.Share,
}
err = sellerDb.Create(&newSeller).Error
if err != nil {
logger.Error("Error While creating new account" + err.Error())
// return errs.NewUnexpectedError("Unexpected error from database")
return nil
}
}
return nil
}

func NewUserRepositoryDb(dbCLient *sqlx.DB)UserRepositoryDb{
func NewUserRepositoryDb(dbCLient *gorm.DB) UserRepositoryDb {
return UserRepositoryDb{dbCLient}
}
}
Loading

0 comments on commit 6db7092

Please sign in to comment.