init commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
from importlib.metadata import PackageNotFoundError, version
|
||||
|
||||
try:
|
||||
__version__ = version("djangorestframework_simplejwt")
|
||||
except PackageNotFoundError:
|
||||
# package is not installed
|
||||
__version__ = None
|
||||
@@ -0,0 +1,180 @@
|
||||
from typing import Optional, TypeVar
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AbstractBaseUser
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import HTTP_HEADER_ENCODING, authentication
|
||||
from rest_framework.request import Request
|
||||
|
||||
from .exceptions import AuthenticationFailed, InvalidToken, TokenError
|
||||
from .models import TokenUser
|
||||
from .settings import api_settings
|
||||
from .tokens import Token
|
||||
from .utils import get_md5_hash_password
|
||||
|
||||
AUTH_HEADER_TYPES = api_settings.AUTH_HEADER_TYPES
|
||||
|
||||
if not isinstance(api_settings.AUTH_HEADER_TYPES, (list, tuple)):
|
||||
AUTH_HEADER_TYPES = (AUTH_HEADER_TYPES,)
|
||||
|
||||
AUTH_HEADER_TYPE_BYTES: set[bytes] = {
|
||||
h.encode(HTTP_HEADER_ENCODING) for h in AUTH_HEADER_TYPES
|
||||
}
|
||||
|
||||
AuthUser = TypeVar("AuthUser", AbstractBaseUser, TokenUser)
|
||||
|
||||
|
||||
class JWTAuthentication(authentication.BaseAuthentication):
|
||||
"""
|
||||
An authentication plugin that authenticates requests through a JSON web
|
||||
token provided in a request header.
|
||||
"""
|
||||
|
||||
www_authenticate_realm = "api"
|
||||
media_type = "application/json"
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self.user_model = get_user_model()
|
||||
|
||||
def authenticate(self, request: Request) -> Optional[tuple[AuthUser, Token]]:
|
||||
header = self.get_header(request)
|
||||
if header is None:
|
||||
return None
|
||||
|
||||
raw_token = self.get_raw_token(header)
|
||||
if raw_token is None:
|
||||
return None
|
||||
|
||||
validated_token = self.get_validated_token(raw_token)
|
||||
|
||||
return self.get_user(validated_token), validated_token
|
||||
|
||||
def authenticate_header(self, request: Request) -> str:
|
||||
return '{} realm="{}"'.format(
|
||||
AUTH_HEADER_TYPES[0],
|
||||
self.www_authenticate_realm,
|
||||
)
|
||||
|
||||
def get_header(self, request: Request) -> bytes:
|
||||
"""
|
||||
Extracts the header containing the JSON web token from the given
|
||||
request.
|
||||
"""
|
||||
header = request.META.get(api_settings.AUTH_HEADER_NAME)
|
||||
|
||||
if isinstance(header, str):
|
||||
# Work around django test client oddness
|
||||
header = header.encode(HTTP_HEADER_ENCODING)
|
||||
|
||||
return header
|
||||
|
||||
def get_raw_token(self, header: bytes) -> Optional[bytes]:
|
||||
"""
|
||||
Extracts an unvalidated JSON web token from the given "Authorization"
|
||||
header value.
|
||||
"""
|
||||
parts = header.split()
|
||||
|
||||
if len(parts) == 0:
|
||||
# Empty AUTHORIZATION header sent
|
||||
return None
|
||||
|
||||
if parts[0] not in AUTH_HEADER_TYPE_BYTES:
|
||||
# Assume the header does not contain a JSON web token
|
||||
return None
|
||||
|
||||
if len(parts) != 2:
|
||||
raise AuthenticationFailed(
|
||||
_("Authorization header must contain two space-delimited values"),
|
||||
code="bad_authorization_header",
|
||||
)
|
||||
|
||||
return parts[1]
|
||||
|
||||
def get_validated_token(self, raw_token: bytes) -> Token:
|
||||
"""
|
||||
Validates an encoded JSON web token and returns a validated token
|
||||
wrapper object.
|
||||
"""
|
||||
messages = []
|
||||
for AuthToken in api_settings.AUTH_TOKEN_CLASSES:
|
||||
try:
|
||||
return AuthToken(raw_token)
|
||||
except TokenError as e:
|
||||
messages.append(
|
||||
{
|
||||
"token_class": AuthToken.__name__,
|
||||
"token_type": AuthToken.token_type,
|
||||
"message": e.args[0],
|
||||
}
|
||||
)
|
||||
|
||||
raise InvalidToken(
|
||||
{
|
||||
"detail": _("Given token not valid for any token type"),
|
||||
"messages": messages,
|
||||
}
|
||||
)
|
||||
|
||||
def get_user(self, validated_token: Token) -> AuthUser:
|
||||
"""
|
||||
Attempts to find and return a user using the given validated token.
|
||||
"""
|
||||
try:
|
||||
user_id = validated_token[api_settings.USER_ID_CLAIM]
|
||||
except KeyError:
|
||||
raise InvalidToken(_("Token contained no recognizable user identification"))
|
||||
|
||||
try:
|
||||
user = self.user_model.objects.get(**{api_settings.USER_ID_FIELD: user_id})
|
||||
except self.user_model.DoesNotExist:
|
||||
raise AuthenticationFailed(_("User not found"), code="user_not_found")
|
||||
|
||||
if api_settings.CHECK_USER_IS_ACTIVE and not user.is_active:
|
||||
raise AuthenticationFailed(_("User is inactive"), code="user_inactive")
|
||||
|
||||
if api_settings.CHECK_REVOKE_TOKEN:
|
||||
if validated_token.get(
|
||||
api_settings.REVOKE_TOKEN_CLAIM
|
||||
) != get_md5_hash_password(user.password):
|
||||
raise AuthenticationFailed(
|
||||
_("The user's password has been changed."), code="password_changed"
|
||||
)
|
||||
|
||||
return user
|
||||
|
||||
|
||||
class JWTStatelessUserAuthentication(JWTAuthentication):
|
||||
"""
|
||||
An authentication plugin that authenticates requests through a JSON web
|
||||
token provided in a request header without performing a database lookup to obtain a user instance.
|
||||
"""
|
||||
|
||||
def get_user(self, validated_token: Token) -> AuthUser:
|
||||
"""
|
||||
Returns a stateless user object which is backed by the given validated
|
||||
token.
|
||||
"""
|
||||
if api_settings.USER_ID_CLAIM not in validated_token:
|
||||
# The TokenUser class assumes tokens will have a recognizable user
|
||||
# identifier claim.
|
||||
raise InvalidToken(_("Token contained no recognizable user identification"))
|
||||
|
||||
return api_settings.TOKEN_USER_CLASS(validated_token)
|
||||
|
||||
|
||||
JWTTokenUserAuthentication = JWTStatelessUserAuthentication
|
||||
|
||||
|
||||
def default_user_authentication_rule(user: AuthUser) -> bool:
|
||||
# Prior to Django 1.10, inactive users could be authenticated with the
|
||||
# default `ModelBackend`. As of Django 1.10, the `ModelBackend`
|
||||
# prevents inactive users from authenticating. App designers can still
|
||||
# allow inactive users to authenticate by opting for the new
|
||||
# `AllowAllUsersModelBackend`. However, we explicitly prevent inactive
|
||||
# users from authenticating to enforce a reasonable policy and provide
|
||||
# sensible backwards compatibility with older Django versions.
|
||||
return user is not None and (
|
||||
not api_settings.CHECK_USER_IS_ACTIVE or user.is_active
|
||||
)
|
||||
@@ -0,0 +1,177 @@
|
||||
import json
|
||||
from collections.abc import Iterable
|
||||
from datetime import timedelta
|
||||
from functools import cached_property
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import jwt
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from jwt import (
|
||||
ExpiredSignatureError,
|
||||
InvalidAlgorithmError,
|
||||
InvalidTokenError,
|
||||
algorithms,
|
||||
)
|
||||
|
||||
from .exceptions import TokenBackendError, TokenBackendExpiredToken
|
||||
from .tokens import Token
|
||||
from .utils import format_lazy
|
||||
|
||||
try:
|
||||
from jwt import PyJWKClient, PyJWKClientError
|
||||
|
||||
JWK_CLIENT_AVAILABLE = True
|
||||
except ImportError:
|
||||
JWK_CLIENT_AVAILABLE = False
|
||||
|
||||
ALLOWED_ALGORITHMS = {
|
||||
"HS256",
|
||||
"HS384",
|
||||
"HS512",
|
||||
"RS256",
|
||||
"RS384",
|
||||
"RS512",
|
||||
"ES256",
|
||||
"ES384",
|
||||
"ES512",
|
||||
}.union(algorithms.requires_cryptography)
|
||||
|
||||
|
||||
class TokenBackend:
|
||||
def __init__(
|
||||
self,
|
||||
algorithm: str,
|
||||
signing_key: Optional[str] = None,
|
||||
verifying_key: str = "",
|
||||
audience: Union[str, Iterable, None] = None,
|
||||
issuer: Optional[str] = None,
|
||||
jwk_url: Optional[str] = None,
|
||||
leeway: Union[float, int, timedelta, None] = None,
|
||||
json_encoder: Optional[type[json.JSONEncoder]] = None,
|
||||
) -> None:
|
||||
self._validate_algorithm(algorithm)
|
||||
|
||||
self.algorithm = algorithm
|
||||
self.signing_key = signing_key
|
||||
self.verifying_key = verifying_key
|
||||
self.audience = audience
|
||||
self.issuer = issuer
|
||||
|
||||
if JWK_CLIENT_AVAILABLE:
|
||||
self.jwks_client = PyJWKClient(jwk_url) if jwk_url else None
|
||||
else:
|
||||
self.jwks_client = None
|
||||
|
||||
self.leeway = leeway
|
||||
self.json_encoder = json_encoder
|
||||
|
||||
@cached_property
|
||||
def prepared_signing_key(self) -> Any:
|
||||
return self._prepare_key(self.signing_key)
|
||||
|
||||
@cached_property
|
||||
def prepared_verifying_key(self) -> Any:
|
||||
return self._prepare_key(self.verifying_key)
|
||||
|
||||
def _prepare_key(self, key: Optional[str]) -> Any:
|
||||
# Support for PyJWT 1.7.1 or empty signing key
|
||||
if key is None or not getattr(jwt.PyJWS, "get_algorithm_by_name", None):
|
||||
return key
|
||||
jws_alg = jwt.PyJWS().get_algorithm_by_name(self.algorithm)
|
||||
return jws_alg.prepare_key(key)
|
||||
|
||||
def _validate_algorithm(self, algorithm: str) -> None:
|
||||
"""
|
||||
Ensure that the nominated algorithm is recognized, and that cryptography is installed for those
|
||||
algorithms that require it
|
||||
"""
|
||||
if algorithm not in ALLOWED_ALGORITHMS:
|
||||
raise TokenBackendError(
|
||||
format_lazy(_("Unrecognized algorithm type '{}'"), algorithm)
|
||||
)
|
||||
|
||||
if algorithm in algorithms.requires_cryptography and not algorithms.has_crypto:
|
||||
raise TokenBackendError(
|
||||
format_lazy(
|
||||
_("You must have cryptography installed to use {}."), algorithm
|
||||
)
|
||||
)
|
||||
|
||||
def get_leeway(self) -> timedelta:
|
||||
if self.leeway is None:
|
||||
return timedelta(seconds=0)
|
||||
elif isinstance(self.leeway, (int, float)):
|
||||
return timedelta(seconds=self.leeway)
|
||||
elif isinstance(self.leeway, timedelta):
|
||||
return self.leeway
|
||||
else:
|
||||
raise TokenBackendError(
|
||||
format_lazy(
|
||||
_(
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
),
|
||||
type(self.leeway),
|
||||
)
|
||||
)
|
||||
|
||||
def get_verifying_key(self, token: Token) -> Any:
|
||||
if self.algorithm.startswith("HS"):
|
||||
return self.prepared_signing_key
|
||||
|
||||
if self.jwks_client:
|
||||
try:
|
||||
return self.jwks_client.get_signing_key_from_jwt(token).key
|
||||
except PyJWKClientError as ex:
|
||||
raise TokenBackendError(_("Token is invalid")) from ex
|
||||
|
||||
return self.prepared_verifying_key
|
||||
|
||||
def encode(self, payload: dict[str, Any]) -> str:
|
||||
"""
|
||||
Returns an encoded token for the given payload dictionary.
|
||||
"""
|
||||
jwt_payload = payload.copy()
|
||||
if self.audience is not None:
|
||||
jwt_payload["aud"] = self.audience
|
||||
if self.issuer is not None:
|
||||
jwt_payload["iss"] = self.issuer
|
||||
|
||||
token = jwt.encode(
|
||||
jwt_payload,
|
||||
self.prepared_signing_key,
|
||||
algorithm=self.algorithm,
|
||||
json_encoder=self.json_encoder,
|
||||
)
|
||||
if isinstance(token, bytes):
|
||||
# For PyJWT <= 1.7.1
|
||||
return token.decode("utf-8")
|
||||
# For PyJWT >= 2.0.0a1
|
||||
return token
|
||||
|
||||
def decode(self, token: Token, verify: bool = True) -> dict[str, Any]:
|
||||
"""
|
||||
Performs a validation of the given token and returns its payload
|
||||
dictionary.
|
||||
|
||||
Raises a `TokenBackendError` if the token is malformed, if its
|
||||
signature check fails, or if its 'exp' claim indicates it has expired.
|
||||
"""
|
||||
try:
|
||||
return jwt.decode(
|
||||
token,
|
||||
self.get_verifying_key(token),
|
||||
algorithms=[self.algorithm],
|
||||
audience=self.audience,
|
||||
issuer=self.issuer,
|
||||
leeway=self.get_leeway(),
|
||||
options={
|
||||
"verify_aud": self.audience is not None,
|
||||
"verify_signature": verify,
|
||||
},
|
||||
)
|
||||
except InvalidAlgorithmError as ex:
|
||||
raise TokenBackendError(_("Invalid algorithm specified")) from ex
|
||||
except ExpiredSignatureError as ex:
|
||||
raise TokenBackendExpiredToken(_("Token is expired")) from ex
|
||||
except InvalidTokenError as ex:
|
||||
raise TokenBackendError(_("Token is invalid")) from ex
|
||||
@@ -0,0 +1,56 @@
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import exceptions, status
|
||||
|
||||
|
||||
class TokenError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ExpiredTokenError(TokenError):
|
||||
pass
|
||||
|
||||
|
||||
class TokenBackendError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TokenBackendExpiredToken(TokenBackendError):
|
||||
pass
|
||||
|
||||
|
||||
class DetailDictMixin:
|
||||
default_detail: str
|
||||
default_code: str
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
detail: Union[dict[str, Any], str, None] = None,
|
||||
code: Optional[str] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Builds a detail dictionary for the error to give more information to API
|
||||
users.
|
||||
"""
|
||||
detail_dict = {"detail": self.default_detail, "code": self.default_code}
|
||||
|
||||
if isinstance(detail, dict):
|
||||
detail_dict.update(detail)
|
||||
elif detail is not None:
|
||||
detail_dict["detail"] = detail
|
||||
|
||||
if code is not None:
|
||||
detail_dict["code"] = code
|
||||
|
||||
super().__init__(detail_dict) # type: ignore
|
||||
|
||||
|
||||
class AuthenticationFailed(DetailDictMixin, exceptions.AuthenticationFailed):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidToken(AuthenticationFailed):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
default_detail = _("Token is invalid or expired")
|
||||
default_code = "token_not_valid"
|
||||
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <info@lukasrod.cz>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-20 17:30+0100\n"
|
||||
"Last-Translator: Ahmed Jazzar <me@ahmedjazzar.com>\n"
|
||||
"Language: ar\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
|
||||
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "يجب أن يحتوي رأس التفويض على قيمتين مفصولتين بمسافات"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "تأشيرة المرور غير صالحة لأي نوع من أنواع التأشيرات"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "لا تحتوي تأشيرة المرور على هوية مستخدم يمكن التعرف عليها"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "لم يتم العثور على المستخدم"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "الحساب غير مفعل"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "نوع الخوارزمية غير معروف '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "يجب أن يكون لديك تشفير مثبت لاستخدام {}."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
"نوع غير معروف '{}'. يجب أن تكون 'leeway' عددًا صحيحًا أو عددًا نسبيًا أو فرق وقت."
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "تأشيرة المرور غير صالحة أو منتهية الصلاحية"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "تم تحديد خوارزمية غير صالحة"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "تأشيرة المرور غير صالحة أو منتهية الصلاحية"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "تأشيرة المرور غير صالحة أو منتهية الصلاحية"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "لم يتم العثور على حساب نشط للبيانات المقدمة"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "لم يتم العثور على حساب نشط للبيانات المقدمة"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"تمت إزالة الإعداد '{}'. يرجى الرجوع إلى '{}' للتعرف على الإعدادات المتاحة."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "المستخدم"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "أنشئت في"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "تنتهي في"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "قائمة تأشيرات المرور السوداء"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "لا يمكن إنشاء تأشيرة مرور بدون نوع أو عمر"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "التأشيرة ليس لها معرف"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "التأشيرة ليس لها نوع"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "التأشيرة لها نوع خاطئ"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "التأشيرة ليس لديها مطالبة '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "انتهى عمر المطالبة بالتأشيرة '{}'"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "التأشيرة مدرجة في القائمة السوداء"
|
||||
Binary file not shown.
@@ -0,0 +1,133 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <info@lukasrod.cz>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"Last-Translator: Lukáš Rod <info@lukasrod.cz>\n"
|
||||
"Language: cs\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "Autorizační hlavička musí obsahovat dvě hodnoty oddělené mezerou"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Daný token není validní pro žádný typ tokenu"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Token neobsahoval žádnou rozpoznatelnou identifikaci uživatele"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Uživatel nenalezen"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Uživatel není aktivní"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Nerozpoznaný typ algoritmu '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Token není validní nebo vypršela jeho platnost"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Token není validní nebo vypršela jeho platnost"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Token není validní nebo vypršela jeho platnost"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Žádný aktivní účet s danými údaji nebyl nalezen"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Žádný aktivní účet s danými údaji nebyl nalezen"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr "Nastavení '{}' bylo odstraněno. Dostupná nastavení jsou v '{}'"
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "uživatel"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "vytvořený v"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "platí do"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Token Blacklist"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Nelze vytvořit token bez zadaného typu nebo životnosti"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token nemá žádný identifikátor"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token nemá žádný typ"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Token má špatný typ"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token nemá žádnou hodnotu '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Hodnota tokenu '{}' vypršela"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token je na černé listině"
|
||||
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <rene@matraxi.ch>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"Last-Translator: rene <rene@matraxi.ch>\n"
|
||||
"Language: de_CH\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"Der Authorizationheader muss zwei leerzeichen-getrennte Werte enthalten"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Der Token ist für keinen Tokentyp gültig"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Token enthält keine erkennbare Benutzeridentifikation"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Benutzer nicht gefunden"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Inaktiver Benutzer"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Unerkannter Algorithmustyp '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Ungültiger oder abgelaufener Token"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Ungültiger oder abgelaufener Token"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Ungültiger oder abgelaufener Token"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Kein aktiver Account mit diesen Zugangsdaten gefunden"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Kein aktiver Account mit diesen Zugangsdaten gefunden"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Die Einstellung '{}' wurde gelöscht. Bitte beachte '{}' für verfügbare "
|
||||
"Einstellungen."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "erstellt am"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "läuft ab am"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Token Blacklist"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Ein Token ohne Typ oder Lebensdauer kann nicht erstellt werden"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token hat keine Id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token hat keinen Typ"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Token hat den falschen Typ"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token hat kein '{}' Recht"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Das Tokenrecht '{}' ist abgelaufen"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token steht auf der Blacklist"
|
||||
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <zeack@protonmail.com>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"Last-Translator: zeack <zeack@protonmail.com>\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"El encabezado 'Authorization' debe contener valores delimitados por espacios"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "El token dado no es valido para ningun tipo de token"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "El token no contenía identificación de usuario reconocible"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Usuario no encontrado"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "El usuario está inactivo"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Tipo de algoritmo no reconocido '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Debe tener criptografía instalada para usar {}."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "El token es inválido o ha expirado"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "Algoritmo especificado no válido"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "El token es inválido o ha expirado"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "El token es inválido o ha expirado"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "La combinación de credenciales no tiene una cuenta activa"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "La combinación de credenciales no tiene una cuenta activa"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"La configuración '{}' fue removida. Por favor, refiérase a '{}' para "
|
||||
"consultar las disponibles."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "usuario"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "creado en"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "expira en"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Lista negra de Tokens"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "No se puede crear un token sin tipo o de tan larga vida"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "El token no tiene id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "El token no tiene tipo"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "El token tiene un tipo incorrecto"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "El token no tiene el privilegio '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "El privilegio '{}' del token ha expirado"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "El token está en lista negra"
|
||||
Binary file not shown.
@@ -0,0 +1,144 @@
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Ariel Torti <arieltorti14@gmail.com>, 2020.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"Last-Translator: Ariel Torti <arieltort14@gmail.com>\n"
|
||||
"Language: es_AR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"El header de autorización debe contener dos valores delimitados por espacio"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "El token dado no es válido para ningún tipo de token"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "El token no contiene ninguna identificación de usuario"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Usuario no encontrado"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "El usuario está inactivo"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Tipo de algoritmo no reconocido '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "El token es inválido o ha expirado"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "El token es inválido o ha expirado"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "El token es inválido o ha expirado"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr ""
|
||||
"No se encontró una cuenta de usuario activa para las credenciales dadas"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr ""
|
||||
"No se encontró una cuenta de usuario activa para las credenciales dadas"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"La configuración '{}' fue removida. Por favor, refiérase a '{}' para "
|
||||
"consultar las configuraciones disponibles."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "usuario"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "creado en"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "expira en"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Lista negra de Tokens"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "No es posible crear un token sin tipo o tiempo de vida"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "El token no tiene id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "El token no tiene tipo"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "El token tiene un tipo incorrecto"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "El token no tiene el privilegio '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "El privilegio '{}' del token ha expirado"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "El token está en la lista negra"
|
||||
Binary file not shown.
@@ -0,0 +1,139 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <alfonso.pola@gmail.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"Last-Translator: Alfonso Pola <alfonso.pola@gmail.com>\n"
|
||||
"Language: es_CL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"El header de autorización debe contener dos valores delimitados por espacio"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "El token provisto no es válido para ningún tipo de token"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "El token no contiene identificación de usuario reconocible"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Usuario no encontrado"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "El usuario está inactivo"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Tipo de algoritmo no reconocido '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Token inválido o expirado"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Token inválido o expirado"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Token inválido o expirado"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr ""
|
||||
"No se encontró una cuenta de usuario activa para las credenciales provistas"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr ""
|
||||
"No se encontró una cuenta de usuario activa para las credenciales provistas"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"La configuración '{}' fue removida. Por favor, refiérase a '{}' para "
|
||||
"configuraciones disponibles."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "Usuario"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "creado en"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "expira en"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Token Blacklist"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "No es posible crear un token sin tipo o tiempo de vida"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token no tiene id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token no tiene tipo"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Token tiene tipo erróneo"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token no tiene privilegio '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "El provilegio '{}' del token está expirado"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token está en la blacklist"
|
||||
Binary file not shown.
@@ -0,0 +1,139 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <mahdi.rahimi95@gmail.com>\>, 2023.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-07-04 09:31+0330\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Mahdi Rahimi <mahdi.rahimi95@gmail.com>\n"
|
||||
"Language: fa\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "هدر اعتبارسنجی باید شامل دو مقدار جدا شده با فاصله باشد"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "توکن داده شده برای هیچ نوع توکنی معتبر نمیباشد"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "توکن شامل هیچ شناسه قابل تشخیصی از کاربر نیست"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "کاربر یافت نشد"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "کاربر غیرفعال است"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr "رمز عبور کاربر تغییر کرده است"
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "نوع الگوریتم ناشناخته '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "برای استفاده از {} باید رمزنگاری را نصب کرده باشید."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr "نوع ناشناخته '{}'، 'leeway' باید از نوع int، float یا timedelta باشد."
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "توکن نامعتبر است یا منقضی شده است"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "الگوریتم نامعتبر مشخص شده است"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "توکن نامعتبر است یا منقضی شده است"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "توکن نامعتبر است یا منقضی شده است"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "هیچ اکانت فعالی برای اطلاعات داده شده یافت نشد"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "هیچ اکانت فعالی برای اطلاعات داده شده یافت نشد"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr "تنظیمات '{}' حذف شده است. لطفا به '{}' برای تنظیمات موجود مراجعه کنید."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "کاربر"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "زمان ایجاد"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "زمان انقضا"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "لیست سیاه توکن"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "توکن بدون هیچ نوع و طول عمر قابل ساخت نیست"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "توکن id ندارد"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "توکن نوع ندارد"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "توکن نوع اشتباهی دارد"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "توکن دارای '{}' claim نمیباشد"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "'{}' claim توکن منقضی شده"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "توکن به لیست سیاه رفته است"
|
||||
Binary file not shown.
@@ -0,0 +1,133 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <hirad.daneshvar@gmail.com>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-07-06 12:57+0330\n"
|
||||
"Last-Translator: Mahdi Rahimi <mahdi.rahimi95@gmail.com>\n"
|
||||
"Language: fa_IR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "هدر اعتبارسنجی باید شامل دو مقدار جدا شده با فاصله باشد"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "توکن داده شده برای هیچ نوع توکنی معتبر نمیباشد"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "توکن شامل هیچ شناسه قابل تشخیصی از کاربر نیست"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "کاربر یافت نشد"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "کاربر غیرفعال است"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr "رمز عبور کاربر تغییر کرده است"
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "نوع الگوریتم ناشناخته '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "برای استفاده از {} باید رمزنگاری را نصب کرده باشید."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr "نوع ناشناخته '{}'، 'leeway' باید از نوع int، float یا timedelta باشد."
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "توکن نامعتبر است یا منقضی شده است"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "الگوریتم نامعتبر مشخص شده است"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "توکن نامعتبر است یا منقضی شده است"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "توکن نامعتبر است یا منقضی شده است"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "هیچ اکانت فعالی برای اطلاعات داده شده یافت نشد"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "هیچ اکانت فعالی برای اطلاعات داده شده یافت نشد"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr "تنظیمات '{}' حذف شده است. لطفا به '{}' برای تنظیمات موجود مراجعه کنید."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "کاربر"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "زمان ایجاد"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "زمان انقضا"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "لیست سیاه توکن"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "توکن بدون هیچ نوع و طول عمر قابل ساخت نیست"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "توکن id ندارد"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "توکن نوع ندارد"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "توکن نوع اشتباهی دارد"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "توکن دارای '{}' claim نمیباشد"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "'{}' claim توکن منقضی شده"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "توکن به لیست سیاه رفته است"
|
||||
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <stephane.maltaesousa@ne.ch>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"Last-Translator: Stéphane Malta e Sousa <stephane.maltaesousa@ne.ch>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"L'en-tête 'Authorization' doit contenir deux valeurs séparées par des espaces"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Le type de jeton fourni n'est pas valide"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr ""
|
||||
"Le jeton ne contient aucune information permettant d'identifier l'utilisateur"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "L'utilisateur n'a pas été trouvé"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "L'utilisateur est désactivé"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Type d'algorithme non reconnu '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Vous devez installer cryptography afin d'utiliser {}."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Le jeton est invalide ou expiré"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "L'algorithme spécifié est invalide"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Le jeton est invalide ou expiré"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Le jeton est invalide ou expiré"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Aucun compte actif n'a été trouvé avec les identifiants fournis"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Aucun compte actif n'a été trouvé avec les identifiants fournis"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Le paramètre '{}' a été supprimé. Voir '{}' pour la liste des paramètres "
|
||||
"disponibles."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "Utilisateur"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "Créé le"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "Expire le"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Liste des jetons bannis"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Ne peut pas créer de jeton sans type ni durée de vie"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Le jeton n'a pas d'id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Le jeton n'a pas de type"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Le jeton a un type erroné"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Le jeton n'a pas le privilège '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Le privilège '{}' du jeton a expiré"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Le jeton a été banni"
|
||||
Binary file not shown.
@@ -0,0 +1,138 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <zeack@protonmail.com>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: he\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==2 ? 1 : n>10 && n%10==0 ? "
|
||||
"2 : 3);\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "Authorization Header חייבת להכיל שני ערכים מופרדים ברווח"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "המזהה הנתון אינו תקף עבור אף סיווג"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "המזהה לא הכיל זיהוי משתמש שניתן לזהות"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "משתמש לא נמצא"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "המשתמש אינו פעיל"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "סוג אלגוריתם לא מזוהה '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "עליך להתקין קריפטוגרפיה כדי להשתמש ב-{}."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr "סוג לא מזוהה '{}', 'leeway' חייב להיות מסוג int, float או timedelta."
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "המזהה אינו חוקי או שפג תוקפו"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "צוין אלגוריתם לא חוקי"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "המזהה אינו חוקי או שפג תוקפו"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "המזהה אינו חוקי או שפג תוקפו"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "לא נמצא חשבון עם פרטי זיהוי אלו"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "לא נמצא חשבון עם פרטי זיהוי אלו"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr "ההגדרה '{}' הוסרה. בבקשה קראו כאן: '{}' בשביל לראות הגדרות אפשרויות"
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "משתמש"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "נוצר בשעה"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "פג תוקף בשעה"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "רשימה שחורה של מזהים"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "לא ניתן ליצור מזהה ללא סוג או אורך חיים"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "למזהה אין מספר זיהוי"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "למזהה אין סוג"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "למזהה יש סוג לא נכון"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "למזהה אין '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "מזהה '{}' פג תוקף"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "המזהה ברשימה השחורה."
|
||||
Binary file not shown.
@@ -0,0 +1,141 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# <oon.arfiandwi@gmail.com>, 2020
|
||||
# Kira <kiraware@github.com>, 2023
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"PO-Revision-Date: 2023-03-09 08:14+0000\n"
|
||||
"Last-Translator: Kira <kiraware@github.com>\n"
|
||||
"Language: id_ID\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "Header otorisasi harus berisi dua nilai yang dipisahkan spasi"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Token yang diberikan tidak valid untuk semua jenis token"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Token tidak mengandung identifikasi pengguna yang dapat dikenali"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Pengguna tidak ditemukan"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Pengguna tidak aktif"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Jenis algoritma tidak dikenal '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Anda harus memasang cryptography untuk menggunakan {}."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
"Tipe '{}' tidak dikenali, 'leeway' harus bertipe int, float, atau timedelta."
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Token tidak valid atau kedaluwarsa"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "Algoritma yang ditentukan tidak valid"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Token tidak valid atau kedaluwarsa"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Token tidak valid atau kedaluwarsa"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Tidak ada akun aktif yang ditemukan dengan kredensial yang diberikan"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Tidak ada akun aktif yang ditemukan dengan kredensial yang diberikan"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Setelan '{}' telah dihapus. Silakan merujuk ke '{}' untuk pengaturan yang "
|
||||
"tersedia."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "pengguna"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "created at"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "kedaluwarsa pada"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Daftar Hitam Token"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Tidak dapat membuat token tanpa tipe atau masa pakai"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token tidak memiliki id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token tidak memiliki tipe"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Jenis token salah"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token tidak memiliki klaim '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Klaim token '{}' telah kedaluwarsa"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token masuk daftar hitam"
|
||||
Binary file not shown.
@@ -0,0 +1,140 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <95adriano@gmail.com>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Adriano Di Dio <95adriano@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: it_IT\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.6\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"L'header di autorizzazione deve contenere due valori delimitati da uno spazio"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Il token dato non è valido per qualsiasi tipo di token"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Il token non conteneva nessuna informazione riconoscibile dell'utente"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Utente non trovato"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Utente non attivo"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Algoritmo di tipo '{}' non riconosciuto"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Devi avere installato cryptography per usare '{}'."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Il token non è valido o è scaduto"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "L'algoritmo specificato non è valido"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Il token non è valido o è scaduto"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Il token non è valido o è scaduto"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Nessun account attivo trovato con queste credenziali"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Nessun account attivo trovato con queste credenziali"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"L'impostazione '{}' è stata rimossa. Per favore utilizza '{}' per "
|
||||
"visualizzare le impostazioni valide."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "utente"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "creato il"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "scade il"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Blacklist dei token"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Impossibile creare un token senza tipo o durata"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Il token non ha un id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Il token non ha un tipo"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Il token ha un tipo sbagliato"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Il token non contiene il parametro '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Il parametro '{}' del token è scaduto"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Il token è stato inserito nella blacklist"
|
||||
Binary file not shown.
@@ -0,0 +1,136 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR 양영광 <immutable000@gmail.com>, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-05 06:48+0900\n"
|
||||
"Last-Translator: 정재균 <tiwcegoddessana1229@gmail.com>\n"
|
||||
"Language: ko_KR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "인증 헤더에는 공백으로 구분 된 두 개의 값이 포함되어야 합니다"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "이 토큰은 모든 타입의 토큰에 대해 유효하지 않습니다"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "토큰에 사용자 식별자가 포함되어 있지 않습니다"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "찾을 수 없는 사용자입니다"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "비활성화된 사용자입니다"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr "사용자의 비밀번호가 바뀌었습니다."
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "'{}' 는 알 수 없는 알고리즘 유형입니다"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "{}를 사용하려면 암호화가 설치되어 있어야 합니다."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
"알 수 없는 타입 '{}', 'leeway' 값은 반드시 int, float 또는 timedelta 타입이어"
|
||||
"야 합니다."
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "유효하지 않거나 만료된 토큰입니다"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "잘못된 알고리즘이 지정되었습니다"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "유효하지 않거나 만료된 토큰입니다"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "유효하지 않거나 만료된 토큰입니다"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "지정된 자격 증명에 해당하는 활성화된 사용자를 찾을 수 없습니다"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "지정된 자격 증명에 해당하는 활성화된 사용자를 찾을 수 없습니다"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr "'{}' 설정이 제거되었습니다. 사용 가능한 설정은 '{}'을 참조하십시오."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "사용자"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "생성 시간"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "만료 시간"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "토큰 블랙리스트"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "타입 또는 수명이 없는 토큰을 생성할 수 없습니다"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "토큰에 식별자가 주어지지 않았습니다"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "토큰 타입이 주어지지 않았습니다"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "잘못된 토큰 타입입니다"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "토큰에 '{}' 클레임이 없습니다"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "토큰 '{}' 클레임이 만료되었습니다"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "블랙리스트에 추가된 토큰입니다"
|
||||
Binary file not shown.
@@ -0,0 +1,135 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <rene@roadbearstudios.com>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-06-17 11:06+0200\n"
|
||||
"Last-Translator: rene <rene@roadbearstudios.com>\n"
|
||||
"Language: nl_NL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"Authorisatie header moet twee waarden bevatten, gescheiden door een spatie"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Het token is voor geen enkel token-type geldig"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Token bevat geen herkenbare gebruikersidentificatie"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Gebruiker niet gevonden"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Gebruiker is inactief"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Niet herkend algoritme type '{}"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Token is niet geldig of verlopen"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Token is niet geldig of verlopen"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Token is niet geldig of verlopen"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Geen actief account gevonden voor deze gegevens"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Geen actief account gevonden voor deze gegevens"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"De '{}' instelling bestaat niet meer. Zie '{}' for beschikbareinstellingen."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "gebruiker"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "aangemaakt op"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "verloopt op"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Token Blacklist"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Kan geen token maken zonder type of levensduur"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token heeft geen id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token heeft geen type"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Token heeft het verkeerde type"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token heeft geen '{}' recht"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Token '{}' recht is verlopen"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token is ge-blacklist"
|
||||
Binary file not shown.
@@ -0,0 +1,134 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <mat.slisz@yahoo.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"Last-Translator: Mateusz Slisz <mat.slisz@yahoo.com>\n"
|
||||
"Language: pl_PL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "Nagłówek autoryzacji musi zawierać dwie wartości rodzielone spacjami"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Podany token jest błędny dla każdego typu tokena"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Token nie zawierał rozpoznawalnej identyfikacji użytkownika"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Użytkownik nie znaleziony"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Użytkownik jest nieaktywny"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Nierozpoznany typ algorytmu '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Token jest niepoprawny lub wygasł"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Token jest niepoprawny lub wygasł"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Token jest niepoprawny lub wygasł"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Nie znaleziono aktywnego konta dla podanych danych uwierzytelniających"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Nie znaleziono aktywnego konta dla podanych danych uwierzytelniających"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Ustawienie '{}' zostało usunięte. Dostępne ustawienia znajdują sie w '{}'"
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "użytkownik"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "stworzony w"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "wygasa o"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Token Blacklist"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Nie można utworzyć tokena bez podanego typu lub żywotności"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token nie posiada numeru identyfikacyjnego"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token nie posiada typu"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Token posiada zły typ"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token nie posiada upoważnienia '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Upoważnienie tokena '{}' wygasło"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token znajduję się na czarnej liście"
|
||||
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <sinvalju@gmail.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"Last-Translator: Bruno Ducraux <bruno.drx@gmail.com>\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"Cabeçalho de autorização deve conter dois valores delimitados por espaço"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "O token informado não é válido para qualquer tipo de token"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "O token não continha nenhuma identificação reconhecível do usuário"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Usuário não encontrado"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Usuário está inativo"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Tipo de algoritmo '{}' não reconhecido"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Você deve ter criptografia instalada para usar {}."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "O token é inválido ou expirado"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "Algoritmo inválido especificado"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "O token é inválido ou expirado"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "O token é inválido ou expirado"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Usuário e/ou senha incorreto(s)"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Usuário e/ou senha incorreto(s)"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"A configuração '{}' foi removida. Por favor, consulte '{}' para disponível "
|
||||
"definições."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "usuário"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "criado em"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "expira em"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Lista negra de Tokens"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Não é possível criar token sem tipo ou tempo de vida"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token não tem id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token não tem nenhum tipo"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Token tem tipo errado"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token não tem '{}' privilégio"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "O privilégio '{}' do token expirou"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token está na blacklist"
|
||||
Binary file not shown.
@@ -0,0 +1,139 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR Daniel Cuznetov <danielcuznetov04@gmail.com>, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-07-13 10:45+0100\n"
|
||||
"Last-Translator: Daniel Cuznetov <danielcuznetov04@gmail.com>\n"
|
||||
"Language: ro\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"Header-ul(antetul) de autorizare trebuie să conțină două valori separate "
|
||||
"prin spațiu"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Tokenul dat nu este valid pentru niciun tip de token"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Tokenul nu conține date de identificare a utilizatorului"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Utilizatorul nu a fost găsit"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Utilizatorul este inactiv"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Tipul de algoritm '{}' nu este recunoscut"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Trebuie să aveți instalată criptografia pentru a utiliza {}."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
"Tipul '{}' nu este recunoscut, 'leeway' trebuie să fie de tip int, float sau "
|
||||
"timedelta."
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Token nu este valid sau a expirat"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "Algoritm nevalid specificat"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Token nu este valid sau a expirat"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Token nu este valid sau a expirat"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Nu a fost găsit cont activ cu aceste date de autentificare"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Nu a fost găsit cont activ cu aceste date de autentificare"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Setarea '{}' a fost ștearsă. Referați la '{}' pentru setări disponibile."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "utilizator"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "creat la"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "expiră la"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Listă de token-uri blocate"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Nu se poate crea token fără tip sau durată de viață"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Tokenul nu are id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Tokenul nu are tip"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Tokenul are tipul greșit"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Tokenul nu are reclamația '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Reclamația tokenului '{}' a expirat"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Tokenul este în listă de tokenuri blocate"
|
||||
Binary file not shown.
@@ -0,0 +1,141 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <sinvalju@gmail.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-22 17:30+0100\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Sergey Ozeranskiy <sozeranskiy@dreamclass.ru>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: ru_RU\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
|
||||
"X-Generator: Poedit 2.2.1\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"Заголовок авторизации должен содержать два значения, разделенных пробелом"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Данный токен недействителен для любого типа токена"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Токен не содержит идентификатор пользователя"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Пользователь не найден"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Пользователь неактивен"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Нераспознанный тип алгоритма '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Токен недействителен или просрочен"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Токен недействителен или просрочен"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Токен недействителен или просрочен"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Не найдено активной учетной записи с указанными данными"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Не найдено активной учетной записи с указанными данными"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Параметр '{}' был удален. Пожалуйста, обратитесь к '{}' для просмотра "
|
||||
"доступных настроек."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "пользователь"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "создан"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "истекает"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Token Blacklist"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Невозможно создать токен без типа или времени жизни"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "У токена нет идентификатора"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Токен не имеет типа"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Токен имеет неправильный тип"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Токен не содержит '{}'"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Токен имеет просроченное значение '{}'"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Токен занесен в черный список"
|
||||
Binary file not shown.
@@ -0,0 +1,141 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <prevcurban@gmail.com>, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-19 20:46+0100\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Urban Prevc <prevcurban@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: sl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.6\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"Glava 'Authorization' mora vsebovati dve vrednosti, ločeni s presledkom"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Podan žeton ni veljaven za nobeno vrsto žetona"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Žeton ni vseboval prepoznavne identifikacije uporabnika"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Uporabnik ni najden"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Uporabnik je neaktiven"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Neprepoznana vrsta algoritma'{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Za uporabo '{}' je potrebna namestitev 'cryptography'."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
"Neprepoznana vrsta '{}', 'leeway' mora biti vrste int, float ali timedelta."
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Žeton je neveljaven ali potekel"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "Naveden algoritem je neveljaven"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Žeton je neveljaven ali potekel"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Žeton je neveljaven ali potekel"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Aktiven račun s podanimi poverilnicami ni najden"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Aktiven račun s podanimi poverilnicami ni najden"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Nastavitev '{}' je bila odstranjena. Prosimo, oglejte si '{}' za "
|
||||
"razpoložljive nastavitve."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "uporabnik"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "ustvarjen ob"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "poteče ob"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Črni seznam žetonov"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Ni mogoče ustvariti žetona brez vrste ali življenjske dobe"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Žetonu manjka id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Žetonu manjka vrsta"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Žeton je napačne vrste"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Žeton nima '{}' zahtevka"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "'{}' zahtevek žetona je potekel"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Žeton je na črnem seznamu"
|
||||
Binary file not shown.
@@ -0,0 +1,135 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR Pasindu <pasinduprabashitha@gmail.com>, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-05-29 17:30+0100\n"
|
||||
"Last-Translator: Pasindu <pasinduprabashitha@gmail.com>\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "Auktoriseringshuvudet måste innehålla två mellanslagsavgränsade värden"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Givet token är inte giltigt för någon tokentyp"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Token innehöll ingen identifiering av användaren"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Användaren hittades inte"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Användaren är inaktiv"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Okänd algoritmtyp '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Du måste ha kryptografi installerad för att kunna använda {}."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Token är ogiltig eller har löpt ut"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "Ogiltig algoritm har angetts"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Token är ogiltig eller har löpt ut"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Token är ogiltig eller har löpt ut"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Inget aktivt konto hittades med de angivna användaruppgifterna"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Inget aktivt konto hittades med de angivna användaruppgifterna"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Inställningen '{}' har tagits bort. Se '{}' för tillgängliga inställningar"
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "användare"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "skapad vid"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "går ut kl"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Token svartlist"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Kan inte skapa token utan typ eller livslängd"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token har inget id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token har ingen typ"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Token har fel typ"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token har inget '{}'-anspråk"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Token '{}'-anspråket har löpt ut"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token är svartlistad"
|
||||
Binary file not shown.
@@ -0,0 +1,136 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <suayip.541@gmail.com>, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-13 23:05+0300\n"
|
||||
"Last-Translator: Şuayip Üzülmez <suayip.541@gmail.com>\n"
|
||||
"Language: tr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr ""
|
||||
"Yetkilendirme header'i boşlukla sınırlandırılmış iki değer bulundurmak "
|
||||
"zorunda"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Verilen token hiçbir token tipi için geçerli değil"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Token tanınabilir bir kullanıcı kimliği içermiyor"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Kullanıcı bulunamadı"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Kullanıcı etkin değil"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Tanınmayan algortima tipi '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "{} kullanmak için cryptography yüklemeniz gerekiyor."
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Token geçersiz veya süresi geçmiş"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "Geçersiz algoritma belirtildi"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Token geçersiz veya süresi geçmiş"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Token geçersiz veya süresi geçmiş"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Verilen kimlik bilgileriyle aktif bir hesap bulunamadı"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Verilen kimlik bilgileriyle aktif bir hesap bulunamadı"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr "'{}' ayarı kaldırıldı. Mevcut ayarlar için '{}' adresini ziyaret edin."
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "kullanıcı"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "oluşturulma tarihi"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "sona erme tarihi"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Token Kara Listesi"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Tipi veya geçerlilik süresi olmayan token oluşturulamaz"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "Token'in id'si yok"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "Token'in tipi yok"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "Token'in tipi yanlış"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "Token'in '{}' claim'i yok"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Token'in '{}' claim'i sona erdi"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Token kara listeye alınmış"
|
||||
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Artiukhov Artem <defenite@meta.ua>, 2021.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-06-17 12:32+0300\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Artiukhov Artem <defenite@meta.ua>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: uk_UA\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "Авторизаційний заголовок має містити два значення розділені пробілом"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "Наданий токен не відповідає жодному типу ключа"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "Наданий токен не мітить жодної ідентифікаційної інформації"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "Користувач не знайдений"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "Користувач неактивний"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "Тип алгоритму '{}' не розпізнаний"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "Встановіть модуль cryptography щоб використовувати {}"
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "Токен некоректний або термін його дії вичерпаний"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "Вказаний невірний алгоритм"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "Токен некоректний або термін його дії вичерпаний"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "Токен некоректний або термін його дії вичерпаний"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "Не знайдено жодного облікового запису по наданих облікових даних"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "Не знайдено жодного облікового запису по наданих облікових даних"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr "Налаштування '{}' видалене. Подивіться у '{}' для інших доступних"
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "користувач"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "створений о"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "дійстний по"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "Чорний список токенів"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "Неможливо створити токен без типу або строку дії"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "У ключі доступу не міститься id"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "У ключі доступу не міститься тип"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "токен позначений невірним типом"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "У токені не міститься '{}' заголовку"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "Заголовок '{}' токена не дійсний"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "Токен занесений у чорний список"
|
||||
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2021
|
||||
# This file is distributed under the same license as the Simple JWT package.
|
||||
# zengqiu <zengqiu@qq.com>, 2021.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: djangorestframework_simplejwt\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-06-23 13:29+0800\n"
|
||||
"PO-Revision-Date: 2021-06-23 13:29+080\n"
|
||||
"Last-Translator: zengqiu <zengqiu@qq.com>\n"
|
||||
"Language: zh_Hans\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: authentication.py:89
|
||||
msgid "Authorization header must contain two space-delimited values"
|
||||
msgstr "授权头必须包含两个用空格分隔的值"
|
||||
|
||||
#: authentication.py:115
|
||||
msgid "Given token not valid for any token type"
|
||||
msgstr "此令牌对任何类型的令牌无效"
|
||||
|
||||
#: authentication.py:127 authentication.py:162
|
||||
msgid "Token contained no recognizable user identification"
|
||||
msgstr "令牌未包含用户标识符"
|
||||
|
||||
#: authentication.py:132
|
||||
msgid "User not found"
|
||||
msgstr "未找到该用户"
|
||||
|
||||
#: authentication.py:135
|
||||
msgid "User is inactive"
|
||||
msgstr "该用户已禁用"
|
||||
|
||||
#: authentication.py:142
|
||||
msgid "The user's password has been changed."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:90
|
||||
msgid "Unrecognized algorithm type '{}'"
|
||||
msgstr "未知算法类型 '{}'"
|
||||
|
||||
#: backends.py:96
|
||||
msgid "You must have cryptography installed to use {}."
|
||||
msgstr "你必须安装 cryptography 才能使用 {}。"
|
||||
|
||||
#: backends.py:111
|
||||
msgid ""
|
||||
"Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:125 backends.py:177 tokens.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is invalid"
|
||||
msgstr "令牌无效或已过期"
|
||||
|
||||
#: backends.py:173
|
||||
msgid "Invalid algorithm specified"
|
||||
msgstr "指定的算法无效"
|
||||
|
||||
#: backends.py:175 tokens.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Token is invalid or expired"
|
||||
msgid "Token is expired"
|
||||
msgstr "令牌无效或已过期"
|
||||
|
||||
#: exceptions.py:55
|
||||
msgid "Token is invalid or expired"
|
||||
msgstr "令牌无效或已过期"
|
||||
|
||||
#: serializers.py:35
|
||||
msgid "No active account found with the given credentials"
|
||||
msgstr "找不到指定凭据对应的有效用户"
|
||||
|
||||
#: serializers.py:108
|
||||
#, fuzzy
|
||||
#| msgid "No active account found with the given credentials"
|
||||
msgid "No active account found for the given token."
|
||||
msgstr "找不到指定凭据对应的有效用户"
|
||||
|
||||
#: settings.py:74
|
||||
msgid ""
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available "
|
||||
"settings."
|
||||
msgstr "'{}' 配置已被移除。 请参阅 '{}' 获取可用的配置。"
|
||||
|
||||
#: token_blacklist/admin.py:79
|
||||
msgid "jti"
|
||||
msgstr "jti"
|
||||
|
||||
#: token_blacklist/admin.py:85
|
||||
msgid "user"
|
||||
msgstr "用户"
|
||||
|
||||
#: token_blacklist/admin.py:91
|
||||
msgid "created at"
|
||||
msgstr "创建时间"
|
||||
|
||||
#: token_blacklist/admin.py:97
|
||||
msgid "expires at"
|
||||
msgstr "过期时间"
|
||||
|
||||
#: token_blacklist/apps.py:7
|
||||
msgid "Token Blacklist"
|
||||
msgstr "令牌黑名单"
|
||||
|
||||
#: tokens.py:52
|
||||
msgid "Cannot create token with no type or lifetime"
|
||||
msgstr "无法创建没有类型或生存期的令牌"
|
||||
|
||||
#: tokens.py:126
|
||||
msgid "Token has no id"
|
||||
msgstr "令牌没有标识符"
|
||||
|
||||
#: tokens.py:138
|
||||
msgid "Token has no type"
|
||||
msgstr "令牌没有类型"
|
||||
|
||||
#: tokens.py:141
|
||||
msgid "Token has wrong type"
|
||||
msgstr "令牌类型错误"
|
||||
|
||||
#: tokens.py:200
|
||||
msgid "Token has no '{}' claim"
|
||||
msgstr "令牌没有 '{}' 声明"
|
||||
|
||||
#: tokens.py:205
|
||||
msgid "Token '{}' claim has expired"
|
||||
msgstr "令牌 '{}' 声明已过期"
|
||||
|
||||
#: tokens.py:292
|
||||
msgid "Token is blacklisted"
|
||||
msgstr "令牌已被加入黑名单"
|
||||
@@ -0,0 +1,115 @@
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union
|
||||
|
||||
from django.contrib.auth import models as auth_models
|
||||
from django.db.models.manager import EmptyManager
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from .settings import api_settings
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .tokens import Token
|
||||
|
||||
|
||||
class TokenUser:
|
||||
"""
|
||||
A dummy user class modeled after django.contrib.auth.models.AnonymousUser.
|
||||
Used in conjunction with the `JWTStatelessUserAuthentication` backend to
|
||||
implement single sign-on functionality across services which share the same
|
||||
secret key. `JWTStatelessUserAuthentication` will return an instance of this
|
||||
class instead of a `User` model instance. Instances of this class act as
|
||||
stateless user objects which are backed by validated tokens.
|
||||
"""
|
||||
|
||||
# User is always active since Simple JWT will never issue a token for an
|
||||
# inactive user
|
||||
is_active = True
|
||||
|
||||
_groups = EmptyManager(auth_models.Group)
|
||||
_user_permissions = EmptyManager(auth_models.Permission)
|
||||
|
||||
def __init__(self, token: "Token") -> None:
|
||||
self.token = token
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"TokenUser {self.id}"
|
||||
|
||||
@cached_property
|
||||
def id(self) -> Union[int, str]:
|
||||
return self.token[api_settings.USER_ID_CLAIM]
|
||||
|
||||
@cached_property
|
||||
def pk(self) -> Union[int, str]:
|
||||
return self.id
|
||||
|
||||
@cached_property
|
||||
def username(self) -> str:
|
||||
return self.token.get("username", "")
|
||||
|
||||
@cached_property
|
||||
def is_staff(self) -> bool:
|
||||
return self.token.get("is_staff", False)
|
||||
|
||||
@cached_property
|
||||
def is_superuser(self) -> bool:
|
||||
return self.token.get("is_superuser", False)
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, TokenUser):
|
||||
return NotImplemented
|
||||
return self.id == other.id
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.id)
|
||||
|
||||
def save(self) -> None:
|
||||
raise NotImplementedError("Token users have no DB representation")
|
||||
|
||||
def delete(self) -> None:
|
||||
raise NotImplementedError("Token users have no DB representation")
|
||||
|
||||
def set_password(self, raw_password: str) -> None:
|
||||
raise NotImplementedError("Token users have no DB representation")
|
||||
|
||||
def check_password(self, raw_password: str) -> None:
|
||||
raise NotImplementedError("Token users have no DB representation")
|
||||
|
||||
@property
|
||||
def groups(self) -> auth_models.Group:
|
||||
return self._groups
|
||||
|
||||
@property
|
||||
def user_permissions(self) -> auth_models.Permission:
|
||||
return self._user_permissions
|
||||
|
||||
def get_group_permissions(self, obj: Optional[object] = None) -> set:
|
||||
return set()
|
||||
|
||||
def get_all_permissions(self, obj: Optional[object] = None) -> set:
|
||||
return set()
|
||||
|
||||
def has_perm(self, perm: str, obj: Optional[object] = None) -> bool:
|
||||
return False
|
||||
|
||||
def has_perms(self, perm_list: list[str], obj: Optional[object] = None) -> bool:
|
||||
return False
|
||||
|
||||
def has_module_perms(self, module: str) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_anonymous(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_authenticated(self) -> bool:
|
||||
return True
|
||||
|
||||
def get_username(self) -> str:
|
||||
return self.username
|
||||
|
||||
def __getattr__(self, attr: str) -> Optional[Any]:
|
||||
"""This acts as a backup attribute getter for custom claims defined in Token serializers."""
|
||||
return self.token.get(attr, None)
|
||||
@@ -0,0 +1,193 @@
|
||||
from typing import Any, Optional, TypeVar
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import authenticate, get_user_model
|
||||
from django.contrib.auth.models import AbstractBaseUser, update_last_login
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import exceptions, serializers
|
||||
from rest_framework.exceptions import AuthenticationFailed, ValidationError
|
||||
|
||||
from .models import TokenUser
|
||||
from .settings import api_settings
|
||||
from .tokens import RefreshToken, SlidingToken, Token, UntypedToken
|
||||
|
||||
AuthUser = TypeVar("AuthUser", AbstractBaseUser, TokenUser)
|
||||
|
||||
if api_settings.BLACKLIST_AFTER_ROTATION:
|
||||
from .token_blacklist.models import BlacklistedToken
|
||||
|
||||
|
||||
class PasswordField(serializers.CharField):
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
kwargs.setdefault("style", {})
|
||||
|
||||
kwargs["style"]["input_type"] = "password"
|
||||
kwargs["write_only"] = True
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class TokenObtainSerializer(serializers.Serializer):
|
||||
username_field = get_user_model().USERNAME_FIELD
|
||||
token_class: Optional[type[Token]] = None
|
||||
|
||||
default_error_messages = {
|
||||
"no_active_account": _("No active account found with the given credentials")
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields[self.username_field] = serializers.CharField(write_only=True)
|
||||
self.fields["password"] = PasswordField()
|
||||
|
||||
def validate(self, attrs: dict[str, Any]) -> dict[Any, Any]:
|
||||
authenticate_kwargs = {
|
||||
self.username_field: attrs[self.username_field],
|
||||
"password": attrs["password"],
|
||||
}
|
||||
try:
|
||||
authenticate_kwargs["request"] = self.context["request"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
self.user = authenticate(**authenticate_kwargs)
|
||||
|
||||
if not api_settings.USER_AUTHENTICATION_RULE(self.user):
|
||||
raise exceptions.AuthenticationFailed(
|
||||
self.error_messages["no_active_account"],
|
||||
"no_active_account",
|
||||
)
|
||||
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def get_token(cls, user: AuthUser) -> Token:
|
||||
return cls.token_class.for_user(user) # type: ignore
|
||||
|
||||
|
||||
class TokenObtainPairSerializer(TokenObtainSerializer):
|
||||
token_class = RefreshToken
|
||||
|
||||
def validate(self, attrs: dict[str, Any]) -> dict[str, str]:
|
||||
data = super().validate(attrs)
|
||||
|
||||
refresh = self.get_token(self.user)
|
||||
|
||||
data["refresh"] = str(refresh)
|
||||
data["access"] = str(refresh.access_token)
|
||||
|
||||
if api_settings.UPDATE_LAST_LOGIN:
|
||||
update_last_login(None, self.user)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class TokenObtainSlidingSerializer(TokenObtainSerializer):
|
||||
token_class = SlidingToken
|
||||
|
||||
def validate(self, attrs: dict[str, Any]) -> dict[str, str]:
|
||||
data = super().validate(attrs)
|
||||
|
||||
token = self.get_token(self.user)
|
||||
|
||||
data["token"] = str(token)
|
||||
|
||||
if api_settings.UPDATE_LAST_LOGIN:
|
||||
update_last_login(None, self.user)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class TokenRefreshSerializer(serializers.Serializer):
|
||||
refresh = serializers.CharField()
|
||||
access = serializers.CharField(read_only=True)
|
||||
token_class = RefreshToken
|
||||
|
||||
default_error_messages = {
|
||||
"no_active_account": _("No active account found for the given token.")
|
||||
}
|
||||
|
||||
def validate(self, attrs: dict[str, Any]) -> dict[str, str]:
|
||||
refresh = self.token_class(attrs["refresh"])
|
||||
|
||||
user_id = refresh.payload.get(api_settings.USER_ID_CLAIM, None)
|
||||
if user_id and (
|
||||
user := get_user_model().objects.get(
|
||||
**{api_settings.USER_ID_FIELD: user_id}
|
||||
)
|
||||
):
|
||||
if not api_settings.USER_AUTHENTICATION_RULE(user):
|
||||
raise AuthenticationFailed(
|
||||
self.error_messages["no_active_account"],
|
||||
"no_active_account",
|
||||
)
|
||||
|
||||
data = {"access": str(refresh.access_token)}
|
||||
|
||||
if api_settings.ROTATE_REFRESH_TOKENS:
|
||||
if api_settings.BLACKLIST_AFTER_ROTATION:
|
||||
try:
|
||||
# Attempt to blacklist the given refresh token
|
||||
refresh.blacklist()
|
||||
except AttributeError:
|
||||
# If blacklist app not installed, `blacklist` method will
|
||||
# not be present
|
||||
pass
|
||||
|
||||
refresh.set_jti()
|
||||
refresh.set_exp()
|
||||
refresh.set_iat()
|
||||
refresh.outstand()
|
||||
|
||||
data["refresh"] = str(refresh)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class TokenRefreshSlidingSerializer(serializers.Serializer):
|
||||
token = serializers.CharField()
|
||||
token_class = SlidingToken
|
||||
|
||||
def validate(self, attrs: dict[str, Any]) -> dict[str, str]:
|
||||
token = self.token_class(attrs["token"])
|
||||
|
||||
# Check that the timestamp in the "refresh_exp" claim has not
|
||||
# passed
|
||||
token.check_exp(api_settings.SLIDING_TOKEN_REFRESH_EXP_CLAIM)
|
||||
|
||||
# Update the "exp" and "iat" claims
|
||||
token.set_exp()
|
||||
token.set_iat()
|
||||
|
||||
return {"token": str(token)}
|
||||
|
||||
|
||||
class TokenVerifySerializer(serializers.Serializer):
|
||||
token = serializers.CharField(write_only=True)
|
||||
|
||||
def validate(self, attrs: dict[str, None]) -> dict[Any, Any]:
|
||||
token = UntypedToken(attrs["token"])
|
||||
|
||||
if (
|
||||
api_settings.BLACKLIST_AFTER_ROTATION
|
||||
and "rest_framework_simplejwt.token_blacklist" in settings.INSTALLED_APPS
|
||||
):
|
||||
jti = token.get(api_settings.JTI_CLAIM)
|
||||
if BlacklistedToken.objects.filter(token__jti=jti).exists():
|
||||
raise ValidationError("Token is blacklisted")
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
class TokenBlacklistSerializer(serializers.Serializer):
|
||||
refresh = serializers.CharField(write_only=True)
|
||||
token_class = RefreshToken
|
||||
|
||||
def validate(self, attrs: dict[str, Any]) -> dict[Any, Any]:
|
||||
refresh = self.token_class(attrs["refresh"])
|
||||
try:
|
||||
refresh.blacklist()
|
||||
except AttributeError:
|
||||
pass
|
||||
return {}
|
||||
@@ -0,0 +1,96 @@
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
from django.conf import settings
|
||||
from django.test.signals import setting_changed
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework.settings import APISettings as _APISettings
|
||||
|
||||
from .utils import format_lazy
|
||||
|
||||
USER_SETTINGS = getattr(settings, "SIMPLE_JWT", None)
|
||||
|
||||
DEFAULTS = {
|
||||
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
|
||||
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
|
||||
"ROTATE_REFRESH_TOKENS": False,
|
||||
"BLACKLIST_AFTER_ROTATION": False,
|
||||
"UPDATE_LAST_LOGIN": False,
|
||||
"ALGORITHM": "HS256",
|
||||
"SIGNING_KEY": settings.SECRET_KEY,
|
||||
"VERIFYING_KEY": "",
|
||||
"AUDIENCE": None,
|
||||
"ISSUER": None,
|
||||
"JSON_ENCODER": None,
|
||||
"JWK_URL": None,
|
||||
"LEEWAY": 0,
|
||||
"AUTH_HEADER_TYPES": ("Bearer",),
|
||||
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
|
||||
"USER_ID_FIELD": "id",
|
||||
"USER_ID_CLAIM": "user_id",
|
||||
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
|
||||
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
|
||||
"TOKEN_TYPE_CLAIM": "token_type",
|
||||
"JTI_CLAIM": "jti",
|
||||
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
|
||||
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
|
||||
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
|
||||
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
|
||||
"TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
|
||||
"TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
|
||||
"TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
|
||||
"TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
|
||||
"SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
|
||||
"SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
|
||||
"CHECK_REVOKE_TOKEN": False,
|
||||
"REVOKE_TOKEN_CLAIM": "hash_password",
|
||||
"CHECK_USER_IS_ACTIVE": True,
|
||||
}
|
||||
|
||||
IMPORT_STRINGS = (
|
||||
"AUTH_TOKEN_CLASSES",
|
||||
"JSON_ENCODER",
|
||||
"TOKEN_USER_CLASS",
|
||||
"USER_AUTHENTICATION_RULE",
|
||||
)
|
||||
|
||||
REMOVED_SETTINGS = (
|
||||
"AUTH_HEADER_TYPE",
|
||||
"AUTH_TOKEN_CLASS",
|
||||
"SECRET_KEY",
|
||||
"TOKEN_BACKEND_CLASS",
|
||||
)
|
||||
|
||||
|
||||
class APISettings(_APISettings): # pragma: no cover
|
||||
def __check_user_settings(self, user_settings: dict[str, Any]) -> dict[str, Any]:
|
||||
SETTINGS_DOC = "https://django-rest-framework-simplejwt.readthedocs.io/en/latest/settings.html"
|
||||
|
||||
for setting in REMOVED_SETTINGS:
|
||||
if setting in user_settings:
|
||||
raise RuntimeError(
|
||||
format_lazy(
|
||||
_(
|
||||
"The '{}' setting has been removed. Please refer to '{}' for available settings."
|
||||
),
|
||||
setting,
|
||||
SETTINGS_DOC,
|
||||
)
|
||||
)
|
||||
|
||||
return user_settings
|
||||
|
||||
|
||||
api_settings = APISettings(USER_SETTINGS, DEFAULTS, IMPORT_STRINGS)
|
||||
|
||||
|
||||
def reload_api_settings(*args, **kwargs) -> None: # pragma: no cover
|
||||
global api_settings
|
||||
|
||||
setting, value = kwargs["setting"], kwargs["value"]
|
||||
|
||||
if setting == "SIMPLE_JWT":
|
||||
api_settings = APISettings(value, DEFAULTS, IMPORT_STRINGS)
|
||||
|
||||
|
||||
setting_changed.connect(reload_api_settings)
|
||||
@@ -0,0 +1,13 @@
|
||||
from .backends import TokenBackend
|
||||
from .settings import api_settings
|
||||
|
||||
token_backend = TokenBackend(
|
||||
api_settings.ALGORITHM,
|
||||
api_settings.SIGNING_KEY,
|
||||
api_settings.VERIFYING_KEY,
|
||||
api_settings.AUDIENCE,
|
||||
api_settings.ISSUER,
|
||||
api_settings.JWK_URL,
|
||||
api_settings.LEEWAY,
|
||||
api_settings.JSON_ENCODER,
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
from django import VERSION
|
||||
|
||||
if VERSION < (3, 2):
|
||||
default_app_config = (
|
||||
"rest_framework_simplejwt.token_blacklist.apps.TokenBlacklistConfig"
|
||||
)
|
||||
@@ -0,0 +1,101 @@
|
||||
from datetime import datetime
|
||||
from typing import Any, Optional, TypeVar
|
||||
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.models import AbstractBaseUser
|
||||
from django.db.models import QuerySet
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework.request import Request
|
||||
|
||||
from ..models import TokenUser
|
||||
from .models import BlacklistedToken, OutstandingToken
|
||||
|
||||
AuthUser = TypeVar("AuthUser", AbstractBaseUser, TokenUser)
|
||||
|
||||
|
||||
class OutstandingTokenAdmin(admin.ModelAdmin):
|
||||
list_display = (
|
||||
"jti",
|
||||
"user",
|
||||
"created_at",
|
||||
"expires_at",
|
||||
)
|
||||
search_fields = (
|
||||
"user__id",
|
||||
"jti",
|
||||
)
|
||||
ordering = ("user",)
|
||||
|
||||
def get_queryset(self, *args, **kwargs) -> QuerySet:
|
||||
qs = super().get_queryset(*args, **kwargs)
|
||||
|
||||
return qs.select_related("user")
|
||||
|
||||
# Read-only behavior defined below
|
||||
actions = None
|
||||
|
||||
def get_readonly_fields(self, *args, **kwargs) -> list[Any]:
|
||||
return [f.name for f in self.model._meta.fields]
|
||||
|
||||
def has_add_permission(self, *args, **kwargs) -> bool:
|
||||
return False
|
||||
|
||||
def has_delete_permission(self, *args, **kwargs) -> bool:
|
||||
return False
|
||||
|
||||
def has_change_permission(
|
||||
self, request: Request, obj: Optional[object] = None
|
||||
) -> bool:
|
||||
return request.method in ["GET", "HEAD"] and super().has_change_permission(
|
||||
request, obj
|
||||
)
|
||||
|
||||
|
||||
admin.site.register(OutstandingToken, OutstandingTokenAdmin)
|
||||
|
||||
|
||||
class BlacklistedTokenAdmin(admin.ModelAdmin):
|
||||
list_display = (
|
||||
"token_jti",
|
||||
"token_user",
|
||||
"token_created_at",
|
||||
"token_expires_at",
|
||||
"blacklisted_at",
|
||||
)
|
||||
search_fields = (
|
||||
"token__user__id",
|
||||
"token__jti",
|
||||
)
|
||||
ordering = ("token__user",)
|
||||
|
||||
def get_queryset(self, *args, **kwargs) -> QuerySet:
|
||||
qs = super().get_queryset(*args, **kwargs)
|
||||
|
||||
return qs.select_related("token__user")
|
||||
|
||||
def token_jti(self, obj: BlacklistedToken) -> str:
|
||||
return obj.token.jti
|
||||
|
||||
token_jti.short_description = _("jti") # type: ignore
|
||||
token_jti.admin_order_field = "token__jti" # type: ignore
|
||||
|
||||
def token_user(self, obj: BlacklistedToken) -> AuthUser:
|
||||
return obj.token.user
|
||||
|
||||
token_user.short_description = _("user") # type: ignore
|
||||
token_user.admin_order_field = "token__user" # type: ignore
|
||||
|
||||
def token_created_at(self, obj: BlacklistedToken) -> datetime:
|
||||
return obj.token.created_at
|
||||
|
||||
token_created_at.short_description = _("created at") # type: ignore
|
||||
token_created_at.admin_order_field = "token__created_at" # type: ignore
|
||||
|
||||
def token_expires_at(self, obj: BlacklistedToken) -> datetime:
|
||||
return obj.token.expires_at
|
||||
|
||||
token_expires_at.short_description = _("expires at") # type: ignore
|
||||
token_expires_at.admin_order_field = "token__expires_at" # type: ignore
|
||||
|
||||
|
||||
admin.site.register(BlacklistedToken, BlacklistedTokenAdmin)
|
||||
@@ -0,0 +1,8 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class TokenBlacklistConfig(AppConfig):
|
||||
name = "rest_framework_simplejwt.token_blacklist"
|
||||
verbose_name = _("Token Blacklist")
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
@@ -0,0 +1,12 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from rest_framework_simplejwt.utils import aware_utcnow
|
||||
|
||||
from ...models import OutstandingToken
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Flushes any expired tokens in the outstanding token list"
|
||||
|
||||
def handle(self, *args, **kwargs) -> None:
|
||||
OutstandingToken.objects.filter(expires_at__lte=aware_utcnow()).delete()
|
||||
@@ -0,0 +1,65 @@
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="BlacklistedToken",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("blacklisted_at", models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="OutstandingToken",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("jti", models.UUIDField(unique=True)),
|
||||
("token", models.TextField()),
|
||||
("created_at", models.DateTimeField()),
|
||||
("expires_at", models.DateTimeField()),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"ordering": ("user",),
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="blacklistedtoken",
|
||||
name="token",
|
||||
field=models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="token_blacklist.OutstandingToken",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("token_blacklist", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="outstandingtoken",
|
||||
name="jti_hex",
|
||||
field=models.CharField(blank=True, null=True, max_length=255),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,31 @@
|
||||
from uuid import UUID
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def populate_jti_hex(apps, schema_editor):
|
||||
OutstandingToken = apps.get_model("token_blacklist", "OutstandingToken")
|
||||
|
||||
db_alias = schema_editor.connection.alias
|
||||
for token in OutstandingToken.objects.using(db_alias).all():
|
||||
token.jti_hex = token.jti.hex
|
||||
token.save()
|
||||
|
||||
|
||||
def reverse_populate_jti_hex(apps, schema_editor): # pragma: no cover
|
||||
OutstandingToken = apps.get_model("token_blacklist", "OutstandingToken")
|
||||
|
||||
db_alias = schema_editor.connection.alias
|
||||
for token in OutstandingToken.objects.using(db_alias).all():
|
||||
token.jti = UUID(hex=token.jti_hex)
|
||||
token.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("token_blacklist", "0002_outstandingtoken_jti_hex"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(populate_jti_hex, reverse_populate_jti_hex),
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("token_blacklist", "0003_auto_20171017_2007"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="outstandingtoken",
|
||||
name="jti_hex",
|
||||
field=models.CharField(unique=True, max_length=255),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,14 @@
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("token_blacklist", "0004_auto_20171017_2013"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="outstandingtoken",
|
||||
name="jti",
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("token_blacklist", "0005_remove_outstandingtoken_jti"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name="outstandingtoken",
|
||||
old_name="jti_hex",
|
||||
new_name="jti",
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,27 @@
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("token_blacklist", "0006_auto_20171017_2113"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="outstandingtoken",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="outstandingtoken",
|
||||
name="user",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,24 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("token_blacklist", "0007_auto_20171017_2214"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="blacklistedtoken",
|
||||
name="id",
|
||||
field=models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="outstandingtoken",
|
||||
name="id",
|
||||
field=models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 3.2.3 on 2021-05-27 17:46
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
parent_dir = Path(__file__).resolve(strict=True).parent
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("token_blacklist", "0008_migrate_to_bigautofield"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="blacklistedtoken",
|
||||
name="id",
|
||||
field=models.BigAutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="outstandingtoken",
|
||||
name="id",
|
||||
field=models.BigAutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
import fnmatch
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from django.db import migrations, models # noqa F401
|
||||
|
||||
parent_dir = Path(__file__).resolve(strict=True).parent
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.dependencies = [("token_blacklist", "0010_fix_migrate_to_bigautofield")]
|
||||
_m = sorted(fnmatch.filter(os.listdir(parent_dir), "000*.py"))
|
||||
if len(_m) == 9:
|
||||
self.dependencies.insert(0, ("token_blacklist", os.path.splitext(_m[8])[0]))
|
||||
|
||||
operations = []
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 3.2.10 on 2022-01-24 06:42
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("token_blacklist", "0011_linearizes_history"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="outstandingtoken",
|
||||
name="user",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,52 @@
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
|
||||
|
||||
class OutstandingToken(models.Model):
|
||||
id = models.BigAutoField(primary_key=True, serialize=False)
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True
|
||||
)
|
||||
|
||||
jti = models.CharField(unique=True, max_length=255)
|
||||
token = models.TextField()
|
||||
|
||||
created_at = models.DateTimeField(null=True, blank=True)
|
||||
expires_at = models.DateTimeField()
|
||||
|
||||
class Meta:
|
||||
# Work around for a bug in Django:
|
||||
# https://code.djangoproject.com/ticket/19422
|
||||
#
|
||||
# Also see corresponding ticket:
|
||||
# https://github.com/encode/django-rest-framework/issues/705
|
||||
abstract = (
|
||||
"rest_framework_simplejwt.token_blacklist" not in settings.INSTALLED_APPS
|
||||
)
|
||||
ordering = ("user",)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "Token for {} ({})".format(
|
||||
self.user,
|
||||
self.jti,
|
||||
)
|
||||
|
||||
|
||||
class BlacklistedToken(models.Model):
|
||||
id = models.BigAutoField(primary_key=True, serialize=False)
|
||||
token = models.OneToOneField(OutstandingToken, on_delete=models.CASCADE)
|
||||
|
||||
blacklisted_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
# Work around for a bug in Django:
|
||||
# https://code.djangoproject.com/ticket/19422
|
||||
#
|
||||
# Also see corresponding ticket:
|
||||
# https://github.com/encode/django-rest-framework/issues/705
|
||||
abstract = (
|
||||
"rest_framework_simplejwt.token_blacklist" not in settings.INSTALLED_APPS
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Blacklisted token for {self.token.user}"
|
||||
@@ -0,0 +1,412 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar
|
||||
from uuid import uuid4
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AbstractBaseUser
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .exceptions import (
|
||||
ExpiredTokenError,
|
||||
TokenBackendError,
|
||||
TokenBackendExpiredToken,
|
||||
TokenError,
|
||||
)
|
||||
from .models import TokenUser
|
||||
from .settings import api_settings
|
||||
from .token_blacklist.models import BlacklistedToken, OutstandingToken
|
||||
from .utils import (
|
||||
aware_utcnow,
|
||||
datetime_from_epoch,
|
||||
datetime_to_epoch,
|
||||
format_lazy,
|
||||
get_md5_hash_password,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .backends import TokenBackend
|
||||
|
||||
T = TypeVar("T", bound="Token")
|
||||
|
||||
AuthUser = TypeVar("AuthUser", AbstractBaseUser, TokenUser)
|
||||
|
||||
|
||||
class Token:
|
||||
"""
|
||||
A class which validates and wraps an existing JWT or can be used to build a
|
||||
new JWT.
|
||||
"""
|
||||
|
||||
token_type: Optional[str] = None
|
||||
lifetime: Optional[timedelta] = None
|
||||
|
||||
def __init__(self, token: Optional["Token"] = None, verify: bool = True) -> None:
|
||||
"""
|
||||
!!!! IMPORTANT !!!! MUST raise a TokenError with a user-facing error
|
||||
message if the given token is invalid, expired, or otherwise not safe
|
||||
to use.
|
||||
"""
|
||||
if self.token_type is None or self.lifetime is None:
|
||||
raise TokenError(_("Cannot create token with no type or lifetime"))
|
||||
|
||||
self.token = token
|
||||
self.current_time = aware_utcnow()
|
||||
|
||||
# Set up token
|
||||
if token is not None:
|
||||
# An encoded token was provided
|
||||
token_backend = self.get_token_backend()
|
||||
|
||||
# Decode token
|
||||
try:
|
||||
self.payload = token_backend.decode(token, verify=verify)
|
||||
except TokenBackendExpiredToken:
|
||||
raise ExpiredTokenError(_("Token is expired"))
|
||||
except TokenBackendError:
|
||||
raise TokenError(_("Token is invalid"))
|
||||
|
||||
if verify:
|
||||
self.verify()
|
||||
else:
|
||||
# New token. Skip all the verification steps.
|
||||
self.payload = {api_settings.TOKEN_TYPE_CLAIM: self.token_type}
|
||||
|
||||
# Set "exp" and "iat" claims with default value
|
||||
self.set_exp(from_time=self.current_time, lifetime=self.lifetime)
|
||||
self.set_iat(at_time=self.current_time)
|
||||
|
||||
# Set "jti" claim
|
||||
self.set_jti()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return repr(self.payload)
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
return self.payload[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.payload[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.payload[key]
|
||||
|
||||
def __contains__(self, key: str) -> Any:
|
||||
return key in self.payload
|
||||
|
||||
def get(self, key: str, default: Optional[Any] = None) -> Any:
|
||||
return self.payload.get(key, default)
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
Signs and returns a token as a base64 encoded string.
|
||||
"""
|
||||
return self.get_token_backend().encode(self.payload)
|
||||
|
||||
def verify(self) -> None:
|
||||
"""
|
||||
Performs additional validation steps which were not performed when this
|
||||
token was decoded. This method is part of the "public" API to indicate
|
||||
the intention that it may be overridden in subclasses.
|
||||
"""
|
||||
# According to RFC 7519, the "exp" claim is OPTIONAL
|
||||
# (https://tools.ietf.org/html/rfc7519#section-4.1.4). As a more
|
||||
# correct behavior for authorization tokens, we require an "exp"
|
||||
# claim. We don't want any zombie tokens walking around.
|
||||
self.check_exp()
|
||||
|
||||
# If the defaults are not None then we should enforce the
|
||||
# requirement of these settings.As above, the spec labels
|
||||
# these as optional.
|
||||
if (
|
||||
api_settings.JTI_CLAIM is not None
|
||||
and api_settings.JTI_CLAIM not in self.payload
|
||||
):
|
||||
raise TokenError(_("Token has no id"))
|
||||
|
||||
if api_settings.TOKEN_TYPE_CLAIM is not None:
|
||||
self.verify_token_type()
|
||||
|
||||
def verify_token_type(self) -> None:
|
||||
"""
|
||||
Ensures that the token type claim is present and has the correct value.
|
||||
"""
|
||||
try:
|
||||
token_type = self.payload[api_settings.TOKEN_TYPE_CLAIM]
|
||||
except KeyError:
|
||||
raise TokenError(_("Token has no type"))
|
||||
|
||||
if self.token_type != token_type:
|
||||
raise TokenError(_("Token has wrong type"))
|
||||
|
||||
def set_jti(self) -> None:
|
||||
"""
|
||||
Populates the configured jti claim of a token with a string where there
|
||||
is a negligible probability that the same string will be chosen at a
|
||||
later time.
|
||||
|
||||
See here:
|
||||
https://tools.ietf.org/html/rfc7519#section-4.1.7
|
||||
"""
|
||||
self.payload[api_settings.JTI_CLAIM] = uuid4().hex
|
||||
|
||||
def set_exp(
|
||||
self,
|
||||
claim: str = "exp",
|
||||
from_time: Optional[datetime] = None,
|
||||
lifetime: Optional[timedelta] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Updates the expiration time of a token.
|
||||
|
||||
See here:
|
||||
https://tools.ietf.org/html/rfc7519#section-4.1.4
|
||||
"""
|
||||
if from_time is None:
|
||||
from_time = self.current_time
|
||||
|
||||
if lifetime is None:
|
||||
lifetime = self.lifetime
|
||||
|
||||
self.payload[claim] = datetime_to_epoch(from_time + lifetime)
|
||||
|
||||
def set_iat(self, claim: str = "iat", at_time: Optional[datetime] = None) -> None:
|
||||
"""
|
||||
Updates the time at which the token was issued.
|
||||
|
||||
See here:
|
||||
https://tools.ietf.org/html/rfc7519#section-4.1.6
|
||||
"""
|
||||
if at_time is None:
|
||||
at_time = self.current_time
|
||||
|
||||
self.payload[claim] = datetime_to_epoch(at_time)
|
||||
|
||||
def check_exp(
|
||||
self, claim: str = "exp", current_time: Optional[datetime] = None
|
||||
) -> None:
|
||||
"""
|
||||
Checks whether a timestamp value in the given claim has passed (since
|
||||
the given datetime value in `current_time`). Raises a TokenError with
|
||||
a user-facing error message if so.
|
||||
"""
|
||||
if current_time is None:
|
||||
current_time = self.current_time
|
||||
|
||||
try:
|
||||
claim_value = self.payload[claim]
|
||||
except KeyError:
|
||||
raise TokenError(format_lazy(_("Token has no '{}' claim"), claim))
|
||||
|
||||
claim_time = datetime_from_epoch(claim_value)
|
||||
leeway = self.get_token_backend().get_leeway()
|
||||
if claim_time <= current_time - leeway:
|
||||
raise TokenError(format_lazy(_("Token '{}' claim has expired"), claim))
|
||||
|
||||
def outstand(self) -> OutstandingToken:
|
||||
"""
|
||||
Ensures this token is included in the outstanding token list and
|
||||
adds it to the outstanding token list if not.
|
||||
"""
|
||||
jti = self.payload[api_settings.JTI_CLAIM]
|
||||
exp = self.payload["exp"]
|
||||
user_id = self.payload.get(api_settings.USER_ID_CLAIM)
|
||||
User = get_user_model()
|
||||
try:
|
||||
user = User.objects.get(**{api_settings.USER_ID_FIELD: user_id})
|
||||
except User.DoesNotExist:
|
||||
user = None
|
||||
|
||||
# Ensure outstanding token exists with given jti
|
||||
return OutstandingToken.objects.get_or_create(
|
||||
jti=jti,
|
||||
defaults={
|
||||
"user": user,
|
||||
"created_at": self.current_time,
|
||||
"token": str(self),
|
||||
"expires_at": datetime_from_epoch(exp),
|
||||
},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def for_user(cls: type[T], user: AuthUser) -> T:
|
||||
"""
|
||||
Returns an authorization token for the given user that will be provided
|
||||
after authenticating the user's credentials.
|
||||
"""
|
||||
user_id = getattr(user, api_settings.USER_ID_FIELD)
|
||||
if not isinstance(user_id, int):
|
||||
user_id = str(user_id)
|
||||
|
||||
token = cls()
|
||||
token[api_settings.USER_ID_CLAIM] = user_id
|
||||
|
||||
if api_settings.CHECK_REVOKE_TOKEN:
|
||||
token[api_settings.REVOKE_TOKEN_CLAIM] = get_md5_hash_password(
|
||||
user.password
|
||||
)
|
||||
|
||||
return token
|
||||
|
||||
_token_backend: Optional["TokenBackend"] = None
|
||||
|
||||
@property
|
||||
def token_backend(self) -> "TokenBackend":
|
||||
if self._token_backend is None:
|
||||
self._token_backend = import_string(
|
||||
"rest_framework_simplejwt.state.token_backend"
|
||||
)
|
||||
return self._token_backend
|
||||
|
||||
def get_token_backend(self) -> "TokenBackend":
|
||||
# Backward compatibility.
|
||||
return self.token_backend
|
||||
|
||||
|
||||
class BlacklistMixin(Generic[T]):
|
||||
"""
|
||||
If the `rest_framework_simplejwt.token_blacklist` app was configured to be
|
||||
used, tokens created from `BlacklistMixin` subclasses will insert
|
||||
themselves into an outstanding token list and also check for their
|
||||
membership in a token blacklist.
|
||||
"""
|
||||
|
||||
payload: dict[str, Any]
|
||||
|
||||
if "rest_framework_simplejwt.token_blacklist" in settings.INSTALLED_APPS:
|
||||
|
||||
def verify(self, *args, **kwargs) -> None:
|
||||
self.check_blacklist()
|
||||
|
||||
super().verify(*args, **kwargs) # type: ignore
|
||||
|
||||
def check_blacklist(self) -> None:
|
||||
"""
|
||||
Checks if this token is present in the token blacklist. Raises
|
||||
`TokenError` if so.
|
||||
"""
|
||||
jti = self.payload[api_settings.JTI_CLAIM]
|
||||
|
||||
if BlacklistedToken.objects.filter(token__jti=jti).exists():
|
||||
raise TokenError(_("Token is blacklisted"))
|
||||
|
||||
def blacklist(self) -> BlacklistedToken:
|
||||
"""
|
||||
Ensures this token is included in the outstanding token list and
|
||||
adds it to the blacklist.
|
||||
"""
|
||||
jti = self.payload[api_settings.JTI_CLAIM]
|
||||
exp = self.payload["exp"]
|
||||
user_id = self.payload.get(api_settings.USER_ID_CLAIM)
|
||||
User = get_user_model()
|
||||
try:
|
||||
user = User.objects.get(**{api_settings.USER_ID_FIELD: user_id})
|
||||
except User.DoesNotExist:
|
||||
user = None
|
||||
|
||||
# Ensure outstanding token exists with given jti
|
||||
token, _ = OutstandingToken.objects.get_or_create(
|
||||
jti=jti,
|
||||
defaults={
|
||||
"user": user,
|
||||
"created_at": self.current_time,
|
||||
"token": str(self),
|
||||
"expires_at": datetime_from_epoch(exp),
|
||||
},
|
||||
)
|
||||
|
||||
return BlacklistedToken.objects.get_or_create(token=token)
|
||||
|
||||
@classmethod
|
||||
def for_user(cls: type[T], user: AuthUser) -> T:
|
||||
"""
|
||||
Adds this token to the outstanding token list.
|
||||
"""
|
||||
token = super().for_user(user) # type: ignore
|
||||
|
||||
jti = token[api_settings.JTI_CLAIM]
|
||||
exp = token["exp"]
|
||||
|
||||
OutstandingToken.objects.create(
|
||||
user=user,
|
||||
jti=jti,
|
||||
token=str(token),
|
||||
created_at=token.current_time,
|
||||
expires_at=datetime_from_epoch(exp),
|
||||
)
|
||||
|
||||
return token
|
||||
|
||||
|
||||
class SlidingToken(BlacklistMixin["SlidingToken"], Token):
|
||||
token_type = "sliding"
|
||||
lifetime = api_settings.SLIDING_TOKEN_LIFETIME
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if self.token is None:
|
||||
# Set sliding refresh expiration claim if new token
|
||||
self.set_exp(
|
||||
api_settings.SLIDING_TOKEN_REFRESH_EXP_CLAIM,
|
||||
from_time=self.current_time,
|
||||
lifetime=api_settings.SLIDING_TOKEN_REFRESH_LIFETIME,
|
||||
)
|
||||
|
||||
|
||||
class AccessToken(Token):
|
||||
token_type = "access"
|
||||
lifetime = api_settings.ACCESS_TOKEN_LIFETIME
|
||||
|
||||
|
||||
class RefreshToken(BlacklistMixin["RefreshToken"], Token):
|
||||
token_type = "refresh"
|
||||
lifetime = api_settings.REFRESH_TOKEN_LIFETIME
|
||||
no_copy_claims = (
|
||||
api_settings.TOKEN_TYPE_CLAIM,
|
||||
"exp",
|
||||
# Both of these claims are included even though they may be the same.
|
||||
# It seems possible that a third party token might have a custom or
|
||||
# namespaced JTI claim as well as a default "jti" claim. In that case,
|
||||
# we wouldn't want to copy either one.
|
||||
api_settings.JTI_CLAIM,
|
||||
"jti",
|
||||
)
|
||||
access_token_class = AccessToken
|
||||
|
||||
@property
|
||||
def access_token(self) -> AccessToken:
|
||||
"""
|
||||
Returns an access token created from this refresh token. Copies all
|
||||
claims present in this refresh token to the new access token except
|
||||
those claims listed in the `no_copy_claims` attribute.
|
||||
"""
|
||||
access = self.access_token_class()
|
||||
|
||||
# Use instantiation time of refresh token as relative timestamp for
|
||||
# access token "exp" claim. This ensures that both a refresh and
|
||||
# access token expire relative to the same time if they are created as
|
||||
# a pair.
|
||||
access.set_exp(from_time=self.current_time)
|
||||
|
||||
no_copy = self.no_copy_claims
|
||||
for claim, value in self.payload.items():
|
||||
if claim in no_copy:
|
||||
continue
|
||||
access[claim] = value
|
||||
|
||||
return access
|
||||
|
||||
|
||||
class UntypedToken(Token):
|
||||
token_type = "untyped"
|
||||
lifetime = timedelta(seconds=0)
|
||||
|
||||
def verify_token_type(self) -> None:
|
||||
"""
|
||||
Untyped tokens do not verify the "token_type" claim. This is useful
|
||||
when performing general validation of a token's signature and other
|
||||
properties which do not relate to the token's intended use.
|
||||
"""
|
||||
pass
|
||||
@@ -0,0 +1,48 @@
|
||||
import hashlib
|
||||
from calendar import timegm
|
||||
from datetime import datetime, timezone
|
||||
from typing import Callable
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.functional import lazy
|
||||
|
||||
|
||||
def get_md5_hash_password(password: str) -> str:
|
||||
"""
|
||||
Returns MD5 hash of the given password
|
||||
"""
|
||||
return hashlib.md5(password.encode()).hexdigest().upper()
|
||||
|
||||
|
||||
def make_utc(dt: datetime) -> datetime:
|
||||
if settings.USE_TZ and dt.tzinfo is None:
|
||||
return dt.replace(tzinfo=timezone.utc)
|
||||
|
||||
return dt
|
||||
|
||||
|
||||
def aware_utcnow() -> datetime:
|
||||
dt = datetime.now(tz=timezone.utc)
|
||||
if not settings.USE_TZ:
|
||||
dt = dt.replace(tzinfo=None)
|
||||
|
||||
return dt
|
||||
|
||||
|
||||
def datetime_to_epoch(dt: datetime) -> int:
|
||||
return timegm(dt.utctimetuple())
|
||||
|
||||
|
||||
def datetime_from_epoch(ts: float) -> datetime:
|
||||
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
|
||||
if not settings.USE_TZ:
|
||||
dt = dt.replace(tzinfo=None)
|
||||
|
||||
return dt
|
||||
|
||||
|
||||
def format_lazy(s: str, *args, **kwargs) -> str:
|
||||
return s.format(*args, **kwargs)
|
||||
|
||||
|
||||
format_lazy: Callable = lazy(format_lazy, str)
|
||||
@@ -0,0 +1,120 @@
|
||||
from django.utils.module_loading import import_string
|
||||
from rest_framework import generics, status
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import Serializer
|
||||
|
||||
from .authentication import AUTH_HEADER_TYPES
|
||||
from .exceptions import InvalidToken, TokenError
|
||||
from .settings import api_settings
|
||||
|
||||
|
||||
class TokenViewBase(generics.GenericAPIView):
|
||||
permission_classes = ()
|
||||
authentication_classes = ()
|
||||
|
||||
serializer_class = None
|
||||
_serializer_class = ""
|
||||
|
||||
www_authenticate_realm = "api"
|
||||
|
||||
def get_serializer_class(self) -> Serializer:
|
||||
"""
|
||||
If serializer_class is set, use it directly. Otherwise get the class from settings.
|
||||
"""
|
||||
|
||||
if self.serializer_class:
|
||||
return self.serializer_class
|
||||
try:
|
||||
return import_string(self._serializer_class)
|
||||
except ImportError:
|
||||
msg = f"Could not import serializer '{self._serializer_class}'"
|
||||
raise ImportError(msg)
|
||||
|
||||
def get_authenticate_header(self, request: Request) -> str:
|
||||
return '{} realm="{}"'.format(
|
||||
AUTH_HEADER_TYPES[0],
|
||||
self.www_authenticate_realm,
|
||||
)
|
||||
|
||||
def post(self, request: Request, *args, **kwargs) -> Response:
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
|
||||
try:
|
||||
serializer.is_valid(raise_exception=True)
|
||||
except TokenError as e:
|
||||
raise InvalidToken(e.args[0])
|
||||
|
||||
return Response(serializer.validated_data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class TokenObtainPairView(TokenViewBase):
|
||||
"""
|
||||
Takes a set of user credentials and returns an access and refresh JSON web
|
||||
token pair to prove the authentication of those credentials.
|
||||
"""
|
||||
|
||||
_serializer_class = api_settings.TOKEN_OBTAIN_SERIALIZER
|
||||
|
||||
|
||||
token_obtain_pair = TokenObtainPairView.as_view()
|
||||
|
||||
|
||||
class TokenRefreshView(TokenViewBase):
|
||||
"""
|
||||
Takes a refresh type JSON web token and returns an access type JSON web
|
||||
token if the refresh token is valid.
|
||||
"""
|
||||
|
||||
_serializer_class = api_settings.TOKEN_REFRESH_SERIALIZER
|
||||
|
||||
|
||||
token_refresh = TokenRefreshView.as_view()
|
||||
|
||||
|
||||
class TokenObtainSlidingView(TokenViewBase):
|
||||
"""
|
||||
Takes a set of user credentials and returns a sliding JSON web token to
|
||||
prove the authentication of those credentials.
|
||||
"""
|
||||
|
||||
_serializer_class = api_settings.SLIDING_TOKEN_OBTAIN_SERIALIZER
|
||||
|
||||
|
||||
token_obtain_sliding = TokenObtainSlidingView.as_view()
|
||||
|
||||
|
||||
class TokenRefreshSlidingView(TokenViewBase):
|
||||
"""
|
||||
Takes a sliding JSON web token and returns a new, refreshed version if the
|
||||
token's refresh period has not expired.
|
||||
"""
|
||||
|
||||
_serializer_class = api_settings.SLIDING_TOKEN_REFRESH_SERIALIZER
|
||||
|
||||
|
||||
token_refresh_sliding = TokenRefreshSlidingView.as_view()
|
||||
|
||||
|
||||
class TokenVerifyView(TokenViewBase):
|
||||
"""
|
||||
Takes a token and indicates if it is valid. This view provides no
|
||||
information about a token's fitness for a particular use.
|
||||
"""
|
||||
|
||||
_serializer_class = api_settings.TOKEN_VERIFY_SERIALIZER
|
||||
|
||||
|
||||
token_verify = TokenVerifyView.as_view()
|
||||
|
||||
|
||||
class TokenBlacklistView(TokenViewBase):
|
||||
"""
|
||||
Takes a token and blacklists it. Must be used with the
|
||||
`rest_framework_simplejwt.token_blacklist` app installed.
|
||||
"""
|
||||
|
||||
_serializer_class = api_settings.TOKEN_BLACKLIST_SERIALIZER
|
||||
|
||||
|
||||
token_blacklist = TokenBlacklistView.as_view()
|
||||
Reference in New Issue
Block a user