-
Notifications
You must be signed in to change notification settings - Fork 147
Expand file tree
/
Copy pathDirectMapper.php
More file actions
84 lines (72 loc) 路 2.58 KB
/
Copy pathDirectMapper.php
File metadata and controls
84 lines (72 loc) 路 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<?php
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Richdocuments\Db;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IDBConnection;
use OCP\Security\ISecureRandom;
/** @template-extends QBMapper<Direct> */
class DirectMapper extends QBMapper {
/** @var int Lifetime of a token is 10 minutes */
public const TOKEN_TTL = 600;
public function __construct(
IDBConnection $db,
protected ISecureRandom $random,
protected ITimeFactory $timeFactory,
) {
parent::__construct($db, 'richdocuments_direct', Direct::class);
}
/**
* @param string|null $uid
* @param int $fileid
* @param int $destination
* @return Direct
*/
public function newDirect($uid, $fileid, $template = null, $share = null, $initiatorHost = null, $initiatorToken = null) {
$direct = new Direct();
$direct->setUid($uid);
$direct->setFileid($fileid);
$direct->setToken($this->random->generate(64, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER));
$direct->setTimestamp($this->timeFactory->getTime());
$direct->setTemplateId($template);
$direct->setShare($share);
$direct->setInitiatorHost($initiatorHost);
$direct->setInitiatorToken($initiatorToken);
return $this->insert($direct);
}
/**
* Fetch a direct-link token record.
*
* @param string $token Token value from direct-link URL
* @param bool $forUpdate When true, issues a row-level lock (FOR UPDATE).
* Call only within a DB transaction when token consumption
* must be serialized to avoid concurrent reuse.
*
* @throws DoesNotExistException If token does not exist or is expired (or deletion otherwise fails).
*/
public function getByToken(string $token, bool $forUpdate = false): Direct {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from('richdocuments_direct')
->where($qb->expr()->eq('token', $qb->createNamedParameter($token)));
if ($forUpdate) {
// Lock token row so concurrent requests cannot consume it in parallel.
$qb->forUpdate();
}
try {
$direct = $this->findEntity($qb);
if (($direct->getTimestamp() + self::TOKEN_TTL) < $this->timeFactory->getTime()) {
// Opportunistic cleanup: expired tokens are removed on read.
$this->delete($direct);
throw new DoesNotExistException('Could not find token.');
}
return $direct;
} catch (\Exception) {
}
throw new DoesNotExistException('No asset for token found');
}
}