Skip to content

Commit aba8233

Browse files
authored
Merge pull request #140 from jagerman/subreq-exception-handling
Properly handle subrequest exceptions
2 parents 279c022 + fd1977e commit aba8233

File tree

6 files changed

+69
-68
lines changed

6 files changed

+69
-68
lines changed

sogs/model/exc.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
from ..web import app
2-
from .. import http
3-
import flask
4-
5-
61
class NotFound(LookupError):
72
"""Base class for NoSuchRoom, NoSuchFile, etc."""
83

@@ -84,24 +79,3 @@ class PostRateLimited(PostRejected):
8479

8580
def __init__(self, msg=None):
8681
super().__init__("Rate limited" if msg is None else msg)
87-
88-
89-
# Map uncaught model exceptions into flask http exceptions
90-
@app.errorhandler(NotFound)
91-
def abort_bad_room(e):
92-
flask.abort(http.NOT_FOUND)
93-
94-
95-
@app.errorhandler(BadPermission)
96-
def abort_perm_denied(e):
97-
flask.abort(http.FORBIDDEN)
98-
99-
100-
@app.errorhandler(PostRejected)
101-
def abort_post_rejected(e):
102-
flask.abort(http.TOO_MANY_REQUESTS)
103-
104-
105-
@app.errorhandler(InvalidData)
106-
def abort_invalid_data(e):
107-
flask.abort(http.BAD_REQUEST)

sogs/routes/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from ..web import app
2+
23
from .legacy import legacy as legacy_endpoints
34
from .general import general as general_endpoints
45
from .onion_request import onion_request as onion_request_endpoints
@@ -8,6 +9,8 @@
89
from .dm import dm as dm_endpoints
910
from .views import views as views_endpoints
1011

12+
from . import exc # noqa: F401
13+
1114
app.register_blueprint(dm_endpoints)
1215
app.register_blueprint(rooms_endpoints)
1316
app.register_blueprint(messages_endpoints)

sogs/routes/exc.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from ..web import app
2+
from .. import http
3+
from ..model import exc
4+
5+
6+
# Map uncaught model exceptions into flask http exceptions
7+
@app.errorhandler(exc.NotFound)
8+
def abort_bad_room(e):
9+
return str(e), http.NOT_FOUND
10+
11+
12+
@app.errorhandler(exc.BadPermission)
13+
def abort_perm_denied(e):
14+
return str(e), http.FORBIDDEN
15+
16+
17+
@app.errorhandler(exc.PostRejected)
18+
def abort_post_rejected(e):
19+
return str(e), http.TOO_MANY_REQUESTS
20+
21+
22+
@app.errorhandler(exc.InvalidData)
23+
def abort_invalid_data(e):
24+
return str(e), http.BAD_REQUEST

sogs/routes/subrequest.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ def make_subrequest(
9595
app.logger.debug(f"Initiating sub-request for {method} {path}")
9696
g.user_reauth = user_reauth
9797
with app.request_context(subreq_env):
98-
response = app.full_dispatch_request()
98+
try:
99+
response = app.full_dispatch_request()
100+
except Exception as e:
101+
response = app.make_response(app.handle_exception(e))
99102
if response.status_code >= 400:
100103
app.logger.warning(
101104
f"Sub-request for {method} {path} returned status {response.status_code}"

tests/test_room_routes.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import pytest
21
import time
32
from sogs.model.room import Room
43
from sogs.model.file import File
54
from sogs import utils, crypto
65
import sogs.config
7-
import werkzeug.exceptions as wexc
86
from util import pad64, from_now, config_override
97
from auth import x_sogs
108
from request import sogs_get, sogs_post, sogs_put, sogs_post_raw, sogs_delete
@@ -854,8 +852,8 @@ def room_json():
854852
assert room_json()['info_updates'] == 1
855853

856854
url = "/room/test-room/pin/3"
857-
with pytest.raises(wexc.Forbidden):
858-
r = sogs_post(client, url, {}, user)
855+
r = sogs_post(client, url, {}, user)
856+
assert r.status_code == 403
859857

860858
assert room_json()['info_updates'] == 1
861859

@@ -965,8 +963,8 @@ def test_whisper_to(client, room, user, user2, mod, global_mod):
965963
p = {"data": d, "signature": s, "whisper_to": user2.session_id}
966964

967965
# Regular users can't post whispers:
968-
with pytest.raises(wexc.Forbidden):
969-
r = sogs_post(client, url_post, p, user)
966+
r = sogs_post(client, url_post, p, user)
967+
assert r.status_code == 403
970968

971969
r = sogs_post(client, url_post, p, mod)
972970
assert r.status_code == 201
@@ -1013,8 +1011,8 @@ def test_whisper_mods(client, room, user, user2, mod, global_mod, admin):
10131011
p = {"data": d, "signature": s, "whisper_mods": True}
10141012

10151013
# Regular users can't post mod whispers:
1016-
with pytest.raises(wexc.Forbidden):
1017-
r = sogs_post(client, url_post, p, user)
1014+
r = sogs_post(client, url_post, p, user)
1015+
assert r.status_code == 403
10181016

10191017
r = sogs_post(client, url_post, p, mod)
10201018
assert r.status_code == 201
@@ -1066,9 +1064,9 @@ def test_whisper_both(client, room, user, user2, mod, admin):
10661064
}
10671065

10681066
# Regular users can't post mod whispers:
1069-
with pytest.raises(wexc.Forbidden):
1070-
p = {"data": d, "signature": s, "whisper_mods": True, "whisper_to": mod.session_id}
1071-
r = sogs_post(client, url_post, p, user)
1067+
p = {"data": d, "signature": s, "whisper_mods": True, "whisper_to": mod.session_id}
1068+
r = sogs_post(client, url_post, p, user)
1069+
assert r.status_code == 403
10721070

10731071
d, s = (utils.encode_base64(x) for x in (b"I'm going to scare this guy", pad64("sig2")))
10741072
r = sogs_post(client, url_post, {"data": d, "signature": s, "whisper_mods": True}, mod)
@@ -1165,8 +1163,8 @@ def test_edits(client, room, user, user2, mod, global_admin):
11651163

11661164
# Make sure someone else (even super admin) can't edit our message:
11671165
d, s = (utils.encode_base64(x) for x in (b"post 1no", pad64("sig 1no")))
1168-
with pytest.raises(wexc.Forbidden):
1169-
r = sogs_put(client, url_edit, {"data": d, "signature": s}, global_admin)
1166+
r = sogs_put(client, url_edit, {"data": d, "signature": s}, global_admin)
1167+
assert r.status_code == 403
11701168

11711169
r = sogs_get(client, url_get, user)
11721170
assert filter_timestamps(r.json) == filter_timestamps([p1])
@@ -1260,8 +1258,8 @@ def test_remove_self_message(client, room, user):
12601258

12611259
def test_remove_message_not_allowed(client, room, user, user2):
12621260
id = _make_dummy_post(room, user)
1263-
with pytest.raises(wexc.Forbidden):
1264-
sogs_delete(client, f'/room/{room.token}/message/{id}', user2)
1261+
r = sogs_delete(client, f'/room/{room.token}/message/{id}', user2)
1262+
assert r.status_code == 403
12651263

12661264

12671265
def test_remove_post_non_existing(client, room, user, mod):
@@ -1297,17 +1295,17 @@ def test_remove_all_posts_from_room_not_allowed(client, room, user, user2, no_ra
12971295
for _ in range(256):
12981296
_make_dummy_post(room, user)
12991297
assert len(room.get_messages_for(user, recent=True)) == 256
1300-
with pytest.raises(wexc.Forbidden):
1301-
sogs_delete(client, f'/room/{room.token}/all/{user.session_id}', user2)
1298+
r = sogs_delete(client, f'/room/{room.token}/all/{user.session_id}', user2)
1299+
assert r.status_code == 403
13021300
assert len(room.get_messages_for(user, recent=True)) == 256
13031301
assert room.check_unbanned(user) and room.check_unbanned(user2)
13041302

13051303

13061304
def test_remove_all_posts_from_room_not_allowed_for_user(client, room, mod, user, no_rate_limit):
13071305
for _ in range(256):
13081306
_make_dummy_post(room, mod)
1309-
with pytest.raises(wexc.Forbidden):
1310-
sogs_delete(client, f'/room/{room.token}/all/{mod.session_id}', user)
1307+
r = sogs_delete(client, f'/room/{room.token}/all/{mod.session_id}', user)
1308+
assert r.status_code == 403
13111309
assert len(room.get_messages_for(user, recent=True)) == 256
13121310
assert room.check_unbanned(user) and room.check_unbanned(mod)
13131311

tests/test_user_routes.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import pytest
21
from sogs import db, utils
3-
import werkzeug.exceptions as wexc
42
from request import sogs_get, sogs_post
53
from util import pad64
64
import time
@@ -553,8 +551,8 @@ def test_bans(client, room, room2, user, user2, mod, global_mod):
553551
r = sogs_post(client, url_ban, {'rooms': ['test-room']}, mod)
554552
assert r.status_code == 200
555553

556-
with pytest.raises(wexc.Forbidden):
557-
sogs_post(client, "/room/test-room/message", post, user)
554+
r = sogs_post(client, "/room/test-room/message", post, user)
555+
assert r.status_code == 403
558556

559557
r = sogs_post(client, "/room/test-room/message", post, user2)
560558
assert r.status_code == 201
@@ -570,11 +568,11 @@ def test_bans(client, room, room2, user, user2, mod, global_mod):
570568
r = sogs_post(client, url_ban, {'rooms': ['*']}, global_mod)
571569
assert r.status_code == 200
572570

573-
with pytest.raises(wexc.Forbidden):
574-
sogs_post(client, "/room/test-room/message", post, user)
571+
r = sogs_post(client, "/room/test-room/message", post, user)
572+
assert r.status_code == 403
575573

576-
with pytest.raises(wexc.Forbidden):
577-
sogs_post(client, "/room/room2/message", post, user)
574+
r = sogs_post(client, "/room/room2/message", post, user)
575+
assert r.status_code == 403
578576

579577
r = sogs_post(client, "/room/test-room/message", post, user2)
580578
assert r.status_code == 201
@@ -583,8 +581,8 @@ def test_bans(client, room, room2, user, user2, mod, global_mod):
583581

584582
r = sogs_post(client, "/room/test-room/message", post, user)
585583
assert r.status_code == 201
586-
with pytest.raises(wexc.Forbidden):
587-
r = sogs_post(client, "/room/room2/message", post, user)
584+
r = sogs_post(client, "/room/room2/message", post, user)
585+
assert r.status_code == 403
588586

589587
r = sogs_post(client, url_unban, {'rooms': ['*']}, global_mod)
590588

@@ -641,11 +639,11 @@ def test_ban_timeouts(client, room, room2, user, mod, global_mod):
641639
r = sogs_post(client, url_ban, {'rooms': ['*'], 'timeout': 0.001}, global_mod)
642640
assert r.status_code == 200
643641

644-
with pytest.raises(wexc.Forbidden):
645-
sogs_post(client, "/room/test-room/message", post, user)
642+
r = sogs_post(client, "/room/test-room/message", post, user)
643+
assert r.status_code == 403
646644

647-
with pytest.raises(wexc.Forbidden):
648-
sogs_post(client, "/room/room2/message", post, user)
645+
r = sogs_post(client, "/room/room2/message", post, user)
646+
assert r.status_code == 403
649647

650648
from sogs.cleanup import cleanup
651649

@@ -660,17 +658,18 @@ def test_ban_timeouts(client, room, room2, user, mod, global_mod):
660658
r = sogs_post(client, url_ban, {'rooms': ['*'], 'timeout': 30}, mod)
661659
assert r.status_code == 200
662660

663-
with pytest.raises(wexc.Forbidden):
664-
sogs_post(client, "/room/test-room/message", post, user)
661+
r = sogs_post(client, "/room/test-room/message", post, user)
662+
assert r.status_code == 403
665663

666664
r = sogs_post(client, "/room/room2/message", post, user)
667665
assert r.status_code == 201
668666

669667
# The timed ban shouldn't expire yet:
670668
assert cleanup() == (0, 0, 0, 0, 0)
671669

672-
with pytest.raises(wexc.Forbidden):
673-
sogs_post(client, "/room/test-room/message", post, user)
670+
r = sogs_post(client, "/room/test-room/message", post, user)
671+
assert r.status_code == 403
672+
674673
r = sogs_post(client, "/room/room2/message", post, user)
675674
assert r.status_code == 201
676675

@@ -683,8 +682,8 @@ def test_ban_timeouts(client, room, room2, user, mod, global_mod):
683682
r = sogs_post(client, url_ban, {'rooms': ['*'], 'timeout': 0.001}, mod)
684683
assert r.status_code == 200
685684

686-
with pytest.raises(wexc.Forbidden):
687-
sogs_post(client, "/room/test-room/message", post, user)
685+
r = sogs_post(client, "/room/test-room/message", post, user)
686+
assert r.status_code == 403
688687

689688
time.sleep(0.002)
690689
assert cleanup() == (0, 0, 0, 1, 0)
@@ -717,8 +716,8 @@ def test_ban_timeouts(client, room, room2, user, mod, global_mod):
717716

718717
assert cleanup() == (0, 0, 0, 0, 0)
719718

720-
with pytest.raises(wexc.Forbidden):
721-
sogs_post(client, "/room/test-room/message", post, user)
719+
r = sogs_post(client, "/room/test-room/message", post, user)
720+
assert r.status_code == 403
722721

723722
# Unbanning should remove the ban future
724723
assert sogs_post(client, url_unban, {'rooms': ['*']}, mod).status_code == 200

0 commit comments

Comments
 (0)