BIG MASSIVE REFACTOR OMG
Ripped out literally everything to simplify the backend as much as possible. Some of the code was so horrifically complicated it's insaneeee
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"screenmark/screenmark/.gen/haystack/haystack/enum"
|
||||
"screenmark/screenmark/.gen/haystack/haystack/model"
|
||||
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
||||
|
||||
@@ -18,248 +17,50 @@ type ImageModel struct {
|
||||
dbPool *sql.DB
|
||||
}
|
||||
|
||||
type ImageData struct {
|
||||
model.UserImages
|
||||
func (m ImageModel) Save(ctx context.Context, name string, image []byte, userID uuid.UUID) error {
|
||||
saveImageStmt := Image.INSERT(Image.ImageName, Image.Image, Image.UserID).
|
||||
VALUES(name, image, userID)
|
||||
|
||||
Image model.Image
|
||||
}
|
||||
|
||||
type ProcessingImageData struct {
|
||||
model.UserImagesToProcess
|
||||
|
||||
Image model.Image
|
||||
}
|
||||
|
||||
type UserProcessingImage struct {
|
||||
model.UserImagesToProcess
|
||||
|
||||
Image model.Image
|
||||
}
|
||||
|
||||
func (m ImageModel) Process(ctx context.Context, userId uuid.UUID, image model.Image) (model.UserImagesToProcess, error) {
|
||||
tx, err := m.dbPool.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return model.UserImagesToProcess{}, fmt.Errorf("Failed to begin transaction: %w", err)
|
||||
}
|
||||
|
||||
insertImageStmt := Image.
|
||||
INSERT(Image.ImageName, Image.Image, Image.Description).
|
||||
VALUES(image.ImageName, image.Image, image.Description).
|
||||
RETURNING(Image.ID)
|
||||
|
||||
insertedImage := model.Image{}
|
||||
err = insertImageStmt.QueryContext(ctx, tx, &insertedImage)
|
||||
if err != nil {
|
||||
return model.UserImagesToProcess{}, fmt.Errorf("Could not insert/query new image. SQL %s: %w", insertImageStmt.DebugSql(), err)
|
||||
}
|
||||
|
||||
stmt := UserImagesToProcess.
|
||||
INSERT(UserImagesToProcess.UserID, UserImagesToProcess.ImageID).
|
||||
VALUES(userId, insertedImage.ID).
|
||||
RETURNING(UserImagesToProcess.AllColumns)
|
||||
|
||||
userImage := model.UserImagesToProcess{}
|
||||
err = stmt.QueryContext(ctx, tx, &userImage)
|
||||
if err != nil {
|
||||
return model.UserImagesToProcess{}, fmt.Errorf("Could not insert user_image: %w", err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
|
||||
return userImage, err
|
||||
}
|
||||
|
||||
func (m ImageModel) GetToProcess(ctx context.Context, imageId uuid.UUID) (UserProcessingImage, error) {
|
||||
getToProcessStmt := SELECT(UserImagesToProcess.AllColumns, Image.ID, Image.ImageName).
|
||||
FROM(
|
||||
UserImagesToProcess.INNER_JOIN(
|
||||
Image, Image.ID.EQ(UserImagesToProcess.ImageID),
|
||||
),
|
||||
).
|
||||
WHERE(UserImagesToProcess.ID.EQ(UUID(imageId)))
|
||||
|
||||
images := []UserProcessingImage{}
|
||||
err := getToProcessStmt.QueryContext(ctx, m.dbPool, &images)
|
||||
|
||||
if len(images) != 1 {
|
||||
return UserProcessingImage{}, fmt.Errorf("Expected 1, got %d\n", len(images))
|
||||
}
|
||||
|
||||
return images[0], err
|
||||
}
|
||||
|
||||
func (m ImageModel) GetToProcessWithData(ctx context.Context, imageId uuid.UUID) (ProcessingImageData, error) {
|
||||
stmt := SELECT(UserImagesToProcess.AllColumns, Image.AllColumns).
|
||||
FROM(
|
||||
UserImagesToProcess.INNER_JOIN(
|
||||
Image, Image.ID.EQ(UserImagesToProcess.ImageID),
|
||||
),
|
||||
).WHERE(UserImagesToProcess.ID.EQ(UUID(imageId)))
|
||||
|
||||
images := []ProcessingImageData{}
|
||||
err := stmt.QueryContext(ctx, m.dbPool, &images)
|
||||
|
||||
if len(images) != 1 {
|
||||
return ProcessingImageData{}, fmt.Errorf("Expected 1, got %d\n", len(images))
|
||||
}
|
||||
|
||||
return images[0], err
|
||||
}
|
||||
|
||||
func (m ImageModel) FinishProcessing(ctx context.Context, imageId uuid.UUID) (model.UserImages, error) {
|
||||
imageToProcess, err := m.GetToProcess(ctx, imageId)
|
||||
if err != nil {
|
||||
return model.UserImages{}, err
|
||||
}
|
||||
|
||||
tx, err := m.dbPool.Begin()
|
||||
if err != nil {
|
||||
return model.UserImages{}, err
|
||||
}
|
||||
|
||||
insertImageStmt := UserImages.
|
||||
INSERT(UserImages.UserID, UserImages.ImageID).
|
||||
VALUES(imageToProcess.UserID, imageToProcess.ImageID).
|
||||
RETURNING(UserImages.ID, UserImages.UserID, UserImages.ImageID)
|
||||
|
||||
userImage := model.UserImages{}
|
||||
err = insertImageStmt.QueryContext(ctx, tx, &userImage)
|
||||
if err != nil {
|
||||
return model.UserImages{}, err
|
||||
}
|
||||
|
||||
// Hacky. Update the status before removing so we can get our regular triggers
|
||||
// to work.
|
||||
|
||||
updateStatusStmt := UserImagesToProcess.
|
||||
UPDATE(UserImagesToProcess.Status).
|
||||
SET(model.Progress_Complete).
|
||||
WHERE(UserImagesToProcess.ID.EQ(UUID(imageToProcess.ID)))
|
||||
|
||||
_, err = updateStatusStmt.ExecContext(ctx, tx)
|
||||
if err != nil {
|
||||
return model.UserImages{}, err
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// We cannot delete the image to process because our events rely on it.
|
||||
// This indicates our DB structure with the two tables might need some adjusting.
|
||||
// Or re-doing all together perhaps.
|
||||
// (switching to a one table (user_images) could work)
|
||||
// But for now, we can just not delete the images to process and set them to complete
|
||||
|
||||
// removeProcessingStmt := UserImagesToProcess.
|
||||
// DELETE().
|
||||
// WHERE(UserImagesToProcess.ID.EQ(UUID(imageToProcess.ID)))
|
||||
//
|
||||
// _, err = removeProcessingStmt.ExecContext(ctx, tx)
|
||||
// if err != nil {
|
||||
// return model.UserImages{}, err
|
||||
// }
|
||||
|
||||
err = tx.Commit()
|
||||
return userImage, err
|
||||
}
|
||||
|
||||
func (m ImageModel) GetImageToProcessID(ctx context.Context, imageID uuid.UUID) (uuid.UUID, error) {
|
||||
getImageToProcessIDStmt := UserImagesToProcess.
|
||||
SELECT(UserImagesToProcess.ID).
|
||||
WHERE(UserImagesToProcess.ImageID.EQ(UUID(imageID)))
|
||||
|
||||
imageToProcess := model.UserImagesToProcess{}
|
||||
err := getImageToProcessIDStmt.QueryContext(ctx, m.dbPool, &imageToProcess)
|
||||
|
||||
return imageToProcess.ID, err
|
||||
}
|
||||
|
||||
func (m ImageModel) SetNotStarted(ctx context.Context, processingImageId uuid.UUID) error {
|
||||
startProcessingStmt := UserImagesToProcess.
|
||||
UPDATE(UserImagesToProcess.Status).
|
||||
SET(model.Progress_NotStarted).
|
||||
WHERE(UserImagesToProcess.ID.EQ(UUID(processingImageId)))
|
||||
|
||||
_, err := startProcessingStmt.ExecContext(ctx, m.dbPool)
|
||||
_, err := saveImageStmt.ExecContext(ctx, m.dbPool)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (m ImageModel) StartProcessing(ctx context.Context, processingImageId uuid.UUID) error {
|
||||
startProcessingStmt := UserImagesToProcess.
|
||||
UPDATE(UserImagesToProcess.Status).
|
||||
SET(model.Progress_InProgress).
|
||||
WHERE(UserImagesToProcess.ID.EQ(UUID(processingImageId)))
|
||||
|
||||
_, err := startProcessingStmt.ExecContext(ctx, m.dbPool)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (m ImageModel) Get(ctx context.Context, imageId uuid.UUID) (model.Image, error) {
|
||||
getImageStmt := Image.SELECT(Image.AllColumns).
|
||||
WHERE(Image.ID.EQ(UUID(imageId)))
|
||||
func (m ImageModel) Get(ctx context.Context, imageID uuid.UUID) (model.Image, bool, error) {
|
||||
getImageStmt := Image.SELECT(Image.AllColumns.Except(Image.Image)).WHERE(Image.ID.EQ(UUID(imageID)))
|
||||
|
||||
image := model.Image{}
|
||||
err := getImageStmt.QueryContext(ctx, m.dbPool, &image)
|
||||
|
||||
return image, err
|
||||
return image, err != qrm.ErrNoRows, err
|
||||
}
|
||||
|
||||
func (m ImageModel) GetProcessing(ctx context.Context, userId uuid.UUID) ([]UserProcessingImage, error) {
|
||||
getProcessingStmt := SELECT(UserImagesToProcess.AllColumns, Image.ID, Image.ImageName).
|
||||
FROM(
|
||||
UserImagesToProcess.INNER_JOIN(
|
||||
Image, Image.ID.EQ(UserImagesToProcess.ImageID),
|
||||
),
|
||||
).WHERE(
|
||||
UserImagesToProcess.UserID.EQ(UUID(userId)).
|
||||
AND(UserImagesToProcess.Status.NOT_EQ(enum.Progress.Complete)),
|
||||
)
|
||||
func (m ImageModel) Update(ctx context.Context, image model.Image) (model.Image, error) {
|
||||
updateImageStmt := Image.UPDATE(Image.MutableColumns.Except(Image.Image)).
|
||||
MODEL(image).
|
||||
WHERE(Image.ID.EQ(UUID(image.ID))).
|
||||
RETURNING(Image.AllColumns.Except(Image.Image))
|
||||
|
||||
images := []UserProcessingImage{}
|
||||
err := getProcessingStmt.QueryContext(ctx, m.dbPool, &images)
|
||||
updatedImage := model.Image{}
|
||||
err := updateImageStmt.QueryContext(ctx, m.dbPool, &updatedImage)
|
||||
|
||||
return images, err
|
||||
return updatedImage, err
|
||||
}
|
||||
|
||||
func (m ImageModel) AddDescription(ctx context.Context, imageId uuid.UUID, description string) error {
|
||||
updateImageStmt := Image.UPDATE(Image.Description).
|
||||
SET(description).
|
||||
WHERE(Image.ID.EQ(UUID(imageId)))
|
||||
func (m ImageModel) Delete(ctx context.Context, imageID, userID uuid.UUID) (bool, error) {
|
||||
deleteImageStmt := Image.DELETE().WHERE(Image.ID.EQ(UUID(imageID)).AND(Image.UserID.EQ(UUID(userID))))
|
||||
|
||||
_, err := updateImageStmt.ExecContext(ctx, m.dbPool)
|
||||
r, err := deleteImageStmt.ExecContext(ctx, m.dbPool)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("deleting image: %w", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
rowsAffected, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unreachable: %w", err)
|
||||
}
|
||||
|
||||
func (m ImageModel) DeleteUserImage(ctx context.Context, imageID uuid.UUID) error {
|
||||
deleteImageStmt := UserImages.DELETE().
|
||||
WHERE(UserImages.ImageID.EQ(UUID(imageID)))
|
||||
|
||||
_, err := deleteImageStmt.ExecContext(ctx, m.dbPool)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (m ImageModel) Delete(ctx context.Context, imageID uuid.UUID) error {
|
||||
deleteImageStmt := Image.DELETE().
|
||||
WHERE(Image.ID.EQ(UUID(imageID)))
|
||||
|
||||
_, err := deleteImageStmt.ExecContext(ctx, m.dbPool)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (m ImageModel) IsUserAuthorized(ctx context.Context, imageId uuid.UUID, userId uuid.UUID) bool {
|
||||
getImageUserId := UserImages.SELECT(UserImages.UserID).WHERE(UserImages.ImageID.EQ(UUID(imageId)))
|
||||
getProcessingImageUserId := UserImagesToProcess.SELECT(UserImagesToProcess.UserID).WHERE(UserImagesToProcess.ImageID.EQ(UUID(imageId)))
|
||||
|
||||
userImage := model.UserImages{}
|
||||
userProcessingImage := model.UserImagesToProcess{}
|
||||
|
||||
err1 := getImageUserId.QueryContext(ctx, m.dbPool, &userImage)
|
||||
err2 := getProcessingImageUserId.QueryContext(ctx, m.dbPool, &userProcessingImage)
|
||||
|
||||
return (err1 == nil || err1 == qrm.ErrNoRows) && (err2 == nil || err2 == qrm.ErrNoRows) && (userImage.UserID.String() == userId.String() || userProcessingImage.UserID.String() == userId.String())
|
||||
return rowsAffected > 0, nil
|
||||
}
|
||||
|
||||
func NewImageModel(db *sql.DB) ImageModel {
|
||||
|
||||
@@ -3,7 +3,6 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"screenmark/screenmark/.gen/haystack/haystack/model"
|
||||
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
||||
|
||||
@@ -12,22 +11,18 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ListModel struct {
|
||||
type StackModel struct {
|
||||
dbPool *sql.DB
|
||||
}
|
||||
|
||||
type ListWithItems struct {
|
||||
model.Lists
|
||||
type StackWithItems struct {
|
||||
model.Stacks
|
||||
|
||||
Schema struct {
|
||||
model.Schemas
|
||||
|
||||
SchemaItems []model.SchemaItems
|
||||
}
|
||||
SchemaItems []model.SchemaItems
|
||||
}
|
||||
|
||||
type ImageWithSchema struct {
|
||||
model.ImageLists
|
||||
model.ImageStacks
|
||||
|
||||
Items []model.ImageSchemaItems
|
||||
}
|
||||
@@ -41,35 +36,33 @@ type IDValue struct {
|
||||
// SELECT for lists
|
||||
// ========================================
|
||||
|
||||
func (m ListModel) List(ctx context.Context, userId uuid.UUID) ([]ListWithItems, error) {
|
||||
getListsWithItems := SELECT(
|
||||
Lists.AllColumns,
|
||||
Schemas.AllColumns,
|
||||
func (m StackModel) List(ctx context.Context, userId uuid.UUID) ([]StackWithItems, error) {
|
||||
getStacksWithItems := SELECT(
|
||||
Stacks.AllColumns,
|
||||
SchemaItems.AllColumns,
|
||||
).
|
||||
FROM(
|
||||
Lists.
|
||||
INNER_JOIN(Schemas, Schemas.ListID.EQ(Lists.ID)).
|
||||
INNER_JOIN(SchemaItems, SchemaItems.SchemaID.EQ(Schemas.ID)),
|
||||
Stacks.
|
||||
INNER_JOIN(SchemaItems, SchemaItems.StackID.EQ(Stacks.ID)),
|
||||
).
|
||||
WHERE(Lists.UserID.EQ(UUID(userId)))
|
||||
WHERE(Stacks.UserID.EQ(UUID(userId)))
|
||||
|
||||
lists := []ListWithItems{}
|
||||
err := getListsWithItems.QueryContext(ctx, m.dbPool, &lists)
|
||||
lists := []StackWithItems{}
|
||||
err := getStacksWithItems.QueryContext(ctx, m.dbPool, &lists)
|
||||
|
||||
return lists, err
|
||||
}
|
||||
|
||||
func (m ListModel) ListItems(ctx context.Context, listID uuid.UUID) ([]ImageWithSchema, error) {
|
||||
func (m StackModel) ListItems(ctx context.Context, listID uuid.UUID) ([]ImageWithSchema, error) {
|
||||
getListItems := SELECT(
|
||||
ImageLists.AllColumns,
|
||||
ImageStacks.AllColumns,
|
||||
ImageSchemaItems.AllColumns,
|
||||
).
|
||||
FROM(
|
||||
ImageLists.
|
||||
INNER_JOIN(ImageSchemaItems, ImageSchemaItems.ImageID.EQ(ImageLists.ImageID)),
|
||||
ImageStacks.
|
||||
INNER_JOIN(ImageSchemaItems, ImageSchemaItems.ImageID.EQ(ImageStacks.ImageID)),
|
||||
).
|
||||
WHERE(ImageLists.ListID.EQ(UUID(listID)))
|
||||
WHERE(ImageStacks.StackID.EQ(UUID(listID)))
|
||||
|
||||
listItems := make([]ImageWithSchema, 0)
|
||||
err := getListItems.QueryContext(ctx, m.dbPool, &listItems)
|
||||
@@ -77,174 +70,45 @@ func (m ListModel) ListItems(ctx context.Context, listID uuid.UUID) ([]ImageWith
|
||||
return listItems, err
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// SELECT for specific items
|
||||
// ========================================
|
||||
func (m StackModel) Get(ctx context.Context, listID uuid.UUID) (model.Stacks, error) {
|
||||
getStackStmt := Stacks.SELECT(Stacks.AllColumns).WHERE(Stacks.ID.EQ(UUID(listID)))
|
||||
|
||||
func (m ListModel) GetProcessing(ctx context.Context, processingListID uuid.UUID) (model.ProcessingLists, error) {
|
||||
getProcessingListStmt := ProcessingLists.
|
||||
SELECT(ProcessingLists.AllColumns).
|
||||
WHERE(ProcessingLists.ID.EQ(UUID(processingListID)))
|
||||
stack := model.Stacks{}
|
||||
err := getStackStmt.QueryContext(ctx, m.dbPool, &stack)
|
||||
|
||||
list := model.ProcessingLists{}
|
||||
err := getProcessingListStmt.QueryContext(ctx, m.dbPool, &list)
|
||||
|
||||
return list, err
|
||||
}
|
||||
|
||||
func (m ListModel) GetToProcess(ctx context.Context, listID uuid.UUID) (model.ProcessingLists, error) {
|
||||
getToProcessStmt := ProcessingLists.
|
||||
SELECT(ProcessingLists.AllColumns).
|
||||
WHERE(ProcessingLists.ID.EQ(UUID(listID)))
|
||||
|
||||
stack := []model.ProcessingLists{}
|
||||
err := getToProcessStmt.QueryContext(ctx, m.dbPool, &stack)
|
||||
|
||||
if len(stack) != 1 {
|
||||
return model.ProcessingLists{}, fmt.Errorf("Expected 1, got %d\n", len(stack))
|
||||
}
|
||||
|
||||
return stack[0], err
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// UPDATE
|
||||
// ========================================
|
||||
|
||||
func (m ListModel) StartProcessing(ctx context.Context, processingListID uuid.UUID) error {
|
||||
startProcessingStmt := ProcessingLists.
|
||||
UPDATE(ProcessingLists.Status).
|
||||
SET(model.Progress_InProgress).
|
||||
WHERE(ProcessingLists.ID.EQ(UUID(processingListID)))
|
||||
|
||||
_, err := startProcessingStmt.ExecContext(ctx, m.dbPool)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m ListModel) EndProcessing(ctx context.Context, processingListID uuid.UUID) error {
|
||||
startProcessingStmt := ProcessingLists.
|
||||
UPDATE(ProcessingLists.Status).
|
||||
SET(model.Progress_Complete).
|
||||
WHERE(ProcessingLists.ID.EQ(UUID(processingListID)))
|
||||
|
||||
_, err := startProcessingStmt.ExecContext(ctx, m.dbPool)
|
||||
return err
|
||||
return stack, err
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// INSERT methods
|
||||
// ========================================
|
||||
|
||||
func (m ListModel) Save(ctx context.Context, userId uuid.UUID, name string, description string, schemaItems []model.SchemaItems) (ListWithItems, error) {
|
||||
tx, err := m.dbPool.BeginTx(ctx, nil)
|
||||
func (m StackModel) Save(ctx context.Context, userID uuid.UUID, name string, description string) (model.Stacks, error) {
|
||||
saveListStmt := Stacks.
|
||||
INSERT(Stacks.UserID, Stacks.Name, Stacks.Description).
|
||||
VALUES(userID, name, description).
|
||||
RETURNING(Stacks.ID, Stacks.UserID, Stacks.Name, Stacks.Description, Stacks.CreatedAt)
|
||||
|
||||
stmt := Lists.INSERT(Lists.UserID, Lists.Name, Lists.Description).
|
||||
VALUES(userId, name, description).
|
||||
RETURNING(Lists.ID, Lists.Name, Lists.Description)
|
||||
list := model.Stacks{}
|
||||
err := saveListStmt.QueryContext(ctx, m.dbPool, &list)
|
||||
|
||||
newList := model.Lists{}
|
||||
err = stmt.QueryContext(ctx, tx, &newList)
|
||||
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return ListWithItems{}, fmt.Errorf("Could not save new list. %s", err)
|
||||
}
|
||||
|
||||
insertSchemaStmt := Schemas.INSERT(Schemas.ListID).
|
||||
VALUES(newList.ID).
|
||||
RETURNING(Schemas.ID)
|
||||
|
||||
newSchema := model.Schemas{}
|
||||
err = insertSchemaStmt.QueryContext(ctx, tx, &newSchema)
|
||||
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return ListWithItems{}, fmt.Errorf("Could not save new schema. %s", err)
|
||||
}
|
||||
|
||||
// This is very interesting...
|
||||
for i := range schemaItems {
|
||||
schemaItems[i].SchemaID = newSchema.ID
|
||||
}
|
||||
|
||||
insertSchemaItemsStmt := SchemaItems.INSERT(SchemaItems.Item, SchemaItems.Value, SchemaItems.Description, SchemaItems.SchemaID).
|
||||
MODELS(schemaItems)
|
||||
_, err = insertSchemaItemsStmt.ExecContext(ctx, tx)
|
||||
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return ListWithItems{}, fmt.Errorf("Could not save schema items. %s", err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return ListWithItems{}, fmt.Errorf("Could not commit transaction. %s", err)
|
||||
}
|
||||
|
||||
getListAndItems := SELECT(Lists.AllColumns, Schemas.AllColumns, SchemaItems.AllColumns).
|
||||
FROM(
|
||||
Lists.
|
||||
INNER_JOIN(Schemas, Schemas.ListID.EQ(Lists.ID)).
|
||||
INNER_JOIN(SchemaItems, SchemaItems.SchemaID.EQ(Schemas.ID)),
|
||||
).
|
||||
WHERE(Lists.ID.EQ(UUID(newList.ID)))
|
||||
|
||||
listWithItems := ListWithItems{}
|
||||
err = getListAndItems.QueryContext(ctx, m.dbPool, &listWithItems)
|
||||
|
||||
return listWithItems, err
|
||||
return list, err
|
||||
}
|
||||
|
||||
func (m ListModel) SaveInto(ctx context.Context, listID uuid.UUID, imageID uuid.UUID, schemaValues []IDValue) error {
|
||||
tx, err := m.dbPool.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (m StackModel) SaveItems(ctx context.Context, items []model.SchemaItems) error {
|
||||
saveItemsStmt := SchemaItems.INSERT(SchemaItems.AllColumns).MODELS(items)
|
||||
|
||||
var imageList model.ImageLists
|
||||
stmt := ImageLists.INSERT(ImageLists.ListID, ImageLists.ImageID).
|
||||
VALUES(listID, imageID).
|
||||
RETURNING(ImageLists.ID)
|
||||
_, err := saveItemsStmt.ExecContext(ctx, m.dbPool)
|
||||
|
||||
err = stmt.QueryContext(ctx, m.dbPool, &imageList)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Could not insert new list. %s", err)
|
||||
}
|
||||
|
||||
imageSchemaItems := make([]model.ImageSchemaItems, len(schemaValues))
|
||||
|
||||
for i, v := range schemaValues {
|
||||
parsedId, err := uuid.Parse(v.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
imageSchemaItems[i].SchemaItemID = parsedId
|
||||
imageSchemaItems[i].ImageID = imageList.ID
|
||||
imageSchemaItems[i].Value = &v.Value
|
||||
}
|
||||
|
||||
insertSchemaItemsStmt := ImageSchemaItems.
|
||||
INSERT(ImageSchemaItems.Value, ImageSchemaItems.SchemaItemID, ImageSchemaItems.ImageID).
|
||||
MODELS(imageSchemaItems)
|
||||
|
||||
_, err = insertSchemaItemsStmt.ExecContext(ctx, tx)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("Could not insert schema items. %s", err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
return err
|
||||
}
|
||||
|
||||
func (m ListModel) SaveProcessing(ctx context.Context, userID uuid.UUID, title string, fields string) error {
|
||||
insertListToProcess := ProcessingLists.
|
||||
INSERT(ProcessingLists.UserID, ProcessingLists.Title, ProcessingLists.Fields).
|
||||
VALUES(userID, title, fields)
|
||||
func (m StackModel) SaveImage(ctx context.Context, imageID uuid.UUID, stackID uuid.UUID) error {
|
||||
saveImageStmt := ImageStacks.
|
||||
INSERT(ImageStacks.ImageID, ImageStacks.StackID).
|
||||
VALUES(imageID, stackID)
|
||||
|
||||
_, err := insertListToProcess.ExecContext(ctx, m.dbPool)
|
||||
_, err := saveImageStmt.ExecContext(ctx, m.dbPool)
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -253,11 +117,11 @@ func (m ListModel) SaveProcessing(ctx context.Context, userID uuid.UUID, title s
|
||||
// DELETE methods
|
||||
// ========================================
|
||||
|
||||
func (m ListModel) DeleteImage(ctx context.Context, listID uuid.UUID, imageID uuid.UUID) error {
|
||||
deleteImageListStmt := ImageLists.DELETE().
|
||||
func (m StackModel) DeleteImage(ctx context.Context, listID uuid.UUID, imageID uuid.UUID) error {
|
||||
deleteImageListStmt := ImageStacks.DELETE().
|
||||
WHERE(
|
||||
ImageLists.ListID.EQ(UUID(listID)).
|
||||
AND(ImageLists.ImageID.EQ(UUID(imageID))),
|
||||
ImageStacks.StackID.EQ(UUID(listID)).
|
||||
AND(ImageStacks.ImageID.EQ(UUID(imageID))),
|
||||
)
|
||||
|
||||
_, err := deleteImageListStmt.ExecContext(ctx, m.dbPool)
|
||||
@@ -265,60 +129,14 @@ func (m ListModel) DeleteImage(ctx context.Context, listID uuid.UUID, imageID uu
|
||||
return err
|
||||
}
|
||||
|
||||
func (m ListModel) Delete(ctx context.Context, listID uuid.UUID, userID uuid.UUID) error {
|
||||
// First verify the list belongs to the user
|
||||
checkOwnershipStmt := Lists.
|
||||
SELECT(Lists.ID).
|
||||
WHERE(Lists.ID.EQ(UUID(listID)).AND(Lists.UserID.EQ(UUID(userID))))
|
||||
func (m StackModel) Delete(ctx context.Context, listID uuid.UUID, userID uuid.UUID) error {
|
||||
deleteStackStmt := Stacks.DELETE().WHERE(Stacks.ID.EQ(UUID(listID)).AND(Stacks.UserID.EQ(UUID(userID))))
|
||||
|
||||
var existingList model.Lists
|
||||
err := checkOwnershipStmt.QueryContext(ctx, m.dbPool, &existingList)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not verify list ownership: %w", err)
|
||||
}
|
||||
_, err := deleteStackStmt.ExecContext(ctx, m.dbPool)
|
||||
|
||||
// Start a transaction to ensure all deletions happen atomically
|
||||
tx, err := m.dbPool.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not start transaction: %w", err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
// Delete in reverse order of dependencies:
|
||||
// 1. Delete schema items first
|
||||
deleteSchemaItemsStmt := SchemaItems.DELETE().
|
||||
WHERE(SchemaItems.SchemaID.IN(
|
||||
Schemas.SELECT(Schemas.ID).
|
||||
WHERE(Schemas.ListID.EQ(UUID(listID))),
|
||||
))
|
||||
_, err = deleteSchemaItemsStmt.ExecContext(ctx, tx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not delete schema items: %w", err)
|
||||
}
|
||||
|
||||
// 2. Delete schemas
|
||||
deleteSchemasStmt := Schemas.DELETE().WHERE(Schemas.ListID.EQ(UUID(listID)))
|
||||
_, err = deleteSchemasStmt.ExecContext(ctx, tx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not delete schemas: %w", err)
|
||||
}
|
||||
|
||||
// 3. Delete the list itself
|
||||
deleteListStmt := Lists.DELETE().WHERE(Lists.ID.EQ(UUID(listID)))
|
||||
_, err = deleteListStmt.ExecContext(ctx, tx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not delete list: %w", err)
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not commit transaction: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func NewListModel(db *sql.DB) ListModel {
|
||||
return ListModel{dbPool: db}
|
||||
func NewListModel(db *sql.DB) StackModel {
|
||||
return StackModel{dbPool: db}
|
||||
}
|
||||
|
||||
@@ -49,28 +49,20 @@ func (m UserModel) Save(ctx context.Context, user model.Users) (model.Users, err
|
||||
}
|
||||
|
||||
type UserImageWithImage struct {
|
||||
model.UserImages
|
||||
|
||||
Image struct {
|
||||
model.Image
|
||||
ImageLists []model.ImageLists
|
||||
}
|
||||
model.Image
|
||||
ImageStacks []model.ImageStacks
|
||||
}
|
||||
|
||||
func (m UserModel) GetUserImages(ctx context.Context, userId uuid.UUID) ([]UserImageWithImage, error) {
|
||||
getUserImagesStmt := SELECT(
|
||||
UserImages.AllColumns,
|
||||
Image.ID,
|
||||
Image.ImageName,
|
||||
Image.Description,
|
||||
ImageLists.AllColumns,
|
||||
Image.AllColumns.Except(Image.Image),
|
||||
ImageStacks.AllColumns,
|
||||
).
|
||||
FROM(
|
||||
UserImages.
|
||||
INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID)).
|
||||
LEFT_JOIN(ImageLists, ImageLists.ImageID.EQ(UserImages.ImageID)),
|
||||
Image.
|
||||
LEFT_JOIN(ImageStacks, ImageStacks.ImageID.EQ(ImageStacks.ID)),
|
||||
).
|
||||
WHERE(UserImages.UserID.EQ(UUID(userId)))
|
||||
WHERE(Image.UserID.EQ(UUID(userId)))
|
||||
|
||||
userImages := []UserImageWithImage{}
|
||||
err := getUserImagesStmt.QueryContext(ctx, m.dbPool, &userImages)
|
||||
@@ -79,16 +71,12 @@ func (m UserModel) GetUserImages(ctx context.Context, userId uuid.UUID) ([]UserI
|
||||
}
|
||||
|
||||
type ListsWithImages struct {
|
||||
model.Lists
|
||||
model.Stacks
|
||||
|
||||
Schema struct {
|
||||
model.Schemas
|
||||
|
||||
SchemaItems []model.SchemaItems
|
||||
}
|
||||
SchemaItems []model.SchemaItems
|
||||
|
||||
Images []struct {
|
||||
model.ImageLists
|
||||
model.ImageStacks
|
||||
|
||||
Items []model.ImageSchemaItems
|
||||
}
|
||||
@@ -96,20 +84,18 @@ type ListsWithImages struct {
|
||||
|
||||
func (m UserModel) ListWithImages(ctx context.Context, userId uuid.UUID) ([]ListsWithImages, error) {
|
||||
stmt := SELECT(
|
||||
Lists.AllColumns,
|
||||
ImageLists.AllColumns,
|
||||
Schemas.AllColumns,
|
||||
Stacks.AllColumns,
|
||||
ImageStacks.AllColumns,
|
||||
SchemaItems.AllColumns,
|
||||
ImageSchemaItems.AllColumns,
|
||||
).
|
||||
FROM(
|
||||
Lists.
|
||||
INNER_JOIN(Schemas, Schemas.ListID.EQ(Lists.ID)).
|
||||
INNER_JOIN(SchemaItems, SchemaItems.SchemaID.EQ(Schemas.ID)).
|
||||
LEFT_JOIN(ImageLists, ImageLists.ListID.EQ(Lists.ID)).
|
||||
LEFT_JOIN(ImageSchemaItems, ImageSchemaItems.ImageID.EQ(ImageLists.ID)),
|
||||
Stacks.
|
||||
INNER_JOIN(SchemaItems, SchemaItems.StackID.EQ(Stacks.ID)).
|
||||
LEFT_JOIN(ImageStacks, ImageStacks.StackID.EQ(Stacks.ID)).
|
||||
LEFT_JOIN(ImageSchemaItems, ImageSchemaItems.ImageID.EQ(ImageStacks.ID)),
|
||||
).
|
||||
WHERE(Lists.UserID.EQ(UUID(userId)))
|
||||
WHERE(Stacks.UserID.EQ(UUID(userId)))
|
||||
|
||||
lists := []ListsWithImages{}
|
||||
err := stmt.QueryContext(ctx, m.dbPool, &lists)
|
||||
|
||||
Reference in New Issue
Block a user