feature(up-dow-avatar): tidy avatar upload, enforce BearerAuth, add apidog types
This commit is contained in:
parent
3c52ec5e3a
commit
47ef207454
@ -4,6 +4,7 @@
|
||||
"@heroicons/react": "^2.2.0",
|
||||
"@supabase/supabase-js": "^2.75.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"next": "^16.0.0",
|
||||
"react-big-calendar": "^1.19.4",
|
||||
"react-signature-canvas": "^1.1.0-alpha.2"
|
||||
}
|
||||
|
||||
1107
pnpm-lock.yaml
generated
Normal file
1107
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -2771,30 +2771,27 @@ export async function uploadFotoPaciente(_id: string | number, _file: File): Pro
|
||||
};
|
||||
const ext = extMap[_file.type] || 'jpg';
|
||||
|
||||
// O bucket deve ser 'avatars' e o caminho do objeto será userId/avatar.ext
|
||||
const bucket = 'avatars';
|
||||
const objectPath = `${userId}/avatar.${ext}`;
|
||||
const uploadUrl = `${ENV_CONFIG.SUPABASE_URL}/storage/v1/object/${bucket}/${encodeURIComponent(objectPath)}`;
|
||||
const uploadUrl = `https://mock.apidog.com/m1/1053378-0-default/storage/v1/object/avatars/${encodeURI(objectPath)}`;
|
||||
|
||||
// Build multipart form data
|
||||
const form = new FormData();
|
||||
form.append('file', _file, `avatar.${ext}`);
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
// Supabase requires the anon key in 'apikey' header for client-side uploads
|
||||
apikey: ENV_CONFIG.SUPABASE_ANON_KEY,
|
||||
// Accept json
|
||||
Accept: 'application/json',
|
||||
Accept: 'application/json'
|
||||
};
|
||||
// if user is logged in, include Authorization header
|
||||
const jwt = getAuthToken();
|
||||
if (jwt) headers.Authorization = `Bearer ${jwt}`;
|
||||
|
||||
console.debug('[uploadFotoPaciente] Iniciando upload:', {
|
||||
const jwt = getAuthToken();
|
||||
if (!jwt) {
|
||||
throw new Error('Autenticação necessária: token JWT obrigatório para upload de avatar');
|
||||
}
|
||||
headers.Authorization = `Bearer ${jwt}`;
|
||||
|
||||
console.debug('[uploadFotoPaciente] Iniciando upload:', {
|
||||
url: uploadUrl,
|
||||
fileType: _file.type,
|
||||
fileSize: _file.size,
|
||||
hasAuth: !!jwt
|
||||
hasAuth: true
|
||||
});
|
||||
|
||||
const res = await fetch(uploadUrl, {
|
||||
@ -2827,7 +2824,7 @@ export async function uploadFotoPaciente(_id: string | number, _file: File): Pro
|
||||
|
||||
// The API may not return a structured body; return the Key we constructed
|
||||
const key = (json && (json.Key || json.key)) ?? objectPath;
|
||||
const publicUrl = `${ENV_CONFIG.SUPABASE_URL}/storage/v1/object/public/avatars/${encodeURIComponent(userId)}/avatar.${ext}`;
|
||||
const publicUrl = `https://mock.apidog.com/m1/1053378-0-default/storage/v1/object/avatars/${encodeURIComponent(userId)}/avatar.${ext}`;
|
||||
return { foto_url: publicUrl, Key: key };
|
||||
}
|
||||
|
||||
@ -2842,21 +2839,22 @@ export function getAvatarPublicUrl(userId: string | number): string {
|
||||
// Example: https://<project>.supabase.co/storage/v1/object/public/avatars/{userId}/avatar
|
||||
const id = String(userId || '').trim();
|
||||
if (!id) throw new Error('userId é obrigatório para obter URL pública do avatar');
|
||||
const base = String(ENV_CONFIG.SUPABASE_URL).replace(/\/$/, '');
|
||||
// Note: Supabase public object path does not require an extension in some setups
|
||||
return `${base}/storage/v1/object/public/${encodeURIComponent('avatars')}/${encodeURIComponent(id)}/avatar`;
|
||||
return `https://mock.apidog.com/m1/1053378-0-default/storage/v1/object/avatars/${encodeURIComponent(id)}/avatar`;
|
||||
}
|
||||
|
||||
export async function removerFotoPaciente(_id: string | number): Promise<void> {
|
||||
const userId = String(_id || '').trim();
|
||||
if (!userId) throw new Error('ID do paciente é obrigatório para remover foto');
|
||||
const deleteUrl = `${ENV_CONFIG.SUPABASE_URL}/storage/v1/object/avatars/${encodeURIComponent(userId)}/avatar`;
|
||||
const objectPath = `${userId}/avatar`;
|
||||
const deleteUrl = `https://mock.apidog.com/m1/1053378-0-default/storage/v1/object/avatars/${encodeURI(objectPath)}`;
|
||||
const headers: Record<string,string> = {
|
||||
apikey: ENV_CONFIG.SUPABASE_ANON_KEY,
|
||||
Accept: 'application/json',
|
||||
Accept: 'application/json'
|
||||
};
|
||||
|
||||
// Require auth for delete (follow security expectations)
|
||||
const jwt = getAuthToken();
|
||||
if (jwt) headers.Authorization = `Bearer ${jwt}`;
|
||||
if (!jwt) throw new Error('Autenticação necessária: token JWT obrigatório para remover avatar');
|
||||
headers.Authorization = `Bearer ${jwt}`;
|
||||
|
||||
try {
|
||||
console.debug('[removerFotoPaciente] Deleting avatar for user:', userId, 'url:', deleteUrl);
|
||||
|
||||
11
susconecta/types/apidog.ts
Normal file
11
susconecta/types/apidog.ts
Normal file
@ -0,0 +1,11 @@
|
||||
// Types for APIdog/OpenAPI helper models
|
||||
export interface ApidogModel {
|
||||
/**
|
||||
* Path parameter used by the mock/OpenAPI for storage endpoints.
|
||||
* Example: "user-123/avatar.jpg"
|
||||
*/
|
||||
path: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export default ApidogModel;
|
||||
Loading…
x
Reference in New Issue
Block a user