feat: add storage service table (#1070)

* feat: add storage service table

* update json field name

* update table name

* add updated_ts
pull/1072/head
Zeng1998 2 years ago committed by GitHub
parent b11d2130a0
commit 11924ad4c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,40 @@
package api
type Storage struct {
ID int `json:"id"`
CreatorID int `json:"creatorId"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
Name string `json:"name"`
EndPoint string `json:"endPoint"`
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
Bucket string `json:"bucket"`
}
type StorageCreate struct {
CreatorID int `json:"creatorId"`
Name string `json:"name"`
EndPoint string `json:"endPoint"`
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
Bucket string `json:"bucket"`
}
type StoragePatch struct {
ID int `json:"id"`
UpdatedTs *int64
Name *string `json:"name"`
EndPoint *string `json:"endPoint"`
AccessKey *string `json:"accessKey"`
SecretKey *string `json:"secretKey"`
Bucket *string `json:"bucket"`
}
type StorageFind struct {
CreatorID *int `json:"creatorId"`
}
type StorageDelete struct {
ID int `json:"id"`
}

@ -102,4 +102,17 @@ CREATE TABLE activity (
type TEXT NOT NULL DEFAULT '', type TEXT NOT NULL DEFAULT '',
level TEXT NOT NULL CHECK (level IN ('INFO', 'WARN', 'ERROR')) DEFAULT 'INFO', level TEXT NOT NULL CHECK (level IN ('INFO', 'WARN', 'ERROR')) DEFAULT 'INFO',
payload TEXT NOT NULL DEFAULT '{}' payload TEXT NOT NULL DEFAULT '{}'
);
-- storage
CREATE TABLE storage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
creator_id INTEGER NOT NULL,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
name TEXT NOT NULL DEFAULT '',
end_point TEXT NOT NULL DEFAULT '',
access_key TEXT NOT NULL DEFAULT '',
secret_key TEXT NOT NULL DEFAULT '',
bucket TEXT NOT NULL DEFAULT ''
); );

@ -0,0 +1,261 @@
package store
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/usememos/memos/api"
"github.com/usememos/memos/common"
)
type storageRaw struct {
ID int
CreatorID int
CreatedTs int64
UpdatedTs int64
Name string
EndPoint string
AccessKey string
SecretKey string
Bucket string
}
func (raw *storageRaw) toStorage() *api.Storage {
return &api.Storage{
ID: raw.ID,
CreatorID: raw.CreatorID,
CreatedTs: raw.CreatedTs,
UpdatedTs: raw.UpdatedTs,
Name: raw.Name,
EndPoint: raw.EndPoint,
AccessKey: raw.AccessKey,
SecretKey: raw.SecretKey,
Bucket: raw.Bucket,
}
}
func (s *Store) CreateStorage(ctx context.Context, create *api.StorageCreate) (*api.Storage, error) {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return nil, FormatError(err)
}
defer tx.Rollback()
storageRaw, err := createStorageRaw(ctx, tx, create)
if err != nil {
return nil, err
}
if err := tx.Commit(); err != nil {
return nil, FormatError(err)
}
return storageRaw.toStorage(), nil
}
func (s *Store) PatchStorage(ctx context.Context, patch *api.StoragePatch) (*api.Storage, error) {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return nil, FormatError(err)
}
defer tx.Rollback()
storageRaw, err := patchStorageRaw(ctx, tx, patch)
if err != nil {
return nil, err
}
if err := tx.Commit(); err != nil {
return nil, FormatError(err)
}
return storageRaw.toStorage(), nil
}
func (s *Store) FindStorageList(ctx context.Context, find *api.StorageFind) ([]*api.Storage, error) {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return nil, FormatError(err)
}
defer tx.Rollback()
storageRawList, err := findStorageRawList(ctx, tx, find)
if err != nil {
return nil, err
}
list := []*api.Storage{}
for _, raw := range storageRawList {
list = append(list, raw.toStorage())
}
return list, nil
}
func (s *Store) DeleteStorage(ctx context.Context, delete *api.StorageDelete) error {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return FormatError(err)
}
defer tx.Rollback()
if err := deleteStorage(ctx, tx, delete); err != nil {
return FormatError(err)
}
if err := tx.Commit(); err != nil {
return FormatError(err)
}
return nil
}
func createStorageRaw(ctx context.Context, tx *sql.Tx, create *api.StorageCreate) (*storageRaw, error) {
set := []string{"creator_id", "name", "end_point", "access_key", "secret_key", "bucket"}
args := []interface{}{create.CreatorID, create.Name, create.AccessKey, create.SecretKey, create.Bucket}
placeholder := []string{"?", "?", "?", "?", "?", "?"}
query := `
INSERT INTO storage (
` + strings.Join(set, ", ") + `
)
VALUES (` + strings.Join(placeholder, ",") + `)
RETURNING id, creator_id, created_ts, updated_ts, name, end_point, access_key, secret_key, bucket
`
var storageRaw storageRaw
if err := tx.QueryRowContext(ctx, query, args...).Scan(
&storageRaw.ID,
&storageRaw.CreatorID,
&storageRaw.CreatedTs,
&storageRaw.UpdatedTs,
&storageRaw.Name,
&storageRaw.EndPoint,
&storageRaw.AccessKey,
&storageRaw.SecretKey,
&storageRaw.Bucket,
); err != nil {
return nil, FormatError(err)
}
return &storageRaw, nil
}
func patchStorageRaw(ctx context.Context, tx *sql.Tx, patch *api.StoragePatch) (*storageRaw, error) {
set, args := []string{}, []interface{}{}
if v := patch.UpdatedTs; v != nil {
set, args = append(set, "updated_ts = ?"), append(args, *v)
}
if v := patch.Name; v != nil {
set, args = append(set, "name = ?"), append(args, *v)
}
if v := patch.EndPoint; v != nil {
set, args = append(set, "end_point = ?"), append(args, *v)
}
if v := patch.AccessKey; v != nil {
set, args = append(set, "access_key = ?"), append(args, *v)
}
if v := patch.SecretKey; v != nil {
set, args = append(set, "secret_key = ?"), append(args, *v)
}
if v := patch.Bucket; v != nil {
set, args = append(set, "bucket = ?"), append(args, *v)
}
args = append(args, patch.ID)
query := `
UPDATE storage
SET ` + strings.Join(set, ", ") + `
WHERE id = ?
RETURNING id, creator_id, created_ts, updated_ts, name, end_point, access_key, secret_key, bucket
`
var storageRaw storageRaw
if err := tx.QueryRowContext(ctx, query, args...).Scan(
&storageRaw.ID,
&storageRaw.CreatorID,
&storageRaw.CreatedTs,
&storageRaw.UpdatedTs,
&storageRaw.Name,
&storageRaw.EndPoint,
&storageRaw.AccessKey,
&storageRaw.SecretKey,
&storageRaw.Bucket,
); err != nil {
return nil, FormatError(err)
}
return &storageRaw, nil
}
func findStorageRawList(ctx context.Context, tx *sql.Tx, find *api.StorageFind) ([]*storageRaw, error) {
where, args := []string{"1 = 1"}, []interface{}{}
if v := find.CreatorID; v != nil {
where, args = append(where, "creator_id = ?"), append(args, *v)
}
query := `
SELECT
id,
creator_id,
created_ts,
name,
end_point,
access_key,
secret_key,
bucket
FROM storage
WHERE ` + strings.Join(where, " AND ") + `
ORDER BY created_ts DESC
`
rows, err := tx.QueryContext(ctx, query, args...)
if err != nil {
return nil, FormatError(err)
}
defer rows.Close()
storageRawList := make([]*storageRaw, 0)
for rows.Next() {
var storageRaw storageRaw
if err := rows.Scan(
&storageRaw.ID,
&storageRaw.CreatorID,
&storageRaw.CreatedTs,
&storageRaw.Name,
&storageRaw.EndPoint,
&storageRaw.AccessKey,
&storageRaw.SecretKey,
&storageRaw.Bucket,
); err != nil {
return nil, FormatError(err)
}
storageRawList = append(storageRawList, &storageRaw)
}
if err := rows.Err(); err != nil {
return nil, FormatError(err)
}
return storageRawList, nil
}
func deleteStorage(ctx context.Context, tx *sql.Tx, delete *api.StorageDelete) error {
where, args := []string{"id = ?"}, []interface{}{delete.ID}
stmt := `DELETE FROM storage WHERE ` + strings.Join(where, " AND ")
result, err := tx.ExecContext(ctx, stmt, args...)
if err != nil {
return FormatError(err)
}
rows, _ := result.RowsAffected()
if rows == 0 {
return &common.Error{Code: common.NotFound, Err: fmt.Errorf("storage not found")}
}
return nil
}
Loading…
Cancel
Save