Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: DIA-1959: remove jwt token ff #7143

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions label_studio/jwt_auth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ class TokenAuthenticationPhaseout(TokenAuthentication):

def authenticate(self, request):
"""Authenticate the request and log if successful."""
from core.feature_flags import flag_set

auth_result = super().authenticate(request)
JWT_ACCESS_TOKEN_ENABLED = flag_set('fflag__feature_develop__prompts__dia_1829_jwt_token_auth')
if JWT_ACCESS_TOKEN_ENABLED and (auth_result is not None):
if auth_result is not None:
user, _ = auth_result
org = user.active_organization
org_id = org.id if org else None
Expand Down
6 changes: 1 addition & 5 deletions label_studio/jwt_auth/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,14 @@ def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
from core.feature_flags import flag_set
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import AuthenticationFailed, InvalidToken, TokenError

try:
user_and_token = JWTAuthentication().authenticate(request)
if user_and_token:
user = User.objects.get(pk=user_and_token[0].pk)
JWT_ACCESS_TOKEN_ENABLED = flag_set(
'fflag__feature_develop__prompts__dia_1829_jwt_token_auth', user=user
)
if JWT_ACCESS_TOKEN_ENABLED and user.active_organization.jwt.api_tokens_enabled:
if user.active_organization.jwt.api_tokens_enabled:
request.user = user
request.is_jwt = True
except User.DoesNotExist:
Expand Down
14 changes: 5 additions & 9 deletions label_studio/organizations/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,15 @@


def create_organization(title, created_by, **kwargs):
from core.feature_flags import flag_set

JWT_ACCESS_TOKEN_ENABLED = flag_set('fflag__feature_develop__prompts__dia_1829_jwt_token_auth')

with transaction.atomic():
org = Organization.objects.create(title=title, created_by=created_by, **kwargs)
OrganizationMember.objects.create(user=created_by, organization=org)
if JWT_ACCESS_TOKEN_ENABLED:
# set auth tokens to new system for new users
org.jwt.api_tokens_enabled = True
org.jwt.legacy_api_tokens_enabled = False
org.jwt.save()
return org
# set auth tokens to new system for new users
org.jwt.api_tokens_enabled = True
org.jwt.legacy_api_tokens_enabled = False
org.jwt.save()
return org


def destroy_organization(org):
Expand Down
4 changes: 0 additions & 4 deletions label_studio/tests/jwt_auth/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient

from ..utils import mock_feature_flag
from .utils import create_user_with_token_settings


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_logging_when_legacy_token_auth_enabled(caplog):
user = create_user_with_token_settings(api_tokens_enabled=False, legacy_api_tokens_enabled=True)
Expand All @@ -29,7 +27,6 @@ def test_logging_when_legacy_token_auth_enabled(caplog):
assert record.endpoint == '/api/projects/'


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_no_logging_when_legacy_token_auth_disabled(caplog):
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand All @@ -44,7 +41,6 @@ def test_no_logging_when_legacy_token_auth_disabled(caplog):
assert len(basic_auth_logs) == 0


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_legacy_api_token_disabled_user_cannot_use_legacy_token():
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand Down
9 changes: 0 additions & 9 deletions label_studio/tests/jwt_auth/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,16 @@
from rest_framework.test import APIClient
from users.models import User

from ..utils import mock_feature_flag
from .utils import create_user_with_token_settings


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_request_without_auth_header_returns_401():
client = APIClient()
response = client.get('/api/projects/')
assert response.status_code == status.HTTP_401_UNAUTHORIZED


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_request_with_invalid_token_returns_401():
client = APIClient()
Expand All @@ -27,7 +24,6 @@ def test_request_with_invalid_token_returns_401():
assert response.status_code == status.HTTP_401_UNAUTHORIZED


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_request_with_valid_token_returns_authenticated_user():
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand All @@ -41,7 +37,6 @@ def test_request_with_valid_token_returns_authenticated_user():
assert response.wsgi_request.user == user


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_jwt_token_auth_disabled_user_cannot_use_jwt_token():
user = create_user_with_token_settings(api_tokens_enabled=False, legacy_api_tokens_enabled=True)
Expand All @@ -53,7 +48,6 @@ def test_jwt_token_auth_disabled_user_cannot_use_jwt_token():
assert response.status_code == status.HTTP_401_UNAUTHORIZED


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_user_with_both_auth_enabled_can_use_both_methods():
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=True)
Expand All @@ -78,7 +72,6 @@ def test_user_with_both_auth_enabled_can_use_both_methods():
assert response.wsgi_request.user == user


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_user_with_no_auth_enabled_cannot_use_either_method():
user = create_user_with_token_settings(api_tokens_enabled=False, legacy_api_tokens_enabled=False)
Expand All @@ -101,7 +94,6 @@ def test_user_with_no_auth_enabled_cannot_use_either_method():
assert response.status_code == status.HTTP_401_UNAUTHORIZED


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_jwt_token_invalid_after_user_deleted():
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand All @@ -119,7 +111,6 @@ def test_jwt_token_invalid_after_user_deleted():
assert response.status_code == status.HTTP_401_UNAUTHORIZED


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_user_with_default_auth_settings_can_use_jwt_but_not_legacy_token():
# Create user and org with default settings from create_organization
Expand Down
7 changes: 0 additions & 7 deletions label_studio/tests/jwt_auth/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
from rest_framework_simplejwt.settings import api_settings as simple_jwt_settings
from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken, OutstandingToken

from ..utils import mock_feature_flag
from .utils import create_user_with_token_settings


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_jwt_settings_permissions():
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand All @@ -28,7 +26,6 @@ def test_jwt_settings_permissions():
assert org.jwt.has_permission(user) is False


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.fixture
def token_backend():
return LSTokenBackend(
Expand All @@ -43,7 +40,6 @@ def token_backend():
)


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
def test_encode_returns_only_header_and_payload(token_backend):
payload = {
'user_id': 123,
Expand All @@ -59,7 +55,6 @@ def test_encode_returns_only_header_and_payload(token_backend):
assert all(part.replace('-', '+').replace('_', '/') for part in parts)


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
def test_encode_full_returns_complete_jwt(token_backend):
payload = {
'user_id': 123,
Expand All @@ -74,7 +69,6 @@ def test_encode_full_returns_complete_jwt(token_backend):
assert all(part.replace('-', '+').replace('_', '/') for part in parts)


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
def test_encode_vs_encode_full_comparison(token_backend):
payload = {
'user_id': 123,
Expand All @@ -87,7 +81,6 @@ def test_encode_vs_encode_full_comparison(token_backend):
assert full_token.startswith(partial_token)


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_token_lifecycle():
"""Test full token lifecycle including creation, access token generation, blacklisting, and validation"""
Expand Down
6 changes: 0 additions & 6 deletions label_studio/tests/jwt_auth/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
from rest_framework.test import APIClient
from rest_framework_simplejwt.exceptions import TokenError
from tests.jwt_auth.utils import create_user_with_token_settings
from tests.utils import mock_feature_flag


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_blacklist_view_returns_404_with_already_blacklisted_token(client):
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand All @@ -20,7 +18,6 @@ def test_blacklist_view_returns_404_with_already_blacklisted_token(client):
assert response.status_code == status.HTTP_404_NOT_FOUND


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_blacklist_view_returns_204_with_valid_token(client):
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand All @@ -34,7 +31,6 @@ def test_blacklist_view_returns_204_with_valid_token(client):
token.check_blacklist()


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_create_token_when_no_existing_token():
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand All @@ -49,7 +45,6 @@ def test_create_token_when_no_existing_token():
assert 'token' in response.data


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_create_token_when_existing_valid_token():
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand All @@ -69,7 +64,6 @@ def test_create_token_when_existing_valid_token():
assert 'You already have a valid token' in response.data['detail']


@mock_feature_flag(flag_name='fflag__feature_develop__prompts__dia_1829_jwt_token_auth', value=True)
@pytest.mark.django_db
def test_create_token_after_blacklisting_previous():
user = create_user_with_token_settings(api_tokens_enabled=True, legacy_api_tokens_enabled=False)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Space } from "../../../components/Space/Space";
import { useAPI } from "../../../providers/ApiProvider";
import { useConfig } from "../../../providers/ConfigProvider";
import { Block, Elem } from "../../../utils/bem";
import { FF_AUTH_TOKENS, FF_LSDV_E_297, isFF } from "../../../utils/feature-flags";
import { FF_LSDV_E_297, isFF } from "../../../utils/feature-flags";
import { copyText } from "../../../utils/helpers";
import "./PeopleInvitation.scss";
import { PeopleList } from "./PeopleList";
Expand Down Expand Up @@ -157,7 +157,9 @@ export const PeoplePage = () => {
<Space />

<Space>
{isFF(FF_AUTH_TOKENS) && <Button onClick={showApiTokenSettingsModal}>API Tokens Settings</Button>}
<Button onClick={showApiTokenSettingsModal}>
API Tokens Settings
</Button>
<Button icon={<LsPlus />} primary onClick={showInvitationModal}>
Add People
</Button>
Expand Down
10 changes: 6 additions & 4 deletions web/apps/labelstudio/src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { ProjectsPage } from "./Projects/Projects";
import { OrganizationPage } from "./Organization";
import { ModelsPage } from "./Organization/Models/ModelsPage";
import { AccountSettingsPage } from "@humansignal/core";
import { FF_AUTH_TOKENS, isFF } from "../utils/feature-flags";

export const Pages = [ProjectsPage, OrganizationPage, ModelsPage, isFF(FF_AUTH_TOKENS) && AccountSettingsPage].filter(
Boolean,
);
export const Pages = [
ProjectsPage,
OrganizationPage,
ModelsPage,
AccountSettingsPage,
].filter(Boolean);
3 changes: 0 additions & 3 deletions web/libs/core/src/lib/utils/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,10 @@ export const FF_UNSAVED_CHANGES = "fflag_feat_front_leap_1198_unsaved_changes_18
/**
* Enables JWT tokens
*/
export const FF_AUTH_TOKENS = "fflag__feature_develop__prompts__dia_1829_jwt_token_auth";

export function isFF(id: string) {
// TODO: remove the override + if statement once LSE and LSO start building react the same way and fflag_fix_front_lsdv_4620_memory_leaks_100723_short is removed
const override: Record<string, boolean> = {
fflag_fix_front_lsdv_4620_memory_leaks_100723_short: false,
// [FF_AUTH_TOKENS]: false,
};
if (window?.APP_SETTINGS?.sentry_environment === "opensource" && id in override) {
return override[id];
Expand Down
18 changes: 8 additions & 10 deletions web/libs/core/src/pages/AccountSettings/sections/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type React from "react";
import { PersonalJWTToken } from "./PersonalJWTToken";
import "./index.raw.css";
import type { AuthTokenSettings } from "../types";
import { FF_AUTH_TOKENS, isFF } from "@humansignal/core/lib/utils/feature-flags";

type SectionType = {
title: string;
Expand All @@ -32,16 +31,15 @@ export const accountSettingsSections = (settings: AuthTokenSettings): SectionTyp
id: "membership-info",
component: MembershipInfo,
},
settings.api_tokens_enabled &&
isFF(FF_AUTH_TOKENS) && {
title: "Personal Access Token",
id: "personal-access-token",
// component: PersonalAccessToken,
component: PersonalJWTToken,
description: PersonalAccessTokenDescription,
},
settings.api_tokens_enabled && {
title: "Personal Access Token",
id: "personal-access-token",
// component: PersonalAccessToken,
component: PersonalJWTToken,
description: PersonalAccessTokenDescription,
},
settings.legacy_api_tokens_enabled && {
title: isFF(FF_AUTH_TOKENS) ? "Legacy Token" : "Access Token",
title: "Legacy Token",
id: "personal-access-token",
// component: PersonalAccessToken,
component: PersonalAccessToken,
Expand Down
Loading