Skip to content

Commit

Permalink
feat: fixed user repo
Browse files Browse the repository at this point in the history
  • Loading branch information
jirevwe committed Nov 14, 2024
1 parent ff89e06 commit aee13bd
Show file tree
Hide file tree
Showing 4 changed files with 289 additions and 209 deletions.
43 changes: 40 additions & 3 deletions database/sqlite3/sqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ import (
"fmt"
"github.com/frain-dev/convoy/database/hooks"
"github.com/frain-dev/convoy/pkg/log"
"gopkg.in/guregu/null.v4"
"io"
"time"

"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
)

const pkgName = "sqlite3"

type DbCtxKey string

const TransactionCtx DbCtxKey = "transaction"
const (
pkgName = "sqlite3"
Rfc3339Milli = "2006-01-02T15:04:05.000Z"
TransactionCtx DbCtxKey = "transaction"
)

type Sqlite struct {
dbx *sqlx.DB
Expand Down Expand Up @@ -103,3 +107,36 @@ func GetTx(ctx context.Context, db *sqlx.DB) (*sqlx.Tx, bool, error) {

return tx, isWrapped, nil
}

func timeAsString(t time.Time) string {
return t.Format(Rfc3339Milli)
}

func nullTimeAsString(t null.Time) *string {
strVal := ""
if t.Valid {
strVal = t.Time.Format(Rfc3339Milli)
return &strVal
}
return &strVal
}

func asTime(ts string) time.Time {
t, err := time.Parse(Rfc3339Milli, ts)
if err != nil {
return time.Now()
}
return t
}

func asNullTime(ts *string) null.Time {
if ts == nil {
return null.NewTime(time.Time{}, false)
}

t, err := time.Parse(Rfc3339Milli, *ts)
if err != nil {
return null.NewTime(time.Now(), false)
}
return null.NewTime(t, true)
}
2 changes: 1 addition & 1 deletion database/sqlite3/sqlite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func getDB(t *testing.T) (database.Database, func()) {
dbHooks := hooks.Init()
dbHooks.RegisterHook(datastore.EndpointCreated, func(data interface{}, changelog interface{}) {})

_db, err = NewDB("file::memory:?cache=shared", log.NewLogger(os.Stdout))
_db, err = NewDB("test.db?cache=shared", log.NewLogger(os.Stdout))
require.NoError(t, err)

// run migrations
Expand Down
99 changes: 68 additions & 31 deletions database/sqlite3/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,35 @@ import (
"database/sql"
"errors"
"fmt"
"strings"

"github.com/frain-dev/convoy/database"
"github.com/frain-dev/convoy/datastore"
"github.com/jmoiron/sqlx"
"strings"
"time"
)

const (
createUser = `
INSERT INTO users (
id,first_name,last_name,email,password,
email_verified,reset_password_token, email_verification_token,
reset_password_expires_at,email_verification_expires_at, auth_type)
id,first_name,last_name,email,password, email_verified,
reset_password_token, email_verification_token, reset_password_expires_at,
email_verification_expires_at, auth_type)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)
`

updateUser = `
UPDATE users SET
first_name = $2,
last_name=$3,
email=$4,
password=$5,
email_verified=$6,
reset_password_token=$7,
email_verification_token=$8,
reset_password_expires_at=$9,
email_verification_expires_at=$10
WHERE id = $1 AND deleted_at IS NULL;
first_name=$1,
last_name=$2,
email=$3,
password=$4,
email_verified=$5,
reset_password_token=$6,
email_verification_token=$7,
reset_password_expires_at=$8,
email_verification_expires_at=$9,
updated_at=$10
WHERE id = $11 AND deleted_at IS NULL;
`

fetchUsers = `
Expand Down Expand Up @@ -75,7 +76,7 @@ func (u *userRepo) CreateUser(ctx context.Context, user *datastore.User) error {
user.AuthType,
)
if err != nil {
if strings.Contains(err.Error(), "duplicate") {
if strings.Contains(err.Error(), "constraint") {
return datastore.ErrDuplicateEmail
}
return err
Expand All @@ -94,9 +95,9 @@ func (u *userRepo) CreateUser(ctx context.Context, user *datastore.User) error {
}

func (u *userRepo) UpdateUser(ctx context.Context, user *datastore.User) error {
result, err := u.db.Exec(
updateUser, user.UID, user.FirstName, user.LastName, user.Email, user.Password, user.EmailVerified, user.ResetPasswordToken,
user.EmailVerificationToken, user.ResetPasswordExpiresAt, user.EmailVerificationExpiresAt,
result, err := u.db.ExecContext(ctx,
updateUser, user.FirstName, user.LastName, user.Email, user.Password, user.EmailVerified, user.ResetPasswordToken,
user.EmailVerificationToken, user.ResetPasswordExpiresAt, user.EmailVerificationExpiresAt, time.Now(), user.UID,
)
if err != nil {
return err
Expand All @@ -115,7 +116,7 @@ func (u *userRepo) UpdateUser(ctx context.Context, user *datastore.User) error {
}

func (u *userRepo) FindUserByEmail(ctx context.Context, email string) (*datastore.User, error) {
user := &datastore.User{}
user := &dbUser{}
err := u.db.QueryRowxContext(ctx, fmt.Sprintf("%s AND email = $1;", fetchUsers), email).StructScan(user)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
Expand All @@ -124,11 +125,11 @@ func (u *userRepo) FindUserByEmail(ctx context.Context, email string) (*datastor
return nil, err
}

return user, nil
return user.toDatastoreUser(), nil
}

func (u *userRepo) FindUserByID(ctx context.Context, id string) (*datastore.User, error) {
user := &datastore.User{}
user := &dbUser{}
err := u.db.QueryRowxContext(ctx, fmt.Sprintf("%s AND id = $1;", fetchUsers), id).StructScan(user)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
Expand All @@ -137,11 +138,11 @@ func (u *userRepo) FindUserByID(ctx context.Context, id string) (*datastore.User
return nil, err
}

return user, nil
return user.toDatastoreUser(), nil
}

func (u *userRepo) FindUserByToken(ctx context.Context, token string) (*datastore.User, error) {
user := &datastore.User{}
user := &dbUser{}
err := u.db.QueryRowxContext(ctx, fmt.Sprintf("%s AND reset_password_token = $1;", fetchUsers), token).StructScan(user)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
Expand All @@ -150,11 +151,11 @@ func (u *userRepo) FindUserByToken(ctx context.Context, token string) (*datastor
return nil, err
}

return user, nil
return user.toDatastoreUser(), nil
}

func (u *userRepo) FindUserByEmailVerificationToken(ctx context.Context, token string) (*datastore.User, error) {
user := &datastore.User{}
user := &dbUser{}
err := u.db.QueryRowxContext(ctx, fmt.Sprintf("%s AND email_verification_token = $1;", fetchUsers), token).StructScan(user)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
Expand All @@ -163,15 +164,51 @@ func (u *userRepo) FindUserByEmailVerificationToken(ctx context.Context, token s
return nil, err
}

return user, nil
return user.toDatastoreUser(), nil
}

func (o *userRepo) CountUsers(ctx context.Context) (int64, error) {
var count int64
err := o.db.GetContext(ctx, &count, countUsers)
func (u *userRepo) CountUsers(ctx context.Context) (int64, error) {
var userCount int64
err := u.db.GetContext(ctx, &userCount, countUsers)
if err != nil {
return 0, err
}

return count, nil
return userCount, nil
}

type dbUser struct {
UID string `db:"id"`
FirstName string `db:"first_name"`
LastName string `db:"last_name"`
Email string `db:"email"`
EmailVerified bool `db:"email_verified"`
Password string `db:"password"`
ResetPasswordToken string `db:"reset_password_token"`
EmailVerificationToken string `db:"email_verification_token"`
CreatedAt string `db:"created_at,omitempty"`
UpdatedAt string `db:"updated_at,omitempty"`
DeletedAt *string `db:"deleted_at"`
ResetPasswordExpiresAt string `db:"reset_password_expires_at,omitempty"`
EmailVerificationExpiresAt string `db:"email_verification_expires_at,omitempty"`
AuthType string `db:"auth_type"`
}

func (uu *dbUser) toDatastoreUser() *datastore.User {
return &datastore.User{
UID: uu.UID,
FirstName: uu.FirstName,
LastName: uu.LastName,
Email: uu.Email,
AuthType: uu.AuthType,
EmailVerified: uu.EmailVerified,
Password: uu.Password,
ResetPasswordToken: uu.ResetPasswordToken,
EmailVerificationToken: uu.EmailVerificationToken,
CreatedAt: asTime(uu.CreatedAt),
UpdatedAt: asTime(uu.UpdatedAt),
DeletedAt: asNullTime(uu.DeletedAt),
ResetPasswordExpiresAt: asTime(uu.ResetPasswordExpiresAt),
EmailVerificationExpiresAt: asTime(uu.EmailVerificationExpiresAt),
}
}
Loading

0 comments on commit aee13bd

Please sign in to comment.