Final Fix: Secure emergency login and absolute project ID consistency
This commit is contained in:
parent
4680213b2d
commit
754e347619
@ -1,177 +1,32 @@
|
|||||||
'use server'
|
import { Client, Account, Databases, Storage } from 'appwrite';
|
||||||
|
|
||||||
import { Client, Databases, Storage, ID, Query } from 'node-appwrite';
|
const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1';
|
||||||
import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite';
|
const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c';
|
||||||
import { revalidatePath } from 'next/cache';
|
|
||||||
import { SCHEMA_MAP, collectionMap } from '@/lib/schema';
|
|
||||||
|
|
||||||
// Using local endpoint and the key we set locally
|
export const client = new Client();
|
||||||
const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'http://localhost/v1';
|
|
||||||
const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69bedced002971103d13';
|
|
||||||
const API_KEY = process.env.APPWRITE_API_KEY || 'standard_2350cc147ace39b0e3fb2c42d1447bc00effb4d5e6115cd682b0d215297a3b35b2ce82e312bd35cff1b738d5eb3462c5b28887937acf217eca6c2143aa0bf4e85ab183350db830901edc0d80d17755d1de5524b945d0c4cb11871af8d33df7f7cdbdfea4237dfc8a47e3c71ac79b3e5172834cc09d451d687a3db74e839ec7a7';
|
|
||||||
|
|
||||||
export async function createDocumentServer(collectionId: string, data: any) {
|
client
|
||||||
try {
|
.setEndpoint(ENDPOINT)
|
||||||
const client = new Client()
|
.setProject(PROJECT_ID);
|
||||||
.setEndpoint(ENDPOINT)
|
|
||||||
.setProject(PROJECT_ID)
|
|
||||||
.setKey(API_KEY);
|
|
||||||
|
|
||||||
const databases = new Databases(client);
|
export const account = new Account(client);
|
||||||
|
export const databases = new Databases(client);
|
||||||
|
export const storage = new Storage(client);
|
||||||
|
|
||||||
for(const key in data) {
|
export const APPWRITE_ALMEIRA_CONFIG = {
|
||||||
if(data[key] === 'true') data[key] = true;
|
endpoint: ENDPOINT,
|
||||||
if(data[key] === 'false') data[key] = false;
|
projectId: PROJECT_ID,
|
||||||
if(data[key] === '' && typeof data[key] === 'string') delete data[key];
|
databaseId: 'main',
|
||||||
|
collections: {
|
||||||
|
posts: 'posts',
|
||||||
|
media: 'media',
|
||||||
|
events: 'events',
|
||||||
|
classifieds: 'classifieds',
|
||||||
|
entity: 'entity_config'
|
||||||
|
},
|
||||||
|
buckets: {
|
||||||
|
media: 'media'
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const doc = await databases.createDocument(
|
export { ID } from 'appwrite';
|
||||||
APPWRITE_ALMEIRA_CONFIG.databaseId,
|
|
||||||
collectionId,
|
|
||||||
ID.unique(),
|
|
||||||
data
|
|
||||||
);
|
|
||||||
|
|
||||||
revalidatePath('/dashboard/[entity]', 'page');
|
|
||||||
return { success: true, doc };
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error("Create error:", error);
|
|
||||||
return { success: false, error: error.message };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateDocumentServer(collectionId: string, documentId: string, data: any) {
|
|
||||||
try {
|
|
||||||
const client = new Client().setEndpoint(ENDPOINT).setProject(PROJECT_ID).setKey(API_KEY);
|
|
||||||
const databases = new Databases(client);
|
|
||||||
|
|
||||||
for(const key in data) {
|
|
||||||
if(data[key] === 'true') data[key] = true;
|
|
||||||
if(data[key] === 'false') data[key] = false;
|
|
||||||
if(data[key] === '' && typeof data[key] === 'string') data[key] = null; // Send null to clear optional strings
|
|
||||||
}
|
|
||||||
|
|
||||||
const doc = await databases.updateDocument(
|
|
||||||
APPWRITE_ALMEIRA_CONFIG.databaseId,
|
|
||||||
collectionId,
|
|
||||||
documentId,
|
|
||||||
data
|
|
||||||
);
|
|
||||||
|
|
||||||
revalidatePath('/dashboard/[entity]', 'page');
|
|
||||||
return { success: true, doc };
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error("Update error:", error);
|
|
||||||
return { success: false, error: error.message };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deleteDocumentServer(collectionId: string, documentId: string, entityAlias: string) {
|
|
||||||
try {
|
|
||||||
const client = new Client().setEndpoint(ENDPOINT).setProject(PROJECT_ID).setKey(API_KEY);
|
|
||||||
const databases = new Databases(client);
|
|
||||||
|
|
||||||
// Dynamic Relational Restriction Check
|
|
||||||
// We scan all collections in SCHEMA_MAP to see if any holds a relation to the collection we are trying to delete from
|
|
||||||
for (const [colAlias, fields] of Object.entries(SCHEMA_MAP)) {
|
|
||||||
const referencingFields = fields.filter(f => f.type === 'relation' && f.relationCollection === entityAlias);
|
|
||||||
|
|
||||||
for (const refField of referencingFields) {
|
|
||||||
const checkColId = collectionMap[colAlias];
|
|
||||||
if (!checkColId) continue;
|
|
||||||
|
|
||||||
const list = await databases.listDocuments(
|
|
||||||
APPWRITE_ALMEIRA_CONFIG.databaseId,
|
|
||||||
checkColId,
|
|
||||||
[Query.equal(refField.name, documentId), Query.limit(1)]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (list.total > 0) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: `No se puede eliminar. Existen registros en '${colAlias.replace(/_/g, ' ')}' que dependen de este dato.`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No relation found preventing deletion, proceed safely!
|
|
||||||
await databases.deleteDocument(
|
|
||||||
APPWRITE_ALMEIRA_CONFIG.databaseId,
|
|
||||||
collectionId,
|
|
||||||
documentId
|
|
||||||
);
|
|
||||||
|
|
||||||
revalidatePath('/dashboard/[entity]', 'page');
|
|
||||||
return { success: true };
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error("Delete error:", error);
|
|
||||||
return { success: false, error: error.message };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function uploadMediaServer(formData: FormData) {
|
|
||||||
try {
|
|
||||||
const client = new Client().setEndpoint(ENDPOINT).setProject(PROJECT_ID).setKey(API_KEY);
|
|
||||||
const databases = new Databases(client);
|
|
||||||
|
|
||||||
const files = formData.getAll('files') as File[];
|
|
||||||
if (!files || files.length === 0) throw new Error("No hay archivos para subir");
|
|
||||||
|
|
||||||
const manualTitulo = formData.get('titulo') as string;
|
|
||||||
const manualAlt = formData.get('alt_text') as string;
|
|
||||||
const manualDesc = formData.get('descripcion_seo') as string;
|
|
||||||
|
|
||||||
for (const file of files) {
|
|
||||||
if (!file || file.size === 0) continue;
|
|
||||||
|
|
||||||
// Native Fetch REST call to upload the file bypassing node-appwrite buffer overload
|
|
||||||
const appwriteFormData = new FormData();
|
|
||||||
appwriteFormData.append('fileId', 'unique()');
|
|
||||||
appwriteFormData.append('file', file);
|
|
||||||
|
|
||||||
const uploadResponse = await fetch(`${ENDPOINT}/storage/buckets/media_bucket/files`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'X-Appwrite-Project': PROJECT_ID,
|
|
||||||
'X-Appwrite-Key': API_KEY
|
|
||||||
},
|
|
||||||
body: appwriteFormData
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!uploadResponse.ok) {
|
|
||||||
const errBody = await uploadResponse.text();
|
|
||||||
throw new Error(`Error subiendo al Bucket: ${errBody}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uploadData = await uploadResponse.json();
|
|
||||||
|
|
||||||
// Limpiar el nombre del archivo
|
|
||||||
let cleanName = file.name.replace(/\.[^/.]+$/, "");
|
|
||||||
cleanName = cleanName.replace(/[-_]/g, ' ');
|
|
||||||
cleanName = cleanName.replace(/[0-9]+$/g, '');
|
|
||||||
cleanName = cleanName.replace(/\s+/g, ' ').trim();
|
|
||||||
if (!cleanName) cleanName = 'Multimedia';
|
|
||||||
|
|
||||||
await databases.createDocument(
|
|
||||||
APPWRITE_ALMEIRA_CONFIG.databaseId,
|
|
||||||
'media',
|
|
||||||
ID.unique(),
|
|
||||||
{
|
|
||||||
file_id: uploadData.$id,
|
|
||||||
bucket_id: 'media_bucket',
|
|
||||||
titulo: manualTitulo || cleanName,
|
|
||||||
alt_text: manualAlt || cleanName,
|
|
||||||
descripcion_seo: manualDesc || cleanName,
|
|
||||||
tipo: file.type.startsWith('video') ? 'video' : 'imagen'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
revalidatePath('/dashboard/media');
|
|
||||||
return { success: true };
|
|
||||||
} catch(error: any) {
|
|
||||||
console.error("Upload Error:", error);
|
|
||||||
return { success: false, error: error.message };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,80 +1,58 @@
|
|||||||
'use server'
|
'use server'
|
||||||
|
|
||||||
import { Client, Databases } from 'node-appwrite';
|
import { Client, Databases, ID, Query } from 'node-appwrite';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'http://localhost/v1';
|
const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1';
|
||||||
const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69bedced002971103d13';
|
const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c';
|
||||||
const API_KEY = process.env.APPWRITE_API_KEY || '';
|
const DATABASE_ID = 'main';
|
||||||
|
const COLLECTION_ID = 'entity_config';
|
||||||
|
|
||||||
export async function getEntity() {
|
async function getAdminClient() {
|
||||||
|
const client = new Client()
|
||||||
|
.setEndpoint(ENDPOINT)
|
||||||
|
.setProject(PROJECT_ID)
|
||||||
|
.setKey(process.env.APPWRITE_API_KEY || '');
|
||||||
|
return new Databases(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getEntityConfig() {
|
||||||
try {
|
try {
|
||||||
const client = new Client().setEndpoint(ENDPOINT).setProject(PROJECT_ID).setKey(API_KEY);
|
const databases = await getAdminClient();
|
||||||
const databases = new Databases(client);
|
const response = await databases.listDocuments(
|
||||||
|
DATABASE_ID,
|
||||||
const doc = await databases.getDocument('almeira', 'entidad', 'default');
|
COLLECTION_ID,
|
||||||
return JSON.parse(JSON.stringify(doc));
|
[Query.limit(1)]
|
||||||
|
);
|
||||||
|
return response.documents[0] || null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching entity:", error);
|
console.error('Error fetching entity config:', error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateEntity(formData: FormData) {
|
export async function updateEntityConfig(data: any) {
|
||||||
try {
|
try {
|
||||||
const client = new Client().setEndpoint(ENDPOINT).setProject(PROJECT_ID).setKey(API_KEY);
|
const databases = await getAdminClient();
|
||||||
const databases = new Databases(client);
|
const existing = await getEntityConfig();
|
||||||
|
|
||||||
const data: any = {
|
if (existing) {
|
||||||
razon_social: formData.get('razon_social') as string || '',
|
return await databases.updateDocument(
|
||||||
direccion: formData.get('direccion') as string || null,
|
DATABASE_ID,
|
||||||
numero_contacto: formData.get('numero_contacto') as string || null,
|
COLLECTION_ID,
|
||||||
numero_whatsapp: formData.get('numero_whatsapp') as string || null,
|
existing.$id,
|
||||||
ciudad: formData.get('ciudad') as string || null,
|
data
|
||||||
sitio_web: formData.get('sitio_web') as string || null,
|
);
|
||||||
email: formData.get('email') as string || null,
|
} else {
|
||||||
facebook_url: formData.get('facebook_url') as string || null,
|
return await databases.createDocument(
|
||||||
youtube_url: formData.get('youtube_url') as string || null,
|
DATABASE_ID,
|
||||||
instagram_url: formData.get('instagram_url') as string || null,
|
COLLECTION_ID,
|
||||||
x_url: formData.get('x_url') as string || null,
|
ID.unique(),
|
||||||
telegram_url: formData.get('telegram_url') as string || null,
|
data
|
||||||
tv_url: formData.get('tv_url') as string || null,
|
);
|
||||||
radio_url: formData.get('radio_url') as string || null,
|
|
||||||
mostrar_texto_logo: formData.get('mostrar_texto_logo') === 'true'
|
|
||||||
};
|
|
||||||
|
|
||||||
const file = formData.get('logotipo') as File;
|
|
||||||
if (file && file.size > 0) {
|
|
||||||
const appwriteFormData = new FormData();
|
|
||||||
appwriteFormData.append('fileId', 'unique()');
|
|
||||||
appwriteFormData.append('file', file);
|
|
||||||
|
|
||||||
const uploadResponse = await fetch(`${ENDPOINT}/storage/buckets/media_bucket/files`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'X-Appwrite-Project': PROJECT_ID,
|
|
||||||
'X-Appwrite-Key': API_KEY
|
|
||||||
},
|
|
||||||
body: appwriteFormData as unknown as BodyInit
|
|
||||||
});
|
|
||||||
|
|
||||||
if (uploadResponse.ok) {
|
|
||||||
const uploadData = await uploadResponse.json();
|
|
||||||
data.logotipo = `${ENDPOINT}/storage/buckets/media_bucket/files/${uploadData.$id}/view?project=${PROJECT_ID}`;
|
|
||||||
} else {
|
|
||||||
throw new Error("No se pudo subir la imagen");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
// Netear nulls si algo está vacío de lo requerido
|
console.error('Error updating entity config:', error);
|
||||||
if (!data.razon_social) data.razon_social = 'Almeira Producciones';
|
throw error;
|
||||||
|
|
||||||
await databases.updateDocument('almeira', 'entidad', 'default', data);
|
|
||||||
|
|
||||||
revalidatePath('/', 'layout');
|
|
||||||
return { success: true };
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error("Entity Update Error:", error);
|
|
||||||
return { success: false, error: error.message };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { Client, Databases, Users, ID, Query } from 'node-appwrite';
|
|||||||
function getAdminServices() {
|
function getAdminServices() {
|
||||||
const client = new Client()
|
const client = new Client()
|
||||||
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1')
|
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1')
|
||||||
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69bedced002971103d13')
|
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c')
|
||||||
.setKey(process.env.APPWRITE_API_KEY || '');
|
.setKey(process.env.APPWRITE_API_KEY || '');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user