Coverage for app / backend / src / tests / test_pages.py: 100%

518 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-19 14:14 +0000

1import grpc 

2import pytest 

3from google.protobuf import wrappers_pb2 

4 

5from couchers.crypto import random_hex 

6from couchers.db import session_scope 

7from couchers.models import ( 

8 Cluster, 

9 ClusterRole, 

10 ClusterSubscription, 

11 Node, 

12 NodeType, 

13 Page, 

14 PageType, 

15 PageVersion, 

16 Thread, 

17 Upload, 

18) 

19from couchers.proto import pages_pb2 

20from couchers.utils import create_polygon_lat_lng, now, to_aware_datetime, to_multi 

21from tests.fixtures.db import generate_user 

22from tests.fixtures.sessions import pages_session 

23from tests.test_communities import create_community 

24 

25 

26@pytest.fixture(autouse=True) 

27def _(testconfig): 

28 pass 

29 

30 

31def test_create_place_errors(db): 

32 user, token = generate_user() 

33 with session_scope() as session: 

34 create_community(session, 0, 2, "Root node", [user], [], None) 

35 

36 with pages_session(token) as api: 

37 with pytest.raises(grpc.RpcError) as e: 

38 api.CreatePlace( 

39 pages_pb2.CreatePlaceReq( 

40 title=None, 

41 content="dummy content", 

42 address="dummy address", 

43 location=pages_pb2.Coordinate( 

44 lat=1, 

45 lng=1, 

46 ), 

47 ) 

48 ) 

49 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

50 assert e.value.details() == "Missing page title." 

51 

52 with pages_session(token) as api: 

53 with pytest.raises(grpc.RpcError) as e: 

54 api.CreatePlace( 

55 pages_pb2.CreatePlaceReq( 

56 title="dummy title", 

57 content=None, 

58 address="dummy address", 

59 location=pages_pb2.Coordinate( 

60 lat=1, 

61 lng=1, 

62 ), 

63 ) 

64 ) 

65 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

66 assert e.value.details() == "Missing page text." 

67 

68 with pages_session(token) as api: 

69 with pytest.raises(grpc.RpcError) as e: 

70 api.CreatePlace( 

71 pages_pb2.CreatePlaceReq( 

72 title="dummy title", 

73 content="dummy content", 

74 address=None, 

75 location=pages_pb2.Coordinate( 

76 lat=1, 

77 lng=1, 

78 ), 

79 ) 

80 ) 

81 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

82 assert e.value.details() == "Missing page address." 

83 

84 with pages_session(token) as api: 

85 with pytest.raises(grpc.RpcError) as e: 

86 api.CreatePlace( 

87 pages_pb2.CreatePlaceReq( 

88 title="dummy title", 

89 content="dummy content", 

90 address="dummy address", 

91 ) 

92 ) 

93 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

94 assert e.value.details() == "Missing page geo-location." 

95 

96 

97def test_create_guide_errors(db): 

98 user, token = generate_user() 

99 with session_scope() as session: 

100 c_id = create_community(session, 0, 2, "Root node", [user], [], None).id 

101 

102 with pages_session(token) as api: 

103 with pytest.raises(grpc.RpcError) as e: 

104 api.CreateGuide( 

105 pages_pb2.CreateGuideReq( 

106 title=None, 

107 content="dummy content", 

108 parent_community_id=c_id, 

109 ) 

110 ) 

111 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

112 assert e.value.details() == "Missing page title." 

113 

114 with pages_session(token) as api: 

115 with pytest.raises(grpc.RpcError) as e: 

116 api.CreateGuide( 

117 pages_pb2.CreateGuideReq( 

118 title="dummy title", 

119 content=None, 

120 parent_community_id=c_id, 

121 ) 

122 ) 

123 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

124 assert e.value.details() == "Missing page text." 

125 

126 with pages_session(token) as api: 

127 with pytest.raises(grpc.RpcError) as e: 

128 api.CreateGuide( 

129 pages_pb2.CreateGuideReq( 

130 title="dummy title", 

131 content="dummy content", 

132 ) 

133 ) 

134 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

135 assert e.value.details() == "Missing page parent." 

136 

137 with pages_session(token) as api: 

138 with pytest.raises(grpc.RpcError) as e: 

139 api.CreateGuide( 

140 pages_pb2.CreateGuideReq( 

141 title="dummy title", 

142 content="dummy content", 

143 parent_community_id=9999, 

144 ) 

145 ) 

146 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

147 assert e.value.details() == "Community not found." 

148 

149 with pages_session(token) as api: 

150 with pytest.raises(grpc.RpcError) as e: 

151 api.CreateGuide( 

152 pages_pb2.CreateGuideReq( 

153 title="dummy title", 

154 content="dummy content", 

155 address="dummy address", 

156 parent_community_id=c_id, 

157 ) 

158 ) 

159 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

160 assert e.value.details() == "You need to either supply an address and location or neither for a guide." 

161 

162 with pages_session(token) as api: 

163 with pytest.raises(grpc.RpcError) as e: 

164 api.CreateGuide( 

165 pages_pb2.CreateGuideReq( 

166 title="dummy title", 

167 content="dummy content", 

168 location=pages_pb2.Coordinate( 

169 lat=1, 

170 lng=1, 

171 ), 

172 parent_community_id=c_id, 

173 ) 

174 ) 

175 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

176 assert e.value.details() == "You need to either supply an address and location or neither for a guide." 

177 

178 

179def test_create_page_place(db): 

180 user, token = generate_user() 

181 with session_scope() as session: 

182 c_id = create_community(session, 0, 2, "Root node", [user], [], None).id 

183 

184 with pages_session(token) as api: 

185 time_before = now() 

186 res = api.CreatePlace( 

187 pages_pb2.CreatePlaceReq( 

188 title="dummy !#¤%&/-*' title", 

189 content="dummy content", 

190 address="dummy address", 

191 location=pages_pb2.Coordinate( 

192 lat=1, 

193 lng=1, 

194 ), 

195 ) 

196 ) 

197 

198 assert res.title == "dummy !#¤%&/-*' title" 

199 assert res.type == pages_pb2.PAGE_TYPE_PLACE 

200 assert res.content == "dummy content" 

201 assert res.address == "dummy address" 

202 assert res.location.lat == 1 

203 assert res.location.lng == 1 

204 assert res.slug == "dummy-title" 

205 assert time_before <= to_aware_datetime(res.created) <= now() 

206 assert time_before <= to_aware_datetime(res.last_edited) <= now() 

207 assert res.last_editor_user_id == user.id 

208 assert res.creator_user_id == user.id 

209 assert res.owner_user_id == user.id 

210 assert not res.owner_community_id 

211 assert not res.owner_group_id 

212 assert res.editor_user_ids == [user.id] 

213 assert res.can_edit 

214 assert res.can_moderate 

215 

216 

217def test_create_page_guide(db): 

218 user, token = generate_user() 

219 with session_scope() as session: 

220 c_id = create_community(session, 0, 2, "Root node", [user], [], None).id 

221 

222 with pages_session(token) as api: 

223 time_before = now() 

224 res = api.CreateGuide( 

225 pages_pb2.CreateGuideReq( 

226 title="dummy title", 

227 content="dummy content", 

228 address="dummy address", 

229 location=pages_pb2.Coordinate( 

230 lat=1, 

231 lng=1, 

232 ), 

233 parent_community_id=c_id, 

234 ) 

235 ) 

236 

237 assert res.title == "dummy title" 

238 assert res.type == pages_pb2.PAGE_TYPE_GUIDE 

239 assert res.content == "dummy content" 

240 assert res.address == "dummy address" 

241 assert res.location.lat == 1 

242 assert res.location.lng == 1 

243 assert res.slug == "dummy-title" 

244 assert time_before <= to_aware_datetime(res.created) <= now() 

245 assert time_before <= to_aware_datetime(res.last_edited) <= now() 

246 assert res.last_editor_user_id == user.id 

247 assert res.creator_user_id == user.id 

248 assert res.owner_user_id == user.id 

249 assert not res.owner_community_id 

250 assert not res.owner_group_id 

251 assert res.editor_user_ids == [user.id] 

252 assert res.can_edit 

253 assert res.can_moderate 

254 

255 with pages_session(token) as api: 

256 time_before = now() 

257 res = api.CreateGuide( 

258 pages_pb2.CreateGuideReq( 

259 title="dummy title", 

260 content="dummy content", 

261 parent_community_id=c_id, 

262 ) 

263 ) 

264 

265 assert res.title == "dummy title" 

266 assert res.type == pages_pb2.PAGE_TYPE_GUIDE 

267 assert res.content == "dummy content" 

268 assert not res.address 

269 assert not res.HasField("location") 

270 assert res.slug == "dummy-title" 

271 assert time_before <= to_aware_datetime(res.created) <= now() 

272 assert time_before <= to_aware_datetime(res.last_edited) <= now() 

273 assert res.last_editor_user_id == user.id 

274 assert res.creator_user_id == user.id 

275 assert res.owner_user_id == user.id 

276 assert not res.owner_community_id 

277 assert not res.owner_group_id 

278 assert res.editor_user_ids == [user.id] 

279 assert res.can_edit 

280 assert res.can_moderate 

281 

282 

283def test_get_page(db): 

284 user1, token1 = generate_user() 

285 user2, token2 = generate_user() 

286 with session_scope() as session: 

287 c_id = create_community(session, 0, 2, "Root node", [user1], [], None).id 

288 

289 with pages_session(token1) as api: 

290 time_before_create = now() 

291 page_id = api.CreatePlace( 

292 pages_pb2.CreatePlaceReq( 

293 title="dummy title", 

294 content="dummy content", 

295 address="dummy address", 

296 location=pages_pb2.Coordinate( 

297 lat=1, 

298 lng=1, 

299 ), 

300 ) 

301 ).page_id 

302 

303 with pages_session(token2) as api: 

304 time_before_get = now() 

305 res = api.GetPage(pages_pb2.GetPageReq(page_id=page_id)) 

306 assert res.title == "dummy title" 

307 assert res.content == "dummy content" 

308 assert res.address == "dummy address" 

309 assert res.location.lat == 1 

310 assert res.location.lng == 1 

311 assert res.slug == "dummy-title" 

312 assert time_before_create <= to_aware_datetime(res.created) <= time_before_get 

313 assert time_before_create <= to_aware_datetime(res.last_edited) <= time_before_get 

314 assert res.last_editor_user_id == user1.id 

315 assert res.creator_user_id == user1.id 

316 assert res.owner_user_id == user1.id 

317 assert not res.owner_community_id 

318 assert not res.owner_group_id 

319 assert res.editor_user_ids == [user1.id] 

320 assert not res.can_edit 

321 assert not res.can_moderate 

322 assert res.thread.thread_id > 0 

323 assert res.thread.num_responses == 0 

324 

325 

326def test_update_page(db): 

327 user, token = generate_user() 

328 with session_scope() as session: 

329 c_id = create_community(session, 0, 2, "Root node", [user], [], None).id 

330 

331 with pages_session(token) as api: 

332 time_before_create = now() 

333 page_id = api.CreatePlace( 

334 pages_pb2.CreatePlaceReq( 

335 title="dummy title", 

336 content="dummy content", 

337 address="dummy address", 

338 location=pages_pb2.Coordinate( 

339 lat=1, 

340 lng=1, 

341 ), 

342 ) 

343 ).page_id 

344 

345 time_before_update = now() 

346 api.UpdatePage( 

347 pages_pb2.UpdatePageReq( 

348 page_id=page_id, 

349 title=wrappers_pb2.StringValue(value="test title"), 

350 ) 

351 ) 

352 

353 time_before_get = now() 

354 res = api.GetPage(pages_pb2.GetPageReq(page_id=page_id)) 

355 assert res.title == "test title" 

356 assert res.content == "dummy content" 

357 assert res.address == "dummy address" 

358 assert res.location.lat == 1 

359 assert res.location.lng == 1 

360 assert res.slug == "test-title" 

361 assert time_before_create <= to_aware_datetime(res.created) <= time_before_update 

362 assert time_before_update <= to_aware_datetime(res.last_edited) <= time_before_get 

363 assert to_aware_datetime(res.created) <= to_aware_datetime(res.last_edited) 

364 assert res.last_editor_user_id == user.id 

365 assert res.creator_user_id == user.id 

366 assert res.owner_user_id == user.id 

367 assert not res.owner_community_id 

368 assert not res.owner_group_id 

369 assert res.editor_user_ids == [user.id] 

370 assert res.can_edit 

371 assert res.can_moderate 

372 

373 time_before_second_update = now() 

374 api.UpdatePage( 

375 pages_pb2.UpdatePageReq( 

376 page_id=page_id, 

377 content=wrappers_pb2.StringValue(value="test content"), 

378 ) 

379 ) 

380 

381 time_before_second_get = now() 

382 res = api.GetPage(pages_pb2.GetPageReq(page_id=page_id)) 

383 assert res.title == "test title" 

384 assert res.content == "test content" 

385 assert res.address == "dummy address" 

386 assert res.location.lat == 1 

387 assert res.location.lng == 1 

388 assert res.slug == "test-title" 

389 assert time_before_create <= to_aware_datetime(res.created) <= time_before_update 

390 assert time_before_second_update <= to_aware_datetime(res.last_edited) <= time_before_second_get 

391 assert to_aware_datetime(res.created) <= to_aware_datetime(res.last_edited) 

392 assert res.last_editor_user_id == user.id 

393 assert res.creator_user_id == user.id 

394 assert res.owner_user_id == user.id 

395 assert not res.owner_community_id 

396 assert not res.owner_group_id 

397 assert res.editor_user_ids == [user.id] 

398 assert res.can_edit 

399 assert res.can_moderate 

400 assert res.thread.thread_id > 0 

401 assert res.thread.num_responses == 0 

402 

403 time_before_third_update = now() 

404 api.UpdatePage( 

405 pages_pb2.UpdatePageReq( 

406 page_id=page_id, 

407 address=wrappers_pb2.StringValue(value="test address"), 

408 ) 

409 ) 

410 

411 time_before_third_get = now() 

412 res = api.GetPage(pages_pb2.GetPageReq(page_id=page_id)) 

413 assert res.title == "test title" 

414 assert res.content == "test content" 

415 assert res.address == "test address" 

416 assert res.location.lat == 1 

417 assert res.location.lng == 1 

418 assert res.slug == "test-title" 

419 assert time_before_create <= to_aware_datetime(res.created) <= time_before_update 

420 assert time_before_third_update <= to_aware_datetime(res.last_edited) <= time_before_third_get 

421 assert to_aware_datetime(res.created) <= to_aware_datetime(res.last_edited) 

422 assert res.last_editor_user_id == user.id 

423 assert res.creator_user_id == user.id 

424 assert res.owner_user_id == user.id 

425 assert not res.owner_community_id 

426 assert not res.owner_group_id 

427 assert res.editor_user_ids == [user.id] 

428 assert res.can_edit 

429 assert res.can_moderate 

430 assert res.thread.thread_id > 0 

431 assert res.thread.num_responses == 0 

432 

433 time_before_fourth_update = now() 

434 api.UpdatePage( 

435 pages_pb2.UpdatePageReq( 

436 page_id=page_id, 

437 location=pages_pb2.Coordinate( 

438 lat=3, 

439 lng=1.222, 

440 ), 

441 ) 

442 ) 

443 

444 time_before_fourth_get = now() 

445 res = api.GetPage(pages_pb2.GetPageReq(page_id=page_id)) 

446 assert res.title == "test title" 

447 assert res.content == "test content" 

448 assert res.address == "test address" 

449 assert res.location.lat == 3 

450 assert res.location.lng == 1.222 

451 assert res.slug == "test-title" 

452 assert time_before_create <= to_aware_datetime(res.created) <= time_before_update 

453 assert time_before_fourth_update <= to_aware_datetime(res.last_edited) <= time_before_fourth_get 

454 assert to_aware_datetime(res.created) <= to_aware_datetime(res.last_edited) 

455 assert res.last_editor_user_id == user.id 

456 assert res.creator_user_id == user.id 

457 assert res.owner_user_id == user.id 

458 assert not res.owner_community_id 

459 assert not res.owner_group_id 

460 assert res.editor_user_ids == [user.id] 

461 assert res.can_edit 

462 assert res.can_moderate 

463 assert res.thread.thread_id > 0 

464 assert res.thread.num_responses == 0 

465 

466 

467def test_owner_not_moderator(db): 

468 """ 

469 You can be the owner of content yet not have moderation rights 

470 """ 

471 user1, token1 = generate_user() 

472 user2, token2 = generate_user() 

473 with session_scope() as session: 

474 c_id = create_community(session, 0, 2, "Root node", [user1], [], None).id 

475 

476 # user2 makes page, is owner but not moderator, so can edit, not moderate 

477 with pages_session(token2) as api: 

478 res = api.CreatePlace( 

479 pages_pb2.CreatePlaceReq( 

480 title="dummy title", 

481 content="dummy content", 

482 address="dummy address", 

483 location=pages_pb2.Coordinate( 

484 lat=1, 

485 lng=1, 

486 ), 

487 ) 

488 ) 

489 assert res.title == "dummy title" 

490 assert res.content == "dummy content" 

491 assert res.address == "dummy address" 

492 assert res.location.lat == 1 

493 assert res.location.lng == 1 

494 assert res.slug == "dummy-title" 

495 assert res.last_editor_user_id == user2.id 

496 assert res.creator_user_id == user2.id 

497 assert res.owner_user_id == user2.id 

498 assert not res.owner_community_id 

499 assert not res.owner_group_id 

500 assert res.editor_user_ids == [user2.id] 

501 assert res.can_edit 

502 assert not res.can_moderate 

503 

504 page_id = res.page_id 

505 

506 # user1 is not owner so can't edit but can moderate 

507 with pages_session(token1) as api: 

508 res = api.GetPage(pages_pb2.GetPageReq(page_id=page_id)) 

509 assert res.title == "dummy title" 

510 assert res.content == "dummy content" 

511 assert res.address == "dummy address" 

512 assert res.location.lat == 1 

513 assert res.location.lng == 1 

514 assert res.slug == "dummy-title" 

515 assert res.last_editor_user_id == user2.id 

516 assert res.creator_user_id == user2.id 

517 assert res.owner_user_id == user2.id 

518 assert not res.owner_community_id 

519 assert not res.owner_group_id 

520 assert res.editor_user_ids == [user2.id] 

521 assert res.can_edit 

522 assert res.can_moderate 

523 assert res.thread.thread_id > 0 

524 assert res.thread.num_responses == 0 

525 

526 

527def test_update_page_errors(db): 

528 user, token = generate_user() 

529 with session_scope() as session: 

530 c_id = create_community(session, 0, 2, "Root node", [user], [], None).id 

531 

532 with pages_session(token) as api: 

533 page_id = api.CreatePlace( 

534 pages_pb2.CreatePlaceReq( 

535 title="dummy title", 

536 content="dummy content", 

537 address="dummy address", 

538 location=pages_pb2.Coordinate( 

539 lat=1, 

540 lng=1, 

541 ), 

542 ) 

543 ).page_id 

544 

545 with pytest.raises(grpc.RpcError) as e: 

546 api.UpdatePage( 

547 pages_pb2.UpdatePageReq( 

548 page_id=page_id, 

549 title=wrappers_pb2.StringValue(value=""), 

550 ) 

551 ) 

552 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

553 assert e.value.details() == "Missing page title." 

554 

555 with pytest.raises(grpc.RpcError) as e: 

556 api.UpdatePage( 

557 pages_pb2.UpdatePageReq( 

558 page_id=page_id, 

559 content=wrappers_pb2.StringValue(value=""), 

560 ) 

561 ) 

562 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

563 assert e.value.details() == "Missing page text." 

564 

565 with pytest.raises(grpc.RpcError) as e: 

566 api.UpdatePage( 

567 pages_pb2.UpdatePageReq( 

568 page_id=page_id, 

569 address=wrappers_pb2.StringValue(value=""), 

570 ) 

571 ) 

572 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

573 assert e.value.details() == "Missing page address." 

574 

575 

576def test_page_transfer(db): 

577 # transfers the pages 

578 user1, token1 = generate_user() 

579 # admin of the community/group 

580 user2, token2 = generate_user() 

581 # member of the community/group, shouldn't ever have edit access to anything 

582 user3, token3 = generate_user() 

583 with session_scope() as session: 

584 # create a community 

585 node = Node( 

586 geom=to_multi(create_polygon_lat_lng([[0, 0], [0, 2], [2, 2], [2, 0], [0, 0]])), node_type=NodeType.world 

587 ) 

588 session.add(node) 

589 session.flush() 

590 community_cluster = Cluster( 

591 name="Testing Community", 

592 description="Description for testing community", 

593 parent_node_id=node.id, 

594 is_official_cluster=True, 

595 ) 

596 session.add(community_cluster) 

597 session.flush() 

598 thread = Thread() 

599 session.add(thread) 

600 session.flush() 

601 main_page = Page( 

602 parent_node_id=community_cluster.parent_node_id, 

603 creator_user_id=user2.id, 

604 owner_cluster_id=community_cluster.id, 

605 type=PageType.main_page, 

606 thread_id=thread.id, 

607 ) 

608 session.add(main_page) 

609 session.flush() 

610 session.add( 

611 PageVersion( 

612 page_id=main_page.id, 

613 editor_user_id=user2.id, 

614 title="Main page for the testing community", 

615 content="Empty.", 

616 ) 

617 ) 

618 community_cluster.cluster_subscriptions.append( 

619 ClusterSubscription( 

620 user_id=user2.id, 

621 cluster_id=community_cluster.id, 

622 role=ClusterRole.admin, 

623 ) 

624 ) 

625 community_cluster.cluster_subscriptions.append( 

626 ClusterSubscription( 

627 user_id=user3.id, 

628 cluster_id=community_cluster.id, 

629 role=ClusterRole.member, 

630 ) 

631 ) 

632 

633 # create a group 

634 group_cluster = Cluster( 

635 name="Testing Group", 

636 description="Description for testing group", 

637 parent_node_id=node.id, 

638 ) 

639 session.add(group_cluster) 

640 session.flush() 

641 thread = Thread() 

642 session.add(thread) 

643 session.flush() 

644 main_page = Page( 

645 parent_node_id=group_cluster.parent_node_id, 

646 creator_user_id=user2.id, 

647 owner_cluster_id=group_cluster.id, 

648 type=PageType.main_page, 

649 thread_id=thread.id, 

650 ) 

651 session.add(main_page) 

652 session.flush() 

653 session.add( 

654 PageVersion( 

655 page_id=main_page.id, 

656 editor_user_id=user2.id, 

657 title="Main page for the testing community", 

658 content="Empty.", 

659 ) 

660 ) 

661 group_cluster.cluster_subscriptions.append( 

662 ClusterSubscription( 

663 user_id=user2.id, 

664 cluster_id=group_cluster.id, 

665 role=ClusterRole.admin, 

666 ) 

667 ) 

668 group_cluster.cluster_subscriptions.append( 

669 ClusterSubscription( 

670 user_id=user3.id, 

671 cluster_id=group_cluster.id, 

672 role=ClusterRole.member, 

673 ) 

674 ) 

675 session.flush() 

676 

677 community_id = node.id 

678 community_cluster_id = community_cluster.id 

679 group_id = group_cluster.id 

680 

681 with pages_session(token1) as api: 

682 create_page_req = pages_pb2.CreatePlaceReq( 

683 title="title", 

684 content="content", 

685 address="address", 

686 location=pages_pb2.Coordinate( 

687 lat=1, 

688 lng=1, 

689 ), 

690 ) 

691 

692 # transfer should work fine to a community 

693 page1 = api.CreatePlace(create_page_req) 

694 assert page1.owner_user_id == user1.id 

695 assert page1.can_edit 

696 assert not page1.can_moderate 

697 

698 with pages_session(token2) as api: 

699 assert api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_edit 

700 assert api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_moderate 

701 

702 with pages_session(token3) as api: 

703 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_edit 

704 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_moderate 

705 

706 with pages_session(token1) as api: 

707 page1 = api.TransferPage( 

708 pages_pb2.TransferPageReq( 

709 page_id=page1.page_id, 

710 new_owner_community_id=community_id, 

711 ) 

712 ) 

713 assert page1.owner_community_id == community_id 

714 assert not page1.can_edit 

715 assert not page1.can_moderate 

716 

717 with pages_session(token2) as api: 

718 assert api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_edit 

719 assert api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_moderate 

720 

721 with pages_session(token3) as api: 

722 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_edit 

723 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_moderate 

724 

725 with pages_session(token1) as api: 

726 # now we're no longer the owner, can't transfer 

727 page1 = api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)) 

728 with pytest.raises(grpc.RpcError) as e: 

729 api.TransferPage( 

730 pages_pb2.TransferPageReq( 

731 page_id=page1.page_id, 

732 new_owner_group_id=group_id, 

733 ) 

734 ) 

735 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

736 assert e.value.details() == "You're not allowed to transfer that page." 

737 page1 = api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)) 

738 assert page1.owner_community_id == community_id 

739 assert not page1.can_edit 

740 assert not page1.can_moderate 

741 

742 with pages_session(token2) as api: 

743 assert api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_edit 

744 assert api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_moderate 

745 

746 with pages_session(token3) as api: 

747 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_edit 

748 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page1.page_id)).can_moderate 

749 

750 with pages_session(token1) as api: 

751 # try a new page, just for fun 

752 page2 = api.CreatePlace(create_page_req) 

753 assert page2.owner_user_id == user1.id 

754 

755 page2 = api.TransferPage( 

756 pages_pb2.TransferPageReq( 

757 page_id=page2.page_id, 

758 new_owner_community_id=community_id, 

759 ) 

760 ) 

761 assert page2.owner_community_id == community_id 

762 

763 with pages_session(token2) as api: 

764 assert api.GetPage(pages_pb2.GetPageReq(page_id=page2.page_id)).can_edit 

765 assert api.GetPage(pages_pb2.GetPageReq(page_id=page2.page_id)).can_moderate 

766 

767 with pages_session(token3) as api: 

768 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page2.page_id)).can_edit 

769 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page2.page_id)).can_moderate 

770 

771 with pages_session(token1) as api: 

772 # can't transfer a page to an official cluster, only through community 

773 page3 = api.CreatePlace(create_page_req) 

774 assert page3.owner_user_id == user1.id 

775 

776 with pytest.raises(grpc.RpcError) as e: 

777 api.TransferPage( 

778 pages_pb2.TransferPageReq( 

779 page_id=page3.page_id, 

780 new_owner_community_id=community_cluster_id, 

781 ) 

782 ) 

783 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

784 assert e.value.details() == "Group or community not found." 

785 page3 = api.GetPage(pages_pb2.GetPageReq(page_id=page3.page_id)) 

786 assert page3.owner_user_id == user1.id 

787 

788 # can transfer to group 

789 page4 = api.CreatePlace(create_page_req) 

790 assert page4.owner_user_id == user1.id 

791 assert page4.can_edit 

792 assert not page4.can_moderate 

793 

794 with pages_session(token2) as api: 

795 assert api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)).can_edit 

796 assert api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)).can_moderate 

797 

798 with pages_session(token3) as api: 

799 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)).can_edit 

800 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)).can_moderate 

801 

802 with pages_session(token1) as api: 

803 page4 = api.TransferPage( 

804 pages_pb2.TransferPageReq( 

805 page_id=page4.page_id, 

806 new_owner_group_id=group_id, 

807 ) 

808 ) 

809 assert page4.owner_group_id == group_id 

810 assert not page4.can_edit 

811 assert not page4.can_moderate 

812 

813 with pages_session(token2) as api: 

814 assert api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)).can_edit 

815 assert api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)).can_moderate 

816 

817 with pages_session(token3) as api: 

818 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)).can_edit 

819 assert not api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)).can_moderate 

820 

821 with pages_session(token1) as api: 

822 # now we're no longer the owner, can't transfer 

823 with pytest.raises(grpc.RpcError) as e: 

824 api.TransferPage( 

825 pages_pb2.TransferPageReq( 

826 page_id=page4.page_id, 

827 new_owner_community_id=community_id, 

828 ) 

829 ) 

830 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

831 assert e.value.details() == "You're not allowed to transfer that page." 

832 page4 = api.GetPage(pages_pb2.GetPageReq(page_id=page4.page_id)) 

833 assert page4.owner_group_id == group_id 

834 

835 

836def test_page_photo(db): 

837 user, token = generate_user() 

838 with session_scope() as session: 

839 c_id = create_community(session, 0, 2, "Root node", [user], [], None).id 

840 

841 with pages_session(token) as api: 

842 key1 = random_hex(32) 

843 filename1 = random_hex(32) 

844 

845 with session_scope() as session: 

846 session.add( 

847 Upload( 

848 key=key1, 

849 filename=filename1, 

850 creator_user_id=user.id, 

851 ) 

852 ) 

853 

854 res = api.CreatePlace( 

855 pages_pb2.CreatePlaceReq( 

856 title="dummy title", 

857 content="dummy content", 

858 photo_key=key1, 

859 address="dummy address", 

860 location=pages_pb2.Coordinate( 

861 lat=1, 

862 lng=1, 

863 ), 

864 ) 

865 ) 

866 

867 assert filename1 in res.photo_url 

868 

869 # can't create with non-existent photo 

870 with pytest.raises(grpc.RpcError) as e: 

871 api.CreatePlace( 

872 pages_pb2.CreatePlaceReq( 

873 title="dummy title", 

874 content="dummy content", 

875 photo_key="nonexisten", 

876 address="dummy address", 

877 location=pages_pb2.Coordinate( 

878 lat=1, 

879 lng=1, 

880 ), 

881 ) 

882 ) 

883 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

884 assert e.value.details() == "Photo not found." 

885 

886 # can create page with no photo 

887 res = api.CreatePlace( 

888 pages_pb2.CreatePlaceReq( 

889 title="dummy title", 

890 content="dummy content", 

891 address="dummy address", 

892 location=pages_pb2.Coordinate( 

893 lat=1, 

894 lng=1, 

895 ), 

896 ) 

897 ) 

898 

899 assert res.photo_url == "" 

900 

901 page_id = res.page_id 

902 

903 # can't set it to non-existent stuff 

904 with pytest.raises(grpc.RpcError) as e: 

905 api.UpdatePage( 

906 pages_pb2.UpdatePageReq( 

907 page_id=page_id, 

908 photo_key=wrappers_pb2.StringValue(value="non-existent id"), 

909 ) 

910 ) 

911 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

912 assert e.value.details() == "Photo not found." 

913 

914 key2 = random_hex(32) 

915 filename2 = random_hex(32) 

916 

917 with session_scope() as session: 

918 session.add( 

919 Upload( 

920 key=key2, 

921 filename=filename2, 

922 creator_user_id=user.id, 

923 ) 

924 ) 

925 

926 res = api.UpdatePage( 

927 pages_pb2.UpdatePageReq( 

928 page_id=page_id, 

929 photo_key=wrappers_pb2.StringValue(value=key2), 

930 ) 

931 ) 

932 

933 assert filename2 in res.photo_url 

934 

935 # can unset it 

936 

937 res = api.UpdatePage( 

938 pages_pb2.UpdatePageReq( 

939 page_id=page_id, 

940 photo_key=wrappers_pb2.StringValue(value=""), 

941 ) 

942 ) 

943 

944 assert res.photo_url == "" 

945 

946 

947def test_list_user_places(db): 

948 user1, token1 = generate_user() 

949 with session_scope() as session: 

950 c_id = create_community(session, 0, 2, "Root node", [user1], [], None).id 

951 

952 with pages_session(token1) as api: 

953 place1_id = api.CreatePlace( 

954 pages_pb2.CreatePlaceReq( 

955 title="dummy title", 

956 content="dummy content", 

957 address="dummy address", 

958 location=pages_pb2.Coordinate( 

959 lat=1, 

960 lng=1, 

961 ), 

962 ) 

963 ).page_id 

964 

965 place2_id = api.CreatePlace( 

966 pages_pb2.CreatePlaceReq( 

967 title="dummy title 2", 

968 content="dummy content 2", 

969 address="dummy address 2", 

970 location=pages_pb2.Coordinate( 

971 lat=1, 

972 lng=1, 

973 ), 

974 ) 

975 ).page_id 

976 

977 with pages_session(token1) as api: 

978 res = api.ListUserPlaces(pages_pb2.ListUserPlacesReq()) 

979 assert [p.page_id for p in res.places] == [place1_id, place2_id] 

980 

981 

982def test_list_other_user_places(db): 

983 user1, token1 = generate_user() 

984 user2, token2 = generate_user() 

985 with session_scope() as session: 

986 c_id = create_community(session, 0, 2, "Root node", [user1], [], None).id 

987 

988 with pages_session(token1) as api: 

989 place1_id = api.CreatePlace( 

990 pages_pb2.CreatePlaceReq( 

991 title="dummy title", 

992 content="dummy content", 

993 address="dummy address", 

994 location=pages_pb2.Coordinate( 

995 lat=1, 

996 lng=1, 

997 ), 

998 ) 

999 ).page_id 

1000 

1001 place2_id = api.CreatePlace( 

1002 pages_pb2.CreatePlaceReq( 

1003 title="dummy title 2", 

1004 content="dummy content 2", 

1005 address="dummy address 2", 

1006 location=pages_pb2.Coordinate( 

1007 lat=1, 

1008 lng=1, 

1009 ), 

1010 ) 

1011 ).page_id 

1012 

1013 with pages_session(token2) as api: 

1014 res = api.ListUserPlaces(pages_pb2.ListUserPlacesReq(user_id=user1.id)) 

1015 assert [p.page_id for p in res.places] == [place1_id, place2_id] 

1016 

1017 

1018def test_list_user_guides(db): 

1019 user1, token1 = generate_user() 

1020 with session_scope() as session: 

1021 c_id = create_community(session, 0, 2, "Root node", [user1], [], None).id 

1022 

1023 with pages_session(token1) as api: 

1024 guide1_id = api.CreateGuide( 

1025 pages_pb2.CreateGuideReq( 

1026 title="dummy title", 

1027 content="dummy content", 

1028 address="dummy address", 

1029 location=pages_pb2.Coordinate( 

1030 lat=1, 

1031 lng=1, 

1032 ), 

1033 parent_community_id=c_id, 

1034 ) 

1035 ).page_id 

1036 

1037 guide2_id = api.CreateGuide( 

1038 pages_pb2.CreateGuideReq( 

1039 title="dummy title 2", 

1040 content="dummy content 2", 

1041 address="dummy address 2", 

1042 location=pages_pb2.Coordinate( 

1043 lat=1, 

1044 lng=1, 

1045 ), 

1046 parent_community_id=c_id, 

1047 ) 

1048 ).page_id 

1049 

1050 with pages_session(token1) as api: 

1051 res = api.ListUserGuides(pages_pb2.ListUserGuidesReq()) 

1052 assert [p.page_id for p in res.guides] == [guide1_id, guide2_id] 

1053 

1054 

1055def test_list_other_user_guides(db): 

1056 user1, token1 = generate_user() 

1057 user2, token2 = generate_user() 

1058 with session_scope() as session: 

1059 c_id = create_community(session, 0, 2, "Root node", [user1], [], None).id 

1060 

1061 with pages_session(token1) as api: 

1062 guide1_id = api.CreateGuide( 

1063 pages_pb2.CreateGuideReq( 

1064 title="dummy title", 

1065 content="dummy content", 

1066 address="dummy address", 

1067 location=pages_pb2.Coordinate( 

1068 lat=1, 

1069 lng=1, 

1070 ), 

1071 parent_community_id=c_id, 

1072 ) 

1073 ).page_id 

1074 

1075 guide2_id = api.CreateGuide( 

1076 pages_pb2.CreateGuideReq( 

1077 title="dummy title 2", 

1078 content="dummy content 2", 

1079 address="dummy address 2", 

1080 location=pages_pb2.Coordinate( 

1081 lat=1, 

1082 lng=1, 

1083 ), 

1084 parent_community_id=c_id, 

1085 ) 

1086 ).page_id 

1087 

1088 with pages_session(token2) as api: 

1089 res = api.ListUserGuides(pages_pb2.ListUserGuidesReq(user_id=user1.id)) 

1090 assert [p.page_id for p in res.guides] == [guide1_id, guide2_id]