Apprendre à intégrer ONLYOFFICE Docs à l’outil de travail collaboratif Confluence

ONLYOFFICE

Pour réagir au contenu de cet article, un espace de dialogue vous est proposé sur le forum. Commentez

- Titre : Apprendre à intégrer ONLYOFFICE Docs à l’outil de travail collaboratif Confluence

- Auteur : ONLYOFFICE

- Parution : 19 avril 2021

- Licence : Copyright ® 2020 ONLYOFFICE . Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Prérequis

- III. Ajouter les boutons à l’interface

- IV. Configuration des servlets et de l’extension

- V. Lancement et tests

- VI. Édition et coédition

- VII. Configuration des services de sécurité

- VIII. Utiliser ONLYOFFICE Docs au sein de l’environnement Confluence

- IX. Remerciements Developpez.com

I - Introduction

Nous continuons la série de tutoriels qui apprennent à intégrer la suite bureautique en ligne ONLYOFFICE Docs avec des services web tiers dont par exemple Nextcloud ou une application GED en Python. Parmi les intégrations disponibles figurent notamment ownCloud, SharePoint, Seafile, Liferay, Plone, Nuxeo, Chamilo, Jalios, eXo Platform, GoFast et bien d’autres applications web reliées avec ONLYOFFICE Docs via les connecteurs prêts à l’emploi fournis par ONLYOFFICE ou résultant de partenariats technologiques.

Quel est l’objectif principal de ces intégrations ? Le but est de compléter l’éventail de leurs outils existants avec des éditeurs en ligne assurant la mise en forme des documents texte, des classeurs et des présentations (DOCX, XLSX, PPTX) de toute complexité et leur rédaction collaborative en temps réel directement dans l’interface de ces plateformes. Pour en savoir davantage sur les capacités fonctionnelles de ONLYOFFICE Docs, consultez cet article.

Dans ce tutoriel, nous allons vous montrer comment créer une application d’intégration qui va servir de pont reliant les instances ONLYOFFICE Docs et Confluence, la solution de travail collaboratif se focalisant sur la gestion et le partage des contenus.

II - Prérequis

Avant tout, il est indispensable d’installer des éléments nécessaires à l’intégration.

- ONLYOFFICE Docs

Vous pouvez déployer ONLYOFFICE Document Server en utilisant les paquets DEB ou RPM, l’image Docker, le paquet Snap, la machine virtuelle Univention, Amazon, l’environnement Cloudron, les conteneurs Kubernets qui sont disponibles sur le site officiel.

- Environnement Confluence

Avant tout, vous avez besoin d’installer le SDK Atlassian qui encapsule le binaire Maven permettant de créer les extensions et les tester au sein d’une application Atlassian lancée.

Pour l’installer, suivez ces consignes pour Windows, Linux ou Mac.

Ensuite, créez le fichier de base pour l’extension Confluence. Ouvrez la ligne de commande et lancez la commande suivante : atlas-create-confluence-plugin. L’outil va vous demander quelques détails pour la création d’une extension simple.

Vous pouvez paramétrer l’ouverture de l’extension dans votre environnement de développement intégré. Pour cela, il vous faudra définir quelques paramètres supplémentaires.

Il n’y a pas de consignes spéciales sur la configuration de l’éditeur VSCode, vous pouvez le paramétrer en utilisant Maven qui vient ensemble avec le SDK. Créez le fichier de configuration settings.json dans le dossier .vscode en y plaçant ce code :

1. {

4. "maven.executable.path": "C:\\Applications\\Atlassian\\atlassian-plugin-sdk-8.0.16\\apache-maven-3.5.4\\bin\\mvn",

5. "java.configuration.maven.userSettings": "C:\\Applications\\Atlassian\\atlassian-plugin-sdk-8.0.16\\apache-maven-3.5.4\\conf\\settings.xml"

7. }

Veuillez noter que le chemin peut varier selon l’emplacement de l’installation du SDK.

III - Ajouter les boutons à l’interface

Nous avons besoin d’ajouter le bouton « Éditer » à l’interface et la page avec les éditeurs.

Pour l’ajout du bouton, vous n’avez même pas à développer le code. Les applications Atlassian utilisent le fichier XML qui sert à spécifier les composants que l’extension comprend. Ce fichier est disponible à : src\main\resources\atlassian-plugin.xml. Il permet également de définir les classes Java que l’application va instancier.

(Veuillez noter qu’il vous faudra supprimer toutes les lignes import de votre code pour gagner de la place.)

Pour créer le bouton, il vous suffit d’ajouter les lignes suivantes :

1. <web-item key="onlyoffice-doceditor" name="Link for the attachment editing" section="system.attachment" weight="9">

3. <condition class="onlyoffice.IsOfficeFileAttachment">

5. <param name="forEdit">true</param>

7. </condition>

9. <description>The link and the text for it to open the document which is available for editing.</description>

11. <label key="onlyoffice.connector.editlink"/>

13. <link><![CDATA[/plugins/servlet/onlyoffice/doceditor?attachmentId=$attachment.id]]></link>

15. <styleClass>onlyoffice-doceditor</styleClass>

17. </web-item>

Pour de plus amples informations sur les paramètres qui figurent dans les lignes au-dessus, lisez cet article.

La plupart des paramètres sont évidents. L’attribut section sert à définir l’emplacement des liens. L’élément <condition> spécifie la classe Java qui va être utilisée pour filtrer les pièces jointes sur lesquelles nos liens seront affichés. Parmi les conditions figurent notamment l’accès des utilisateurs, la taille du fichier, l’extension du fichier. Pour mieux comprendre comment cela fonctionne, consultez le code sur GitHub.

En ce qui concerne d’autres boutons pour afficher et convertir les documents, leur création est similaire à celle du bouton « Éditer ».

Voyons de plus près l’élément <link>. Vous le reliez directement avec la servlet contenant le paramètre ID de la pièce jointe (le lien va se composer comme suit confluence/servlet/attachment_Id). La servlet elle-même va traiter les demandes des utilisateurs et ouvrir la page pour charger l’interface des éditeurs.

La servlet est la classe Java qui étend javax.servlet.http.HttpServlet et surcharge sa méthode doGet.

1. public class OnlyOfficeEditorServlet extends HttpServlet {

4. private static final Logger log = LogManager.getLogger("onlyoffice.OnlyOfficeEditorServlet");

7. @Override

9. public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

11. return VelocityUtils.getRenderedTemplate("templates/editor.vm", defaults);

13. }

15. }

Vous pouvez aussi ajouter le Velocity Template : src\main\resources\templates\editor.vm.

À l’intérieur de ce template, il y a le code JavaScript qui va charger la page avec les éditeurs. Pour rendre la servlet opérationnelle, il est indispensable de faire quelques ajustements dans l’application Atlassian en modifiant le fichier atlassian-plugin.xml.

IV - Configuration des servlets et de l’extension

À cette étape, nous sommes presque prêts à ouvrir le document pour la lecture. Nous avons besoin de fournir les variables à notre page template. L’une des variables inclut l’URL qui mène vers notre Document Server, et nous ne souhaitons pas le code en dur. Heureusement, nous sommes en mesure de travailler sur les paramètres de l’extension directement dans l’interface, y compris la conception UI.

Maintenant il nous est indispensable de créer une autre servlet pour notre configuration (n’oubliez pas de l’ajouter au fichier atlassian-plugin.xml).

1. public class OnlyOfficeConfServlet extends HttpServlet {

5. @ComponentImport

7. private final UserManager userManager;

10. @ComponentImport

12. private final PluginSettingsFactory pluginSettingsFactory;

15. @Inject

17. public OnlyOfficeConfServlet(UserManager userManager, PluginSettingsFactory pluginSettingsFactory) {

19. this.userManager = userManager;

21. this.pluginSettingsFactory = pluginSettingsFactory;

23. }

26. private static final Logger log = LogManager.getLogger("onlyoffice.OnlyOfficeConfServlet");

29. private static final long serialVersionUID = 1L;

32. private String AppendSlash(String str) {

34. if (str == null || str.isEmpty() || str.endsWith("/"))

36. return str;

38. return str + "/";

40. }

43. private String getBody(InputStream stream) {

45. Scanner scanner = null;

47. Scanner scannerUseDelimiter = null;

51. try {

53. scanner = new Scanner(stream);

55. scannerUseDelimiter = scanner.useDelimiter("\\A");

57. return scanner.hasNext() ? scanner.next() : "";

59. } finally {

61. scannerUseDelimiter.close();

63. scanner.close();

65. }

67. }

69. }

Il y a deux méthodes utilitaires qui sont explicites. Nous avons besoin d’en ajouter encore deux.

La première est doGet. Nous prenons nos paramètres existants et les ajoutons à notre template.

1. @Override

3. public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

6. String username = userManager.getRemoteUsername(request);

9. if (username == null || !userManager.isSystemAdmin(username)) {

11. SettingsManager settingsManager = (SettingsManager) ContainerManager.getComponent("settingsManager");

13. String baseUrl = settingsManager.getGlobalSettings().getBaseUrl();

15. response.sendRedirect(baseUrl);

17. return;

19. }

22. PluginSettings pluginSettings = pluginSettingsFactory.createGlobalSettings();

24. String apiUrl = (String) pluginSettings.get("onlyoffice.apiUrl");

27. response.setContentType("text/html;charset=UTF-8");

29. PrintWriter writer = response.getWriter();

32. Map<String, Object> contextMap = MacroUtils.defaultVelocityContext();

35. contextMap.put("docserviceApiUrl", apiUrl);

37. writer.write(getTemplate(contextMap));

39. }

42. private String getTemplate(Map<String, Object> map) throws UnsupportedEncodingException {

44. return VelocityUtils.getRenderedTemplate("templates/configure.vm", map);

46. }

La seconde méthode est doPost. Celle-l va prendre l’objet JSON, l’analyser et annuler les paramètres existants.

1. @Override

3. public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

6. String username = userManager.getRemoteUsername(request);

8. if (username == null || !userManager.isSystemAdmin(username)) {

10. response.setStatus(HttpServletResponse.SC_FORBIDDEN);

12. return;

14. }

17. String body = getBody(request.getInputStream());

19. if (body.isEmpty()) {

21. response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

23. return;

25. }

28. String apiUrl;

30. try {

32. JSONObject jsonObj = new JSONObject(body);

34. apiUrl = AppendSlash(jsonObj.getString("apiUrl"));

36. } catch (Exception ex) {

38. StringWriter sw = new StringWriter();

40. PrintWriter pw = new PrintWriter(sw);

42. ex.printStackTrace(pw);

44. String error = ex.toString() + "\n" + sw.toString();

46. log.error(error);

49. response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

51. response.getWriter().write("{\"success\": false, \"message\": \"jsonparse\"}");

53. return;

55. }

58. PluginSettings pluginSettings = pluginSettingsFactory.createGlobalSettings();

60. pluginSettings.put("onlyoffice.apiUrl", apiUrl);

63. response.getWriter().write("{\"success\": true}");

65. }

Dans les deux cas, nous allons vérifier si l’utilisateur possède un accès à ces paramètres. En réalité, nous allons aussi vérifier la connexion au Document Server et dans le sens inverse pour que nous puissions identifier les problèmes qui peuvent se produire à cette étape. Le code complet est disponible ici.

Nous pouvons également ajouter les boutons « Configurer » sur la page de gestion du plugin Atlassian. Pour le faire, il suffit d’ajouter cette ligne à l’élément <plugin-info> dans le fichier atlassian-plugin.xml.

1. <param name="configure.url">/plugins/servlet/onlyoffice/configure</param>

N’oubliez surtout pas le Velocity template.

Revenons à la servlet de l’éditeur pour la modifier.

1. public class OnlyOfficeEditorServlet extends HttpServlet {

3. @ComponentImport

5. private final LocaleManager localeManager;

7. private final UrlManager urlManager;

10. @Inject

12. public OnlyOfficeEditorServlet(LocaleManager localeManager, UrlManager urlManager) {

14. this.urlManager = urlManager;

16. this.localeManager = localeManager;

18. }

21. private static final Logger log = LogManager.getLogger("onlyoffice.OnlyOfficeEditorServlet");

23. private static final long serialVersionUID = 1L;

26. private Properties properties;

29. @Override

31. public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

33. if (!AuthContext.checkUserAuthorisation(request, response)) {

35. return;

37. }

40. String apiUrl = urlManager.getPublicDocEditorUrl();

42. if (apiUrl == null || apiUrl.isEmpty()) {

44. apiUrl = "";

46. }

49. ConfigurationManager configurationManager = new ConfigurationManager();

51. properties = configurationManager.GetProperties();

54. String fileUrl = "";

56. String key = "";

58. String fileName = "";

60. String errorMessage = "";

62. ConfluenceUser user = null;

65. String attachmentIdString = request.getParameter("attachmentId");

67. Long attachmentId;

70. try {

72. attachmentId = Long.parseLong(attachmentIdString);

74. log.info("attachmentId " + attachmentId);

77. user = AuthenticatedUserThreadLocal.get();

79. log.info("user " + user);

81. if (AttachmentUtil.checkAccess(attachmentId, user, false)) {

83. key = DocumentManager.getKeyOfFile(attachmentId);

86. fileName = AttachmentUtil.getFileName(attachmentId);

89. fileUrl = urlManager.GetFileUri(attachmentId);

91. } else {

93. log.error("access deny");

95. errorMessage = "You don not have enough permission to view the file";

97. }

99. } catch (Exception ex) {

101. StringWriter sw = new StringWriter();

103. PrintWriter pw = new PrintWriter(sw);

105. ex.printStackTrace(pw);

107. String error = ex.toString() + "\n" + sw.toString();

109. log.error(error);

111. errorMessage = ex.toString();

113. }

116. response.setContentType("text/html;charset=UTF-8");

118. PrintWriter writer = response.getWriter();

121. writer.write(getTemplate(apiUrl,  fileUrl, key, fileName, user, errorMessage));

123. }

126. private String getTemplate(String apiUrl, String fileUrl, String key, String fileName,

128. ConfluenceUser user, String errorMessage) throws UnsupportedEncodingException {

130. Map<String, Object> defaults = MacroUtils.defaultVelocityContext();

132. Map<String, String> config = new HashMap<String, String>();

135. String docTitle = fileName.trim();

137. String docExt = docTitle.substring(docTitle.lastIndexOf(".") + 1).trim().toLowerCase();

140. config.put("docserviceApiUrl", apiUrl + properties.getProperty("files.docservice.url.api"));

142. config.put("errorMessage", errorMessage);

144. config.put("docTitle", docTitle);

147. JSONObject responseJson = new JSONObject();

149. JSONObject documentObject = new JSONObject();

151. JSONObject editorConfigObject = new JSONObject();

153. JSONObject userObject = new JSONObject();

155. JSONObject permObject = new JSONObject();

158. try {

160. responseJson.put("type", "desktop");

162. responseJson.put("width", "100%");

164. responseJson.put("height", "100%");

166. responseJson.put("documentType", getDocType(docExt));

169. responseJson.put("document", documentObject);

171. documentObject.put("title", docTitle);

173. documentObject.put("url", fileUrl);

175. documentObject.put("fileType", docExt);

177. documentObject.put("key", key);

179. documentObject.put("permissions", permObject);

181. permObject.put("edit", false);

184. responseJson.put("editorConfig", editorConfigObject);

186. editorConfigObject.put("lang", localeManager.getLocale(user).toLanguageTag());

188. editorConfigObject.put("mode", "edit");

191. if (user != null) {

193. editorConfigObject.put("user", userObject);

195. userObject.put("id", user.getName());

197. userObject.put("name", user.getFullName());

199. }

202. // AsHtml at the end disables automatic html encoding

204. config.put("jsonAsHtml", responseJson.toString());

206. } catch (Exception ex) {

208. StringWriter sw = new StringWriter();

210. PrintWriter pw = new PrintWriter(sw);

212. ex.printStackTrace(pw);

214. String error = ex.toString() + "\n" + sw.toString();

216. log.error(error);

218. }

221. defaults.putAll(config);

223. return VelocityUtils.getRenderedTemplate("templates/editor.vm", defaults);

225. }

228. private String getDocType(String ext) {

230. if (".doc.docx.docm.dot.dotx.dotm.odt.fodt.ott.rtf.txt.html.htm.mht.pdf.djvu.fb2.epub.xps".indexOf(ext) != -1)

232. return "text";

234. if (".xls.xlsx.xlsm.xlt.xltx.xltm.ods.fods.ots.csv".indexOf(ext) != -1)

236. return "spreadsheet";

238. if (".pps.ppsx.ppsm.ppt.pptx.pptm.pot.potx.potm.odp.fodp.otp".indexOf(ext) != -1)

240. return "presentation";

242. return null;

244. }

246. }

Cela créera un objet JSON qui est indispensable pour ouvrir la page des éditeurs. Veuillez noter que nous plaçons notre objet JSON dans la variable qui se termine par AsHtml. De cette manière, le codage HTML automatique sera désactivé pour que nous le mettions dans le tag <script> au sein de notre template :

1. var json = '${jsonAsHtml}';

Juste pour votre information, nous avons utilisé trois classes utilitaires dont AttachmentUtil, UrlManager et DocumentManager.

Enfin et surtout, il nous reste à paramétrer la livraison des documents vers Document Server.

À cet effet, il nous faut créer encore une servlet. La seule méthode ici va assurer la disponibilité du fichier.

1. public class OnlyOfficeSaveFileServlet extends HttpServlet {

3. private static final long serialVersionUID = 1L;

5. private static final Logger log = LogManager.getLogger("onlyoffice.OnlyOfficeSaveFileServlet");

8. @ComponentImport

10. private final PluginSettingsFactory pluginSettingsFactory;

13. private final PluginSettings settings;

16. @Inject

18. public OnlyOfficeSaveFileServlet(PluginSettingsFactory pluginSettingsFactory, JwtManager jwtManager) {

20. this.pluginSettingsFactory = pluginSettingsFactory;

22. settings = pluginSettingsFactory.createGlobalSettings();

24. }

27. @Override

29. public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

31. String vkey = request.getParameter("vkey");

33. log.info("vkey = " + vkey);

35. String attachmentIdString = DocumentManager.ReadHash(vkey);

38. Long attachmentId = Long.parseLong(attachmentIdString);

40. log.info("attachmentId " + attachmentId);

43. String contentType = AttachmentUtil.getMediaType(attachmentId);

45. response.setContentType(contentType);

48. InputStream inputStream = AttachmentUtil.getAttachmentData(attachmentId);

50. response.setContentLength(inputStream.available());

53. byte[] buffer = new byte[10240];

56. OutputStream output = response.getOutputStream();

58. for (int length = 0; (length = inputStream.read(buffer)) > 0;) {

60. output.write(buffer, 0, length);

62. }

64. }

66. }

V - Lancement et tests

Cette étape consiste à nous assurer que tout fonctionne correctement et nous sommes capables d’ouvrir les documents pour la lecture.

Lancez la commande atlas-run pour créer l’extension et lancer Confluence.

Un autre moyen consiste à lancer atlas-package pour créer .jar.

Quelle que soit l’option que vous choisissiez, passez aux Paramètres -> Gérer les apps, ensuite chargez l’extension et cliquez « Configurer ». Veillez à spécifier l’adresse URL du Document Server et testez l’extension.

VI - Édition et coédition

Pour pouvoir ouvrir le document pour l’édition, il faut apporter quelques modifications supplémentaires.

Le paramètre callbackUrl doit s’adresser à la servlet qui va obtenir les données décrivant le statut de l’édition du document de la part du Document Server. Quand l’utilisateur ferme le document, le serveur enverra la notification que l’édition a été terminée, aussi bien que l’URL vers le document mis à jour que nous allons télécharger.

Si vous vous questionnez comment la rédaction collaborative fonctionne, suivez les consignes ci-dessous.

Les utilisateurs vont éditer le seul document tant que le paramètre clé est le même. Il y a deux aspects importants à prendre en considération lors de la génération de la clé pour un fichier :

1. La clé doit être unique pour chaque document ;

2. La clé doit être modifiée lorsque le document est modifié.

D’habitude, la paire ID + ModifiedDate fonctionne très bien. Cependant il y a un scénario qui n’est pas compatible avec cette combinaison. Si vous envisagez de mettre en place un enregistrement obligatoire, il vous est indispensable de générer la clé qui demeurera exactement la même durant toute la session d’édition.

La génération de la clé se fait dans AttachmentUtil et DocumentManager.

Ajoutez cette ligne dans la servlet de notre éditeur juste après la ligne

fileUrl = urlManager.GetFileUri(attachmentId); :

1. if (AttachmentUtil.checkAccess(attachmentId, user, true)) {

3. callbackUrl = urlManager.getCallbackUrl(attachmentId);

5. }

Passez-la à notre fonction getTemplate :

writer.write(getTemplate(apiUrl, callbackUrl, fileUrl, key, fileName, user, errorMessage));

Utilisez la clé ici :

permObject.put("edit", callbackUrl != null && !callbackUrl.isEmpty());

...

editorConfigObject.put("callbackUrl", callbackUrl);

Maintenant, il vous faut créer une fonction de rappel. Pour le faire, modifiez OnlyOfficeSaveFileServlet que nous avons utilisé pour livrer le document. Cela se fait facilement : nous analysons un objet JSON entrant, vérifions son statut et enregistrons le document si nécessaire. La documentation détaillée est disponible ici.

1. @Override

3. public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

5. response.setContentType("text/plain; charset=utf-8");

8. String vkey = request.getParameter("vkey");

10. log.info("vkey = " + vkey);

12. String attachmentIdString = DocumentManager.ReadHash(vkey);

15. String error = "";

17. try {

19. processData(attachmentIdString, request);

21. } catch (Exception e) {

23. error = e.getMessage();

25. }

28. PrintWriter writer = response.getWriter();

30. if (error.isEmpty()) {

32. writer.write("{\"error\":0}");

34. } else {

36. response.setStatus(500);

38. writer.write("{\"error\":1,\"message\":\"" + error + "\"}");

40. }

43. log.info("error = " + error);

45. }

48. private void processData(String attachmentIdString, HttpServletRequest request) throws Exception {

50. log.info("attachmentId = " + attachmentIdString);

52. InputStream requestStream = request.getInputStream();

54. if (attachmentIdString.isEmpty()) {

56. throw new IllegalArgumentException("attachmentId is empty");

58. }

61. HttpURLConnection connection = null;

63. try {

65. Long attachmentId = Long.parseLong(attachmentIdString);

68. String body = getBody(requestStream);

70. log.info("body = " + body);

72. if (body.isEmpty()) {

74. throw new IllegalArgumentException("requestBody is empty");

76. }

79. JSONObject jsonObj = new JSONObject(body);

82. long status = jsonObj.getLong("status");

84. log.info("status = " + status);

87. // MustSave, Corrupted

89. if (status == 2 || status == 3) {

91. ConfluenceUser user = null;

93. JSONArray users = jsonObj.getJSONArray("users");

95. if (users.length() > 0) {

97. String userName = users.getString(0);

100. UserAccessor userAccessor = (UserAccessor) ContainerManager.getComponent("userAccessor");

102. user = userAccessor.getUserByName(userName);

104. log.info("user = " + user);

106. }

109. if (user == null || !AttachmentUtil.checkAccess(attachmentId, user, true)) {

111. throw new SecurityException("Try save without access: " + user);

113. }

116. String downloadUrl = jsonObj.getString("url");

118. log.info("downloadUri = " + downloadUrl);

121. URL url = new URL(downloadUrl);

124. connection = (HttpURLConnection) url.openConnection();

126. int size = connection.getContentLength();

128. log.info("size = " + size);

131. InputStream stream = connection.getInputStream();

134. AttachmentUtil.saveAttachment(attachmentId, stream, size, user);

136. }

138. } catch (Exception ex) {

140. StringWriter sw = new StringWriter();

142. PrintWriter pw = new PrintWriter(sw);

144. ex.printStackTrace(pw);

146. String error = ex.toString() + "\n" + sw.toString();

148. log.error(error);

151. throw ex;

153. } finally {

155. if (connection != null) {

157. connection.disconnect();

159. }

161. }

163. }

166. private String getBody(InputStream stream) {

168. Scanner scanner = null;

170. Scanner scannerUseDelimiter = null;

172. try {

174. scanner = new Scanner(stream);

176. scannerUseDelimiter = scanner.useDelimiter("\\A");

178. return scanner.hasNext() ? scanner.next() : "";

180. } finally {

182. scannerUseDelimiter.close();

184. scanner.close();

186. }

187. }

Au stade final, recompilez le projet et testez-le.

VII - Configuration des services de sécurité

Comment vous assurer que JSON qui a été attribué à notre servlet via la méthode POST provient de notre Document Server ? La réponse est simple : le serveur des documents utilise la méthode JWT pour accomplir cette tâche.

Nous utilisons la classe JwtManager. JWT est une méthode JSON hachée basée sur la clé secrète.

Premièrement, ajoutez les nouveaux paramètres pour notre clé secrète. Vous trouverez le code ici : configure.vm template, configuration servlet.

Ensuite, ajoutez JwtManager à la servlet de l’éditeur et placez-le avant la ligne config.put("jsonAsHtml", responseJson.toString());  :

1. if (jwtManager.jwtEnabled()) {

3. responseJson.put("token", jwtManager.createToken(responseJson));

5. }

Dès maintenant Document Server va considérer le service comme fiable.

Pour vous assurer de la fiabilité du Document Server, veuillez utiliser JWT lors du traitement de la fonction de rappel.

En fonction de la configuration, Document Server possède deux moyens pour passer JWT: au sein de l’en-tête HTTP ou au sein de JSON. Nous allons les examiner tous les deux.

Modifiez la servlet de la fonction de rappel en ajoutant JwtManager et placez-la juste après la ligne JSONObject jsonObj = new JSONObject(body); :

1. if (jwtManager.jwtEnabled()) {

3. String token = jsonObj.optString("token");

5. Boolean inBody = true;

8. if (token == null || token == "") {

10. String jwth = (String) settings.get("onlyoffice.jwtHeader");

12. String header = (String) request.getHeader(jwth == null || jwth.isEmpty() ? "Authorization" : jwth);

14. token = (header != null && header.startsWith("Bearer ")) ? header.substring(7) : header;

16. inBody = false;

18. }

21. if (token == null || token == "") {

23. throw new SecurityException("Try save without JWT");

25. }

28. if (!jwtManager.verify(token)) {

30. throw new SecurityException("Try save with wrong JWT");

32. }

35. JSONObject bodyFromToken = new JSONObject(

37. new String(Base64.getUrlDecoder().decode(token.split("\\.")[1]), "UTF-8"));

40. if (inBody) {

42. jsonObj = bodyFromToken;

44. } else {

46. jsonObj = bodyFromToken.getJSONObject("payload");

48. }

50. }

Vous avez dorénavant à votre disposition les outils de lecture et d’édition des documents protégés par la méthode JWT contre un accès indésirable et la configuration facile.

VIII - Utiliser ONLYOFFICE Docs au sein de l’environnement Confluence

Une fois installée et correctement paramétrée, l’application d’intégration va ajouter une nouvelle option « Éditer avec ONLYOFFICE » au menu du document pour tous les fichiers.

Dès maintenant vos êtes en mesure de :

- créer de nouveaux fichiers bureautiques ou modifier des documents DOCX, XLSX, PPTX existants ;

- convertir les documents ODT, DOC, ODP, PPT, ODS, XLS aux formats Office Open XML correspondants ;

- collaborer sur les documents en temps réel en activant le mode de coédition qui vous convient le mieux (affichage des modifications en temps réel ou verrouillage d’un extrait en cours d’édition), le suivi des modifications, les commentaires, la messagerie instantanée, la comparaison des documents et l’historique des versions.

Si vous souhaitez aller encore plus loin en étendant les fonctionnalités de la suite ONLYOFFICE Docs, consultez cet article pour apprendre à installer et utiliser les modules complémentaires ONLYOFFICE.

IX - Remerciements Developpez.com

Nous tenons à remercier Malick pour la mise au gabarit et Claude Leloup pour la relecture orthographique.