Passed
Push — master ( 90d2cb...d07838 )
by Julius
16:46 queued 13s
created
lib/private/DirectEditing/Manager.php 1 patch
Indentation   +266 added lines, -266 removed lines patch added patch discarded remove patch
@@ -51,270 +51,270 @@
 block discarded – undo
51 51
 use function in_array;
52 52
 
53 53
 class Manager implements IManager {
54
-	private const TOKEN_CLEANUP_TIME = 12 * 60 * 60 ;
55
-
56
-	public const TABLE_TOKENS = 'direct_edit';
57
-
58
-	/** @var IEditor[] */
59
-	private $editors = [];
60
-	/** @var IDBConnection */
61
-	private $connection;
62
-	/** @var IUserSession */
63
-	private $userSession;
64
-	/** @var ISecureRandom */
65
-	private $random;
66
-	/** @var string|null */
67
-	private $userId;
68
-	/** @var IRootFolder */
69
-	private $rootFolder;
70
-	/** @var IL10N */
71
-	private $l10n;
72
-	/** @var EncryptionManager */
73
-	private $encryptionManager;
74
-
75
-	public function __construct(
76
-		ISecureRandom $random,
77
-		IDBConnection $connection,
78
-		IUserSession $userSession,
79
-		IRootFolder $rootFolder,
80
-		IFactory $l10nFactory,
81
-		EncryptionManager $encryptionManager
82
-	) {
83
-		$this->random = $random;
84
-		$this->connection = $connection;
85
-		$this->userSession = $userSession;
86
-		$this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null;
87
-		$this->rootFolder = $rootFolder;
88
-		$this->l10n = $l10nFactory->get('lib');
89
-		$this->encryptionManager = $encryptionManager;
90
-	}
91
-
92
-	public function registerDirectEditor(IEditor $directEditor): void {
93
-		$this->editors[$directEditor->getId()] = $directEditor;
94
-	}
95
-
96
-	public function getEditors(): array {
97
-		return $this->editors;
98
-	}
99
-
100
-	public function getTemplates(string $editor, string $type): array {
101
-		if (!array_key_exists($editor, $this->editors)) {
102
-			throw new \RuntimeException('No matching editor found');
103
-		}
104
-		$templates = [];
105
-		foreach ($this->editors[$editor]->getCreators() as $creator) {
106
-			if ($creator->getId() === $type) {
107
-				$templates = [
108
-					'empty' => [
109
-						'id' => 'empty',
110
-						'title' => $this->l10n->t('Empty file'),
111
-						'preview' => null
112
-					]
113
-				];
114
-
115
-				if ($creator instanceof ACreateFromTemplate) {
116
-					$templates = $creator->getTemplates();
117
-				}
118
-
119
-				$templates = array_map(function ($template) use ($creator) {
120
-					$template['extension'] = $creator->getExtension();
121
-					$template['mimetype'] = $creator->getMimetype();
122
-					return $template;
123
-				}, $templates);
124
-			}
125
-		}
126
-		$return = [];
127
-		$return['templates'] = $templates;
128
-		return $return;
129
-	}
130
-
131
-	public function create(string $path, string $editorId, string $creatorId, $templateId = null): string {
132
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
133
-		if ($userFolder->nodeExists($path)) {
134
-			throw new \RuntimeException('File already exists');
135
-		} else {
136
-			if (!$userFolder->nodeExists(dirname($path))) {
137
-				throw new \RuntimeException('Invalid path');
138
-			}
139
-			/** @var Folder $folder */
140
-			$folder = $userFolder->get(dirname($path));
141
-			$file = $folder->newFile(basename($path));
142
-			$editor = $this->getEditor($editorId);
143
-			$creators = $editor->getCreators();
144
-			foreach ($creators as $creator) {
145
-				if ($creator->getId() === $creatorId) {
146
-					$creator->create($file, $creatorId, $templateId);
147
-					return $this->createToken($editorId, $file, $path);
148
-				}
149
-			}
150
-		}
151
-
152
-		throw new \RuntimeException('No creator found');
153
-	}
154
-
155
-	public function open(string $filePath, string $editorId = null): string {
156
-		/** @var File $file */
157
-		$file = $this->rootFolder->getUserFolder($this->userId)->get($filePath);
158
-
159
-		if ($editorId === null) {
160
-			$editorId = $this->findEditorForFile($file);
161
-		}
162
-		if (!array_key_exists($editorId, $this->editors)) {
163
-			throw new \RuntimeException("Editor $editorId is unknown");
164
-		}
165
-
166
-		return $this->createToken($editorId, $file, $filePath);
167
-	}
168
-
169
-	private function findEditorForFile(File $file) {
170
-		foreach ($this->editors as $editor) {
171
-			if (in_array($file->getMimeType(), $editor->getMimetypes())) {
172
-				return $editor->getId();
173
-			}
174
-		}
175
-		throw new \RuntimeException('No default editor found for files mimetype');
176
-	}
177
-
178
-	public function edit(string $token): Response {
179
-		try {
180
-			/** @var IEditor $editor */
181
-			$tokenObject = $this->getToken($token);
182
-			if ($tokenObject->hasBeenAccessed()) {
183
-				throw new \RuntimeException('Token has already been used and can only be used for followup requests');
184
-			}
185
-			$editor = $this->getEditor($tokenObject->getEditor());
186
-			$this->accessToken($token);
187
-		} catch (Throwable $throwable) {
188
-			$this->invalidateToken($token);
189
-			return new NotFoundResponse();
190
-		}
191
-
192
-		try {
193
-			$this->invokeTokenScope($tokenObject->getUser());
194
-			return $editor->open($tokenObject);
195
-		} finally {
196
-			$this->revertTokenScope();
197
-		}
198
-	}
199
-
200
-	public function editSecure(File $file, string $editorId): TemplateResponse {
201
-		// TODO: Implementation in follow up
202
-	}
203
-
204
-	private function getEditor($editorId): IEditor {
205
-		if (!array_key_exists($editorId, $this->editors)) {
206
-			throw new \RuntimeException('No editor found');
207
-		}
208
-		return $this->editors[$editorId];
209
-	}
210
-
211
-	public function getToken(string $token): IToken {
212
-		$query = $this->connection->getQueryBuilder();
213
-		$query->select('*')->from(self::TABLE_TOKENS)
214
-			->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));
215
-		$result = $query->execute();
216
-		if ($tokenRow = $result->fetch(FetchMode::ASSOCIATIVE)) {
217
-			return new Token($this, $tokenRow);
218
-		}
219
-		throw new \RuntimeException('Failed to validate the token');
220
-	}
221
-
222
-	public function cleanup(): int {
223
-		$query = $this->connection->getQueryBuilder();
224
-		$query->delete(self::TABLE_TOKENS)
225
-			->where($query->expr()->lt('timestamp', $query->createNamedParameter(time() - self::TOKEN_CLEANUP_TIME)));
226
-		return $query->execute();
227
-	}
228
-
229
-	public function refreshToken(string $token): bool {
230
-		$query = $this->connection->getQueryBuilder();
231
-		$query->update(self::TABLE_TOKENS)
232
-			->set('timestamp', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
233
-			->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));
234
-		$result = $query->execute();
235
-		return $result !== 0;
236
-	}
237
-
238
-
239
-	public function invalidateToken(string $token): bool {
240
-		$query = $this->connection->getQueryBuilder();
241
-		$query->delete(self::TABLE_TOKENS)
242
-			->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));
243
-		$result = $query->execute();
244
-		return $result !== 0;
245
-	}
246
-
247
-	public function accessToken(string $token): bool {
248
-		$query = $this->connection->getQueryBuilder();
249
-		$query->update(self::TABLE_TOKENS)
250
-			->set('accessed', $query->createNamedParameter(true, IQueryBuilder::PARAM_BOOL))
251
-			->set('timestamp', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
252
-			->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));
253
-		$result = $query->execute();
254
-		return $result !== 0;
255
-	}
256
-
257
-	public function invokeTokenScope($userId): void {
258
-		\OC_User::setIncognitoMode(true);
259
-		\OC_User::setUserId($userId);
260
-	}
261
-
262
-	public function revertTokenScope(): void {
263
-		$this->userSession->setUser(null);
264
-		\OC_User::setIncognitoMode(false);
265
-	}
266
-
267
-	public function createToken($editorId, File $file, string $filePath, IShare $share = null): string {
268
-		$token = $this->random->generate(64, ISecureRandom::CHAR_HUMAN_READABLE);
269
-		$query = $this->connection->getQueryBuilder();
270
-		$query->insert(self::TABLE_TOKENS)
271
-			->values([
272
-				'token' => $query->createNamedParameter($token),
273
-				'editor_id' => $query->createNamedParameter($editorId),
274
-				'file_id' => $query->createNamedParameter($file->getId()),
275
-				'file_path' => $query->createNamedParameter($filePath),
276
-				'user_id' => $query->createNamedParameter($this->userId),
277
-				'share_id' => $query->createNamedParameter($share !== null ? $share->getId(): null),
278
-				'timestamp' => $query->createNamedParameter(time())
279
-			]);
280
-		$query->execute();
281
-		return $token;
282
-	}
283
-
284
-	/**
285
-	 * @param $userId
286
-	 * @param $fileId
287
-	 * @param null $filePath
288
-	 * @return Node
289
-	 * @throws NotFoundException
290
-	 */
291
-	public function getFileForToken($userId, $fileId, $filePath = null): Node {
292
-		$userFolder = $this->rootFolder->getUserFolder($userId);
293
-		if ($filePath !== null) {
294
-			return $userFolder->get($filePath);
295
-		}
296
-		$files = $userFolder->getById($fileId);
297
-		if (count($files) === 0) {
298
-			throw new NotFoundException('File nound found by id ' . $fileId);
299
-		}
300
-		return $files[0];
301
-	}
302
-
303
-	public function isEnabled(): bool {
304
-		if (!$this->encryptionManager->isEnabled()) {
305
-			return true;
306
-		}
307
-
308
-		try {
309
-			$moduleId = $this->encryptionManager->getDefaultEncryptionModuleId();
310
-			$module = $this->encryptionManager->getEncryptionModule($moduleId);
311
-			/** @var \OCA\Encryption\Util $util */
312
-			$util = \OC::$server->get(\OCA\Encryption\Util::class);
313
-			if ($module->isReadyForUser($this->userId) && $util->isMasterKeyEnabled()) {
314
-				return true;
315
-			}
316
-		} catch (Throwable $e) {
317
-		}
318
-		return false;
319
-	}
54
+    private const TOKEN_CLEANUP_TIME = 12 * 60 * 60 ;
55
+
56
+    public const TABLE_TOKENS = 'direct_edit';
57
+
58
+    /** @var IEditor[] */
59
+    private $editors = [];
60
+    /** @var IDBConnection */
61
+    private $connection;
62
+    /** @var IUserSession */
63
+    private $userSession;
64
+    /** @var ISecureRandom */
65
+    private $random;
66
+    /** @var string|null */
67
+    private $userId;
68
+    /** @var IRootFolder */
69
+    private $rootFolder;
70
+    /** @var IL10N */
71
+    private $l10n;
72
+    /** @var EncryptionManager */
73
+    private $encryptionManager;
74
+
75
+    public function __construct(
76
+        ISecureRandom $random,
77
+        IDBConnection $connection,
78
+        IUserSession $userSession,
79
+        IRootFolder $rootFolder,
80
+        IFactory $l10nFactory,
81
+        EncryptionManager $encryptionManager
82
+    ) {
83
+        $this->random = $random;
84
+        $this->connection = $connection;
85
+        $this->userSession = $userSession;
86
+        $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null;
87
+        $this->rootFolder = $rootFolder;
88
+        $this->l10n = $l10nFactory->get('lib');
89
+        $this->encryptionManager = $encryptionManager;
90
+    }
91
+
92
+    public function registerDirectEditor(IEditor $directEditor): void {
93
+        $this->editors[$directEditor->getId()] = $directEditor;
94
+    }
95
+
96
+    public function getEditors(): array {
97
+        return $this->editors;
98
+    }
99
+
100
+    public function getTemplates(string $editor, string $type): array {
101
+        if (!array_key_exists($editor, $this->editors)) {
102
+            throw new \RuntimeException('No matching editor found');
103
+        }
104
+        $templates = [];
105
+        foreach ($this->editors[$editor]->getCreators() as $creator) {
106
+            if ($creator->getId() === $type) {
107
+                $templates = [
108
+                    'empty' => [
109
+                        'id' => 'empty',
110
+                        'title' => $this->l10n->t('Empty file'),
111
+                        'preview' => null
112
+                    ]
113
+                ];
114
+
115
+                if ($creator instanceof ACreateFromTemplate) {
116
+                    $templates = $creator->getTemplates();
117
+                }
118
+
119
+                $templates = array_map(function ($template) use ($creator) {
120
+                    $template['extension'] = $creator->getExtension();
121
+                    $template['mimetype'] = $creator->getMimetype();
122
+                    return $template;
123
+                }, $templates);
124
+            }
125
+        }
126
+        $return = [];
127
+        $return['templates'] = $templates;
128
+        return $return;
129
+    }
130
+
131
+    public function create(string $path, string $editorId, string $creatorId, $templateId = null): string {
132
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
133
+        if ($userFolder->nodeExists($path)) {
134
+            throw new \RuntimeException('File already exists');
135
+        } else {
136
+            if (!$userFolder->nodeExists(dirname($path))) {
137
+                throw new \RuntimeException('Invalid path');
138
+            }
139
+            /** @var Folder $folder */
140
+            $folder = $userFolder->get(dirname($path));
141
+            $file = $folder->newFile(basename($path));
142
+            $editor = $this->getEditor($editorId);
143
+            $creators = $editor->getCreators();
144
+            foreach ($creators as $creator) {
145
+                if ($creator->getId() === $creatorId) {
146
+                    $creator->create($file, $creatorId, $templateId);
147
+                    return $this->createToken($editorId, $file, $path);
148
+                }
149
+            }
150
+        }
151
+
152
+        throw new \RuntimeException('No creator found');
153
+    }
154
+
155
+    public function open(string $filePath, string $editorId = null): string {
156
+        /** @var File $file */
157
+        $file = $this->rootFolder->getUserFolder($this->userId)->get($filePath);
158
+
159
+        if ($editorId === null) {
160
+            $editorId = $this->findEditorForFile($file);
161
+        }
162
+        if (!array_key_exists($editorId, $this->editors)) {
163
+            throw new \RuntimeException("Editor $editorId is unknown");
164
+        }
165
+
166
+        return $this->createToken($editorId, $file, $filePath);
167
+    }
168
+
169
+    private function findEditorForFile(File $file) {
170
+        foreach ($this->editors as $editor) {
171
+            if (in_array($file->getMimeType(), $editor->getMimetypes())) {
172
+                return $editor->getId();
173
+            }
174
+        }
175
+        throw new \RuntimeException('No default editor found for files mimetype');
176
+    }
177
+
178
+    public function edit(string $token): Response {
179
+        try {
180
+            /** @var IEditor $editor */
181
+            $tokenObject = $this->getToken($token);
182
+            if ($tokenObject->hasBeenAccessed()) {
183
+                throw new \RuntimeException('Token has already been used and can only be used for followup requests');
184
+            }
185
+            $editor = $this->getEditor($tokenObject->getEditor());
186
+            $this->accessToken($token);
187
+        } catch (Throwable $throwable) {
188
+            $this->invalidateToken($token);
189
+            return new NotFoundResponse();
190
+        }
191
+
192
+        try {
193
+            $this->invokeTokenScope($tokenObject->getUser());
194
+            return $editor->open($tokenObject);
195
+        } finally {
196
+            $this->revertTokenScope();
197
+        }
198
+    }
199
+
200
+    public function editSecure(File $file, string $editorId): TemplateResponse {
201
+        // TODO: Implementation in follow up
202
+    }
203
+
204
+    private function getEditor($editorId): IEditor {
205
+        if (!array_key_exists($editorId, $this->editors)) {
206
+            throw new \RuntimeException('No editor found');
207
+        }
208
+        return $this->editors[$editorId];
209
+    }
210
+
211
+    public function getToken(string $token): IToken {
212
+        $query = $this->connection->getQueryBuilder();
213
+        $query->select('*')->from(self::TABLE_TOKENS)
214
+            ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));
215
+        $result = $query->execute();
216
+        if ($tokenRow = $result->fetch(FetchMode::ASSOCIATIVE)) {
217
+            return new Token($this, $tokenRow);
218
+        }
219
+        throw new \RuntimeException('Failed to validate the token');
220
+    }
221
+
222
+    public function cleanup(): int {
223
+        $query = $this->connection->getQueryBuilder();
224
+        $query->delete(self::TABLE_TOKENS)
225
+            ->where($query->expr()->lt('timestamp', $query->createNamedParameter(time() - self::TOKEN_CLEANUP_TIME)));
226
+        return $query->execute();
227
+    }
228
+
229
+    public function refreshToken(string $token): bool {
230
+        $query = $this->connection->getQueryBuilder();
231
+        $query->update(self::TABLE_TOKENS)
232
+            ->set('timestamp', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
233
+            ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));
234
+        $result = $query->execute();
235
+        return $result !== 0;
236
+    }
237
+
238
+
239
+    public function invalidateToken(string $token): bool {
240
+        $query = $this->connection->getQueryBuilder();
241
+        $query->delete(self::TABLE_TOKENS)
242
+            ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));
243
+        $result = $query->execute();
244
+        return $result !== 0;
245
+    }
246
+
247
+    public function accessToken(string $token): bool {
248
+        $query = $this->connection->getQueryBuilder();
249
+        $query->update(self::TABLE_TOKENS)
250
+            ->set('accessed', $query->createNamedParameter(true, IQueryBuilder::PARAM_BOOL))
251
+            ->set('timestamp', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
252
+            ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));
253
+        $result = $query->execute();
254
+        return $result !== 0;
255
+    }
256
+
257
+    public function invokeTokenScope($userId): void {
258
+        \OC_User::setIncognitoMode(true);
259
+        \OC_User::setUserId($userId);
260
+    }
261
+
262
+    public function revertTokenScope(): void {
263
+        $this->userSession->setUser(null);
264
+        \OC_User::setIncognitoMode(false);
265
+    }
266
+
267
+    public function createToken($editorId, File $file, string $filePath, IShare $share = null): string {
268
+        $token = $this->random->generate(64, ISecureRandom::CHAR_HUMAN_READABLE);
269
+        $query = $this->connection->getQueryBuilder();
270
+        $query->insert(self::TABLE_TOKENS)
271
+            ->values([
272
+                'token' => $query->createNamedParameter($token),
273
+                'editor_id' => $query->createNamedParameter($editorId),
274
+                'file_id' => $query->createNamedParameter($file->getId()),
275
+                'file_path' => $query->createNamedParameter($filePath),
276
+                'user_id' => $query->createNamedParameter($this->userId),
277
+                'share_id' => $query->createNamedParameter($share !== null ? $share->getId(): null),
278
+                'timestamp' => $query->createNamedParameter(time())
279
+            ]);
280
+        $query->execute();
281
+        return $token;
282
+    }
283
+
284
+    /**
285
+     * @param $userId
286
+     * @param $fileId
287
+     * @param null $filePath
288
+     * @return Node
289
+     * @throws NotFoundException
290
+     */
291
+    public function getFileForToken($userId, $fileId, $filePath = null): Node {
292
+        $userFolder = $this->rootFolder->getUserFolder($userId);
293
+        if ($filePath !== null) {
294
+            return $userFolder->get($filePath);
295
+        }
296
+        $files = $userFolder->getById($fileId);
297
+        if (count($files) === 0) {
298
+            throw new NotFoundException('File nound found by id ' . $fileId);
299
+        }
300
+        return $files[0];
301
+    }
302
+
303
+    public function isEnabled(): bool {
304
+        if (!$this->encryptionManager->isEnabled()) {
305
+            return true;
306
+        }
307
+
308
+        try {
309
+            $moduleId = $this->encryptionManager->getDefaultEncryptionModuleId();
310
+            $module = $this->encryptionManager->getEncryptionModule($moduleId);
311
+            /** @var \OCA\Encryption\Util $util */
312
+            $util = \OC::$server->get(\OCA\Encryption\Util::class);
313
+            if ($module->isReadyForUser($this->userId) && $util->isMasterKeyEnabled()) {
314
+                return true;
315
+            }
316
+        } catch (Throwable $e) {
317
+        }
318
+        return false;
319
+    }
320 320
 }
Please login to merge, or discard this patch.
apps/files/lib/Controller/DirectEditingViewController.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -34,38 +34,38 @@
 block discarded – undo
34 34
 
35 35
 class DirectEditingViewController extends Controller {
36 36
 
37
-	/** @var IEventDispatcher */
38
-	private $eventDispatcher;
37
+    /** @var IEventDispatcher */
38
+    private $eventDispatcher;
39 39
 
40
-	/** @var IManager */
41
-	private $directEditingManager;
40
+    /** @var IManager */
41
+    private $directEditingManager;
42 42
 
43
-	/** @var ILogger */
44
-	private $logger;
43
+    /** @var ILogger */
44
+    private $logger;
45 45
 
46
-	public function __construct($appName, IRequest $request, IEventDispatcher $eventDispatcher, IManager $manager, ILogger $logger) {
47
-		parent::__construct($appName, $request);
46
+    public function __construct($appName, IRequest $request, IEventDispatcher $eventDispatcher, IManager $manager, ILogger $logger) {
47
+        parent::__construct($appName, $request);
48 48
 
49
-		$this->eventDispatcher = $eventDispatcher;
50
-		$this->directEditingManager = $manager;
51
-		$this->logger = $logger;
52
-	}
49
+        $this->eventDispatcher = $eventDispatcher;
50
+        $this->directEditingManager = $manager;
51
+        $this->logger = $logger;
52
+    }
53 53
 
54
-	/**
55
-	 * @PublicPage
56
-	 * @NoCSRFRequired
57
-	 * @UseSession
58
-	 *
59
-	 * @param string $token
60
-	 * @return Response
61
-	 */
62
-	public function edit(string $token): Response {
63
-		$this->eventDispatcher->dispatchTyped(new RegisterDirectEditorEvent($this->directEditingManager));
64
-		try {
65
-			return $this->directEditingManager->edit($token);
66
-		} catch (Exception $e) {
67
-			$this->logger->logException($e);
68
-			return new NotFoundResponse();
69
-		}
70
-	}
54
+    /**
55
+     * @PublicPage
56
+     * @NoCSRFRequired
57
+     * @UseSession
58
+     *
59
+     * @param string $token
60
+     * @return Response
61
+     */
62
+    public function edit(string $token): Response {
63
+        $this->eventDispatcher->dispatchTyped(new RegisterDirectEditorEvent($this->directEditingManager));
64
+        try {
65
+            return $this->directEditingManager->edit($token);
66
+        } catch (Exception $e) {
67
+            $this->logger->logException($e);
68
+            return new NotFoundResponse();
69
+        }
70
+    }
71 71
 }
Please login to merge, or discard this patch.