fix: Superhuman sync solo agencia — mensaje claro y botón oculto a cliente
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,7 +20,15 @@ async function requireAgency() {
|
|||||||
data: { user },
|
data: { user },
|
||||||
} = await supabase.auth.getUser();
|
} = await supabase.auth.getUser();
|
||||||
if (!user || !isAgencyRole(userRole(user))) {
|
if (!user || !isAgencyRole(userRole(user))) {
|
||||||
return { error: NextResponse.json({ error: 'Forbidden' }, { status: 403 }) };
|
return {
|
||||||
|
error: NextResponse.json(
|
||||||
|
{
|
||||||
|
error:
|
||||||
|
'Forbidden: sincronizar Superhuman requiere rol agencia (admin/team).',
|
||||||
|
},
|
||||||
|
{ status: 403 }
|
||||||
|
),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (!superhumanConfigured()) {
|
if (!superhumanConfigured()) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ export async function GET() {
|
|||||||
portfolioWide: false,
|
portfolioWide: false,
|
||||||
tenantId,
|
tenantId,
|
||||||
entries,
|
entries,
|
||||||
|
isAgency: agency,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Payload = {
|
|||||||
tenantId?: string;
|
tenantId?: string;
|
||||||
hint?: string;
|
hint?: string;
|
||||||
entries: Entry[];
|
entries: Entry[];
|
||||||
|
isAgency?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function typeLabel(t: string) {
|
function typeLabel(t: string) {
|
||||||
@@ -237,19 +238,21 @@ export default function SeguimientoBoard() {
|
|||||||
<Send className="w-3.5 h-3.5" />
|
<Send className="w-3.5 h-3.5" />
|
||||||
{noteBusy ? 'Guardando…' : 'Añadir al seguimiento'}
|
{noteBusy ? 'Guardando…' : 'Añadir al seguimiento'}
|
||||||
</button>
|
</button>
|
||||||
<button
|
{data.isAgency ? (
|
||||||
type="button"
|
<button
|
||||||
disabled={syncBusy || !data.tenantId}
|
type="button"
|
||||||
onClick={() => void syncSuperhuman()}
|
disabled={syncBusy || !data.tenantId}
|
||||||
className="inline-flex items-center gap-2 rounded-xl border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 disabled:opacity-50"
|
onClick={() => void syncSuperhuman()}
|
||||||
>
|
className="inline-flex items-center gap-2 rounded-xl border border-gray-200 bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 disabled:opacity-50"
|
||||||
{syncBusy ? (
|
>
|
||||||
<Loader2 className="w-3.5 h-3.5 animate-spin" />
|
{syncBusy ? (
|
||||||
) : (
|
<Loader2 className="w-3.5 h-3.5 animate-spin" />
|
||||||
<Radio className="w-3.5 h-3.5 text-emerald-600" />
|
) : (
|
||||||
)}
|
<Radio className="w-3.5 h-3.5 text-emerald-600" />
|
||||||
Traer notas Superhuman
|
)}
|
||||||
</button>
|
Traer notas Superhuman
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
{noteMsg ? (
|
{noteMsg ? (
|
||||||
<p className="text-xs text-emerald-700">{noteMsg}</p>
|
<p className="text-xs text-emerald-700">{noteMsg}</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -97,7 +97,13 @@ export async function middleware(req: NextRequest) {
|
|||||||
|
|
||||||
if (user && role === 'client' && path.startsWith('/api/admin/')) {
|
if (user && role === 'client' && path.startsWith('/api/admin/')) {
|
||||||
return withSecurityHeaders(
|
return withSecurityHeaders(
|
||||||
NextResponse.json({ error: 'Forbidden' }, { status: 403 })
|
NextResponse.json(
|
||||||
|
{
|
||||||
|
error:
|
||||||
|
'Forbidden: solo usuarios agencia (admin/team) pueden usar esta acción. Entra con marketing@4ventures.es.',
|
||||||
|
},
|
||||||
|
{ status: 403 }
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user