File: test_response.py

package info (click to toggle)
flask-security 5.6.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,420 kB
  • sloc: python: 23,164; javascript: 204; makefile: 138
file content (158 lines) | stat: -rw-r--r-- 5,167 bytes parent folder | download | duplicates (2)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
"""
test_response
~~~~~~~~~~~~~~~~~

Tests for validating default and plugable responses.

:copyright: (c) 2019-2020 by J. Christopher Wagner (jwag).
:license: MIT, see LICENSE for more details.
"""

import pytest

from flask import jsonify

from tests.test_utils import authenticate


def test_render_json(app, client):
    @app.security.render_json
    def my_json(payload, code, headers=None, user=None):
        return jsonify(dict(myresponse=payload, code=code))

    response = client.get(
        "/login", data={}, headers={"Content-Type": "application/json"}
    )
    assert "myresponse" in response.json
    assert response.json["code"] == 200


def _my_json(payload, code, headers=None, user=None):
    return jsonify(dict(myresponse=payload, code=code))


def test_render_json2(app, client):
    app.extensions["security"].render_json(_my_json)
    response = client.get(
        "/login", data={}, headers={"Content-Type": "application/json"}
    )
    assert "myresponse" in response.json
    assert response.json["code"] == 200


def test_render_json_logout(app, client):
    app.extensions["security"].render_json(_my_json)
    response = client.post("/logout", headers={"Content-Type": "application/json"})
    assert "myresponse" in response.json
    assert response.json["code"] == 200


def test_default_unauthn(app, client):
    """Test default unauthn handler with and without json"""

    response = client.get("/profile")
    assert response.status_code == 302
    assert response.location == "/login?next=/profile"

    response = client.get("/profile", headers={"Accept": "application/json"})
    assert response.status_code == 401
    assert response.json["meta"]["code"] == 401
    # While "Basic" is acceptable, we never get a WWW-Authenticate header back since
    # most browsers intercept it.
    assert "WWW-Authenticate" not in response.headers


@pytest.mark.settings(login_url="/mylogin", url_prefix="/myprefix")
def test_default_unauthn_bp(app, client):
    """Test default unauthn handler with blueprint prefix and login url"""

    response = client.get("/profile")
    assert response.status_code == 302
    assert response.location == "/myprefix/mylogin?next=/profile"


def test_default_unauthn_myjson(app, client):
    """Make sure render_json gets called for unauthn errors"""

    @app.security.render_json
    def my_json(payload, code, headers=None, user=None):
        return jsonify(dict(myresponse=payload, code=code)), code, headers

    response = client.get("/multi_auth", headers={"Accept": "application/json"})
    assert response.status_code == 401
    assert response.json["code"] == 401
    assert "myresponse" in response.json


def test_my_unauthn_handler(app, client):
    @app.security.unauthn_handler
    def my_unauthn(mechanisms, headers=None):
        return app.security._render_json({"mechanisms": mechanisms}, 401, headers, None)

    response = client.get("/multi_auth", headers={"Accept": "application/json"})
    assert response.status_code == 401
    assert all(
        m in response.json["response"]["mechanisms"]
        for m in ["session", "token", "basic"]
    )


def test_default_unauthz(app, client):
    """Test default unauthz handler with and without json"""
    authenticate(client, "joe@lp.com", "password")

    response = client.get("/admin")
    # This is the result of abort(403) since there is no UNAUTHORIZED_VIEW
    assert response.status_code == 403

    response = client.get("/admin", headers={"Accept": "application/json"})
    assert response.status_code == 403
    assert response.json["meta"]["code"] == 403


def test_default_unauthz_myjson(app, client):
    """Make sure render_json gets called for unauthn errors"""

    @app.security.render_json
    def my_json(payload, code, headers=None, user=None):
        return jsonify(dict(myresponse=payload, code=code)), code, headers

    authenticate(client, "joe@lp.com", "password")

    response = client.get("/admin", headers={"Accept": "application/json"})
    assert response.status_code == 403
    assert response.json["code"] == 403


def test_my_unauthz_handler(app, client):
    @app.security.unauthz_handler
    def my_unauthz(func_name, params):
        return (
            jsonify(dict(myresponse={"func": func_name, "params": params}, code=403)),
            403,
        )

    authenticate(client, "joe@lp.com", "password")

    response = client.get("/admin", headers={"Accept": "application/json"})
    assert response.status_code == 403
    assert response.json["code"] == 403
    assert response.json["myresponse"]["func"] == "roles_required"
    assert response.json["myresponse"]["params"] == ["admin"]


def test_my_unauthz_handler_exc(app, client):
    """Verify that can use exceptions in unauthz handler"""

    @app.security.unauthz_handler
    def my_unauthz(func, params):
        raise ValueError("Bad Value")

    @app.errorhandler(ValueError)
    def error_handler(ex):
        return jsonify(dict(code=403)), 403

    authenticate(client, "joe@lp.com", "password")

    response = client.get("/admin", headers={"Accept": "application/json"})
    assert response.status_code == 403