fix(db): add sqlite store back with some fixes

This commit is contained in:
hexxa 2022-09-21 16:16:29 +08:00 committed by Hexxa
parent 5cae5be837
commit 81e97bdd55
16 changed files with 1696 additions and 286 deletions

View file

@ -1,4 +1,4 @@
package sqlite
package default
import (
"context"
@ -8,7 +8,7 @@ import (
"github.com/ihexxa/quickshare/src/db"
)
func (st *SQLiteStore) getCfg(ctx context.Context, tx *sql.Tx) (*db.SiteConfig, error) {
func (st *DefaultStore) getCfg(ctx context.Context, tx *sql.Tx) (*db.SiteConfig, error) {
var configStr string
err := tx.QueryRowContext(
ctx,
@ -32,7 +32,7 @@ func (st *SQLiteStore) getCfg(ctx context.Context, tx *sql.Tx) (*db.SiteConfig,
return config, nil
}
func (st *SQLiteStore) setCfg(ctx context.Context, tx *sql.Tx, cfg *db.SiteConfig) error {
func (st *DefaultStore) setCfg(ctx context.Context, tx *sql.Tx, cfg *db.SiteConfig) error {
if err := db.CheckSiteCfg(cfg, false); err != nil {
return err
}
@ -52,7 +52,7 @@ func (st *SQLiteStore) setCfg(ctx context.Context, tx *sql.Tx, cfg *db.SiteConfi
return err
}
func (st *SQLiteStore) SetClientCfg(ctx context.Context, cfg *db.ClientConfig) error {
func (st *DefaultStore) SetClientCfg(ctx context.Context, cfg *db.ClientConfig) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -73,7 +73,7 @@ func (st *SQLiteStore) SetClientCfg(ctx context.Context, cfg *db.ClientConfig) e
return tx.Commit()
}
func (st *SQLiteStore) GetCfg(ctx context.Context) (*db.SiteConfig, error) {
func (st *DefaultStore) GetCfg(ctx context.Context) (*db.SiteConfig, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err

View file

@ -1,4 +1,4 @@
package sqlite
package default
import (
"context"
@ -12,7 +12,7 @@ import (
"github.com/ihexxa/quickshare/src/db"
)
func (st *SQLiteStore) getFileInfo(ctx context.Context, tx *sql.Tx, itemPath string) (*db.FileInfo, error) {
func (st *DefaultStore) getFileInfo(ctx context.Context, tx *sql.Tx, itemPath string) (*db.FileInfo, error) {
var infoStr string
fInfo := &db.FileInfo{}
var isDir bool
@ -48,7 +48,7 @@ func (st *SQLiteStore) getFileInfo(ctx context.Context, tx *sql.Tx, itemPath str
return fInfo, nil
}
func (st *SQLiteStore) GetFileInfo(ctx context.Context, itemPath string) (*db.FileInfo, error) {
func (st *DefaultStore) GetFileInfo(ctx context.Context, itemPath string) (*db.FileInfo, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err
@ -58,7 +58,7 @@ func (st *SQLiteStore) GetFileInfo(ctx context.Context, itemPath string) (*db.Fi
return st.getFileInfo(ctx, tx, itemPath)
}
func (st *SQLiteStore) ListFileInfos(ctx context.Context, itemPaths []string) (map[string]*db.FileInfo, error) {
func (st *DefaultStore) ListFileInfos(ctx context.Context, itemPaths []string) (map[string]*db.FileInfo, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err
@ -116,7 +116,7 @@ func (st *SQLiteStore) ListFileInfos(ctx context.Context, itemPaths []string) (m
return fInfos, nil
}
func (st *SQLiteStore) addFileInfo(ctx context.Context, tx *sql.Tx, userId uint64, itemPath string, info *db.FileInfo) error {
func (st *DefaultStore) addFileInfo(ctx context.Context, tx *sql.Tx, userId uint64, itemPath string, info *db.FileInfo) error {
infoStr, err := json.Marshal(info)
if err != nil {
return err
@ -144,7 +144,7 @@ func (st *SQLiteStore) addFileInfo(ctx context.Context, tx *sql.Tx, userId uint6
return err
}
func (st *SQLiteStore) AddFileInfo(ctx context.Context, userId uint64, itemPath string, info *db.FileInfo) error {
func (st *DefaultStore) AddFileInfo(ctx context.Context, userId uint64, itemPath string, info *db.FileInfo) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -164,7 +164,7 @@ func (st *SQLiteStore) AddFileInfo(ctx context.Context, userId uint64, itemPath
return tx.Commit()
}
func (st *SQLiteStore) delFileInfo(ctx context.Context, tx *sql.Tx, itemPath string) error {
func (st *DefaultStore) delFileInfo(ctx context.Context, tx *sql.Tx, itemPath string) error {
_, err := tx.ExecContext(
ctx,
`delete from t_file_info
@ -175,7 +175,7 @@ func (st *SQLiteStore) delFileInfo(ctx context.Context, tx *sql.Tx, itemPath str
return err
}
func (st *SQLiteStore) SetSha1(ctx context.Context, itemPath, sign string) error {
func (st *DefaultStore) SetSha1(ctx context.Context, itemPath, sign string) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -207,7 +207,7 @@ func (st *SQLiteStore) SetSha1(ctx context.Context, itemPath, sign string) error
return tx.Commit()
}
func (st *SQLiteStore) DelFileInfo(ctx context.Context, userID uint64, itemPath string) error {
func (st *DefaultStore) DelFileInfo(ctx context.Context, userID uint64, itemPath string) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -266,7 +266,7 @@ func (st *SQLiteStore) DelFileInfo(ctx context.Context, userID uint64, itemPath
return tx.Commit()
}
func (st *SQLiteStore) MoveFileInfo(ctx context.Context, userId uint64, oldPath, newPath string, isDir bool) error {
func (st *DefaultStore) MoveFileInfo(ctx context.Context, userId uint64, oldPath, newPath string, isDir bool) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err

View file

@ -1,4 +1,4 @@
package sqlite
package default
import (
"context"
@ -14,7 +14,7 @@ import (
"github.com/ihexxa/quickshare/src/db"
)
func (st *SQLiteStore) generateShareID(payload string) (string, error) {
func (st *DefaultStore) generateShareID(payload string) (string, error) {
if len(payload) == 0 {
return "", db.ErrEmpty
}
@ -29,7 +29,7 @@ func (st *SQLiteStore) generateShareID(payload string) (string, error) {
return fmt.Sprintf("%x", h.Sum(nil))[:7], nil
}
func (st *SQLiteStore) IsSharing(ctx context.Context, dirPath string) (bool, error) {
func (st *DefaultStore) IsSharing(ctx context.Context, dirPath string) (bool, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return false, err
@ -56,7 +56,7 @@ func (st *SQLiteStore) IsSharing(ctx context.Context, dirPath string) (bool, err
return shareId != "", nil
}
func (st *SQLiteStore) GetSharingDir(ctx context.Context, hashID string) (string, error) {
func (st *DefaultStore) GetSharingDir(ctx context.Context, hashID string) (string, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return "", err
@ -84,7 +84,7 @@ func (st *SQLiteStore) GetSharingDir(ctx context.Context, hashID string) (string
return sharedPath, nil
}
func (st *SQLiteStore) AddSharing(ctx context.Context, userId uint64, dirPath string) error {
func (st *DefaultStore) AddSharing(ctx context.Context, userId uint64, dirPath string) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -147,7 +147,7 @@ func (st *SQLiteStore) AddSharing(ctx context.Context, userId uint64, dirPath st
return tx.Commit()
}
func (st *SQLiteStore) DelSharing(ctx context.Context, userId uint64, dirPath string) error {
func (st *DefaultStore) DelSharing(ctx context.Context, userId uint64, dirPath string) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -167,7 +167,7 @@ func (st *SQLiteStore) DelSharing(ctx context.Context, userId uint64, dirPath st
return tx.Commit()
}
func (st *SQLiteStore) ListSharingsByLocation(ctx context.Context, location string) (map[string]string, error) {
func (st *DefaultStore) ListSharingsByLocation(ctx context.Context, location string) (map[string]string, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err

View file

@ -1,4 +1,4 @@
package sqlite
package default
import (
"context"
@ -8,7 +8,7 @@ import (
"github.com/ihexxa/quickshare/src/db"
)
func (st *SQLiteStore) addUploadInfoOnly(ctx context.Context, tx *sql.Tx, userId uint64, tmpPath, filePath string, fileSize int64) error {
func (st *DefaultStore) addUploadInfoOnly(ctx context.Context, tx *sql.Tx, userId uint64, tmpPath, filePath string, fileSize int64) error {
_, err := tx.ExecContext(
ctx,
`insert into t_file_uploading (
@ -22,7 +22,7 @@ func (st *SQLiteStore) addUploadInfoOnly(ctx context.Context, tx *sql.Tx, userId
return err
}
func (st *SQLiteStore) AddUploadInfos(ctx context.Context, userId uint64, tmpPath, filePath string, info *db.FileInfo) error {
func (st *DefaultStore) AddUploadInfos(ctx context.Context, userId uint64, tmpPath, filePath string, info *db.FileInfo) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -57,7 +57,7 @@ func (st *SQLiteStore) AddUploadInfos(ctx context.Context, userId uint64, tmpPat
return tx.Commit()
}
func (st *SQLiteStore) DelUploadingInfos(ctx context.Context, userId uint64, realPath string) error {
func (st *DefaultStore) DelUploadingInfos(ctx context.Context, userId uint64, realPath string) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -72,7 +72,7 @@ func (st *SQLiteStore) DelUploadingInfos(ctx context.Context, userId uint64, rea
return tx.Commit()
}
func (st *SQLiteStore) delUploadingInfos(ctx context.Context, tx *sql.Tx, userId uint64, realPath string) error {
func (st *DefaultStore) delUploadingInfos(ctx context.Context, tx *sql.Tx, userId uint64, realPath string) error {
_, size, _, err := st.getUploadInfo(ctx, tx, userId, realPath)
if err != nil {
// info may not exist
@ -92,7 +92,7 @@ func (st *SQLiteStore) delUploadingInfos(ctx context.Context, tx *sql.Tx, userId
return st.setUser(ctx, tx, userInfo)
}
func (st *SQLiteStore) delUploadInfoOnly(ctx context.Context, tx *sql.Tx, userId uint64, filePath string) error {
func (st *DefaultStore) delUploadInfoOnly(ctx context.Context, tx *sql.Tx, userId uint64, filePath string) error {
_, err := tx.ExecContext(
ctx,
`delete from t_file_uploading
@ -102,7 +102,7 @@ func (st *SQLiteStore) delUploadInfoOnly(ctx context.Context, tx *sql.Tx, userId
return err
}
func (st *SQLiteStore) MoveUploadingInfos(ctx context.Context, userId uint64, uploadPath, itemPath string) error {
func (st *DefaultStore) MoveUploadingInfos(ctx context.Context, userId uint64, uploadPath, itemPath string) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -127,7 +127,7 @@ func (st *SQLiteStore) MoveUploadingInfos(ctx context.Context, userId uint64, up
return tx.Commit()
}
func (st *SQLiteStore) SetUploadInfo(ctx context.Context, userId uint64, filePath string, newUploaded int64) error {
func (st *DefaultStore) SetUploadInfo(ctx context.Context, userId uint64, filePath string, newUploaded int64) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -161,7 +161,7 @@ func (st *SQLiteStore) SetUploadInfo(ctx context.Context, userId uint64, filePat
return tx.Commit()
}
func (st *SQLiteStore) getUploadInfo(
func (st *DefaultStore) getUploadInfo(
ctx context.Context, tx *sql.Tx, userId uint64, filePath string,
) (string, int64, int64, error) {
var size, uploaded int64
@ -179,7 +179,7 @@ func (st *SQLiteStore) getUploadInfo(
return filePath, size, uploaded, nil
}
func (st *SQLiteStore) GetUploadInfo(ctx context.Context, userId uint64, filePath string) (string, int64, int64, error) {
func (st *DefaultStore) GetUploadInfo(ctx context.Context, userId uint64, filePath string) (string, int64, int64, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return "", 0, 0, err
@ -189,7 +189,7 @@ func (st *SQLiteStore) GetUploadInfo(ctx context.Context, userId uint64, filePat
return st.getUploadInfo(ctx, tx, userId, filePath)
}
func (st *SQLiteStore) ListUploadInfos(ctx context.Context, userId uint64) ([]*db.UploadInfo, error) {
func (st *DefaultStore) ListUploadInfos(ctx context.Context, userId uint64) ([]*db.UploadInfo, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err

View file

@ -0,0 +1,226 @@
package default
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"sync"
"time"
"github.com/ihexxa/quickshare/src/db"
_ "github.com/mattn/go-sqlite3"
)
type DefaultDB struct {
db.IDB
dbPath string
}
func NewDefaultDB(driverName, dbPath string) (*DefaultDB, error) {
db, err := sql.Open(driverName, dbPath)
if err != nil {
return nil, err
}
return &DefaultDB{
IDB: db,
dbPath: dbPath,
}, nil
}
type DefaultStore struct {
db db.IDB
}
func NewDefaultStore(db db.IDB) (*DefaultStore, error) {
return &DefaultStore{
db: db,
}, nil
}
func (st *DefaultStore) Close() error {
return st.db.Close()
}
func (st *DefaultStore) Lock() {
st.mtx.Lock()
}
func (st *DefaultStore) Unlock() {
st.mtx.Unlock()
}
func (st *DefaultStore) RLock() {
st.mtx.RLock()
}
func (st *DefaultStore) RUnlock() {
st.mtx.RUnlock()
}
func (st *DefaultStore) IsInited() bool {
// always try to init the db
return false
}
func (st *DefaultStore) Init(ctx context.Context, rootName, rootPwd string, cfg *db.SiteConfig) error {
err := st.InitUserTable(ctx, rootName, rootPwd)
if err != nil {
return err
}
if err = st.InitFileTables(ctx); err != nil {
return err
}
return st.InitConfigTable(ctx, cfg)
}
func (st *DefaultStore) InitUserTable(ctx context.Context, rootName, rootPwd string) error {
_, err := st.db.ExecContext(
ctx,
`create table if not exists t_user (
id bigint not null,
name varchar not null unique,
pwd varchar not null,
role integer not null,
used_space bigint not null,
quota varchar not null,
preference varchar not null,
primary key(id)
)`,
)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`create index if not exists i_user_name on t_user (name)`,
)
if err != nil {
return err
}
admin := &db.User{
ID: 0,
Name: rootName,
Pwd: rootPwd,
Role: db.AdminRole,
Quota: &db.Quota{
SpaceLimit: db.DefaultSpaceLimit,
UploadSpeedLimit: db.DefaultUploadSpeedLimit,
DownloadSpeedLimit: db.DefaultDownloadSpeedLimit,
},
Preferences: &db.DefaultPreferences,
}
visitor := &db.User{
ID: db.VisitorID,
Name: db.VisitorName,
Pwd: rootPwd,
Role: db.VisitorRole,
Quota: &db.Quota{
SpaceLimit: 0,
UploadSpeedLimit: db.VisitorUploadSpeedLimit,
DownloadSpeedLimit: db.VisitorDownloadSpeedLimit,
},
Preferences: &db.DefaultPreferences,
}
for _, user := range []*db.User{admin, visitor} {
err = st.AddUser(ctx, user)
if err != nil {
return err
}
}
return nil
}
func (st *DefaultStore) InitFileTables(ctx context.Context) error {
_, err := st.db.ExecContext(
ctx,
`create table if not exists t_file_info (
path varchar not null,
user bigint not null,
location varchar not null,
parent varchar not null,
name varchar not null,
is_dir boolean not null,
size bigint not null,
share_id varchar not null,
info varchar not null,
primary key(path)
)`,
)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`create index if not exists t_file_share on t_file_info (share_id, location)`,
)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`create table if not exists t_file_uploading (
real_path varchar not null,
tmp_path varchar not null unique,
user bigint not null,
size bigint not null,
uploaded bigint not null,
primary key(real_path)
)`,
)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`create index if not exists t_file_uploading_path on t_file_uploading (real_path, user)`,
)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`create index if not exists t_file_uploading_user on t_file_uploading (user)`,
)
return err
}
func (st *DefaultStore) InitConfigTable(ctx context.Context, cfg *db.SiteConfig) error {
st.Lock()
defer st.Unlock()
_, err := st.db.ExecContext(
ctx,
`create table if not exists t_config (
id bigint not null,
config varchar not null,
modified datetime not null,
primary key(id)
)`,
)
if err != nil {
return err
}
cfgStr, err := json.Marshal(cfg)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`insert into t_config
(id, config, modified) values (?, ?, ?)`,
0, cfgStr, time.Now(),
)
return err
}

View file

@ -1,4 +1,4 @@
package sqlite
package default
import (
"context"
@ -11,12 +11,7 @@ import (
"github.com/ihexxa/quickshare/src/db"
)
type SQLiteStore struct {
db db.IDB
mtx *sync.RWMutex
}
func (st *SQLiteStore) setUser(ctx context.Context, tx *sql.Tx, user *db.User) error {
func (st *DefaultStore) setUser(ctx context.Context, tx *sql.Tx, user *db.User) error {
var err error
if err = db.CheckUser(user, false); err != nil {
return err
@ -46,7 +41,7 @@ func (st *SQLiteStore) setUser(ctx context.Context, tx *sql.Tx, user *db.User) e
return err
}
func (st *SQLiteStore) getUser(ctx context.Context, tx *sql.Tx, id uint64) (*db.User, error) {
func (st *DefaultStore) getUser(ctx context.Context, tx *sql.Tx, id uint64) (*db.User, error) {
user := &db.User{}
var quotaStr, preferenceStr string
err := tx.QueryRowContext(
@ -82,7 +77,7 @@ func (st *SQLiteStore) getUser(ctx context.Context, tx *sql.Tx, id uint64) (*db.
return user, nil
}
func (st *SQLiteStore) AddUser(ctx context.Context, user *db.User) error {
func (st *DefaultStore) AddUser(ctx context.Context, user *db.User) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -115,7 +110,7 @@ func (st *SQLiteStore) AddUser(ctx context.Context, user *db.User) error {
return tx.Commit()
}
func (st *SQLiteStore) DelUser(ctx context.Context, id uint64) error {
func (st *DefaultStore) DelUser(ctx context.Context, id uint64) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -134,7 +129,7 @@ func (st *SQLiteStore) DelUser(ctx context.Context, id uint64) error {
return tx.Commit()
}
func (st *SQLiteStore) GetUser(ctx context.Context, id uint64) (*db.User, error) {
func (st *DefaultStore) GetUser(ctx context.Context, id uint64) (*db.User, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err
@ -149,7 +144,7 @@ func (st *SQLiteStore) GetUser(ctx context.Context, id uint64) (*db.User, error)
return user, err
}
func (st *SQLiteStore) GetUserByName(ctx context.Context, name string) (*db.User, error) {
func (st *DefaultStore) GetUserByName(ctx context.Context, name string) (*db.User, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err
@ -191,7 +186,7 @@ func (st *SQLiteStore) GetUserByName(ctx context.Context, name string) (*db.User
return user, nil
}
func (st *SQLiteStore) SetPwd(ctx context.Context, id uint64, pwd string) error {
func (st *DefaultStore) SetPwd(ctx context.Context, id uint64, pwd string) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -214,7 +209,7 @@ func (st *SQLiteStore) SetPwd(ctx context.Context, id uint64, pwd string) error
}
// role + quota
func (st *SQLiteStore) SetInfo(ctx context.Context, id uint64, user *db.User) error {
func (st *DefaultStore) SetInfo(ctx context.Context, id uint64, user *db.User) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -241,7 +236,7 @@ func (st *SQLiteStore) SetInfo(ctx context.Context, id uint64, user *db.User) er
return tx.Commit()
}
func (st *SQLiteStore) SetPreferences(ctx context.Context, id uint64, prefers *db.Preferences) error {
func (st *DefaultStore) SetPreferences(ctx context.Context, id uint64, prefers *db.Preferences) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -268,7 +263,7 @@ func (st *SQLiteStore) SetPreferences(ctx context.Context, id uint64, prefers *d
return tx.Commit()
}
func (st *SQLiteStore) SetUsed(ctx context.Context, id uint64, incr bool, capacity int64) error {
func (st *DefaultStore) SetUsed(ctx context.Context, id uint64, incr bool, capacity int64) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -282,7 +277,7 @@ func (st *SQLiteStore) SetUsed(ctx context.Context, id uint64, incr bool, capaci
return tx.Commit()
}
func (st *SQLiteStore) setUsed(ctx context.Context, tx *sql.Tx, id uint64, incr bool, capacity int64) error {
func (st *DefaultStore) setUsed(ctx context.Context, tx *sql.Tx, id uint64, incr bool, capacity int64) error {
gotUser, err := st.getUser(ctx, tx, id)
if err != nil {
return err
@ -312,7 +307,7 @@ func (st *SQLiteStore) setUsed(ctx context.Context, tx *sql.Tx, id uint64, incr
return err
}
func (st *SQLiteStore) ResetUsed(ctx context.Context, id uint64, used int64) error {
func (st *DefaultStore) ResetUsed(ctx context.Context, id uint64, used int64) error {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -334,7 +329,7 @@ func (st *SQLiteStore) ResetUsed(ctx context.Context, id uint64, used int64) err
return tx.Commit()
}
func (st *SQLiteStore) listUsers(ctx context.Context, tx *sql.Tx) ([]*db.User, error) {
func (st *DefaultStore) listUsers(ctx context.Context, tx *sql.Tx) ([]*db.User, error) {
// TODO: support pagination
rows, err := tx.QueryContext(
ctx,
@ -378,7 +373,7 @@ func (st *SQLiteStore) listUsers(ctx context.Context, tx *sql.Tx) ([]*db.User, e
return users, nil
}
func (st *SQLiteStore) ListUsers(ctx context.Context) ([]*db.User, error) {
func (st *DefaultStore) ListUsers(ctx context.Context) ([]*db.User, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err
@ -388,7 +383,7 @@ func (st *SQLiteStore) ListUsers(ctx context.Context) ([]*db.User, error) {
return st.listUsers(ctx, tx)
}
func (st *SQLiteStore) ListUserIDs(ctx context.Context) (map[string]string, error) {
func (st *DefaultStore) ListUserIDs(ctx context.Context) (map[string]string, error) {
tx, err := st.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return nil, err
@ -407,17 +402,17 @@ func (st *SQLiteStore) ListUserIDs(ctx context.Context) (map[string]string, erro
return nameToId, nil
}
func (st *SQLiteStore) AddRole(role string) error {
func (st *DefaultStore) AddRole(role string) error {
// TODO: implement this after adding grant/revoke
panic("not implemented")
}
func (st *SQLiteStore) DelRole(role string) error {
func (st *DefaultStore) DelRole(role string) error {
// TODO: implement this after adding grant/revoke
panic("not implemented")
}
func (st *SQLiteStore) ListRoles() (map[string]bool, error) {
func (st *DefaultStore) ListRoles() (map[string]bool, error) {
// TODO: implement this after adding grant/revoke
panic("not implemented")
}

View file

@ -0,0 +1,72 @@
package sqlite
import (
"context"
"encoding/json"
"github.com/ihexxa/quickshare/src/db"
)
func (st *SQLiteStore) getCfg(ctx context.Context) (*db.SiteConfig, error) {
var configStr string
err := st.db.QueryRowContext(
ctx,
`select config
from t_config
where id=0`,
).Scan(&configStr)
if err != nil {
return nil, err
}
config := &db.SiteConfig{}
err = json.Unmarshal([]byte(configStr), config)
if err != nil {
return nil, err
}
if err = db.CheckSiteCfg(config, true); err != nil {
return nil, err
}
return config, nil
}
func (st *SQLiteStore) setCfg(ctx context.Context, cfg *db.SiteConfig) error {
if err := db.CheckSiteCfg(cfg, false); err != nil {
return err
}
cfgBytes, err := json.Marshal(cfg)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`update t_config
set config=?
where id=0`,
string(cfgBytes),
)
return err
}
func (st *SQLiteStore) SetClientCfg(ctx context.Context, cfg *db.ClientConfig) error {
st.Lock()
defer st.Unlock()
siteCfg, err := st.getCfg(ctx)
if err != nil {
return err
}
siteCfg.ClientCfg = cfg
return st.setCfg(ctx, siteCfg)
}
func (st *SQLiteStore) GetCfg(ctx context.Context) (*db.SiteConfig, error) {
st.RLock()
defer st.RUnlock()
return st.getCfg(ctx)
}

273
src/db/rdb/sqlite/files.go Normal file
View file

@ -0,0 +1,273 @@
package sqlite
import (
"context"
"database/sql"
"encoding/json"
"errors"
"fmt"
"path"
"strings"
"github.com/ihexxa/quickshare/src/db"
)
func (st *SQLiteStore) getFileInfo(ctx context.Context, itemPath string) (*db.FileInfo, error) {
var infoStr string
fInfo := &db.FileInfo{}
var isDir bool
var size int64
var shareId string
err := st.db.QueryRowContext(
ctx,
`select is_dir, size, share_id, info
from t_file_info
where path=?`,
itemPath,
).Scan(
&isDir,
&size,
&shareId,
&infoStr,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, db.ErrFileInfoNotFound
}
return nil, err
}
err = json.Unmarshal([]byte(infoStr), &fInfo)
if err != nil {
return nil, err
}
fInfo.IsDir = isDir
fInfo.Size = size
fInfo.ShareID = shareId
fInfo.Shared = shareId != ""
return fInfo, nil
}
func (st *SQLiteStore) GetFileInfo(ctx context.Context, itemPath string) (*db.FileInfo, error) {
st.RLock()
defer st.RUnlock()
return st.getFileInfo(ctx, itemPath)
}
func (st *SQLiteStore) ListFileInfos(ctx context.Context, itemPaths []string) (map[string]*db.FileInfo, error) {
st.RLock()
defer st.RUnlock()
// TODO: add pagination
placeholders := []string{}
values := []any{}
for i := 0; i < len(itemPaths); i++ {
placeholders = append(placeholders, "?")
values = append(values, itemPaths[i])
}
rows, err := st.db.QueryContext(
ctx,
fmt.Sprintf(
`select path, is_dir, size, share_id, info
from t_file_info
where path in (%s)
`,
strings.Join(placeholders, ","),
),
values...,
)
if err != nil {
return nil, err
}
defer rows.Close()
var fInfoStr, itemPath, shareId string
var isDir bool
var size int64
fInfos := map[string]*db.FileInfo{}
for rows.Next() {
fInfo := &db.FileInfo{}
err = rows.Scan(&itemPath, &isDir, &size, &shareId, &fInfoStr)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(fInfoStr), fInfo)
if err != nil {
return nil, err
}
fInfo.IsDir = isDir
fInfo.Size = size
fInfo.ShareID = shareId
fInfo.Shared = shareId != ""
fInfos[itemPath] = fInfo
}
if rows.Err() != nil {
return nil, rows.Err()
}
return fInfos, nil
}
func (st *SQLiteStore) addFileInfo(ctx context.Context, userId uint64, itemPath string, info *db.FileInfo) error {
infoStr, err := json.Marshal(info)
if err != nil {
return err
}
location, err := getLocation(itemPath)
if err != nil {
return err
}
dirPath, itemName := path.Split(itemPath)
_, err = st.db.ExecContext(
ctx,
`insert into t_file_info (
path, user, location, parent, name,
is_dir, size, share_id, info
)
values (
?, ?, ?, ?, ?,
?, ?, ?, ?
)`,
itemPath, userId, location, dirPath, itemName,
info.IsDir, info.Size, info.ShareID, infoStr,
)
return err
}
func (st *SQLiteStore) AddFileInfo(ctx context.Context, userId uint64, itemPath string, info *db.FileInfo) error {
st.Lock()
defer st.Unlock()
err := st.addFileInfo(ctx, userId, itemPath, info)
if err != nil {
return err
}
// increase used space
return st.setUsed(ctx, userId, true, info.Size)
}
func (st *SQLiteStore) delFileInfo(ctx context.Context, itemPath string) error {
_, err := st.db.ExecContext(
ctx,
`delete from t_file_info
where path=?
`,
itemPath,
)
return err
}
func (st *SQLiteStore) SetSha1(ctx context.Context, itemPath, sign string) error {
st.Lock()
defer st.Unlock()
info, err := st.getFileInfo(ctx, itemPath)
if err != nil {
return err
}
info.Sha1 = sign
infoStr, err := json.Marshal(info)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`update t_file_info
set info=?
where path=?`,
infoStr,
itemPath,
)
return err
}
func (st *SQLiteStore) DelFileInfo(ctx context.Context, userID uint64, itemPath string) error {
st.Lock()
defer st.Unlock()
// get all children and size
rows, err := st.db.QueryContext(
ctx,
`select path, size
from t_file_info
where path = ? or path like ?
`,
itemPath,
fmt.Sprintf("%s/%%", itemPath),
)
if err != nil {
return err
}
defer rows.Close()
var childrenPath string
var itemSize int64
placeholders := []string{}
values := []any{}
decrSize := int64(0)
for rows.Next() {
err = rows.Scan(&childrenPath, &itemSize)
if err != nil {
return err
}
placeholders = append(placeholders, "?")
values = append(values, childrenPath)
decrSize += itemSize
}
// decrease used space
err = st.setUsed(ctx, userID, false, decrSize)
if err != nil {
return err
}
// delete file info entries
_, err = st.db.ExecContext(
ctx,
fmt.Sprintf(
`delete from t_file_info
where path in (%s)`,
strings.Join(placeholders, ","),
),
values...,
)
return err
}
func (st *SQLiteStore) MoveFileInfo(ctx context.Context, userId uint64, oldPath, newPath string, isDir bool) error {
st.Lock()
defer st.Unlock()
info, err := st.getFileInfo(ctx, oldPath)
if err != nil {
if errors.Is(err, db.ErrFileInfoNotFound) {
// info for file does not exist so no need to move it
// e.g. folder info is not created before
// TODO: but sometimes it could be a bug
return nil
}
return err
}
err = st.delFileInfo(ctx, oldPath)
if err != nil {
return err
}
return st.addFileInfo(ctx, userId, newPath, info)
}
func getLocation(itemPath string) (string, error) {
// location is taken from item path
itemPathParts := strings.Split(itemPath, "/")
if len(itemPathParts) == 0 {
return "", fmt.Errorf("invalid item path '%s'", itemPath)
}
return itemPathParts[0], nil
}

View file

@ -0,0 +1,179 @@
package sqlite
import (
"context"
"crypto/sha1"
"database/sql"
"encoding/json"
"errors"
"fmt"
"io"
"path"
"time"
"github.com/ihexxa/quickshare/src/db"
)
func (st *SQLiteStore) generateShareID(payload string) (string, error) {
if len(payload) == 0 {
return "", db.ErrEmpty
}
msg := fmt.Sprintf("%s-%d", payload, time.Now().Unix())
h := sha1.New()
_, err := io.WriteString(h, msg)
if err != nil {
return "", err
}
return fmt.Sprintf("%x", h.Sum(nil))[:7], nil
}
func (st *SQLiteStore) IsSharing(ctx context.Context, dirPath string) (bool, error) {
st.RLock()
defer st.RUnlock()
var shareId string
err := st.db.QueryRowContext(
ctx,
`select share_id
from t_file_info
where path=?`,
dirPath,
).Scan(
&shareId,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return false, db.ErrFileInfoNotFound
}
return false, err
}
return shareId != "", nil
}
func (st *SQLiteStore) GetSharingDir(ctx context.Context, hashID string) (string, error) {
st.RLock()
defer st.RUnlock()
var sharedPath string
err := st.db.QueryRowContext(
ctx,
`select path
from t_file_info
where share_id=?
`,
hashID,
).Scan(
&sharedPath,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return "", db.ErrSharingNotFound
}
return "", err
}
return sharedPath, nil
}
func (st *SQLiteStore) AddSharing(ctx context.Context, userId uint64, dirPath string) error {
st.Lock()
defer st.Unlock()
shareID, err := st.generateShareID(dirPath)
if err != nil {
return err
}
location, err := getLocation(dirPath)
if err != nil {
return err
}
_, err = st.getFileInfo(ctx, dirPath)
if err != nil && !errors.Is(err, db.ErrFileInfoNotFound) {
return err
}
if errors.Is(err, db.ErrFileInfoNotFound) {
// insert new
parentPath, name := path.Split(dirPath)
info := &db.FileInfo{Shared: true} // TODO: deprecate shared in info
infoStr, err := json.Marshal(info)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`insert into t_file_info (
path, user, location, parent, name,
is_dir, size, share_id, info
)
values (
?, ?, ?, ?, ?,
?, ?, ?, ?
)`,
dirPath, userId, location, parentPath, name,
true, 0, shareID, infoStr,
)
return err
}
_, err = st.db.ExecContext(
ctx,
`update t_file_info
set share_id=?
where path=?`,
shareID, dirPath,
)
return err
}
func (st *SQLiteStore) DelSharing(ctx context.Context, userId uint64, dirPath string) error {
st.Lock()
defer st.Unlock()
_, err := st.db.ExecContext(
ctx,
`update t_file_info
set share_id=''
where path=?`,
dirPath,
)
return err
}
func (st *SQLiteStore) ListSharingsByLocation(ctx context.Context, location string) (map[string]string, error) {
st.RLock()
defer st.RUnlock()
rows, err := st.db.QueryContext(
ctx,
`select path, share_id
from t_file_info
where share_id<>'' and location=?`,
location,
)
if err != nil {
return nil, err
}
defer rows.Close()
var pathname, shareId string
pathToShareId := map[string]string{}
for rows.Next() {
err = rows.Scan(&pathname, &shareId)
if err != nil {
return nil, err
}
pathToShareId[pathname] = shareId
}
if rows.Err() != nil {
return nil, rows.Err()
}
return pathToShareId, nil
}

View file

@ -0,0 +1,196 @@
package sqlite
import (
"context"
"database/sql"
"errors"
"github.com/ihexxa/quickshare/src/db"
)
func (st *SQLiteStore) addUploadInfoOnly(ctx context.Context, userId uint64, tmpPath, filePath string, fileSize int64) error {
_, err := st.db.ExecContext(
ctx,
`insert into t_file_uploading (
real_path, tmp_path, user, size, uploaded
)
values (
?, ?, ?, ?, ?
)`,
filePath, tmpPath, userId, fileSize, 0,
)
return err
}
func (st *SQLiteStore) AddUploadInfos(ctx context.Context, userId uint64, tmpPath, filePath string, info *db.FileInfo) error {
st.Lock()
defer st.Unlock()
userInfo, err := st.getUser(ctx, userId)
if err != nil {
return err
} else if userInfo.UsedSpace+info.Size > int64(userInfo.Quota.SpaceLimit) {
return db.ErrQuota
}
_, _, _, err = st.getUploadInfo(ctx, userId, filePath)
if err == nil {
return db.ErrKeyExisting
} else if err != nil && !errors.Is(err, sql.ErrNoRows) {
return err
}
userInfo.UsedSpace += info.Size
err = st.setUser(ctx, userInfo)
if err != nil {
return err
}
return st.addUploadInfoOnly(ctx, userId, tmpPath, filePath, info.Size)
}
func (st *SQLiteStore) DelUploadingInfos(ctx context.Context, userId uint64, realPath string) error {
st.Lock()
defer st.Unlock()
return st.delUploadingInfos(ctx, userId, realPath)
}
func (st *SQLiteStore) delUploadingInfos(ctx context.Context, userId uint64, realPath string) error {
_, size, _, err := st.getUploadInfo(ctx, userId, realPath)
if err != nil {
// info may not exist
return err
}
err = st.delUploadInfoOnly(ctx, userId, realPath)
if err != nil {
return err
}
userInfo, err := st.getUser(ctx, userId)
if err != nil {
return err
}
userInfo.UsedSpace -= size
return st.setUser(ctx, userInfo)
}
func (st *SQLiteStore) delUploadInfoOnly(ctx context.Context, userId uint64, filePath string) error {
_, err := st.db.ExecContext(
ctx,
`delete from t_file_uploading
where real_path=? and user=?`,
filePath, userId,
)
return err
}
func (st *SQLiteStore) MoveUploadingInfos(ctx context.Context, userId uint64, uploadPath, itemPath string) error {
st.Lock()
defer st.Unlock()
_, size, _, err := st.getUploadInfo(ctx, userId, itemPath)
if err != nil {
return err
}
err = st.delUploadInfoOnly(ctx, userId, itemPath)
if err != nil {
return err
}
return st.addFileInfo(ctx, userId, itemPath, &db.FileInfo{
Size: size,
})
}
func (st *SQLiteStore) SetUploadInfo(ctx context.Context, userId uint64, filePath string, newUploaded int64) error {
st.Lock()
defer st.Unlock()
var size, uploaded int64
err := st.db.QueryRowContext(
ctx,
`select size, uploaded
from t_file_uploading
where real_path=? and user=?`,
filePath, userId,
).Scan(&size, &uploaded)
if err != nil {
return err
} else if newUploaded > size {
return db.ErrGreaterThanSize
}
_, err = st.db.ExecContext(
ctx,
`update t_file_uploading
set uploaded=?
where real_path=? and user=?`,
newUploaded, filePath, userId,
)
return err
}
func (st *SQLiteStore) getUploadInfo(ctx context.Context, userId uint64, filePath string) (string, int64, int64, error) {
var size, uploaded int64
err := st.db.QueryRowContext(
ctx,
`select size, uploaded
from t_file_uploading
where real_path=? and user=?`,
filePath, userId,
).Scan(&size, &uploaded)
if err != nil {
return "", 0, 0, err
}
return filePath, size, uploaded, nil
}
func (st *SQLiteStore) GetUploadInfo(ctx context.Context, userId uint64, filePath string) (string, int64, int64, error) {
st.RLock()
defer st.RUnlock()
return st.getUploadInfo(ctx, userId, filePath)
}
func (st *SQLiteStore) ListUploadInfos(ctx context.Context, userId uint64) ([]*db.UploadInfo, error) {
st.RLock()
defer st.RUnlock()
rows, err := st.db.QueryContext(
ctx,
`select real_path, size, uploaded
from t_file_uploading
where user=?`,
userId,
)
if err != nil {
return nil, err
}
defer rows.Close()
var pathname string
var size, uploaded int64
infos := []*db.UploadInfo{}
for rows.Next() {
err = rows.Scan(
&pathname,
&size,
&uploaded,
)
if err != nil {
return nil, err
}
infos = append(infos, &db.UploadInfo{
RealFilePath: pathname,
Size: size,
Uploaded: uploaded,
})
}
if rows.Err() != nil {
return nil, rows.Err()
}
return infos, nil
}

View file

@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"encoding/json"
"errors"
"fmt"
"sync"
"time"
@ -126,9 +127,17 @@ func (st *SQLiteStore) InitUserTable(ctx context.Context, rootName, rootPwd stri
Preferences: &db.DefaultPreferences,
}
for _, user := range []*db.User{admin, visitor} {
err = st.AddUser(ctx, user)
// TODO: not atomic
_, err := st.GetUser(ctx, user.ID)
if err != nil {
return err
if errors.Is(err, db.ErrUserNotFound) {
err = st.AddUser(ctx, user)
if err != nil {
return err
}
} else {
return err
}
}
}
@ -214,11 +223,20 @@ func (st *SQLiteStore) InitConfigTable(ctx context.Context, cfg *db.SiteConfig)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`insert into t_config
(id, config, modified) values (?, ?, ?)`,
0, cfgStr, time.Now(),
)
return err
_, err = st.getCfg(ctx)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
_, err = st.db.ExecContext(
ctx,
`insert into t_config
(id, config, modified) values (?, ?, ?)`,
0, cfgStr, time.Now(),
)
return err
}
return err
}
return nil
}

361
src/db/rdb/sqlite/users.go Normal file
View file

@ -0,0 +1,361 @@
package sqlite
import (
"context"
"database/sql"
"encoding/json"
"errors"
"fmt"
"sync"
"github.com/ihexxa/quickshare/src/db"
)
type SQLiteStore struct {
db db.IDB
mtx *sync.RWMutex
}
func (st *SQLiteStore) setUser(ctx context.Context, user *db.User) error {
var err error
if err = db.CheckUser(user, false); err != nil {
return err
}
quotaStr, err := json.Marshal(user.Quota)
if err != nil {
return err
}
preferencesStr, err := json.Marshal(user.Preferences)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`update t_user
set name=?, pwd=?, role=?, used_space=?, quota=?, preference=?
where id=?`,
user.Name,
user.Pwd,
user.Role,
user.UsedSpace,
quotaStr,
preferencesStr,
user.ID,
)
return err
}
func (st *SQLiteStore) getUser(ctx context.Context, id uint64) (*db.User, error) {
user := &db.User{}
var quotaStr, preferenceStr string
err := st.db.QueryRowContext(
ctx,
`select id, name, pwd, role, used_space, quota, preference
from t_user
where id=?`,
id,
).Scan(
&user.ID,
&user.Name,
&user.Pwd,
&user.Role,
&user.UsedSpace,
&quotaStr,
&preferenceStr,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, db.ErrUserNotFound
}
return nil, err
}
err = json.Unmarshal([]byte(quotaStr), &user.Quota)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(preferenceStr), &user.Preferences)
if err != nil {
return nil, err
}
return user, nil
}
func (st *SQLiteStore) AddUser(ctx context.Context, user *db.User) error {
st.Lock()
defer st.Unlock()
quotaStr, err := json.Marshal(user.Quota)
if err != nil {
return err
}
preferenceStr, err := json.Marshal(user.Preferences)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`insert into t_user (id, name, pwd, role, used_space, quota, preference) values (?, ?, ?, ?, ?, ?, ?)`,
user.ID,
user.Name,
user.Pwd,
user.Role,
user.UsedSpace,
quotaStr,
preferenceStr,
)
return err
}
func (st *SQLiteStore) DelUser(ctx context.Context, id uint64) error {
st.Lock()
defer st.Unlock()
_, err := st.db.ExecContext(
ctx,
`delete from t_user where id=?`,
id,
)
return err
}
func (st *SQLiteStore) GetUser(ctx context.Context, id uint64) (*db.User, error) {
st.RLock()
defer st.RUnlock()
user, err := st.getUser(ctx, id)
if err != nil {
return nil, err
}
return user, err
}
func (st *SQLiteStore) GetUserByName(ctx context.Context, name string) (*db.User, error) {
st.RLock()
defer st.RUnlock()
user := &db.User{}
var quotaStr, preferenceStr string
err := st.db.QueryRowContext(
ctx,
`select id, name, pwd, role, used_space, quota, preference
from t_user
where name=?`,
name,
).Scan(
&user.ID,
&user.Name,
&user.Pwd,
&user.Role,
&user.UsedSpace,
&quotaStr,
&preferenceStr,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, db.ErrUserNotFound
}
return nil, err
}
err = json.Unmarshal([]byte(quotaStr), &user.Quota)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(preferenceStr), &user.Preferences)
if err != nil {
return nil, err
}
return user, nil
}
func (st *SQLiteStore) SetPwd(ctx context.Context, id uint64, pwd string) error {
st.Lock()
defer st.Unlock()
_, err := st.db.ExecContext(
ctx,
`update t_user
set pwd=?
where id=?`,
pwd,
id,
)
return err
}
// role + quota
func (st *SQLiteStore) SetInfo(ctx context.Context, id uint64, user *db.User) error {
st.Lock()
defer st.Unlock()
quotaStr, err := json.Marshal(user.Quota)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`update t_user
set role=?, quota=?
where id=?`,
user.Role, quotaStr,
id,
)
return err
}
func (st *SQLiteStore) SetPreferences(ctx context.Context, id uint64, prefers *db.Preferences) error {
st.Lock()
defer st.Unlock()
preferenceStr, err := json.Marshal(prefers)
if err != nil {
return err
}
_, err = st.db.ExecContext(
ctx,
`update t_user
set preference=?
where id=?`,
preferenceStr,
id,
)
return err
}
func (st *SQLiteStore) SetUsed(ctx context.Context, id uint64, incr bool, capacity int64) error {
st.Lock()
defer st.Unlock()
return st.setUsed(ctx, id, incr, capacity)
}
func (st *SQLiteStore) setUsed(ctx context.Context, id uint64, incr bool, capacity int64) error {
gotUser, err := st.getUser(ctx, id)
if err != nil {
return err
}
if incr && gotUser.UsedSpace+capacity > int64(gotUser.Quota.SpaceLimit) {
return db.ErrReachedLimit
}
if incr {
gotUser.UsedSpace = gotUser.UsedSpace + capacity
} else {
if gotUser.UsedSpace-capacity < 0 {
return db.ErrNegtiveUsedSpace
}
gotUser.UsedSpace = gotUser.UsedSpace - capacity
}
_, err = st.db.ExecContext(
ctx,
`update t_user
set used_space=?
where id=?`,
gotUser.UsedSpace,
gotUser.ID,
)
if err != nil {
return err
}
return nil
}
func (st *SQLiteStore) ResetUsed(ctx context.Context, id uint64, used int64) error {
st.Lock()
defer st.Unlock()
_, err := st.db.ExecContext(
ctx,
`update t_user
set used_space=?
where id=?`,
used,
id,
)
return err
}
func (st *SQLiteStore) ListUsers(ctx context.Context) ([]*db.User, error) {
st.RLock()
defer st.RUnlock()
// TODO: support pagination
rows, err := st.db.QueryContext(
ctx,
`select id, name, role, used_space, quota, preference
from t_user`,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, db.ErrUserNotFound
}
return nil, err
}
defer rows.Close() // TODO: check error
users := []*db.User{}
for rows.Next() {
user := &db.User{}
var quotaStr, preferenceStr string
err = rows.Scan(
&user.ID,
&user.Name,
&user.Role,
&user.UsedSpace,
&quotaStr,
&preferenceStr,
)
err = json.Unmarshal([]byte(quotaStr), &user.Quota)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(preferenceStr), &user.Preferences)
if err != nil {
return nil, err
}
users = append(users, user)
}
if rows.Err() != nil {
return nil, rows.Err()
}
return users, nil
}
func (st *SQLiteStore) ListUserIDs(ctx context.Context) (map[string]string, error) {
st.RLock()
defer st.RUnlock()
users, err := st.ListUsers(ctx)
if err != nil {
return nil, err
}
nameToId := map[string]string{}
for _, user := range users {
nameToId[user.Name] = fmt.Sprint(user.ID)
}
return nameToId, nil
}
func (st *SQLiteStore) AddRole(role string) error {
// TODO: implement this after adding grant/revoke
panic("not implemented")
}
func (st *SQLiteStore) DelRole(role string) error {
// TODO: implement this after adding grant/revoke
panic("not implemented")
}
func (st *SQLiteStore) ListRoles() (map[string]bool, error) {
// TODO: implement this after adding grant/revoke
panic("not implemented")
}