Skip to content

Commit 9798e76

Browse files
feat(db): set/update share timestamps on ACL create/update
Records created_at on share insertion and updates last_modified_at on every subsequent modification. The created_at value is preserved across updates. Existing shares retain the 0 sentinel (unknown). Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
1 parent 741fa68 commit 9798e76

8 files changed

Lines changed: 100 additions & 11 deletions

File tree

lib/Db/Acl.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
* @method void setOwner(int $owner)
2222
* @method void setToken(string $token)
2323
* @method string getToken()
24+
* @method int getCreatedAt()
25+
* @method void setCreatedAt(int $createdAt)
26+
* @method int getLastModifiedAt()
27+
* @method void setLastModifiedAt(int $lastModifiedAt)
2428
*
2529
*/
2630
class Acl extends RelationalEntity {
@@ -42,6 +46,8 @@ class Acl extends RelationalEntity {
4246
protected $permissionManage = false;
4347
protected $owner = false;
4448
protected $token = null;
49+
protected $createdAt = 0;
50+
protected $lastModifiedAt = 0;
4551

4652
public function __construct() {
4753
$this->addType('id', 'integer');
@@ -52,6 +58,8 @@ public function __construct() {
5258
$this->addType('type', 'integer');
5359
$this->addType('owner', 'boolean');
5460
$this->addType('token', 'string');
61+
$this->addType('createdAt', 'integer');
62+
$this->addType('lastModifiedAt', 'integer');
5563
$this->addRelation('owner');
5664
$this->addResolvable('participant');
5765
}

lib/Db/AclMapper.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace OCA\Deck\Db;
99

1010
use OCP\AppFramework\Db\DoesNotExistException;
11+
use OCP\AppFramework\Db\Entity;
1112
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
1213
use OCP\DB\QueryBuilder\IQueryBuilder;
1314
use OCP\IDBConnection;
@@ -20,7 +21,7 @@ public function __construct(IDBConnection $db) {
2021

2122
public function findByAccessToken(string $accessToken) {
2223
$qb = $this->db->getQueryBuilder();
23-
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage', 'token')
24+
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage', 'token', 'created_at', 'last_modified_at')
2425
->from('deck_board_acl')
2526
->where($qb->expr()->eq('token', $qb->createNamedParameter($accessToken, IQueryBuilder::PARAM_STR)))
2627
->setMaxResults(1);
@@ -34,7 +35,7 @@ public function findByAccessToken(string $accessToken) {
3435
*/
3536
public function findAll(int $boardId, ?int $limit = null, ?int $offset = null) {
3637
$qb = $this->db->getQueryBuilder();
37-
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage', 'token')
38+
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage', 'token', 'created_at', 'last_modified_at')
3839
->from('deck_board_acl')
3940
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
4041
->setMaxResults($limit)
@@ -45,7 +46,7 @@ public function findAll(int $boardId, ?int $limit = null, ?int $offset = null) {
4546

4647
public function findIn(array $boardIds, ?int $limit = null, ?int $offset = null): array {
4748
$qb = $this->db->getQueryBuilder();
48-
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage')
49+
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage', 'created_at', 'last_modified_at')
4950
->from('deck_board_acl')
5051
->where($qb->expr()->in('board_id', $qb->createParameter('boardIds')))
5152
->setMaxResults($limit)
@@ -127,4 +128,18 @@ public function findByType(int $type): array {
127128
->where($qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
128129
return $this->findEntities($qb);
129130
}
131+
132+
public function insert(Entity $entity): Entity {
133+
/** @var Acl $entity */
134+
$now = time();
135+
$entity->setCreatedAt($now);
136+
$entity->setLastModifiedAt($now);
137+
return parent::insert($entity);
138+
}
139+
140+
public function update(Entity $entity): Entity {
141+
/** @var Acl $entity */
142+
$entity->setLastModifiedAt(time());
143+
return parent::update($entity);
144+
}
130145
}

lib/Service/BoardService.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ public function addAcl(int $boardId, int $type, $participant, bool $edit, bool $
400400
$acl->setPermissionEdit($edit);
401401
$acl->setPermissionShare($share);
402402
$acl->setPermissionManage($manage);
403+
$now = time();
404+
$acl->setCreatedAt($now);
405+
$acl->setLastModifiedAt($now);
403406
$newAcl = $this->aclMapper->insert($acl);
404407

405408
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_BOARD, $newAcl, ActivityManager::SUBJECT_BOARD_SHARE, [], $this->userId);
@@ -451,6 +454,7 @@ public function updateAcl(int $id, bool $edit, bool $share, bool $manage): Acl {
451454
$acl->setPermissionEdit($edit);
452455
$acl->setPermissionShare($share);
453456
$acl->setPermissionManage($manage);
457+
$acl->setLastModifiedAt(time());
454458
$this->boardMapper->mapAcl($acl);
455459
$acl = $this->aclMapper->update($acl);
456460
$this->changeHelper->boardChanged($acl->getBoardId());
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
93102
1+
96706

tests/integration/import/ImportExportTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public function testReimportOcc() {
134134
);
135135
}
136136

137-
public static function writeArrayStructure(string $prefix = '', array $array = [], array $skipKeyList = ['id', 'boardId', 'cardId', 'stackId', 'ETag', 'permissions', 'shared', 'version', 'done', 'referenceData', 'token']): string {
137+
public static function writeArrayStructure(string $prefix = '', array $array = [], array $skipKeyList = ['id', 'boardId', 'cardId', 'stackId', 'ETag', 'permissions', 'shared', 'version', 'done', 'referenceData', 'token', 'createdAt', 'lastModifiedAt']): string {
138138
$output = '';
139139
$arrayIsList = array_keys($array) === range(0, count($array) - 1);
140140
foreach ($array as $key => $value) {

tests/unit/Db/AclMapperTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,34 @@ public function testFindBoardIdDatabase() {
120120
$this->assertEquals($this->boards[0]->getId(), $this->aclMapper->findBoardId($this->acls[1]->getId()));
121121
}
122122

123+
public function testInsertSetsCreatedAtAndLastModifiedAt(): void {
124+
$before = time();
125+
$acl = $this->getAcl('user', 'timestamps_user', false, false, false, $this->boards[0]->getId());
126+
$inserted = $this->aclMapper->insert($acl);
127+
$after = time();
128+
129+
$this->assertGreaterThanOrEqual($before, $inserted->getCreatedAt());
130+
$this->assertLessThanOrEqual($after, $inserted->getCreatedAt());
131+
$this->assertGreaterThanOrEqual($before, $inserted->getLastModifiedAt());
132+
$this->assertLessThanOrEqual($after, $inserted->getLastModifiedAt());
133+
134+
$this->aclMapper->delete($inserted);
135+
}
136+
137+
public function testUpdateChangesLastModifiedAtButNotCreatedAt(): void {
138+
$acl = $this->getAcl('user', 'timestamps_user2', false, false, false, $this->boards[0]->getId());
139+
$inserted = $this->aclMapper->insert($acl);
140+
$originalCreatedAt = $inserted->getCreatedAt();
141+
142+
$inserted->setPermissionEdit(true);
143+
$updated = $this->aclMapper->update($inserted);
144+
145+
$this->assertSame($originalCreatedAt, $updated->getCreatedAt());
146+
$this->assertGreaterThan(0, $updated->getLastModifiedAt());
147+
148+
$this->aclMapper->delete($updated);
149+
}
150+
123151
public function tearDown(): void {
124152
parent::tearDown();
125153
foreach ($this->acls as $acl) {

tests/unit/Db/AclTest.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ public function testJsonSerialize() {
5959
'permissionEdit' => true,
6060
'permissionShare' => true,
6161
'permissionManage' => true,
62-
'owner' => false
62+
'owner' => false,
63+
'createdAt' => 0,
64+
'lastModifiedAt' => 0,
6365
], $acl->jsonSerialize());
6466
$acl = $this->createAclGroup();
6567
$this->assertEquals([
@@ -70,7 +72,9 @@ public function testJsonSerialize() {
7072
'permissionEdit' => true,
7173
'permissionShare' => true,
7274
'permissionManage' => true,
73-
'owner' => false
75+
'owner' => false,
76+
'createdAt' => 0,
77+
'lastModifiedAt' => 0,
7478
], $acl->jsonSerialize());
7579
}
7680

@@ -85,7 +89,9 @@ public function testSetOwner() {
8589
'permissionEdit' => true,
8690
'permissionShare' => true,
8791
'permissionManage' => true,
88-
'owner' => true
92+
'owner' => true,
93+
'createdAt' => 0,
94+
'lastModifiedAt' => 0,
8995
], $acl->jsonSerialize());
9096
}
9197

tests/unit/Service/BoardServiceTest.php

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,16 @@ public function testAddAcl() {
301301
->method('sendBoardShared');
302302
$this->aclMapper->expects($this->once())
303303
->method('insert')
304-
->with($acl)
304+
->with($this->callback(function (Acl $actual) use ($acl) {
305+
return $actual->getBoardId() === $acl->getBoardId()
306+
&& $actual->getType() === $acl->getType()
307+
&& $actual->getParticipant() === $acl->getParticipant()
308+
&& $actual->getPermissionEdit() === $acl->getPermissionEdit()
309+
&& $actual->getPermissionShare() === $acl->getPermissionShare()
310+
&& $actual->getPermissionManage() === $acl->getPermissionManage()
311+
&& $actual->getCreatedAt() > 0
312+
&& $actual->getLastModifiedAt() > 0;
313+
}))
305314
->willReturn($acl);
306315
$this->permissionService->expects($this->any())
307316
->method('findUsers')
@@ -407,11 +416,30 @@ public function testAddAclExtendPermission($currentUserAcl, $providedAcl, $resul
407416
$expected = clone $acl;
408417
$this->aclMapper->expects($this->once())
409418
->method('insert')
410-
->with($acl)
419+
->with($this->callback(function (Acl $actual) use ($acl) {
420+
return $actual->getBoardId() === $acl->getBoardId()
421+
&& $actual->getType() === $acl->getType()
422+
&& $actual->getParticipant() === $acl->getParticipant()
423+
&& $actual->getPermissionEdit() === $acl->getPermissionEdit()
424+
&& $actual->getPermissionShare() === $acl->getPermissionShare()
425+
&& $actual->getPermissionManage() === $acl->getPermissionManage()
426+
&& $actual->getCreatedAt() > 0
427+
&& $actual->getLastModifiedAt() > 0;
428+
}))
411429
->willReturn($acl);
412430
$this->eventDispatcher->expects(self::once())
413431
->method('dispatchTyped')
414-
->with(new AclCreatedEvent($acl));
432+
->with($this->callback(function (AclCreatedEvent $event) use ($acl) {
433+
$eventAcl = $event->getAcl();
434+
return $eventAcl->getBoardId() === $acl->getBoardId()
435+
&& $eventAcl->getType() === $acl->getType()
436+
&& $eventAcl->getParticipant() === $acl->getParticipant()
437+
&& $eventAcl->getPermissionEdit() === $acl->getPermissionEdit()
438+
&& $eventAcl->getPermissionShare() === $acl->getPermissionShare()
439+
&& $eventAcl->getPermissionManage() === $acl->getPermissionManage()
440+
&& $eventAcl->getCreatedAt() > 0
441+
&& $eventAcl->getLastModifiedAt() > 0;
442+
}));
415443
$this->assertEquals($expected, $this->service->addAcl(
416444
123, Acl::PERMISSION_TYPE_USER, 'admin', $providedAcl[0], $providedAcl[1], $providedAcl[2]
417445
));

0 commit comments

Comments
 (0)