50 lines
2.6 KiB
Go
50 lines
2.6 KiB
Go
package postgres
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/usememos/memos/store"
|
|
)
|
|
|
|
// postgresMemoAccessPredicate builds the canonical memo-local read predicate
|
|
// for memoAlias and appends its bind values to args. Callers supply distinct
|
|
// aliases when the predicate is embedded more than once in a query.
|
|
func postgresMemoAccessPredicate(access *store.MemoAccessScope, memoAlias, memberAlias string, args *[]any) string {
|
|
clauses := []string{}
|
|
if access.AllowPublic {
|
|
clauses = append(clauses, memoAlias+".visibility = 'PUBLIC'")
|
|
}
|
|
if access.UserID != nil {
|
|
activeHolder := placeholder(len(*args) + 1)
|
|
*args = append(*args, *access.UserID)
|
|
authenticatedClauses := []string{}
|
|
|
|
privateHolder := placeholder(len(*args) + 1)
|
|
*args = append(*args, *access.UserID)
|
|
authenticatedClauses = append(authenticatedClauses, "("+memoAlias+".visibility = 'PRIVATE' AND "+memoAlias+".creator_id = "+privateHolder+")")
|
|
if access.AllowProtected {
|
|
authenticatedClauses = append(authenticatedClauses, memoAlias+".visibility = 'PROTECTED'")
|
|
}
|
|
memberHolder := placeholder(len(*args) + 1)
|
|
*args = append(*args, *access.UserID)
|
|
authenticatedClauses = append(authenticatedClauses, "("+memoAlias+".visibility = 'SPACE' AND EXISTS (SELECT 1 FROM space_member AS "+memberAlias+" WHERE "+memberAlias+".space_id = "+memoAlias+".space_id AND "+memberAlias+".user_id = "+memberHolder+" AND "+memberAlias+".status = 'ACTIVE' AND "+memberAlias+".role IN ('ADMIN', 'USER')))")
|
|
|
|
clauses = append(clauses, `(EXISTS (SELECT 1 FROM "user" AS access_user WHERE access_user.id = `+activeHolder+` AND access_user.row_status = 'NORMAL') AND (`+strings.Join(authenticatedClauses, " OR ")+`))`)
|
|
}
|
|
if len(clauses) == 0 {
|
|
return "1 = 0"
|
|
}
|
|
|
|
validMemo := "(" + memoAlias + ".visibility IN ('PUBLIC', 'PROTECTED', 'PRIVATE', 'SPACE')" +
|
|
` AND EXISTS (SELECT 1 FROM "user" AS valid_creator WHERE valid_creator.id = ` + memoAlias + `.creator_id AND valid_creator.row_status IN ('NORMAL', 'ARCHIVED'))` +
|
|
" AND (" + memoAlias + ".visibility <> 'SPACE' OR (" + memoAlias + ".space_id IS NOT NULL" +
|
|
" AND EXISTS (SELECT 1 FROM space AS valid_space WHERE valid_space.id = " + memoAlias + ".space_id))))"
|
|
validState := memoAlias + ".row_status = 'NORMAL'"
|
|
if access.UserID != nil {
|
|
targetStateHolder := placeholder(len(*args) + 1)
|
|
*args = append(*args, *access.UserID)
|
|
validState = fmt.Sprintf("(%s.row_status = 'NORMAL' OR (%s.row_status = 'ARCHIVED' AND %s.creator_id = %s))", memoAlias, memoAlias, memoAlias, targetStateHolder)
|
|
}
|
|
return "(" + strings.Join(clauses, " OR ") + ") AND " + validMemo + " AND " + validState
|
|
}
|