Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

security: now only authenticated users can post #178

Merged
merged 3 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/app/auth/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Suspense, useEffect } from 'react';
import Login from '../../components/auth/Login';
import { useRouter, useSearchParams } from 'next/navigation';
import { authService } from '@/lib/service';
import { AlertTriangle } from 'lucide-react';

export default function AUthPage() {
return (
Expand All @@ -28,6 +29,20 @@ function Auth() {

return (
<section className="mx-6 lg:m-16">
<div className="bg-red-100 border-l-4 border-red-500 p-4 rounded mb-4">
<div className="flex items-start">
<AlertTriangle className="h-5 w-5 text-red-500 mt-0.5 mr-2" />
<div>
<h2 className="text-red-800 font-bold">
POR MOTIVOS DE SEGURIDAD HEMOS DESHABILITADO LAS PUBLICACIONES ANONIMAS
</h2>
<p className="text-red-700 text-sm mt-1">Ahora debes registrarte para crear una publicacion.</p>
<p className="text-red-900 text-sm mt-1 font-medium">
Por dificultades tecnicas, por favor escríbenos a [email protected]
</p>
</div>
</div>
</div>
<Login onSuccessCallback={() => router.push(redirect)} redirectUrl={redirect} />
</section>
);
Expand Down
19 changes: 18 additions & 1 deletion src/app/ofrecer-ayuda/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
'use client';
import OfferHelp from '@/components/OfferHelp';
import { supabase } from '@/lib/supabase/client';
import { useEffect, useState } from 'react';

export default function OfrecerAyuda() {
return <OfferHelp />;
const [session, setSession] = useState(null);

useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }: any) => {
setSession(session);
});
}, []);

return session ? (
<OfferHelp sessionProp={session} />
) : (
<div className="flex justify-center items-center min-h-screen">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
</div>
);
}
3 changes: 1 addition & 2 deletions src/app/solicitar-ayuda/_components/Form/FormContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ const mapHelpToEnum = (helpTypeMap: FormData['tiposDeAyuda']): Enums['help_type_
[] as Enums['help_type_enum'][],
);

export function FormContainer() {
export function FormContainer({ session }: any) {
const router = useRouter();
const session = useSession();

const userId = session.user?.id;

Expand Down
40 changes: 23 additions & 17 deletions src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,29 @@ export function FormRenderer({
</div>
<PhoneInput phoneNumber={formData.contacto} onChange={handlePhoneChange} required />
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Correo electrónico <span className="text-red-500">*</span>
</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleEmailChange}
className="w-full p-2 border rounded focus:ring-2 focus:ring-green-500 focus:border-green-500"
/>
<p className="mt-1 text-sm text-gray-500">
{isUserLoggedIn
? 'Se utilizará para que puedas eliminar o editar la información de tu solicitud'
: 'Se utilizará para que puedas actualizar tu solicitud y marcarla como completada. Para realizar cambios, deberás registrarte con el mismo email'}
</p>
</div>
{/*
MANTENIDO EN CASO DE RE UTILIZAR EN EL FUTURO
ACTUALMENTE NO APARECERA DE NINGUNA FORMA
*/}
{!isUserLoggedIn && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Correo electrónico <span className="text-red-500">*</span>
</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleEmailChange}
className="w-full p-2 border rounded focus:ring-2 focus:ring-green-500 focus:border-green-500"
/>
<p className="mt-1 text-sm text-gray-500">
{isUserLoggedIn
? 'Se utilizará para que puedas eliminar o editar la información de tu solicitud'
: 'Se utilizará para que puedas actualizar tu solicitud y marcarla como completada. Para realizar cambios, deberás registrarte con el mismo email'}
</p>
</div>
)}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Ubicación exacta <span className="text-red-500">*</span>
Expand Down
22 changes: 19 additions & 3 deletions src/app/solicitar-ayuda/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { AlertTriangle } from 'lucide-react';
'use client';
import { useEffect, useState } from 'react';
import Image from 'next/image';
import { Form } from './_components/Form';
import { CallCenterLink } from '@/components/CallCenterLink';
import { AlertTriangle } from 'lucide-react';
import { supabase } from '@/lib/supabase/client';
import { Form } from './_components/Form';

export default function SolicitarAyuda() {
const [session, setSession] = useState(null);

useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }: any) => {
setSession(session);
});
}, []);
return (
<div className="space-y-6">
{/* Banner de emergencia */}
Expand Down Expand Up @@ -55,7 +65,13 @@ export default function SolicitarAyuda() {
</div>
</div>
</div>
<Form />
{session ? (
<Form session={session} />
) : (
<div className="flex justify-center items-center min-h-screen">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
</div>
)}
</div>
);
}
8 changes: 0 additions & 8 deletions src/app/solicitudes/editar/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import RequestHelp from '@/components/RequestHelp';
import Unauthorized from '@/components/Unauthorized';
import { helpRequestService } from '@/lib/service';
import { createClient } from '@/lib/supabase/server';

export default async function EditarSolicitud({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
const supabase = await createClient();
const { data: session } = await supabase.auth.getUser();
if (session.user === null) {
return <Unauthorized />;
}
const request = await helpRequestService.getOne(Number(id));

return (
Expand Down
44 changes: 26 additions & 18 deletions src/components/OfferHelp.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,20 @@ export default function OfferHelp({
id = 0,
redirect = '/casos-activos/ofertas',
submitType = 'create',
sessionProp = undefined,
}) {
const { towns } = useTowns();
const session = useSession();
const sessionProvider = useSession();
const session = sessionProp || sessionProvider;

const router = useRouter();

const userId = session.user?.id;

const isLoggedIn = Boolean(session?.user);

const [formData, setFormData] = useState({
nombre: data.name || session?.user?.user_metadata?.full_name || '',
nombre: data.name || session?.user?.user_metadata?.full_name || session?.user?.user_metadata?.nombre || '',
telefono: data.contact_info || session?.user?.user_metadata?.telefono || '',
email: data.additional_info?.email || session?.user?.user_metadata?.email || '',
ubicacion: data.location || '',
Expand Down Expand Up @@ -201,7 +205,7 @@ export default function OfferHelp({

{/* Formulario */}

<div className="space-y-6 max-h-[65vh] overflow-y-auto p-2">
<div className="space-y-6 overflow-y-auto p-2">
{/* Datos personales */}
<div className="grid md:grid-cols-2 gap-4">
<div>
Expand All @@ -218,21 +222,25 @@ export default function OfferHelp({
</div>
<PhoneInput phoneNumber={formData.telefono} onChange={handlePhoneChange} required />
</div>

{submitType === 'create' && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-1" htmlFor="userEmail">
Correo electrónico
</label>
<input
id="userEmail"
type="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
className="w-full p-2 border rounded focus:ring-2 focus:ring-green-500 focus:border-green-500"
/>
</div>
)}
{/*
MANTENIDO EN CASO DE RE UTILIZAR EN EL FUTURO
ACTUALMENTE NO APARECERA DE NINGUNA FORMA
*/}
{submitType === 'create' ||
(isLoggedIn && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-1" htmlFor="userEmail">
Correo electrónico
</label>
<input
id="userEmail"
type="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
className="w-full p-2 border rounded focus:ring-2 focus:ring-green-500 focus:border-green-500"
/>
</div>
))}
{submitType === 'edit' && (
<div>
<label htmlFor="status" className="block text-sm font-medium text-gray-700 mb-1">
Expand Down
6 changes: 5 additions & 1 deletion src/components/layout/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export default function Sidebar({ isOpen, toggleAction }: SidebarProps) {
title: 'Mis solicitudes',
description: 'Edita o elimina tus solicitudes',
path: '/solicitudes',
isLogged: true,
color: 'text-red-500',
hide: !hasRequests,
},
Expand All @@ -78,6 +79,7 @@ export default function Sidebar({ isOpen, toggleAction }: SidebarProps) {
title: 'Mis ofertas',
description: 'Edita o elimina tus ofertas',
path: '/ofertas',
isLogged: true,
color: 'text-green-500',
hide: !hasOffers,
},
Expand All @@ -93,13 +95,15 @@ export default function Sidebar({ isOpen, toggleAction }: SidebarProps) {
title: 'Solicitar Ayuda',
description: 'Si necesitas asistencia',
path: '/solicitar-ayuda',
isLogged: true,
color: 'text-red-600',
},
{
icon: HeartHandshake,
title: 'Ofrecer Ayuda',
description: 'Si puedes ayudar a otros',
path: '/ofrecer-ayuda',
isLogged: true,
color: 'text-green-600',
},
{
Expand Down Expand Up @@ -208,7 +212,7 @@ export default function Sidebar({ isOpen, toggleAction }: SidebarProps) {
<button
key={item.path}
onClick={() => {
router.push(item.path);
router.push(item?.isLogged && !userId ? '/auth?redirect=' + item.path : item.path);
if (window.innerWidth < 768) toggleAction();
}}
className={`w-full text-left transition-colors ${
Expand Down
13 changes: 13 additions & 0 deletions src/lib/supabase/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ export async function updateSession(request: NextRequest) {
return NextResponse.redirect(url);
}

const {
data: { user },
} = await supabase.auth.getUser()

if (
!user &&
request.nextUrl.pathname.startsWith('/solicitudes/editar') ||
!user &&
request.nextUrl.pathname.startsWith('/ofertas/editar')
) {
url.pathname = '/auth'
return NextResponse.redirect(url)
}
// IMPORTANT: You *must* return the supabaseResponse object as it is. If you're
// creating a new response object with NextResponse.next() make sure to:
// 1. Pass the request in it, like so:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
drop policy "Enable insert access" on "public"."help_requests";

drop policy "Enable insert for all users" on "public"."help_requests";

drop policy "Enable insert for anonymous users" on "public"."help_requests";

drop policy "Enable_update_for_users_based_on_email" on "public"."help_requests";

create policy "Enable insert access"
on "public"."help_requests"
as permissive
for insert
to authenticated
with check (true);


create policy "Enable insert for all users"
on "public"."help_requests"
as permissive
for insert
to authenticated
with check (true);


create policy "Enable insert for anonymous users"
on "public"."help_requests"
as permissive
for insert
to authenticated
with check (true);


create policy "Enable_update_for_users_based_on_email"
on "public"."help_requests"
as permissive
for update
to authenticated
using (((auth.uid() IS NOT NULL) AND ((additional_info ->> 'email'::text) = auth.email())));



Loading