blob: 8ea086021b25256241a66e5a1f1f8f8463aca179 [file] [log] [blame]
package welcome
import (
"database/sql"
"errors"
"github.com/ncruces/go-sqlite3"
"github.com/giolekva/pcloud/core/installer/soft"
)
const (
errorConstraintPrimaryKeyViolation = 1555
)
var (
ErrorAlreadyExists = errors.New("already exists")
)
type Commit struct {
Hash string
Message string
}
type Store interface {
CreateUser(username string, password []byte, network string) error
GetUserPassword(username string) ([]byte, error)
GetUserNetwork(username string) (string, error)
GetApps() ([]string, error)
GetUserApps(username string) ([]string, error)
CreateApp(name, username string) error
GetAppOwner(name string) (string, error)
CreateCommit(name, hash, message string) error
GetCommitHistory(name string) ([]Commit, error)
}
func NewStore(cf soft.RepoIO, db *sql.DB) (Store, error) {
s := &storeImpl{cf, db}
if err := s.init(); err != nil {
return nil, err
}
return s, nil
}
type storeImpl struct {
cf soft.RepoIO
db *sql.DB
}
func (s *storeImpl) init() error {
_, err := s.db.Exec(`
CREATE TABLE IF NOT EXISTS users (
username TEXT PRIMARY KEY,
password BLOB,
network TEXT
);
CREATE TABLE IF NOT EXISTS apps (
name TEXT PRIMARY KEY,
username TEXT
);
CREATE TABLE IF NOT EXISTS commits (
app_name TEXT,
hash TEXT,
message TEXT
);
`)
return err
}
func (s *storeImpl) CreateUser(username string, password []byte, network string) error {
query := `INSERT INTO users (username, password, network) VALUES (?, ?, ?)`
_, err := s.db.Exec(query, username, password, network)
if err != nil {
sqliteErr, ok := err.(*sqlite3.Error)
if ok && sqliteErr.ExtendedCode() == errorConstraintPrimaryKeyViolation {
return ErrorAlreadyExists
}
}
return err
}
func (s *storeImpl) GetUserPassword(username string) ([]byte, error) {
query := `SELECT password FROM users WHERE username = ?`
row := s.db.QueryRow(query, username)
if err := row.Err(); err != nil {
return nil, err
}
ret := []byte{}
if err := row.Scan(&ret); err != nil {
return nil, err
}
return ret, nil
}
func (s *storeImpl) GetUserNetwork(username string) (string, error) {
query := `SELECT network FROM users WHERE username = ?`
row := s.db.QueryRow(query, username)
if err := row.Err(); err != nil {
return "", err
}
var ret string
if err := row.Scan(&ret); err != nil {
if errors.Is(sql.ErrNoRows, err) {
return "", nil
}
return "", err
}
return ret, nil
}
func (s *storeImpl) CreateApp(name, username string) error {
query := `INSERT INTO apps (name, username) VALUES (?, ?)`
_, err := s.db.Exec(query, name, username)
return err
}
func (s *storeImpl) GetAppOwner(name string) (string, error) {
query := `SELECT username FROM apps WHERE name = ?`
row := s.db.QueryRow(query, name)
if err := row.Err(); err != nil {
return "", err
}
var ret string
if err := row.Scan(&ret); err != nil {
return "", err
}
return ret, nil
}
func (s *storeImpl) GetApps() ([]string, error) {
query := `SELECT name FROM apps`
rows, err := s.db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
ret := []string{}
for rows.Next() {
if err := rows.Err(); err != nil {
return nil, err
}
var name string
if err := rows.Scan(&name); err != nil {
return nil, err
}
ret = append(ret, name)
}
return ret, nil
}
func (s *storeImpl) GetUserApps(username string) ([]string, error) {
query := `SELECT name FROM apps WHERE username = ?`
rows, err := s.db.Query(query, username)
if err != nil {
return nil, err
}
defer rows.Close()
ret := []string{}
for rows.Next() {
if err := rows.Err(); err != nil {
return nil, err
}
var name string
if err := rows.Scan(&name); err != nil {
return nil, err
}
ret = append(ret, name)
}
return ret, nil
}
func (s *storeImpl) CreateCommit(name, hash, message string) error {
query := `INSERT INTO commits (app_name, hash, message) VALUES (?, ?, ?)`
_, err := s.db.Exec(query, name, hash, message)
return err
}
func (s *storeImpl) GetCommitHistory(name string) ([]Commit, error) {
query := `SELECT hash, message FROM commits WHERE app_name = ?`
rows, err := s.db.Query(query, name)
if err != nil {
return nil, err
}
defer rows.Close()
ret := []Commit{}
for rows.Next() {
if err := rows.Err(); err != nil {
return nil, err
}
var c Commit
if err := rows.Scan(&c.Hash, &c.Message); err != nil {
return nil, err
}
ret = append(ret, c)
}
return ret, nil
}