Problème CORS lors de la publication sur Discourse depuis Obsidian

J’ai commencé à utiliser Obsidian pour écrire, j’ai donc décidé de créer un plugin Obsidian pour publier sur mon forum Discourse. En théorie, c’est facile à faire, mais la réponse de ma première tentative a été :

Access to fetch at 'http://localhost:4200/posts.json' from origin 'app://obsidian.md' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

La requête est faite depuis le client, mais le client est l’appareil de l’utilisateur. Si je comprends bien, c’est sûr :

import DiscoursePlugin from "./main";
import { TFile } from "obsidian";

export async function publishToDiscourse(
	plugin: DiscoursePlugin,
	activeFile: TFile
): Promise<{ message: string }> {
	try {
		const content = await plugin.app.vault.read(activeFile);
		const baseUrl = plugin.settings.baseUrl;
		const apiKey = plugin.settings.apiKey;

		const headers = new Headers({
			"Content-Type": "application/json",
			"Api-Key": apiKey,
			"Api-Username": "scossar", // ceci doit être un paramètre
		});
		const body = JSON.stringify({
			title: activeFile.name,
			raw: content, // TODO: analyser le contenu pour corriger les liens internes
			category: 1, // ceci doit être un paramètre
		});
		// TODO: vérifier si la note a déjà été publiée
		const url = `${baseUrl}/posts.json`;

		const response = await fetch(url, { method: "POST", headers, body });

		if (!response.ok) {
			console.error("Erreur lors de la publication sur Discourse :", response.status);
			return { message: "Erreur lors de la publication sur Discourse" };
		}
        
		const jsonResponse = await response.json();
		// TODO: utiliser la réponse pour ajouter une propriété de fichier discoursePostId
		console.log(`jsonResponse: ${JSON.stringify(jsonResponse, null, 2)}`);
		return { message: "success" };
	} catch (error) {
		console.error("Erreur lors de la publication sur Discourse :", error);
		return { message: `Erreur : ${error.message}` };
	}
}

Il est possible qu’il existe une solution évidente que j’ai manquée. Sinon, y a-t-il un moyen pour Discourse de le permettre ? Un plugin Obsidian Discourse pourrait être utile. (Une implémentation correcte serait plus complexe que ce que j’ai posté ci-dessus.)

3 « J'aime »

J’étais confus au début, mais je vois, vous avez configuré votre propre application Obsidian avec votre clé et vous seul y avez accès. Cela ne se passe pas dans un navigateur, donc les gens sur Internet n’ont pas votre clé.

J’ai un plugin Discourse qui traite des formulaires arbitraires (vous pouvez l’utiliser sur https://www.formhoster.com/). Je voulais le rendre capable de fonctionner comme l’utilisateur actuel si l’utilisateur était connecté au site traitant le formulaire et j’ai rencontré ce que je pense être le même problème CORS et j’ai abandonné assez rapidement. Le mien était dans un navigateur plutôt que dans une application comme Obsidian, mais je pense que le problème pourrait être similaire.

Tout cela pour dire que je pense ne pas avoir de bonnes idées, mais j’espère que quelqu’un d’autre en aura. :person_shrugging:

1 « J'aime »

Exact, Obsidian est une application Electron qui s’exécute localement. Elle utilise le stockage local, donc la clé API reste sur l’appareil de l’utilisateur.

Il s’avère qu’il existe une solution pour le problème CORS. Je ne l’ai testée que sur mon ordinateur de bureau jusqu’à présent. De plus, Discourse est génial !

Le code que j’ai posté ci-dessus a dû être modifié pour :

import DiscoursePlugin from "./main";
import { requestUrl, TFile } from "obsidian";

//...

		const response = await requestUrl({
			url: url,
			method: "POST",
			contentType: "application/json",
			body,
			headers,
		});
//...

La prochaine question portera sur l’autorisation des utilisateurs à demander des clés API utilisateur depuis l’application, mais c’est un problème distinct.

3 « J'aime »

Est-ce un plugin sur lequel vous travaillez ? J’ai un utilisateur (et moi-même) qui aimerait beaucoup pouvoir l’utiliser. Je peux essayer de recréer ce que vous avez fait, mais s’il y a un moyen plus simple…

C’était le début de quelque chose. Pour mes propres besoins, je m’intéresse davantage à une application en ligne de commande (CLI) qui permet de synchroniser un coffre-fort Obsidian avec un forum Discourse. Une application CLI facilite la gestion de la synchronisation d’un coffre-fort entier ou d’un sous-répertoire, la gestion des liens internes dans les notes, la gestion des téléchargements, etc. L’approche de l’application CLI s’intègre également à d’autres travaux que j’effectue, j’apprends donc quelque chose d’utile.

Le principal inconvénient de l’application CLI est qu’elle nécessite que toute personne qui l’utilise ait Ruby installé sur son ordinateur. Elle ne fonctionnera également que sur les ordinateurs de bureau. Il y aurait des défis techniques à l’utiliser sur les ordinateurs Windows.

Je publierai un lien vers l’application ici une fois qu’elle sera prête à être partagée.

Si un plugin Obsidian Discourse, par opposition à une application CLI, est quelque chose qui intéresse les gens, j’y regarderai à nouveau à l’avenir. Il est possible que quelqu’un d’autre y parvienne avant moi. Je ne suis pas allé beaucoup plus loin que l’exemple de code posté ci-dessus.

1 « J'aime »

Si c’est tout ce que vous avez jusqu’à présent, cela semble assez simple. Je me demande comment cela gérerait les images à ce stade. Je serais prêt à tenter le coup. Je n’ai jamais écrit de plugin pour Obsidian auparavant, mais d’après ce que j’ai regardé (coups d’œil furtifs à d’autres plugins), cela ne semble pas terriblement compliqué.

1 « J'aime »

Voici le point de départ : Build a plugin - Developer Documentation. J’aimerais lier ce que j’ai fait, mais c’est l’un des rares (espérons-le, le seul) projets que je n’ai pas poussés sur Github avant de réinstaller le système d’exploitation sur mon ordinateur la semaine dernière.

Vous devrez trouver comment le faire avec Node. Il y a un bon exemple en Ruby ici : discourse_api/examples/upload_file.rb at main · discourse/discourse_api · GitHub. Il appelle : discourse_api/lib/discourse_api/api/uploads.rb at main · discourse/discourse_api · GitHub.

Pouvez-vous partager cette partie ?

Hmm, perdre ce code était un peu imprudent. De mémoire, j’importais DiscoursePlugin défini dans main.ts dans un fichier qui gérait un appel à this.addCommand. Pour commencer, vous pouvez tout faire dans main.ts. Je suivrais simplement le guide pour commencer avec le plugin d’exemple. Commencez par jouer avec et essayez de faire quelque chose. Je sais que j’ai utilisé ce plugin comme modèle pour le mien.

Il y a aussi de bons exemples ici : obsidian-wordpress/src at main · devbean/obsidian-wordpress · GitHub.

1 « J'aime »

Eh bien, je vais mettre ça de côté pour l’instant. J’ai fait de très bons progrès, mais il y a quelques points qui ne me plaisent pas.

  • La clé API est stockée en texte brut (TRÈS MAUVAIS)
  • Les images ne se téléchargent pas, il y a des paramètres de configuration que je n’ai pas encore explorés. Mais je n’aime pas configurer un bucket AWS S3. J’y regarderai plus tard.
  • certains choix stylistiques pourraient être meilleurs, mais je voulais quelque chose de fonctionnel
  • Le README doit être mis à jour. Mais, encore une fois, je voulais juste quelque chose de fonctionnel et de publié.
1 « J'aime »

Je me demande s’il existe un moyen de contourner cela. Dans l’application CLI, je la chiffre avec un mot de passe. L’utilisateur doit fournir le mot de passe avant toute opération qui utilise la clé API.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.