memos/store/db/sqlite/memo_policy.go

85 lines
2.8 KiB
Go

package sqlite
import (
"context"
"database/sql"
stderrors "errors"
"github.com/usememos/memos/store"
)
func validateSQLiteMemoWritePolicy(ctx context.Context, executor dbExecutor, memoID int32, policy *store.MemoWritePolicy, update *store.UpdateMemo) error {
var actorStatus store.RowStatus
if err := executor.QueryRowContext(ctx, "SELECT row_status FROM user WHERE id = ?", policy.ActorUserID).Scan(&actorStatus); stderrors.Is(err, sql.ErrNoRows) {
return store.ErrMemoSpaceMembershipRequired
} else if err != nil {
return err
} else if actorStatus != store.Normal {
return store.ErrMemoSpaceMembershipRequired
}
snapshot := new(store.MemoWriteSnapshot)
var spaceID sql.NullInt64
if err := executor.QueryRowContext(ctx, `SELECT creator_id, row_status, space_id, visibility FROM memo WHERE id = ?`, memoID).Scan(
&snapshot.CreatorID, &snapshot.RowStatus, &spaceID, &snapshot.Visibility,
); err != nil {
if stderrors.Is(err, sql.ErrNoRows) {
return store.ErrMemoMutationConflict
}
return err
}
snapshot.SpaceID = store.NullInt32Pointer(spaceID)
if err := populateSQLiteMemoPolicySpaceState(ctx, executor, policy.ActorUserID, update, snapshot); err != nil {
return err
}
if update != nil && update.Visibility != nil && *update.Visibility == store.SpaceAudience {
var shareID int32
err := executor.QueryRowContext(ctx, `SELECT id FROM memo_share
WHERE memo_id = ? AND (expires_ts IS NULL OR expires_ts > CAST(strftime('%s', 'now') AS INTEGER))
LIMIT 1`, memoID).Scan(&shareID)
snapshot.HasActiveShare = err == nil
if err != nil && !stderrors.Is(err, sql.ErrNoRows) {
return err
}
}
return store.ValidateMemoWriteSnapshot(policy, update, snapshot)
}
func populateSQLiteMemoPolicySpaceState(
ctx context.Context,
executor dbExecutor,
actorUserID int32,
update *store.UpdateMemo,
snapshot *store.MemoWriteSnapshot,
) error {
if snapshot.SpaceID != nil {
exists, member, err := sqliteMemoPolicySpaceState(ctx, executor, *snapshot.SpaceID, actorUserID)
if err != nil {
return err
}
snapshot.SourceSpaceExists = exists
snapshot.SourceMemberActive = member
}
if update != nil && update.SpaceID != nil {
exists, member, err := sqliteMemoPolicySpaceState(ctx, executor, *update.SpaceID, actorUserID)
if err != nil {
return err
}
snapshot.TargetSpaceExists = exists
snapshot.TargetMemberActive = member
}
return nil
}
func sqliteMemoPolicySpaceState(ctx context.Context, executor dbExecutor, spaceID, actorUserID int32) (bool, bool, error) {
var exists bool
if err := executor.QueryRowContext(ctx, "SELECT EXISTS(SELECT 1 FROM space WHERE id = ?)", spaceID).Scan(&exists); err != nil {
return false, false, err
}
if !exists {
return false, false, nil
}
member, err := sqliteSpaceMemberActive(ctx, executor, spaceID, actorUserID)
return true, member, err
}