PageRenderTime 25ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/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/vilmospapp/liferay-portal
Java | 409 lines | 308 code | 85 blank | 16 comment | 10 complexity | f58332d003b589d4b1562d411e476235 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. return false;
  141. }
  142. if ((credential.getExpiresInSeconds() <= 0) &&
  143. !credential.refreshToken()) {
  144. return false;
  145. }
  146. return true;
  147. }
  148. @Override
  149. public boolean isConfigured(long companyId) {
  150. return _oAuth2Manager.isConfigured(companyId);
  151. }
  152. @Override
  153. public boolean isGoogleDriveFile(FileEntry fileEntry) {
  154. return Optional.ofNullable(
  155. _dlOpenerFileEntryReferenceLocalService.
  156. fetchDLOpenerFileEntryReference(
  157. DLOpenerGoogleDriveConstants.GOOGLE_DRIVE_REFERENCE_TYPE,
  158. fileEntry)
  159. ).map(
  160. dlOpenerFileEntryReference -> true
  161. ).orElse(
  162. false
  163. );
  164. }
  165. @Override
  166. public void requestAuthorizationToken(
  167. long companyId, long userId, String code, String redirectUri)
  168. throws IOException, PortalException {
  169. _oAuth2Manager.requestAuthorizationToken(
  170. companyId, userId, code, redirectUri);
  171. }
  172. @Override
  173. public DLOpenerGoogleDriveFileReference requestEditAccess(
  174. long userId, FileEntry fileEntry)
  175. throws PortalException {
  176. if (Validator.isNull(_getGoogleDriveFileId(fileEntry))) {
  177. throw new IllegalArgumentException(
  178. StringBundler.concat(
  179. "File entry ", fileEntry.getFileEntryId(),
  180. " is not a Google Drive file"));
  181. }
  182. _checkCredential(fileEntry.getCompanyId(), userId);
  183. return new DLOpenerGoogleDriveFileReference(
  184. fileEntry.getFileEntryId(),
  185. new CachingSupplier<>(
  186. () -> _getGoogleDriveFileTitle(userId, fileEntry)),
  187. () -> _getContentFile(userId, fileEntry), 0);
  188. }
  189. @Override
  190. public void setAuthorizationToken(
  191. long companyId, long userId, String authorizationToken)
  192. throws IOException, PortalException {
  193. _oAuth2Manager.setAccessToken(companyId, userId, authorizationToken);
  194. }
  195. @Activate
  196. protected void activate() throws GeneralSecurityException, IOException {
  197. _jsonFactory = JacksonFactory.getDefaultInstance();
  198. _netHttpTransport = GoogleNetHttpTransport.newTrustedTransport();
  199. }
  200. private BackgroundTask _addBackgroundTask(
  201. String cmd, FileEntry fileEntry, long userId)
  202. throws PortalException {
  203. Map<String, Serializable> taskContextMap =
  204. HashMapBuilder.<String, Serializable>put(
  205. BackgroundTaskContextMapConstants.DELETE_ON_SUCCESS, true
  206. ).put(
  207. GoogleDriveBackgroundTaskConstants.CMD, cmd
  208. ).put(
  209. GoogleDriveBackgroundTaskConstants.COMPANY_ID,
  210. fileEntry.getCompanyId()
  211. ).put(
  212. GoogleDriveBackgroundTaskConstants.FILE_ENTRY_ID,
  213. fileEntry.getFileEntryId()
  214. ).put(
  215. GoogleDriveBackgroundTaskConstants.USER_ID, userId
  216. ).build();
  217. return _backgroundTaskManager.addBackgroundTask(
  218. userId, CompanyConstants.SYSTEM,
  219. StringBundler.concat(
  220. DLOpenerGoogleDriveManager.class.getSimpleName(),
  221. StringPool.POUND, fileEntry.getFileEntryId()),
  222. UploadGoogleDriveDocumentBackgroundTaskExecutor.class.getName(),
  223. taskContextMap, new ServiceContext());
  224. }
  225. private void _checkCredential(long companyId, long userId)
  226. throws PortalException {
  227. _getCredential(companyId, userId);
  228. }
  229. private File _getContentFile(long userId, FileEntry fileEntry) {
  230. try {
  231. Credential credential = _getCredential(
  232. fileEntry.getCompanyId(), userId);
  233. Drive drive = new Drive.Builder(
  234. _netHttpTransport, _jsonFactory, credential
  235. ).build();
  236. Drive.Files driveFiles = drive.files();
  237. Drive.Files.Get get = driveFiles.get(
  238. _getGoogleDriveFileId(fileEntry));
  239. get.setFields("exportLinks");
  240. com.google.api.services.drive.model.File file = get.execute();
  241. Map<String, String> exportLinks = file.getExportLinks();
  242. URL url = new URL(exportLinks.get(fileEntry.getMimeType()));
  243. if (!StringUtil.startsWith(url.getProtocol(), Http.HTTP)) {
  244. throw new SecurityException(
  245. "Only HTTP links are allowed: " + url);
  246. }
  247. if (InetAddressUtil.isLocalInetAddress(
  248. InetAddress.getByName(url.getHost()))) {
  249. throw new SecurityException(
  250. "Local links are not allowed: " + url);
  251. }
  252. URLConnection urlConnection = url.openConnection();
  253. urlConnection.setRequestProperty(
  254. "Authorization", "Bearer " + credential.getAccessToken());
  255. try (InputStream inputStream = urlConnection.getInputStream()) {
  256. return FileUtil.createTempFile(inputStream);
  257. }
  258. }
  259. catch (IOException | PortalException exception) {
  260. throw new RuntimeException(exception);
  261. }
  262. }
  263. private Credential _getCredential(long companyId, long userId)
  264. throws PortalException {
  265. Credential credential = _oAuth2Manager.getCredential(companyId, userId);
  266. if (credential == null) {
  267. throw new PrincipalException(
  268. StringBundler.concat(
  269. "User ", userId,
  270. " does not have a valid Google credential"));
  271. }
  272. return credential;
  273. }
  274. private String _getGoogleDriveFileId(FileEntry fileEntry)
  275. throws PortalException {
  276. DLOpenerFileEntryReference dlOpenerFileEntryReference =
  277. _dlOpenerFileEntryReferenceLocalService.
  278. getDLOpenerFileEntryReference(
  279. DLOpenerGoogleDriveConstants.GOOGLE_DRIVE_REFERENCE_TYPE,
  280. fileEntry);
  281. return dlOpenerFileEntryReference.getReferenceKey();
  282. }
  283. private String _getGoogleDriveFileTitle(long userId, FileEntry fileEntry) {
  284. try {
  285. Drive drive = new Drive.Builder(
  286. _netHttpTransport, _jsonFactory,
  287. _getCredential(fileEntry.getCompanyId(), userId)
  288. ).build();
  289. Drive.Files driveFiles = drive.files();
  290. Drive.Files.Get driveFilesGet = driveFiles.get(
  291. _getGoogleDriveFileId(fileEntry));
  292. com.google.api.services.drive.model.File file =
  293. driveFilesGet.execute();
  294. return file.getName();
  295. }
  296. catch (IOException | PortalException exception) {
  297. throw new RuntimeException(exception);
  298. }
  299. }
  300. @Reference
  301. private BackgroundTaskManager _backgroundTaskManager;
  302. @Reference
  303. private DLOpenerFileEntryReferenceLocalService
  304. _dlOpenerFileEntryReferenceLocalService;
  305. private JsonFactory _jsonFactory;
  306. private NetHttpTransport _netHttpTransport;
  307. @Reference
  308. private OAuth2Manager _oAuth2Manager;
  309. private static class CachingSupplier<T> implements Supplier<T> {
  310. public CachingSupplier(Supplier<T> supplier) {
  311. _supplier = supplier;
  312. }
  313. @Override
  314. public T get() {
  315. if (_value != null) {
  316. return _value;
  317. }
  318. _value = _supplier.get();
  319. return _value;
  320. }
  321. private final Supplier<T> _supplier;
  322. private T _value;
  323. }
  324. }