PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/apps/document-library-opener/document-library-opener-google-drive-web/src/main/java/com/liferay/document/library/opener/google/drive/web/internal/DLOpenerGoogleDriveManager.java

https://github.com/danielreuther/liferay-portal
Java | 406 lines | 306 code | 84 blank | 16 comment | 9 complexity | 4a45d8388891773478ef4078d99207a7 MD5 | raw file
  1. /**
  2. * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or modify it under
  5. * the terms of the GNU Lesser General Public License as published by the Free
  6. * Software Foundation; either version 2.1 of the License, or (at your option)
  7. * any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  12. * details.
  13. */
  14. package com.liferay.document.library.opener.google.drive.web.internal;
  15. import com.google.api.client.auth.oauth2.Credential;
  16. import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
  17. import com.google.api.client.http.javanet.NetHttpTransport;
  18. import com.google.api.client.json.JsonFactory;
  19. import com.google.api.client.json.jackson2.JacksonFactory;
  20. import com.google.api.services.drive.Drive;
  21. import com.liferay.document.library.opener.constants.DLOpenerFileEntryReferenceConstants;
  22. import com.liferay.document.library.opener.google.drive.web.internal.background.task.UploadGoogleDriveDocumentBackgroundTaskExecutor;
  23. import com.liferay.document.library.opener.google.drive.web.internal.constants.DLOpenerGoogleDriveConstants;
  24. import com.liferay.document.library.opener.google.drive.web.internal.constants.GoogleDriveBackgroundTaskConstants;
  25. import com.liferay.document.library.opener.google.drive.web.internal.oauth.OAuth2Manager;
  26. import com.liferay.document.library.opener.model.DLOpenerFileEntryReference;
  27. import com.liferay.document.library.opener.service.DLOpenerFileEntryReferenceLocalService;
  28. import com.liferay.petra.string.StringBundler;
  29. import com.liferay.petra.string.StringPool;
  30. import com.liferay.portal.background.task.constants.BackgroundTaskContextMapConstants;
  31. import com.liferay.portal.kernel.backgroundtask.BackgroundTask;
  32. import com.liferay.portal.kernel.backgroundtask.BackgroundTaskManager;
  33. import com.liferay.portal.kernel.exception.PortalException;
  34. import com.liferay.portal.kernel.model.CompanyConstants;
  35. import com.liferay.portal.kernel.repository.model.FileEntry;
  36. import com.liferay.portal.kernel.security.auth.PrincipalException;
  37. import com.liferay.portal.kernel.service.ServiceContext;
  38. import com.liferay.portal.kernel.util.FileUtil;
  39. import com.liferay.portal.kernel.util.HashMapBuilder;
  40. import com.liferay.portal.kernel.util.Http;
  41. import com.liferay.portal.kernel.util.InetAddressUtil;
  42. import com.liferay.portal.kernel.util.StringUtil;
  43. import com.liferay.portal.kernel.util.Validator;
  44. import java.io.File;
  45. import java.io.IOException;
  46. import java.io.InputStream;
  47. import java.io.Serializable;
  48. import java.net.InetAddress;
  49. import java.net.URL;
  50. import java.net.URLConnection;
  51. import java.security.GeneralSecurityException;
  52. import java.util.Map;
  53. import java.util.Optional;
  54. import java.util.function.Supplier;
  55. import org.osgi.service.component.annotations.Activate;
  56. import org.osgi.service.component.annotations.Component;
  57. import org.osgi.service.component.annotations.Reference;
  58. /**
  59. * @author Adolfo PĂ©rez
  60. */
  61. @Component(
  62. service = {
  63. com.liferay.document.library.opener.google.drive.
  64. DLOpenerGoogleDriveManager.class,
  65. DLOpenerGoogleDriveManager.class
  66. }
  67. )
  68. public class DLOpenerGoogleDriveManager
  69. implements com.liferay.document.library.opener.google.drive.
  70. DLOpenerGoogleDriveManager {
  71. @Override
  72. public DLOpenerGoogleDriveFileReference checkOut(
  73. long userId, FileEntry fileEntry)
  74. throws PortalException {
  75. _dlOpenerFileEntryReferenceLocalService.
  76. addPlaceholderDLOpenerFileEntryReference(
  77. userId,
  78. DLOpenerGoogleDriveConstants.GOOGLE_DRIVE_REFERENCE_TYPE,
  79. fileEntry, DLOpenerFileEntryReferenceConstants.TYPE_EDIT);
  80. BackgroundTask backgroundTask = _addBackgroundTask(
  81. GoogleDriveBackgroundTaskConstants.CHECKOUT, fileEntry, userId);
  82. return new DLOpenerGoogleDriveFileReference(
  83. fileEntry.getFileEntryId(),
  84. new CachingSupplier<>(
  85. () -> _getGoogleDriveFileTitle(userId, fileEntry)),
  86. () -> _getContentFile(userId, fileEntry),
  87. backgroundTask.getBackgroundTaskId());
  88. }
  89. @Override
  90. public DLOpenerGoogleDriveFileReference create(
  91. long userId, FileEntry fileEntry)
  92. throws PortalException {
  93. _dlOpenerFileEntryReferenceLocalService.
  94. addPlaceholderDLOpenerFileEntryReference(
  95. userId,
  96. DLOpenerGoogleDriveConstants.GOOGLE_DRIVE_REFERENCE_TYPE,
  97. fileEntry, DLOpenerFileEntryReferenceConstants.TYPE_NEW);
  98. BackgroundTask backgroundTask = _addBackgroundTask(
  99. GoogleDriveBackgroundTaskConstants.CREATE, fileEntry, userId);
  100. return new DLOpenerGoogleDriveFileReference(
  101. fileEntry.getFileEntryId(),
  102. new CachingSupplier<>(
  103. () -> _getGoogleDriveFileTitle(userId, fileEntry)),
  104. () -> _getContentFile(userId, fileEntry),
  105. backgroundTask.getBackgroundTaskId());
  106. }
  107. @Override
  108. public void delete(long userId, FileEntry fileEntry)
  109. throws PortalException {
  110. try {
  111. Drive drive = new Drive.Builder(
  112. _netHttpTransport, _jsonFactory,
  113. _getCredential(fileEntry.getCompanyId(), userId)
  114. ).build();
  115. Drive.Files driveFiles = drive.files();
  116. Drive.Files.Delete driveFilesDelete = driveFiles.delete(
  117. _getGoogleDriveFileId(fileEntry));
  118. driveFilesDelete.execute();
  119. _dlOpenerFileEntryReferenceLocalService.
  120. deleteDLOpenerFileEntryReference(
  121. DLOpenerGoogleDriveConstants.GOOGLE_DRIVE_REFERENCE_TYPE,
  122. fileEntry);
  123. }
  124. catch (IOException ioException) {
  125. throw new PortalException(ioException);
  126. }
  127. }
  128. @Override
  129. public String getAuthorizationURL(
  130. long companyId, String state, String redirectUri)
  131. throws PortalException {
  132. return _oAuth2Manager.getAuthorizationURL(
  133. companyId, state, redirectUri);
  134. }
  135. @Override
  136. public boolean hasValidCredential(long companyId, long userId)
  137. throws IOException, PortalException {
  138. Credential credential = _oAuth2Manager.getCredential(companyId, userId);
  139. if ((credential == null) ||
  140. ((credential.getExpiresInSeconds() <= 0) &&
  141. !credential.refreshToken())) {
  142. return false;
  143. }
  144. return true;
  145. }
  146. @Override
  147. public boolean isConfigured(long companyId) {
  148. return _oAuth2Manager.isConfigured(companyId);
  149. }
  150. @Override
  151. public boolean isGoogleDriveFile(FileEntry fileEntry) {
  152. return Optional.ofNullable(
  153. _dlOpenerFileEntryReferenceLocalService.
  154. fetchDLOpenerFileEntryReference(
  155. DLOpenerGoogleDriveConstants.GOOGLE_DRIVE_REFERENCE_TYPE,
  156. fileEntry)
  157. ).map(
  158. dlOpenerFileEntryReference -> true
  159. ).orElse(
  160. false
  161. );
  162. }
  163. @Override
  164. public void requestAuthorizationToken(
  165. long companyId, long userId, String code, String redirectUri)
  166. throws IOException, PortalException {
  167. _oAuth2Manager.requestAuthorizationToken(
  168. companyId, userId, code, redirectUri);
  169. }
  170. @Override
  171. public DLOpenerGoogleDriveFileReference requestEditAccess(
  172. long userId, FileEntry fileEntry)
  173. throws PortalException {
  174. if (Validator.isNull(_getGoogleDriveFileId(fileEntry))) {
  175. throw new IllegalArgumentException(
  176. StringBundler.concat(
  177. "File entry ", fileEntry.getFileEntryId(),
  178. " is not a Google Drive file"));
  179. }
  180. _checkCredential(fileEntry.getCompanyId(), userId);
  181. return new DLOpenerGoogleDriveFileReference(
  182. fileEntry.getFileEntryId(),
  183. new CachingSupplier<>(
  184. () -> _getGoogleDriveFileTitle(userId, fileEntry)),
  185. () -> _getContentFile(userId, fileEntry), 0);
  186. }
  187. @Override
  188. public void setAuthorizationToken(
  189. long companyId, long userId, String authorizationToken)
  190. throws IOException, PortalException {
  191. _oAuth2Manager.setAccessToken(companyId, userId, authorizationToken);
  192. }
  193. @Activate
  194. protected void activate() throws GeneralSecurityException, IOException {
  195. _jsonFactory = JacksonFactory.getDefaultInstance();
  196. _netHttpTransport = GoogleNetHttpTransport.newTrustedTransport();
  197. }
  198. private BackgroundTask _addBackgroundTask(
  199. String cmd, FileEntry fileEntry, long userId)
  200. throws PortalException {
  201. Map<String, Serializable> taskContextMap =
  202. HashMapBuilder.<String, Serializable>put(
  203. BackgroundTaskContextMapConstants.DELETE_ON_SUCCESS, true
  204. ).put(
  205. GoogleDriveBackgroundTaskConstants.CMD, cmd
  206. ).put(
  207. GoogleDriveBackgroundTaskConstants.COMPANY_ID,
  208. fileEntry.getCompanyId()
  209. ).put(
  210. GoogleDriveBackgroundTaskConstants.FILE_ENTRY_ID,
  211. fileEntry.getFileEntryId()
  212. ).put(
  213. GoogleDriveBackgroundTaskConstants.USER_ID, userId
  214. ).build();
  215. return _backgroundTaskManager.addBackgroundTask(
  216. userId, CompanyConstants.SYSTEM,
  217. StringBundler.concat(
  218. DLOpenerGoogleDriveManager.class.getSimpleName(),
  219. StringPool.POUND, fileEntry.getFileEntryId()),
  220. UploadGoogleDriveDocumentBackgroundTaskExecutor.class.getName(),
  221. taskContextMap, new ServiceContext());
  222. }
  223. private void _checkCredential(long companyId, long userId)
  224. throws PortalException {
  225. _getCredential(companyId, userId);
  226. }
  227. private File _getContentFile(long userId, FileEntry fileEntry) {
  228. try {
  229. Credential credential = _getCredential(
  230. fileEntry.getCompanyId(), userId);
  231. Drive drive = new Drive.Builder(
  232. _netHttpTransport, _jsonFactory, credential
  233. ).build();
  234. Drive.Files driveFiles = drive.files();
  235. Drive.Files.Get get = driveFiles.get(
  236. _getGoogleDriveFileId(fileEntry));
  237. get.setFields("exportLinks");
  238. com.google.api.services.drive.model.File file = get.execute();
  239. Map<String, String> exportLinks = file.getExportLinks();
  240. URL url = new URL(exportLinks.get(fileEntry.getMimeType()));
  241. if (!StringUtil.startsWith(url.getProtocol(), Http.HTTP)) {
  242. throw new SecurityException(
  243. "Only HTTP links are allowed: " + url);
  244. }
  245. if (InetAddressUtil.isLocalInetAddress(
  246. InetAddress.getByName(url.getHost()))) {
  247. throw new SecurityException(
  248. "Local links are not allowed: " + url);
  249. }
  250. URLConnection urlConnection = url.openConnection();
  251. urlConnection.setRequestProperty(
  252. "Authorization", "Bearer " + credential.getAccessToken());
  253. try (InputStream inputStream = urlConnection.getInputStream()) {
  254. return FileUtil.createTempFile(inputStream);
  255. }
  256. }
  257. catch (IOException | PortalException exception) {
  258. throw new RuntimeException(exception);
  259. }
  260. }
  261. private Credential _getCredential(long companyId, long userId)
  262. throws PortalException {
  263. Credential credential = _oAuth2Manager.getCredential(companyId, userId);
  264. if (credential == null) {
  265. throw new PrincipalException(
  266. StringBundler.concat(
  267. "User ", userId,
  268. " does not have a valid Google credential"));
  269. }
  270. return credential;
  271. }
  272. private String _getGoogleDriveFileId(FileEntry fileEntry)
  273. throws PortalException {
  274. DLOpenerFileEntryReference dlOpenerFileEntryReference =
  275. _dlOpenerFileEntryReferenceLocalService.
  276. getDLOpenerFileEntryReference(
  277. DLOpenerGoogleDriveConstants.GOOGLE_DRIVE_REFERENCE_TYPE,
  278. fileEntry);
  279. return dlOpenerFileEntryReference.getReferenceKey();
  280. }
  281. private String _getGoogleDriveFileTitle(long userId, FileEntry fileEntry) {
  282. try {
  283. Drive drive = new Drive.Builder(
  284. _netHttpTransport, _jsonFactory,
  285. _getCredential(fileEntry.getCompanyId(), userId)
  286. ).build();
  287. Drive.Files driveFiles = drive.files();
  288. Drive.Files.Get driveFilesGet = driveFiles.get(
  289. _getGoogleDriveFileId(fileEntry));
  290. com.google.api.services.drive.model.File file =
  291. driveFilesGet.execute();
  292. return file.getName();
  293. }
  294. catch (IOException | PortalException exception) {
  295. throw new RuntimeException(exception);
  296. }
  297. }
  298. @Reference
  299. private BackgroundTaskManager _backgroundTaskManager;
  300. @Reference
  301. private DLOpenerFileEntryReferenceLocalService
  302. _dlOpenerFileEntryReferenceLocalService;
  303. private JsonFactory _jsonFactory;
  304. private NetHttpTransport _netHttpTransport;
  305. @Reference
  306. private OAuth2Manager _oAuth2Manager;
  307. private static class CachingSupplier<T> implements Supplier<T> {
  308. public CachingSupplier(Supplier<T> supplier) {
  309. _supplier = supplier;
  310. }
  311. @Override
  312. public T get() {
  313. if (_value != null) {
  314. return _value;
  315. }
  316. _value = _supplier.get();
  317. return _value;
  318. }
  319. private final Supplier<T> _supplier;
  320. private T _value;
  321. }
  322. }