refactor: sql queries related to privacy-accounting;
chore: regenerated swagger; feat: utilizing new 410 error when user is banned/unavailable/deleted
This commit is contained in:
@@ -281,7 +281,6 @@ JOIN users ON users.id = profiles.user_id
|
||||
WHERE users.username = $1;
|
||||
|
||||
;-- name: CheckProfileAccess :one
|
||||
-- XXX: recheck, was tired
|
||||
SELECT
|
||||
CASE WHEN u.deleted OR NOT u.verified THEN TRUE ELSE FALSE END AS user_unavailable,
|
||||
CASE WHEN EXISTS (
|
||||
@@ -300,7 +299,6 @@ JOIN users u ON p.user_id = u.id
|
||||
WHERE p.id = $1;
|
||||
|
||||
;-- name: GetProfileByUsernameWithPrivacy :one
|
||||
-- FIXME: tweak backend code to handle privacy correctly
|
||||
SELECT
|
||||
u.username,
|
||||
p.name,
|
||||
@@ -402,7 +400,6 @@ JOIN users u ON u.id = p.user_id
|
||||
WHERE u.username = @username::text;
|
||||
|
||||
-- name: GetWishlistsByUsernameWithPrivacy :many
|
||||
-- XXX: Obsolete, create according access check query instead
|
||||
SELECT
|
||||
wl.*,
|
||||
CASE
|
||||
@@ -496,32 +493,31 @@ FROM updated;
|
||||
SELECT * FROM wishes w
|
||||
WHERE w.guid = (@guid::text)::uuid;
|
||||
|
||||
;-- name: GetWishByGuidWithPrivacy :one
|
||||
-- XXX: Obsolete, create according access check query instead
|
||||
SELECT
|
||||
w.*,
|
||||
CASE
|
||||
WHEN
|
||||
(
|
||||
@requester::text = u.username OR
|
||||
NOT ps.hide_profile_details AND
|
||||
NOT
|
||||
(
|
||||
ps.hide_for_unauthenticated AND
|
||||
@requester::text = ''
|
||||
) AND
|
||||
NOT wl.hidden
|
||||
)
|
||||
THEN TRUE
|
||||
ELSE FALSE
|
||||
END AS access_allowed
|
||||
FROM wishes w
|
||||
JOIN wish_lists wl ON w.wish_list_id = wl.id
|
||||
JOIN profiles p ON wl.profile_id = p.id
|
||||
JOIN profile_settings ps ON ps.profile_id = p.id
|
||||
JOIN users u ON p.user_id = u.id
|
||||
WHERE
|
||||
w.guid = (@guid::text)::uuid AND
|
||||
w.deleted IS FALSE;
|
||||
;-- name: CheckWishAccessByGuid :one
|
||||
SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM wishes w
|
||||
JOIN wish_lists wl ON w.wish_list_id = wl.id
|
||||
JOIN profiles p ON wl.profile_id = p.id
|
||||
JOIN profile_settings ps ON ps.profile_id = p.id
|
||||
JOIN users u ON p.user_id = u.id
|
||||
LEFT JOIN banned_users bu ON u.id = bu.user_id
|
||||
AND bu.pardoned = FALSE
|
||||
AND (bu.expires_at IS NULL OR bu.expires_at > NOW())
|
||||
WHERE w.guid = (@guid::text)::uuid
|
||||
AND ps.hide_profile_details = FALSE
|
||||
AND (
|
||||
@requester::text != ''
|
||||
OR ps.hide_for_unauthenticated IS FALSE
|
||||
)
|
||||
AND (
|
||||
w.fulfilled = FALSE
|
||||
OR ps.hide_fulfilled IS FALSE
|
||||
)
|
||||
AND w.deleted = FALSE
|
||||
AND wl.deleted = FALSE
|
||||
AND u.deleted = FALSE
|
||||
AND bu.id IS NULL -- Ensures owner is not banned
|
||||
);
|
||||
|
||||
--: }}}
|
||||
|
||||
@@ -121,63 +121,3 @@ CREATE TABLE IF NOT EXISTS "wishes" (
|
||||
fulfilled_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
|
||||
CREATE OR REPLACE FUNCTION get_profile(requester_user_id BIGINT, target_profile_id BIGINT)
|
||||
RETURNS JSONB AS $$
|
||||
DECLARE
|
||||
profile_record profiles%ROWTYPE;
|
||||
settings_record profile_settings%ROWTYPE;
|
||||
is_owner BOOLEAN;
|
||||
is_banned BOOLEAN;
|
||||
is_deleted BOOLEAN;
|
||||
BEGIN
|
||||
-- Check if target user exists and is not deleted/banned
|
||||
SELECT p.*, u.deleted INTO profile_record
|
||||
FROM profiles p
|
||||
JOIN users u ON p.user_id = u.id
|
||||
WHERE p.id = target_profile_id;
|
||||
|
||||
IF NOT FOUND THEN
|
||||
RETURN NULL; -- Or raise an exception for "not found"
|
||||
END IF;
|
||||
|
||||
is_deleted := profile_record.deleted; -- From users table
|
||||
IF is_deleted THEN
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
-- Check if requester is banned (simplified; expand as needed)
|
||||
SELECT EXISTS(SELECT 1 FROM banned_users WHERE user_id = requester_user_id AND pardoned = FALSE AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)) INTO is_banned;
|
||||
IF is_banned THEN
|
||||
RAISE EXCEPTION 'Requester is banned';
|
||||
END IF;
|
||||
|
||||
-- Determine ownership
|
||||
is_owner := (profile_record.user_id = requester_user_id);
|
||||
|
||||
-- Fetch settings
|
||||
SELECT * INTO settings_record FROM profile_settings WHERE profile_id = target_profile_id;
|
||||
|
||||
-- Apply privacy: Hide for unauthenticated or based on settings
|
||||
IF requester_user_id IS NULL AND settings_record.hide_for_unauthenticated THEN -- NULL requester means unauth
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
IF NOT is_owner AND settings_record.hide_profile_details THEN
|
||||
RETURN NULL; -- Or return minimal public data
|
||||
END IF;
|
||||
|
||||
-- Sanitize fields based on settings
|
||||
IF NOT is_owner AND settings_record.hide_birthday THEN
|
||||
profile_record.birthday := NULL;
|
||||
END IF;
|
||||
-- Add more field-level masking here (e.g., bio, avatar_url)
|
||||
|
||||
-- Return as JSONB for easy app consumption
|
||||
RETURN row_to_json(profile_record)::JSONB;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RAISE NOTICE 'Access denied: %', SQLERRM;
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
Reference in New Issue
Block a user