File size: 10,179 Bytes
81e3673
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
"""
Admin Authorization Security Tests

Tests cover:
- Super admin role requirement for administrative endpoints
- Standard user access denial to admin endpoints
- WebSocket management authorization
- Rating sync authorization
- Conflict management authorization
"""
import pytest
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session

from tests.factories.user_factory import UserFactory
from tests.security.conftest import create_test_token


class TestWebSocketManagementAuthorization:
    """Test WebSocket management endpoint authorization."""

    def test_websocket_status_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that websocket status endpoint requires super_admin role."""
        # Create a standard member user
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        # Try to access websocket status as standard user
        response = client.get(
            "/api/admin/websocket/status",
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied with 403
        assert response.status_code == 403
        # Check that response contains permission/super_admin related error
        error_detail = response.json()
        if isinstance(error_detail, dict):
            detail = error_detail.get("detail", "")
            assert "super_admin" in str(detail).lower() or "permission" in str(detail).lower()

    def test_websocket_disable_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that websocket disable endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.post(
            "/api/admin/websocket/disable",
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403

    def test_websocket_enable_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that websocket enable endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.post(
            "/api/admin/websocket/enable",
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403

    def test_websocket_reconnect_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that websocket reconnect endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.post(
            "/api/admin/websocket/reconnect",
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403


class TestRatingSyncAuthorization:
    """Test rating sync endpoint authorization."""

    def test_trigger_rating_sync_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that rating sync endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.post(
            "/api/admin/sync/ratings",
            json={"upload_all": False},
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403

    def test_get_failed_rating_uploads_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that failed uploads endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.get(
            "/api/admin/ratings/failed-uploads",
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403

    def test_retry_failed_rating_upload_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that retry upload endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.post(
            "/api/admin/ratings/failed-uploads/test-id/retry",
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403


class TestConflictManagementAuthorization:
    """Test conflict management endpoint authorization."""

    def test_list_conflicts_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that list conflicts endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.get(
            "/api/admin/conflicts",
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403

    def test_get_conflict_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that get conflict endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.get(
            "/api/admin/conflicts/1",
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403

    def test_resolve_conflict_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that resolve conflict endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.post(
            "/api/admin/conflicts/1/resolve",
            json={
                "strategy": "remote_wins",
                "resolved_by": "admin@example.com"
            },
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403

    def test_bulk_resolve_conflicts_requires_super_admin(self, client: TestClient, db_session: Session):
        """Test that bulk resolve conflicts endpoint requires super_admin role."""
        standard_user = UserFactory(
            email="standard@test.com",
            role="member",
            _session=db_session
        )

        response = client.post(
            "/api/admin/conflicts/bulk-resolve",
            json={
                "conflict_ids": [1, 2, 3],
                "strategy": "remote_wins",
                "resolved_by": "admin@example.com"
            },
            headers={"Authorization": f"Bearer {create_test_token(standard_user.id)}"}
        )

        # Should be denied
        assert response.status_code == 403


class TestAdminAuthorizationBypassAttempts:
    """Test that various user roles cannot bypass admin authorization."""

    @pytest.mark.parametrize("role", ["member", "admin", "viewer", "editor"])
    def test_non_super_admin_roles_denied_websocket_access(self, client: TestClient, db_session: Session, role: str):
        """Test that all non-super_admin roles are denied access to websocket endpoints."""
        # Create user with different role
        user = UserFactory(
            email=f"{role}@test.com",
            role=role,
            _session=db_session
        )

        response = client.get(
            "/api/admin/websocket/status",
            headers={"Authorization": f"Bearer {create_test_token(user.id)}"}
        )

        # Should be denied for all non-super_admin roles
        assert response.status_code == 403

    @pytest.mark.parametrize("role", ["member", "admin", "viewer", "editor"])
    def test_non_super_admin_roles_denied_conflict_access(self, client: TestClient, db_session: Session, role: str):
        """Test that all non-super_admin roles are denied access to conflict endpoints."""
        user = UserFactory(
            email=f"{role}@test.com",
            role=role,
            _session=db_session
        )

        response = client.get(
            "/api/admin/conflicts",
            headers={"Authorization": f"Bearer {create_test_token(user.id)}"}
        )

        # Should be denied for all non-super_admin roles
        assert response.status_code == 403


class TestUnauthenticatedAccess:
    """Test that unauthenticated requests are denied."""

    def test_websocket_status_requires_authentication(self, client: TestClient):
        """Test that websocket status endpoint requires authentication."""
        response = client.get("/api/admin/websocket/status")
        assert response.status_code in [401, 403]

    def test_conflict_list_requires_authentication(self, client: TestClient):
        """Test that conflict list endpoint requires authentication."""
        response = client.get("/api/admin/conflicts")
        assert response.status_code in [401, 403]

    def test_rating_sync_requires_authentication(self, client: TestClient):
        """Test that rating sync endpoint requires authentication."""
        response = client.post("/api/admin/sync/ratings", json={})
        assert response.status_code in [401, 403]