feat: prevent users from sharing projects and reviews with themselves

This commit is contained in:
willchen96 2026-05-16 00:05:16 +08:00
parent 9e7046d4aa
commit 87e55d6046
4 changed files with 60 additions and 4 deletions

View file

@ -11,6 +11,7 @@ import { useDirectoryData } from "../shared/useDirectoryData";
import { FileDirectory } from "../shared/FileDirectory";
import { EmailPillInput } from "../shared/EmailPillInput";
import type { MikeProject } from "../shared/types";
import { useAuth } from "@/contexts/AuthContext";
interface Props {
open: boolean;
@ -28,6 +29,8 @@ export function NewProjectModal({ open, onClose, onCreated }: Props) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const fileInputRef = useRef<HTMLInputElement>(null);
const { user } = useAuth();
const ownEmail = user?.email?.trim().toLowerCase() ?? null;
const { loading: dirLoading, standaloneDocuments, projects: dirProjects } = useDirectoryData(open);
@ -49,7 +52,9 @@ export function NewProjectModal({ open, onClose, onCreated }: Props) {
const project = await createProject(
name.trim(),
cmNumber.trim() || undefined,
sharedEmails,
ownEmail
? sharedEmails.filter((email) => email !== ownEmail)
: sharedEmails,
);
await Promise.all([
...[...selectedDocIds].map((id) => addDocumentToProject(project.id, id).catch(() => {})),
@ -137,6 +142,11 @@ export function NewProjectModal({ open, onClose, onCreated }: Props) {
<EmailPillInput
emails={sharedEmails}
onChange={setSharedEmails}
validate={async (email) =>
ownEmail && email === ownEmail
? "You cannot share a project with yourself."
: null
}
placeholder="Add colleagues by email…"
/>
</div>

View file

@ -136,13 +136,22 @@ export function PeopleModal({
}
const trimmedNewEmail = newEmail.trim().toLowerCase();
const normalizedCurrentUserEmail =
currentUserEmail?.trim().toLowerCase() ?? null;
const isValidEmail = EMAIL_RE.test(trimmedNewEmail);
const sharedLower = sharedWith.map((e) => e.toLowerCase());
const alreadyShared = sharedLower.includes(trimmedNewEmail);
const isOwnerEmail =
!!ownerEmail && trimmedNewEmail === ownerEmail.toLowerCase();
const isSelfEmail =
!!normalizedCurrentUserEmail &&
trimmedNewEmail === normalizedCurrentUserEmail;
const canAdd =
isValidEmail && !alreadyShared && !isOwnerEmail && busy === null;
isValidEmail &&
!alreadyShared &&
!isOwnerEmail &&
!isSelfEmail &&
busy === null;
async function handleAdd() {
if (!canAdd || !onSharedWithChange) return;
@ -249,10 +258,16 @@ export function PeopleModal({
{trimmedNewEmail} is the owner.
</p>
)}
{isSelfEmail && !isOwnerEmail && trimmedNewEmail && (
<p className="mt-1.5 text-xs text-gray-400">
You cannot share this with yourself.
</p>
)}
{trimmedNewEmail &&
!isValidEmail &&
!alreadyShared &&
!isOwnerEmail && (
!isOwnerEmail &&
!isSelfEmail && (
<p className="mt-1.5 text-xs text-gray-400">
Enter a valid email.
</p>