You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
3.7 KiB
171 lines
3.7 KiB
package services
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/lib/pq"
|
|
_ "github.com/lib/pq"
|
|
)
|
|
|
|
var dbConn *sql.DB
|
|
|
|
type DB interface {
|
|
// VerifyEmail(email string) error
|
|
// ResetPassword(email string) (string, error)
|
|
// RegisterUser(email, username, password string) (User, error)
|
|
GetLog(int64, time.Time, time.Time, []LogType) ([]StatLog, error)
|
|
AddLog(int64, StatLog) error
|
|
UpdateProfile(int64, User) error
|
|
GetProfileByID(int64) (User, error)
|
|
GetProfileByEmail(string) (User, error)
|
|
}
|
|
|
|
func Connect(host, user, password string) (DB, error) {
|
|
psqlconn := fmt.Sprintf("host=%s port=5432 user=%s password=%s dbname=bodytrack sslmode=disable", host, user, password)
|
|
pgClient, err := sql.Open("postgres", psqlconn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := pgClient.Ping(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return pgdb{DB: pgClient}, nil
|
|
}
|
|
|
|
type pgdb struct{ *sql.DB }
|
|
|
|
func (db pgdb) GetLog(id int64, start, end time.Time, lt []LogType) ([]StatLog, error) {
|
|
|
|
getLogSql := `
|
|
SELECT
|
|
value, logType, recordedTs
|
|
FROM stats.log
|
|
WHERE
|
|
userId = $1 AND recordedTs >= $2 AND recordedTs <= $3
|
|
AND logType = ANY($4)
|
|
ORDER BY recordedTs DESC;`
|
|
|
|
var results []StatLog
|
|
|
|
rows, err := db.Query(getLogSql, id, start, end, pq.Array(lt))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var sl StatLog
|
|
if err := rows.Scan(&sl.Value, &sl.Type, &sl.RecordedTS); err != nil {
|
|
log.Printf("could not scan value for statlog: %v", err)
|
|
}
|
|
|
|
results = append(results, sl)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
func (db pgdb) AddLog(id int64, sl StatLog) error {
|
|
statLogInsertSql := `
|
|
INSERT INTO stats.log (userId, value, logType, recordedTs)
|
|
VALUES ($1, $2, $3, $4);
|
|
`
|
|
|
|
tx, err := db.BeginTx(context.Background(), nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Commit()
|
|
|
|
if _, err := tx.Exec(statLogInsertSql, id, sl.Value, sl.Type, sl.RecordedTS); err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (db pgdb) UpdateProfile(id int64, u User) error {
|
|
updateProfileSql := `
|
|
UPDATE accounts.profile SET
|
|
username = $2, displayunit = $3, birthdate = $4, height = $5
|
|
WHERE userId = $1;
|
|
`
|
|
updateUserSql := `
|
|
UPDATE accounts.users SET
|
|
email = $2, passwordHash = $3
|
|
WHERE id = $1;
|
|
`
|
|
tx, err := db.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelReadCommitted})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Commit()
|
|
|
|
if _, err := tx.Exec(updateProfileSql, id, u.Username, u.DisplayUnit, u.Birthdate, u.Height); err != nil {
|
|
tx.Rollback()
|
|
return fmt.Errorf("could not update profile: %w", err)
|
|
}
|
|
if _, err := tx.Exec(updateUserSql, id, u.Email, u.PasswordHash); err != nil {
|
|
tx.Rollback()
|
|
return fmt.Errorf("could not update user: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (db pgdb) GetProfileByID(id int64) (User, error) {
|
|
sql := `SELECT
|
|
u.id, u.email, u.passwordhash, p.username, p.displayunit, p.birthdate, p.height
|
|
FROM Accounts.Users u JOIN Accounts.Profile p on u.id = p.userId
|
|
WHERE u.id = $1 LIMIT 1;
|
|
`
|
|
var u User
|
|
if err := db.QueryRow(sql, id).Scan(
|
|
&u.ID,
|
|
&u.Email,
|
|
&u.PasswordHash,
|
|
&u.Username,
|
|
&u.DisplayUnit,
|
|
&u.Birthdate,
|
|
&u.Height,
|
|
); err != nil {
|
|
return u, err
|
|
}
|
|
|
|
return u, nil
|
|
|
|
}
|
|
|
|
func (db pgdb) GetProfileByEmail(email string) (User, error) {
|
|
sql := `SELECT
|
|
u.id, u.email, u.passwordhash, p.username, p.displayunit, p.birthdate, p.height
|
|
FROM Accounts.Users u JOIN Accounts.Profile p on u.id = p.userId
|
|
WHERE u.email = $1 LIMIT 1;
|
|
`
|
|
var u User
|
|
if err := db.QueryRow(sql, email).Scan(
|
|
&u.ID,
|
|
&u.Email,
|
|
&u.PasswordHash,
|
|
&u.Username,
|
|
&u.DisplayUnit,
|
|
&u.Birthdate,
|
|
&u.Height,
|
|
); err != nil {
|
|
return u, err
|
|
}
|
|
|
|
return u, nil
|
|
}
|