API - update OAuth2 scopes
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from fittrackee.users.models import User
|
||||
@ -897,3 +898,40 @@ class TestGetRecords(ApiTestCaseMixin):
|
||||
response = client.get('/api/records')
|
||||
|
||||
self.assert_401(response)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1_admin: User,
|
||||
user_2: User,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1_admin, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
'/api/records',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from fittrackee import db
|
||||
@ -138,6 +139,43 @@ class TestGetSports(ApiTestCaseMixin):
|
||||
sport_2_running.serialize(is_admin=True)
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
sport_1_cycling: Sport,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
'/api/sports',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestGetSport(ApiTestCaseMixin):
|
||||
def test_it_gets_a_sport(
|
||||
@ -241,6 +279,43 @@ class TestGetSport(ApiTestCaseMixin):
|
||||
sport_1_cycling_inactive.serialize(is_admin=True)
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
sport_1_cycling: Sport,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
f'/api/sports/{sport_1_cycling.id}',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestUpdateSport(ApiTestCaseMixin):
|
||||
def test_it_disables_a_sport(
|
||||
@ -442,3 +517,41 @@ class TestUpdateSport(ApiTestCaseMixin):
|
||||
|
||||
data = self.assert_404(response)
|
||||
assert len(data['data']['sports']) == 0
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', False),
|
||||
('workouts:write', True),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1_admin: User,
|
||||
user_2: User,
|
||||
sport_1_cycling: Sport,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1_admin, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.patch(
|
||||
f'/api/sports/{sport_1_cycling.id}',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from fittrackee.users.models import User
|
||||
@ -862,6 +863,42 @@ class TestGetStatsByTime(ApiTestCaseMixin):
|
||||
}
|
||||
}
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
f'/api/stats/{user_1.username}/by_time',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestGetStatsBySport(ApiTestCaseMixin):
|
||||
def test_it_returns_error_if_user_is_not_authenticated(
|
||||
@ -1007,6 +1044,42 @@ class TestGetStatsBySport(ApiTestCaseMixin):
|
||||
|
||||
self.assert_500(response)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
f'/api/stats/{user_1.username}/by_sport',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestGetAllStats(ApiTestCaseMixin):
|
||||
def test_it_returns_error_if_user_is_not_authenticated(
|
||||
@ -1089,3 +1162,39 @@ class TestGetAllStats(ApiTestCaseMixin):
|
||||
)
|
||||
|
||||
self.assert_403(response)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1_admin: User,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1_admin, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
'/api/stats/all',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
@ -3,6 +3,7 @@ from typing import List
|
||||
from unittest.mock import patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from fittrackee.users.models import User
|
||||
@ -101,6 +102,42 @@ class TestGetWorkouts(ApiTestCaseMixin):
|
||||
|
||||
self.assert_401(response, 'provide a valid auth token')
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
'/api/workouts',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestGetWorkoutsWithPagination(ApiTestCaseMixin):
|
||||
def test_it_gets_workouts_with_default_pagination(
|
||||
@ -1158,6 +1195,55 @@ class TestGetWorkout(ApiTestCaseMixin):
|
||||
|
||||
self.assert_404_with_message(response, 'Map does not exist')
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
'endpoint',
|
||||
[
|
||||
'/api/workouts/{workout_short_id}',
|
||||
'/api/workouts/{workout_short_id}/gpx',
|
||||
'/api/workouts/{workout_short_id}/chart_data',
|
||||
'/api/workouts/{workout_short_id}/gpx/segment/1',
|
||||
'/api/workouts/{workout_short_id}/chart_data/segment/1',
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
sport_1_cycling: Sport,
|
||||
workout_cycling_user_1: Workout,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
endpoint: str,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
endpoint.format(workout_short_id=workout_cycling_user_1.short_id),
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestDownloadWorkoutGpx(ApiTestCaseMixin):
|
||||
def test_it_returns_404_if_workout_does_not_exist(
|
||||
@ -1242,3 +1328,41 @@ class TestDownloadWorkoutGpx(ApiTestCaseMixin):
|
||||
mimetype='application/gpx+xml',
|
||||
as_attachment=True,
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', True),
|
||||
('workouts:write', False),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
sport_1_cycling: Sport,
|
||||
workout_cycling_user_1: Workout,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
f'/api/workouts/{workout_cycling_user_1.short_id}/gpx/download',
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
@ -621,6 +621,45 @@ class TestPostWorkoutWithGpx(ApiTestCaseMixin, CallArgsMixin):
|
||||
)
|
||||
assert 'data' not in data
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', False),
|
||||
('workouts:write', True),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.post(
|
||||
'/api/workouts',
|
||||
data=dict(),
|
||||
headers=dict(
|
||||
content_type='multipart/form-data',
|
||||
Authorization=f'Bearer {access_token}',
|
||||
),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestPostWorkoutWithoutGpx(ApiTestCaseMixin):
|
||||
def test_it_returns_error_if_user_is_not_authenticated(
|
||||
@ -763,6 +802,45 @@ class TestPostWorkoutWithoutGpx(ApiTestCaseMixin):
|
||||
assert len(data['data']['workouts'][0]['segments']) == 0
|
||||
assert len(data['data']['workouts'][0]['records']) == 0
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', False),
|
||||
('workouts:write', True),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.post(
|
||||
'/api/workouts/no_gpx',
|
||||
data=dict(),
|
||||
headers=dict(
|
||||
content_type='multipart/form-data',
|
||||
Authorization=f'Bearer {access_token}',
|
||||
),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestPostWorkoutWithZipArchive(ApiTestCaseMixin):
|
||||
def test_it_adds_workouts_with_zip_archive(
|
||||
|
@ -221,6 +221,45 @@ class TestEditWorkoutWithGpx(ApiTestCaseMixin):
|
||||
|
||||
self.assert_500(response)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', False),
|
||||
('workouts:write', True),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
sport_1_cycling: Sport,
|
||||
workout_cycling_user_1: Workout,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.patch(
|
||||
f'/api/workouts/{workout_cycling_user_1.short_id}',
|
||||
data=dict(),
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestEditWorkoutWithoutGpx(ApiTestCaseMixin):
|
||||
def test_it_updates_a_workout_wo_gpx(
|
||||
|
@ -1,5 +1,6 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from fittrackee.files import get_absolute_file_path
|
||||
@ -80,6 +81,45 @@ class TestDeleteWorkoutWithGpx(ApiTestCaseMixin):
|
||||
|
||||
self.assert_500(response)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'client_scope, can_access',
|
||||
[
|
||||
('application:write', False),
|
||||
('profile:read', False),
|
||||
('profile:write', False),
|
||||
('users:read', False),
|
||||
('users:write', False),
|
||||
('workouts:read', False),
|
||||
('workouts:write', True),
|
||||
],
|
||||
)
|
||||
def test_expected_scopes_are_defined(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
sport_1_cycling: Sport,
|
||||
workout_cycling_user_1: Workout,
|
||||
client_scope: str,
|
||||
can_access: bool,
|
||||
) -> None:
|
||||
(
|
||||
client,
|
||||
oauth_client,
|
||||
access_token,
|
||||
_,
|
||||
) = self.create_oauth_client_and_issue_token(
|
||||
app, user_1, scope=client_scope
|
||||
)
|
||||
|
||||
response = client.delete(
|
||||
f'/api/workouts/{workout_cycling_user_1.short_id}',
|
||||
data=dict(),
|
||||
content_type='application/json',
|
||||
headers=dict(Authorization=f'Bearer {access_token}'),
|
||||
)
|
||||
|
||||
self.assert_response_scope(response, can_access)
|
||||
|
||||
|
||||
class TestDeleteWorkoutWithoutGpx(ApiTestCaseMixin):
|
||||
def test_it_deletes_a_workout_wo_gpx(
|
||||
|
Reference in New Issue
Block a user