forked from p15670423/monkey
Merge branch 'pwd-hash' into develop
This commit is contained in:
commit
e609094a59
|
@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
performance tests are skipped.
|
performance tests are skipped.
|
||||||
- Zerologon exploiter writes runtime artifacts to a secure temporary directory
|
- Zerologon exploiter writes runtime artifacts to a secure temporary directory
|
||||||
instead of $HOME. #1143
|
instead of $HOME. #1143
|
||||||
|
- Authentication mechanism to use bcrypt on server side. #1139
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Attempted to delete a directory when monkey config reset was called. #1054
|
- Attempted to delete a directory when monkey config reset was called. #1054
|
||||||
|
|
|
@ -6,6 +6,7 @@ name = "pypi"
|
||||||
[packages]
|
[packages]
|
||||||
pyinstaller = "==3.6"
|
pyinstaller = "==3.6"
|
||||||
awscli = "==1.18.131"
|
awscli = "==1.18.131"
|
||||||
|
bcrypt = "==3.2.0"
|
||||||
boto3 = "==1.14.54"
|
boto3 = "==1.14.54"
|
||||||
botocore = "==1.17.54"
|
botocore = "==1.17.54"
|
||||||
cffi = ">=1.8,!=1.11.3"
|
cffi = ">=1.8,!=1.11.3"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "4fdfe90af14139cf855a0363ad0acbe7fb307b35b038e2c099c4d1227322a13b"
|
"sha256": "3057235b1e85593ee307d9e5a2e0d15e26f13437bb709529303c7c900d3c7b41"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -60,6 +60,19 @@
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==1.18.131"
|
"version": "==1.18.131"
|
||||||
},
|
},
|
||||||
|
"bcrypt": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
|
||||||
|
"sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
|
||||||
|
"sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
|
||||||
|
"sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
|
||||||
|
"sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
|
||||||
|
"sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
|
||||||
|
"sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==3.2.0"
|
||||||
|
},
|
||||||
"boto3": {
|
"boto3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:4196b418598851ffd10cf9d1606694673cbfeca4ddf8b25d4e50addbd2fc60bf",
|
"sha256:4196b418598851ffd10cf9d1606694673cbfeca4ddf8b25d4e50addbd2fc60bf",
|
||||||
|
|
|
@ -38,13 +38,12 @@ class EnvironmentConfig:
|
||||||
self._load_from_dict(data)
|
self._load_from_dict(data)
|
||||||
|
|
||||||
def _load_from_dict(self, dict_data: Dict):
|
def _load_from_dict(self, dict_data: Dict):
|
||||||
user_creds = UserCreds.get_from_dict(dict_data)
|
|
||||||
aws = dict_data["aws"] if "aws" in dict_data else None
|
aws = dict_data["aws"] if "aws" in dict_data else None
|
||||||
data_dir = dict_data["data_dir"] if "data_dir" in dict_data else DEFAULT_DATA_DIR
|
data_dir = dict_data["data_dir"] if "data_dir" in dict_data else DEFAULT_DATA_DIR
|
||||||
|
|
||||||
self.server_config = dict_data["server_config"]
|
self.server_config = dict_data["server_config"]
|
||||||
self.deployment = dict_data["deployment"]
|
self.deployment = dict_data["deployment"]
|
||||||
self.user_creds = user_creds
|
self.user_creds = _get_user_credentials_from_config(dict_data)
|
||||||
self.aws = aws
|
self.aws = aws
|
||||||
self.data_dir = data_dir
|
self.data_dir = data_dir
|
||||||
|
|
||||||
|
@ -75,3 +74,10 @@ class EnvironmentConfig:
|
||||||
def get_users(self) -> List[User]:
|
def get_users(self) -> List[User]:
|
||||||
auth_user = self.user_creds.to_auth_user()
|
auth_user = self.user_creds.to_auth_user()
|
||||||
return [auth_user] if auth_user else []
|
return [auth_user] if auth_user else []
|
||||||
|
|
||||||
|
|
||||||
|
def _get_user_credentials_from_config(dict_data: Dict):
|
||||||
|
username = dict_data.get("user", "")
|
||||||
|
password_hash = dict_data.get("password_hash", "")
|
||||||
|
|
||||||
|
return UserCreds(username, password_hash)
|
||||||
|
|
|
@ -7,11 +7,8 @@ __author__ = "itay.mizeretz"
|
||||||
class StandardEnvironment(Environment):
|
class StandardEnvironment(Environment):
|
||||||
_credentials_required = False
|
_credentials_required = False
|
||||||
|
|
||||||
# SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()'
|
NO_AUTH_USER = "1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()"
|
||||||
NO_AUTH_CREDS = (
|
NO_AUTH_SECRET = "$2b$12$frH7uEwV3jkDNGgReW6j2udw8hy/Yw1SWAqytrcBYK48kn1V5lQIa"
|
||||||
"55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062"
|
|
||||||
"8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557"
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_auth_users(self):
|
def get_auth_users(self):
|
||||||
return [User(1, StandardEnvironment.NO_AUTH_CREDS, StandardEnvironment.NO_AUTH_CREDS)]
|
return [User(1, StandardEnvironment.NO_AUTH_USER, StandardEnvironment.NO_AUTH_SECRET)]
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from monkey_island.cc.resources.auth.auth_user import User
|
from monkey_island.cc.resources.auth.auth_user import User
|
||||||
|
|
||||||
|
|
||||||
class UserCreds:
|
class UserCreds:
|
||||||
def __init__(self, username="", password_hash=""):
|
def __init__(self, username, password_hash):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password_hash = password_hash
|
self.password_hash = password_hash
|
||||||
|
|
||||||
|
@ -24,17 +23,3 @@ class UserCreds:
|
||||||
|
|
||||||
def to_auth_user(self) -> User:
|
def to_auth_user(self) -> User:
|
||||||
return User(1, self.username, self.password_hash)
|
return User(1, self.username, self.password_hash)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_from_dict(data_dict: Dict) -> UserCreds:
|
|
||||||
creds = UserCreds()
|
|
||||||
if "user" in data_dict:
|
|
||||||
creds.username = data_dict["user"]
|
|
||||||
if "password_hash" in data_dict:
|
|
||||||
creds.password_hash = data_dict["password_hash"]
|
|
||||||
return creds
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_from_json(json_data: bytes) -> UserCreds:
|
|
||||||
cred_dict = json.loads(json_data)
|
|
||||||
return UserCreds.get_from_dict(cred_dict)
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ import flask_restful
|
||||||
from flask import make_response, request
|
from flask import make_response, request
|
||||||
from flask_jwt_extended.exceptions import JWTExtendedException
|
from flask_jwt_extended.exceptions import JWTExtendedException
|
||||||
from jwt import PyJWTError
|
from jwt import PyJWTError
|
||||||
from werkzeug.security import safe_str_cmp
|
|
||||||
|
|
||||||
import monkey_island.cc.environment.environment_singleton as env_singleton
|
import monkey_island.cc.environment.environment_singleton as env_singleton
|
||||||
|
import monkey_island.cc.resources.auth.password_utils as password_utils
|
||||||
import monkey_island.cc.resources.auth.user_store as user_store
|
import monkey_island.cc.resources.auth.user_store as user_store
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -25,42 +25,55 @@ def init_jwt(app):
|
||||||
|
|
||||||
class Authenticate(flask_restful.Resource):
|
class Authenticate(flask_restful.Resource):
|
||||||
"""
|
"""
|
||||||
Resource for user authentication. The user provides the username and hashed password and we
|
Resource for user authentication. The user provides the username and password and we
|
||||||
give them a JWT.
|
give them a JWT.
|
||||||
See `AuthService.js` file for the frontend counterpart for this code.
|
See `AuthService.js` file for the frontend counterpart for this code.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _authenticate(username, secret):
|
|
||||||
user = user_store.UserStore.username_table.get(username, None)
|
|
||||||
if user and safe_str_cmp(user.secret.encode("utf-8"), secret.encode("utf-8")):
|
|
||||||
return user
|
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
"""
|
"""
|
||||||
Example request:
|
Example request:
|
||||||
{
|
{
|
||||||
"username": "my_user",
|
"username": "my_user",
|
||||||
"password": "343bb87e553b05430e5c44baf99569d4b66..."
|
"password": "my_password"
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
credentials = json.loads(request.data)
|
(username, password) = _get_credentials_from_request(request)
|
||||||
# Unpack auth info from request
|
|
||||||
username = credentials["username"]
|
if _credentials_match_registered_user(username, password):
|
||||||
secret = credentials["password"]
|
access_token = _create_access_token(username)
|
||||||
# If the user and password have been previously registered
|
|
||||||
if self._authenticate(username, secret):
|
|
||||||
access_token = flask_jwt_extended.create_access_token(
|
|
||||||
identity=user_store.UserStore.username_table[username].id
|
|
||||||
)
|
|
||||||
logger.debug(
|
|
||||||
f"Created access token for user {username} that begins with {access_token[:4]}"
|
|
||||||
)
|
|
||||||
return make_response({"access_token": access_token, "error": ""}, 200)
|
return make_response({"access_token": access_token, "error": ""}, 200)
|
||||||
else:
|
else:
|
||||||
return make_response({"error": "Invalid credentials"}, 401)
|
return make_response({"error": "Invalid credentials"}, 401)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_credentials_from_request(request):
|
||||||
|
credentials = json.loads(request.data)
|
||||||
|
|
||||||
|
username = credentials["username"]
|
||||||
|
password = credentials["password"]
|
||||||
|
|
||||||
|
return (username, password)
|
||||||
|
|
||||||
|
|
||||||
|
def _credentials_match_registered_user(username, password):
|
||||||
|
user = user_store.UserStore.username_table.get(username, None)
|
||||||
|
|
||||||
|
if user and password_utils.password_matches_hash(password, user.secret):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _create_access_token(username):
|
||||||
|
access_token = flask_jwt_extended.create_access_token(
|
||||||
|
identity=user_store.UserStore.username_table[username].id
|
||||||
|
)
|
||||||
|
logger.debug(f"Created access token for user {username} that begins with {access_token[:4]}")
|
||||||
|
|
||||||
|
return access_token
|
||||||
|
|
||||||
|
|
||||||
# See https://flask-jwt-extended.readthedocs.io/en/stable/custom_decorators/
|
# See https://flask-jwt-extended.readthedocs.io/en/stable/custom_decorators/
|
||||||
def jwt_required(fn):
|
def jwt_required(fn):
|
||||||
@wraps(fn)
|
@wraps(fn)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import bcrypt
|
||||||
|
|
||||||
|
|
||||||
|
def hash_password(plaintext_password):
|
||||||
|
salt = bcrypt.gensalt()
|
||||||
|
password_hash = bcrypt.hashpw(plaintext_password.encode("utf-8"), salt)
|
||||||
|
|
||||||
|
return password_hash.decode()
|
||||||
|
|
||||||
|
|
||||||
|
def password_matches_hash(plaintext_password, password_hash):
|
||||||
|
return bcrypt.checkpw(plaintext_password.encode("utf-8"), password_hash.encode("utf-8"))
|
|
@ -1,7 +1,10 @@
|
||||||
|
import json
|
||||||
|
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import make_response, request
|
from flask import make_response, request
|
||||||
|
|
||||||
import monkey_island.cc.environment.environment_singleton as env_singleton
|
import monkey_island.cc.environment.environment_singleton as env_singleton
|
||||||
|
import monkey_island.cc.resources.auth.password_utils as password_utils
|
||||||
from common.utils.exceptions import InvalidRegistrationCredentialsError, RegistrationNotNeededError
|
from common.utils.exceptions import InvalidRegistrationCredentialsError, RegistrationNotNeededError
|
||||||
from monkey_island.cc.environment.user_creds import UserCreds
|
from monkey_island.cc.environment.user_creds import UserCreds
|
||||||
|
|
||||||
|
@ -11,9 +14,20 @@ class Registration(flask_restful.Resource):
|
||||||
return {"needs_registration": env_singleton.env.needs_registration()}
|
return {"needs_registration": env_singleton.env.needs_registration()}
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
credentials = UserCreds.get_from_json(request.data)
|
credentials = _get_user_credentials_from_request(request)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
env_singleton.env.try_add_user(credentials)
|
env_singleton.env.try_add_user(credentials)
|
||||||
return make_response({"error": ""}, 200)
|
return make_response({"error": ""}, 200)
|
||||||
except (InvalidRegistrationCredentialsError, RegistrationNotNeededError) as e:
|
except (InvalidRegistrationCredentialsError, RegistrationNotNeededError) as e:
|
||||||
return make_response({"error": str(e)}, 400)
|
return make_response({"error": str(e)}, 400)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_user_credentials_from_request(request):
|
||||||
|
cred_dict = json.loads(request.data)
|
||||||
|
|
||||||
|
username = cred_dict.get("user", "")
|
||||||
|
password = cred_dict.get("password", "")
|
||||||
|
password_hash = password_utils.hash_password(password)
|
||||||
|
|
||||||
|
return UserCreds(username, password_hash)
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
import {SHA3} from 'sha3';
|
|
||||||
import decode from 'jwt-decode';
|
import decode from 'jwt-decode';
|
||||||
|
|
||||||
export default class AuthService {
|
export default class AuthService {
|
||||||
// SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()'
|
NO_AUTH_CREDS = '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()';
|
||||||
NO_AUTH_CREDS =
|
|
||||||
'55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' +
|
|
||||||
'8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557';
|
|
||||||
|
|
||||||
SECONDS_BEFORE_JWT_EXPIRES = 20;
|
SECONDS_BEFORE_JWT_EXPIRES = 20;
|
||||||
AUTHENTICATION_API_ENDPOINT = '/api/auth';
|
AUTHENTICATION_API_ENDPOINT = '/api/auth';
|
||||||
REGISTRATION_API_ENDPOINT = '/api/registration';
|
REGISTRATION_API_ENDPOINT = '/api/registration';
|
||||||
|
|
||||||
login = (username, password) => {
|
login = (username, password) => {
|
||||||
return this._login(username, this.hashSha3(password));
|
return this._login(username, password);
|
||||||
};
|
};
|
||||||
|
|
||||||
authFetch = (url, options) => {
|
authFetch = (url, options) => {
|
||||||
|
@ -25,12 +21,6 @@ export default class AuthService {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
hashSha3(text) {
|
|
||||||
let hash = new SHA3(512);
|
|
||||||
hash.update(text);
|
|
||||||
return this._toHexStr(hash.digest());
|
|
||||||
}
|
|
||||||
|
|
||||||
_login = (username, password) => {
|
_login = (username, password) => {
|
||||||
return this._authFetch(this.AUTHENTICATION_API_ENDPOINT, {
|
return this._authFetch(this.AUTHENTICATION_API_ENDPOINT, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -51,11 +41,7 @@ export default class AuthService {
|
||||||
};
|
};
|
||||||
|
|
||||||
register = (username, password) => {
|
register = (username, password) => {
|
||||||
if (password !== '') {
|
return this._register(username, password);
|
||||||
return this._register(username, this.hashSha3(password));
|
|
||||||
} else {
|
|
||||||
return this._register(username, password);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_register = (username, password) => {
|
_register = (username, password) => {
|
||||||
|
@ -63,7 +49,7 @@ export default class AuthService {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
'user': username,
|
'user': username,
|
||||||
'password_hash': password
|
'password': password
|
||||||
})
|
})
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
@ -156,7 +142,4 @@ export default class AuthService {
|
||||||
return localStorage.getItem('jwt')
|
return localStorage.getItem('jwt')
|
||||||
}
|
}
|
||||||
|
|
||||||
_toHexStr(byteArr) {
|
|
||||||
return byteArr.reduce((acc, x) => (acc + ('0' + x.toString(0x10)).slice(-2)), '');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@ PARTIAL_CREDENTIALS = None
|
||||||
STANDARD_WITH_CREDENTIALS = None
|
STANDARD_WITH_CREDENTIALS = None
|
||||||
STANDARD_ENV = None
|
STANDARD_ENV = None
|
||||||
|
|
||||||
|
EMPTY_USER_CREDENTIALS = UserCreds("", "")
|
||||||
|
FULL_USER_CREDENTIALS = UserCreds(username="test", password_hash="1231234")
|
||||||
|
|
||||||
|
|
||||||
# This fixture is a dirty hack that can be removed once these tests are converted from
|
# This fixture is a dirty hack that can be removed once these tests are converted from
|
||||||
# unittest to pytest. Instead, the appropriate fixtures from conftest.py can be used.
|
# unittest to pytest. Instead, the appropriate fixtures from conftest.py can be used.
|
||||||
|
@ -67,7 +70,7 @@ def get_server_config_file_path_test_version():
|
||||||
class TestEnvironment(TestCase):
|
class TestEnvironment(TestCase):
|
||||||
class EnvironmentCredentialsNotRequired(Environment):
|
class EnvironmentCredentialsNotRequired(Environment):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
config = StubEnvironmentConfig("test", "test", UserCreds())
|
config = StubEnvironmentConfig("test", "test", EMPTY_USER_CREDENTIALS)
|
||||||
super().__init__(config)
|
super().__init__(config)
|
||||||
|
|
||||||
_credentials_required = False
|
_credentials_required = False
|
||||||
|
@ -77,7 +80,7 @@ class TestEnvironment(TestCase):
|
||||||
|
|
||||||
class EnvironmentCredentialsRequired(Environment):
|
class EnvironmentCredentialsRequired(Environment):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
config = StubEnvironmentConfig("test", "test", UserCreds())
|
config = StubEnvironmentConfig("test", "test", EMPTY_USER_CREDENTIALS)
|
||||||
super().__init__(config)
|
super().__init__(config)
|
||||||
|
|
||||||
_credentials_required = True
|
_credentials_required = True
|
||||||
|
@ -98,15 +101,15 @@ class TestEnvironment(TestCase):
|
||||||
@patch.object(target=EnvironmentConfig, attribute="save_to_file", new=MagicMock())
|
@patch.object(target=EnvironmentConfig, attribute="save_to_file", new=MagicMock())
|
||||||
def test_try_add_user(self):
|
def test_try_add_user(self):
|
||||||
env = TestEnvironment.EnvironmentCredentialsRequired()
|
env = TestEnvironment.EnvironmentCredentialsRequired()
|
||||||
credentials = UserCreds(username="test", password_hash="1231234")
|
credentials = FULL_USER_CREDENTIALS
|
||||||
env.try_add_user(credentials)
|
env.try_add_user(credentials)
|
||||||
|
|
||||||
credentials = UserCreds(username="test")
|
credentials = UserCreds(username="test", password_hash="")
|
||||||
with self.assertRaises(InvalidRegistrationCredentialsError):
|
with self.assertRaises(InvalidRegistrationCredentialsError):
|
||||||
env.try_add_user(credentials)
|
env.try_add_user(credentials)
|
||||||
|
|
||||||
env = TestEnvironment.EnvironmentCredentialsNotRequired()
|
env = TestEnvironment.EnvironmentCredentialsNotRequired()
|
||||||
credentials = UserCreds(username="test", password_hash="1231234")
|
credentials = FULL_USER_CREDENTIALS
|
||||||
with self.assertRaises(RegistrationNotNeededError):
|
with self.assertRaises(RegistrationNotNeededError):
|
||||||
env.try_add_user(credentials)
|
env.try_add_user(credentials)
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,45 @@
|
||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
from monkey_island.cc.environment.user_creds import UserCreds
|
from monkey_island.cc.environment.user_creds import UserCreds
|
||||||
|
|
||||||
|
TEST_USER = "Test"
|
||||||
|
TEST_HASH = "abc1231234"
|
||||||
|
TEST_SALT = b"$2b$12$JA7GdT1iyfIsquF2cTZv2."
|
||||||
|
|
||||||
class TestUserCreds(TestCase):
|
|
||||||
def test_to_dict(self):
|
|
||||||
user_creds = UserCreds()
|
|
||||||
self.assertDictEqual(user_creds.to_dict(), {})
|
|
||||||
|
|
||||||
user_creds = UserCreds(username="Test")
|
def test_bool_true():
|
||||||
self.assertDictEqual(user_creds.to_dict(), {"user": "Test"})
|
assert UserCreds(TEST_USER, TEST_HASH)
|
||||||
|
|
||||||
user_creds = UserCreds(password_hash="abc1231234")
|
|
||||||
self.assertDictEqual(user_creds.to_dict(), {"password_hash": "abc1231234"})
|
|
||||||
|
|
||||||
user_creds = UserCreds(username="Test", password_hash="abc1231234")
|
def test_bool_false_empty_password_hash():
|
||||||
self.assertDictEqual(user_creds.to_dict(), {"user": "Test", "password_hash": "abc1231234"})
|
assert not UserCreds(TEST_USER, "")
|
||||||
|
|
||||||
def test_to_auth_user(self):
|
|
||||||
user_creds = UserCreds(username="Test", password_hash="abc1231234")
|
|
||||||
auth_user = user_creds.to_auth_user()
|
|
||||||
self.assertEqual(auth_user.id, 1)
|
|
||||||
self.assertEqual(auth_user.username, "Test")
|
|
||||||
self.assertEqual(auth_user.secret, "abc1231234")
|
|
||||||
|
|
||||||
user_creds = UserCreds(username="Test")
|
def test_bool_false_empty_user():
|
||||||
auth_user = user_creds.to_auth_user()
|
assert not UserCreds("", TEST_HASH)
|
||||||
self.assertEqual(auth_user.id, 1)
|
|
||||||
self.assertEqual(auth_user.username, "Test")
|
|
||||||
self.assertEqual(auth_user.secret, "")
|
|
||||||
|
|
||||||
user_creds = UserCreds(password_hash="abc1231234")
|
|
||||||
auth_user = user_creds.to_auth_user()
|
def test_bool_false_empty_user_and_password_hash():
|
||||||
self.assertEqual(auth_user.id, 1)
|
assert not UserCreds("", "")
|
||||||
self.assertEqual(auth_user.username, "")
|
|
||||||
self.assertEqual(auth_user.secret, "abc1231234")
|
|
||||||
|
def test_to_dict_empty_creds():
|
||||||
|
user_creds = UserCreds("", "")
|
||||||
|
assert user_creds.to_dict() == {}
|
||||||
|
|
||||||
|
|
||||||
|
def test_to_dict_full_creds():
|
||||||
|
user_creds = UserCreds(TEST_USER, TEST_HASH)
|
||||||
|
assert user_creds.to_dict() == {"user": TEST_USER, "password_hash": TEST_HASH}
|
||||||
|
|
||||||
|
|
||||||
|
def test_to_auth_user_full_credentials():
|
||||||
|
user_creds = UserCreds(TEST_USER, TEST_HASH)
|
||||||
|
auth_user = user_creds.to_auth_user()
|
||||||
|
assert auth_user.id == 1
|
||||||
|
assert auth_user.username == TEST_USER
|
||||||
|
assert auth_user.secret == TEST_HASH
|
||||||
|
|
||||||
|
|
||||||
|
def test_member_values(monkeypatch):
|
||||||
|
creds = UserCreds(TEST_USER, TEST_HASH)
|
||||||
|
assert creds.username == TEST_USER
|
||||||
|
assert creds.password_hash == TEST_HASH
|
||||||
|
|
Loading…
Reference in New Issue