forked from p15670423/monkey
TEMP: Quick hack of session based authentication
This commit is contained in:
parent
759de2a055
commit
4321bfafb4
|
@ -32,6 +32,8 @@ marshmallow-enum = "*"
|
|||
readerwriterlock = "*"
|
||||
pymongo = "*"
|
||||
cryptography = "*"
|
||||
flask-login = "*"
|
||||
flask-wtf = "*"
|
||||
|
||||
[dev-packages]
|
||||
virtualenv = ">=20.0.26"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "09e1b190955d23328ac5e2de385904f7b109eb6b748e7ae9b2b5c7bfd62f690c"
|
||||
"sha256": "6b6bff4ffa42faed7e784a6c6820aca5d882e0ec7ddf20834af42f46b5b551fa"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
@ -32,11 +32,11 @@
|
|||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4",
|
||||
"sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"
|
||||
"sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6",
|
||||
"sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==21.4.0"
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==22.1.0"
|
||||
},
|
||||
"bcrypt": {
|
||||
"hashes": [
|
||||
|
@ -210,19 +210,27 @@
|
|||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb",
|
||||
"sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"
|
||||
"sha256:10dc2bae7a9b6ab59111d6dbece2e08fb0015d2e88d296c40323cc0c7aac2c2e",
|
||||
"sha256:98b33b13ad76ee9c7a80d2f56a6c578780e55bf8281790c62d50d4b7fadec2b8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.3"
|
||||
"version": "==2.2.0"
|
||||
},
|
||||
"flask-jwt-extended": {
|
||||
"hashes": [
|
||||
"sha256:793f9e720d0e679cea8f99af6436819bfd1622fc345afeff48878c09f42548f6",
|
||||
"sha256:f582bba980fcf728ab7250dbb6fbdca8d4e074e24eb2915b01184376ffff98c7"
|
||||
"sha256:188907ea9332bdd123a95a457e7487556770480264ce3b78c8835b4347e324cc",
|
||||
"sha256:a2571df484c5635ad996d364242ec28fc69f386915cd69b1842639712b84c36d"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.4.2"
|
||||
"version": "==4.4.3"
|
||||
},
|
||||
"flask-login": {
|
||||
"hashes": [
|
||||
"sha256:1ef79843f5eddd0f143c2cd994c1b05ac83c0401dc6234c143495af9a939613f",
|
||||
"sha256:c0a7baa9fdc448cdd3dd6f0939df72eec5177b2f7abe6cb82fc934d29caac9c3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.6.2"
|
||||
},
|
||||
"flask-pymongo": {
|
||||
"hashes": [
|
||||
|
@ -240,6 +248,14 @@
|
|||
"index": "pypi",
|
||||
"version": "==0.3.9"
|
||||
},
|
||||
"flask-wtf": {
|
||||
"hashes": [
|
||||
"sha256:34fe5c6fee0f69b50e30f81a3b7ea16aa1492a771fe9ad0974d164610c09a6c9",
|
||||
"sha256:9d733658c80be551ce7d5bc13c7a7ac0d80df509be1e23827c847d9520f4359a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.0.1"
|
||||
},
|
||||
"future": {
|
||||
"hashes": [
|
||||
"sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
|
||||
|
@ -799,11 +815,11 @@
|
|||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:0d33c374d41c7863419fc8f6c10bfe25b7b498aa34164d135c622e52580c6b16",
|
||||
"sha256:c04b44a57a6265fe34a4a444e965884716d34bae963119a76353434d6f18e450"
|
||||
"sha256:273b6847ae61f7829c1affcdd9a32f67aa65233be508f4fbaab866c5faa4e408",
|
||||
"sha256:d5340d16943a0f67057329db59b564e938bb3736c6e50ae16ea84d5e5d9ba6d0"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==63.2.0"
|
||||
"version": "==63.3.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
@ -823,19 +839,19 @@
|
|||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec",
|
||||
"sha256:879ba4d1e89654d9769ce13121e0f94310ea32e8d2f8cf587b77c08bbcdb30d6"
|
||||
"sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc",
|
||||
"sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'",
|
||||
"version": "==1.26.10"
|
||||
"version": "==1.26.11"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6",
|
||||
"sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
|
||||
"sha256:4d7013ef96fd197d1cdeb03e066c6c5a491ccb44758a5b2b91137319383e5a5a",
|
||||
"sha256:7e1db6a5ba6b9a8be061e47e900456355b8714c0f238b0313f53afce1a55a79a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.2"
|
||||
"version": "==2.2.1"
|
||||
},
|
||||
"wirerope": {
|
||||
"hashes": [
|
||||
|
@ -843,6 +859,14 @@
|
|||
],
|
||||
"version": "==0.4.5"
|
||||
},
|
||||
"wtforms": {
|
||||
"hashes": [
|
||||
"sha256:6b351bbb12dd58af57ffef05bc78425d08d1914e0fd68ee14143b7ade023c5bc",
|
||||
"sha256:837f2f0e0ca79481b92884962b914eba4e72b7a2daaf1f939c890ed0124b834b"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2",
|
||||
|
@ -933,18 +957,18 @@
|
|||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4",
|
||||
"sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"
|
||||
"sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6",
|
||||
"sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==21.4.0"
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==22.1.0"
|
||||
},
|
||||
"babel": {
|
||||
"hashes": [
|
||||
"sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51",
|
||||
"sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.0'",
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.10.3"
|
||||
},
|
||||
"black": {
|
||||
|
@ -1236,7 +1260,7 @@
|
|||
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
|
||||
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.0'",
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"py": {
|
||||
|
@ -1268,7 +1292,7 @@
|
|||
"sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb",
|
||||
"sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.0'",
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.12.0"
|
||||
},
|
||||
"pyparsing": {
|
||||
|
@ -1326,11 +1350,11 @@
|
|||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:0d33c374d41c7863419fc8f6c10bfe25b7b498aa34164d135c622e52580c6b16",
|
||||
"sha256:c04b44a57a6265fe34a4a444e965884716d34bae963119a76353434d6f18e450"
|
||||
"sha256:273b6847ae61f7829c1affcdd9a32f67aa65233be508f4fbaab866c5faa4e408",
|
||||
"sha256:d5340d16943a0f67057329db59b564e938bb3736c6e50ae16ea84d5e5d9ba6d0"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==63.2.0"
|
||||
"version": "==63.3.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
@ -1392,7 +1416,7 @@
|
|||
"sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07",
|
||||
"sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.0'",
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.0.0"
|
||||
},
|
||||
"sphinxcontrib-jsmath": {
|
||||
|
@ -1483,19 +1507,19 @@
|
|||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec",
|
||||
"sha256:879ba4d1e89654d9769ce13121e0f94310ea32e8d2f8cf587b77c08bbcdb30d6"
|
||||
"sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc",
|
||||
"sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'",
|
||||
"version": "==1.26.10"
|
||||
"version": "==1.26.11"
|
||||
},
|
||||
"virtualenv": {
|
||||
"hashes": [
|
||||
"sha256:288171134a2ff3bfb1a2f54f119e77cd1b81c29fc1265a2356f3e8d14c7d58c4",
|
||||
"sha256:b30aefac647e86af6d82bfc944c556f8f1a9c90427b2fb4e3bfbf338cb82becf"
|
||||
"sha256:0ef5be6d07181946891f5abc8047fda8bc2f0b4b9bf222c64e6e8963baee76db",
|
||||
"sha256:635b272a8e2f77cb051946f46c60a54ace3cb5e25568228bd6b57fc70eca9ff3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==20.15.1"
|
||||
"version": "==20.16.2"
|
||||
},
|
||||
"vulture": {
|
||||
"hashes": [
|
||||
|
|
|
@ -5,7 +5,9 @@ from datetime import timedelta
|
|||
from typing import Iterable, Type
|
||||
|
||||
import flask_restful
|
||||
from flask import Flask, Response, send_from_directory
|
||||
from flask import Flask, Response, jsonify, send_from_directory
|
||||
from flask_login import LoginManager, UserMixin, login_required, logout_user
|
||||
from mongoengine import Document, StringField
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from common import DIContainer
|
||||
|
@ -84,28 +86,44 @@ def serve_home():
|
|||
def init_app_config(app, mongo_url):
|
||||
app.config["MONGO_URI"] = mongo_url
|
||||
|
||||
# See https://flask-jwt-extended.readthedocs.io/en/stable/options
|
||||
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = AUTH_EXPIRATION_TIME
|
||||
# Invalidate the signature of JWTs if the server process restarts. This avoids the edge case
|
||||
# of getting a JWT,
|
||||
# deciding to reset credentials and then still logging in with the old JWT.
|
||||
app.config["JWT_SECRET_KEY"] = str(uuid.uuid4())
|
||||
app.secret_key = str(uuid.uuid4())
|
||||
|
||||
# By default, Flask sorts keys of JSON objects alphabetically.
|
||||
# See https://flask.palletsprojects.com/en/1.1.x/config/#JSON_SORT_KEYS.
|
||||
app.config["JSON_SORT_KEYS"] = False
|
||||
app.config.update(
|
||||
SESSION_COOKIE_HTTPONLY=True,
|
||||
REMEMBER_COOKIE_HTTPONLY=True,
|
||||
SESSION_COOKIE_SAMESITE="Strict",
|
||||
)
|
||||
|
||||
app.url_map.strict_slashes = False
|
||||
app.json_encoder = CustomJSONEncoder
|
||||
|
||||
|
||||
# TODO move
|
||||
class User(Document, UserMixin):
|
||||
username = StringField()
|
||||
password_hash = StringField()
|
||||
|
||||
@staticmethod
|
||||
def get_by_id(id: str):
|
||||
return User.objects.get(id=id)
|
||||
|
||||
|
||||
def init_app_services(app):
|
||||
init_jwt(app)
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
login_manager.session_protection = "strong"
|
||||
mongo.init_app(app)
|
||||
|
||||
with app.app_context():
|
||||
database.init()
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
return User.get_by_id(user_id)
|
||||
|
||||
|
||||
def init_app_url_rules(app):
|
||||
app.add_url_rule("/", "serve_home", serve_home)
|
||||
|
@ -222,4 +240,10 @@ def init_app(mongo_url: str, container: DIContainer):
|
|||
flask_resource_manager = FlaskDIWrapper(api, container)
|
||||
init_api_resources(flask_resource_manager)
|
||||
|
||||
@app.route("/api/logout")
|
||||
@login_required
|
||||
def logout():
|
||||
logout_user()
|
||||
return jsonify({"logout": True})
|
||||
|
||||
return app
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from flask_login import UserMixin
|
||||
from mongoengine import Document, StringField
|
||||
|
||||
|
||||
class User(Document, UserMixin):
|
||||
username = StringField()
|
||||
password_hash = StringField()
|
||||
|
||||
@staticmethod
|
||||
def get_by_id(id: str):
|
||||
return User.objects.get(id)
|
|
@ -2,9 +2,11 @@ import logging
|
|||
from http import HTTPStatus
|
||||
|
||||
import flask_jwt_extended
|
||||
from flask import make_response, request
|
||||
from flask import jsonify, make_response, request
|
||||
from flask_login import current_user, login_required, login_user
|
||||
|
||||
from common.utils.exceptions import IncorrectCredentialsError
|
||||
from monkey_island.cc.models.user import User
|
||||
from monkey_island.cc.resources.AbstractResource import AbstractResource
|
||||
from monkey_island.cc.resources.auth.credential_utils import get_username_password_from_request
|
||||
from monkey_island.cc.resources.request_authentication import create_access_token
|
||||
|
@ -22,8 +24,6 @@ def init_jwt(app):
|
|||
|
||||
class Authenticate(AbstractResource):
|
||||
"""
|
||||
Resource for user authentication. The user provides the username and password and we \
|
||||
give them a JWT. \
|
||||
See `AuthService.js` file for the frontend counterpart for this code. \
|
||||
|
||||
"""
|
||||
|
@ -33,6 +33,9 @@ class Authenticate(AbstractResource):
|
|||
def __init__(self, authentication_service: AuthenticationService):
|
||||
self._authentication_service = authentication_service
|
||||
|
||||
def get(self):
|
||||
return jsonify({"authenticated": current_user.is_authenticated})
|
||||
|
||||
def post(self):
|
||||
"""
|
||||
Example request: \
|
||||
|
@ -45,10 +48,10 @@ class Authenticate(AbstractResource):
|
|||
username, password = get_username_password_from_request(request)
|
||||
|
||||
try:
|
||||
self._authentication_service.authenticate(username, password)
|
||||
access_token = create_access_token(username)
|
||||
user = self._authentication_service.authenticate(username, password)
|
||||
except IncorrectCredentialsError:
|
||||
return make_response({"error": "Invalid credentials"}, HTTPStatus.UNAUTHORIZED)
|
||||
|
||||
# API Spec: Why are we sending "error" here?
|
||||
return make_response({"access_token": access_token, "error": ""}, HTTPStatus.OK)
|
||||
login_user(user)
|
||||
return jsonify({"login": True})
|
||||
|
|
|
@ -2,10 +2,10 @@ import json
|
|||
import logging
|
||||
|
||||
from flask import make_response, request
|
||||
from flask_login import login_required
|
||||
|
||||
from monkey_island.cc.models import IslandMode as IslandModeEnum
|
||||
from monkey_island.cc.resources.AbstractResource import AbstractResource
|
||||
from monkey_island.cc.resources.request_authentication import jwt_required
|
||||
from monkey_island.cc.services import IslandModeService
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -18,7 +18,6 @@ class IslandMode(AbstractResource):
|
|||
self._island_mode_service = island_mode_service
|
||||
|
||||
# API Spec: Instead of POST, this should be PUT
|
||||
@jwt_required
|
||||
def post(self):
|
||||
try:
|
||||
body = json.loads(request.data)
|
||||
|
@ -35,7 +34,7 @@ class IslandMode(AbstractResource):
|
|||
except ValueError:
|
||||
return make_response({}, 422)
|
||||
|
||||
@jwt_required
|
||||
@login_required
|
||||
def get(self):
|
||||
island_mode = self._island_mode_service.get_mode()
|
||||
return make_response({"mode": island_mode.value}, 200)
|
||||
|
|
|
@ -26,7 +26,6 @@ class Root(AbstractResource):
|
|||
else:
|
||||
return make_response(400, {"error": "unknown action"})
|
||||
|
||||
@jwt_required
|
||||
def get_server_info(self):
|
||||
return jsonify(
|
||||
ip_addresses=local_ip_addresses(),
|
||||
|
|
|
@ -8,6 +8,7 @@ from common.utils.exceptions import (
|
|||
UnknownUserError,
|
||||
)
|
||||
from monkey_island.cc.models import UserCredentials
|
||||
from monkey_island.cc.models.user import User
|
||||
from monkey_island.cc.repository import IUserRepository
|
||||
from monkey_island.cc.server_utils.encryption import (
|
||||
ILockableEncryptor,
|
||||
|
@ -29,20 +30,21 @@ class AuthenticationService:
|
|||
self._repository_encryptor = repository_encryptor
|
||||
|
||||
def needs_registration(self) -> bool:
|
||||
return not self._user_repository.has_registered_users()
|
||||
return not User.objects.first()
|
||||
|
||||
def register_new_user(self, username: str, password: str):
|
||||
if not username or not password:
|
||||
raise InvalidRegistrationCredentialsError("Username or password can not be empty.")
|
||||
|
||||
credentials = UserCredentials(username, _hash_password(password))
|
||||
self._user_repository.add_user(credentials)
|
||||
# self._user_repository.add_user(credentials)
|
||||
User(username=username, password_hash=_hash_password(password)).save()
|
||||
self._reset_repository_encryptor(username, password)
|
||||
reset_database()
|
||||
|
||||
def authenticate(self, username: str, password: str):
|
||||
try:
|
||||
registered_user = self._user_repository.get_user_credentials(username)
|
||||
registered_user = User.objects.first()
|
||||
except UnknownUserError:
|
||||
raise IncorrectCredentialsError()
|
||||
|
||||
|
@ -50,6 +52,7 @@ class AuthenticationService:
|
|||
raise IncorrectCredentialsError()
|
||||
|
||||
self._unlock_repository_encryptor(username, password)
|
||||
return registered_user
|
||||
|
||||
def _unlock_repository_encryptor(self, username: str, password: str):
|
||||
secret = _get_secret_from_credentials(username, password)
|
||||
|
|
|
@ -36,6 +36,7 @@ class Database(object):
|
|||
return (
|
||||
not collection.startswith("system.")
|
||||
and not collection == AttackMitigations.COLLECTION_NAME
|
||||
and not collection == "user"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -11,7 +11,7 @@ import LicensePage from './pages/LicensePage';
|
|||
import AuthComponent from './AuthComponent';
|
||||
import LoginPageComponent from './pages/LoginPage';
|
||||
import RegisterPageComponent from './pages/RegisterPage';
|
||||
import LandingPage from "./pages/LandingPage";
|
||||
import LandingPage from './pages/LandingPage';
|
||||
import Notifier from 'react-desktop-notification';
|
||||
import NotFoundPage from './pages/NotFoundPage';
|
||||
import GettingStartedPage from './pages/GettingStartedPage';
|
||||
|
@ -21,13 +21,13 @@ import 'normalize.css/normalize.css';
|
|||
import 'styles/App.css';
|
||||
import 'react-table/react-table.css';
|
||||
import LoadingScreen from './ui-components/LoadingScreen';
|
||||
import SidebarLayoutComponent from "./layouts/SidebarLayoutComponent";
|
||||
import {CompletedSteps} from "./side-menu/CompletedSteps";
|
||||
import SidebarLayoutComponent from './layouts/SidebarLayoutComponent';
|
||||
import {CompletedSteps} from './side-menu/CompletedSteps';
|
||||
import Timeout = NodeJS.Timeout;
|
||||
import IslandHttpClient from "./IslandHttpClient";
|
||||
import _ from "lodash";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {faFileCode, faLightbulb} from "@fortawesome/free-solid-svg-icons";
|
||||
import IslandHttpClient from './IslandHttpClient';
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import {faFileCode, faLightbulb} from '@fortawesome/free-solid-svg-icons';
|
||||
import LogoutPageComponent from './pages/LogoutPage';
|
||||
|
||||
|
||||
let notificationIcon = require('../images/notification-logo-512x512.png');
|
||||
|
@ -41,6 +41,7 @@ export const Routes = {
|
|||
SecurityReport: '/report/security',
|
||||
RansomwareReport: '/report/ransomware',
|
||||
LoginPage: '/login',
|
||||
Logout: '/logout',
|
||||
RegisterPage: '/register',
|
||||
ConfigurePage: '/configure',
|
||||
RunMonkeyPage: '/run-monkey',
|
||||
|
@ -49,7 +50,7 @@ export const Routes = {
|
|||
LicensePage: '/license'
|
||||
}
|
||||
|
||||
export function isReportRoute(route){
|
||||
export function isReportRoute(route) {
|
||||
return route.startsWith(Routes.Report);
|
||||
}
|
||||
|
||||
|
@ -73,8 +74,8 @@ class AppComponent extends AuthComponent {
|
|||
return
|
||||
}
|
||||
|
||||
let res = this.auth.loggedIn();
|
||||
|
||||
this.auth.loggedIn().then((res) => {
|
||||
console.log("called")
|
||||
if (this.state.isLoggedIn !== res) {
|
||||
this.setState({
|
||||
isLoggedIn: res
|
||||
|
@ -89,27 +90,7 @@ class AppComponent extends AuthComponent {
|
|||
});
|
||||
})
|
||||
}
|
||||
|
||||
if (res) {
|
||||
this.setMode()
|
||||
.then(() => {
|
||||
if (this.state.islandMode === "unset") {
|
||||
return
|
||||
}
|
||||
this.authFetch('/api')
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
let completedSteps = CompletedSteps.buildFromResponse(res.completed_steps);
|
||||
// This check is used to prevent unnecessary re-rendering
|
||||
if (_.isEqual(this.state.completedSteps, completedSteps)) {
|
||||
return;
|
||||
}
|
||||
this.setState({completedSteps: completedSteps});
|
||||
this.showInfectionDoneNotification();
|
||||
});
|
||||
}
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
setMode = () => {
|
||||
|
@ -121,6 +102,7 @@ class AppComponent extends AuthComponent {
|
|||
|
||||
renderRoute = (route_path, page_component, is_exact_path = false) => {
|
||||
let render_func = () => {
|
||||
console.log(this.state.isLoggedIn);
|
||||
switch (this.state.isLoggedIn) {
|
||||
case true:
|
||||
if (this.needsRedirectionToLandingPage(route_path)) {
|
||||
|
@ -151,12 +133,12 @@ class AppComponent extends AuthComponent {
|
|||
};
|
||||
|
||||
needsRedirectionToLandingPage = (route_path) => {
|
||||
return (this.state.islandMode === "unset" && route_path !== Routes.LandingPage)
|
||||
return (this.state.islandMode === 'unset' && route_path !== Routes.LandingPage)
|
||||
}
|
||||
|
||||
needsRedirectionToGettingStarted = (route_path) => {
|
||||
return route_path === Routes.LandingPage &&
|
||||
this.state.islandMode !== "unset" && this.state.islandMode !== undefined
|
||||
this.state.islandMode !== 'unset' && this.state.islandMode !== undefined
|
||||
}
|
||||
|
||||
redirectTo = (userPath, targetPath) => {
|
||||
|
@ -176,43 +158,49 @@ class AppComponent extends AuthComponent {
|
|||
}
|
||||
|
||||
getDefaultReport() {
|
||||
if(this.state.islandMode === 'ransomware'){
|
||||
if (this.state.islandMode === 'ransomware') {
|
||||
return Routes.RansomwareReport;
|
||||
} else {
|
||||
return Routes.SecurityReport;
|
||||
}
|
||||
}
|
||||
|
||||
getIslandModeTitle(){
|
||||
if(this.state.islandMode === 'ransomware'){
|
||||
return this.formIslandModeTitle("Ransomware", faFileCode);
|
||||
getIslandModeTitle() {
|
||||
if (this.state.islandMode === 'ransomware') {
|
||||
return this.formIslandModeTitle('Ransomware', faFileCode);
|
||||
} else {
|
||||
return this.formIslandModeTitle("Custom", faLightbulb);
|
||||
return this.formIslandModeTitle('Custom', faLightbulb);
|
||||
}
|
||||
}
|
||||
|
||||
formIslandModeTitle(title, icon){
|
||||
formIslandModeTitle(title, icon) {
|
||||
return (<>
|
||||
<h5 className={'text-muted'}>
|
||||
<FontAwesomeIcon icon={icon} /> {title}
|
||||
<FontAwesomeIcon icon={icon}/> {title}
|
||||
</h5>
|
||||
</>)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
let defaultSideNavProps = {completedSteps: this.state.completedSteps,
|
||||
let defaultSideNavProps = {
|
||||
completedSteps: this.state.completedSteps,
|
||||
onStatusChange: this.updateStatus,
|
||||
islandMode: this.state.islandMode,
|
||||
defaultReport: this.getDefaultReport(),
|
||||
sideNavHeader: this.getIslandModeTitle()}
|
||||
sideNavHeader: this.getIslandModeTitle()
|
||||
}
|
||||
|
||||
return (
|
||||
<Router>
|
||||
<Container fluid>
|
||||
<Switch>
|
||||
<Route path={Routes.LoginPage} render={() => (<LoginPageComponent onStatusChange={this.updateStatus}/>)}/>
|
||||
<Route path={Routes.RegisterPage} render={() => (<RegisterPageComponent onStatusChange={this.updateStatus}/>)}/>
|
||||
<Route path={Routes.LoginPage}
|
||||
render={() => (<LoginPageComponent onStatusChange={this.updateStatus}/>)}/>
|
||||
<Route path={Routes.RegisterPage}
|
||||
render={() => (<RegisterPageComponent onStatusChange={this.updateStatus}/>)}/>
|
||||
<Route path={Routes.Logout}
|
||||
render={() => (<LogoutPageComponent />)}/>
|
||||
{this.renderRoute(Routes.LandingPage,
|
||||
<SidebarLayoutComponent component={LandingPage}
|
||||
sideNavShow={false}
|
||||
|
|
|
@ -9,7 +9,9 @@ class LoginPageComponent extends React.Component {
|
|||
login = (event) => {
|
||||
event.preventDefault()
|
||||
this.auth.login(this.username, this.password).then(res => {
|
||||
if (res['result']) {
|
||||
console.log("HERE")
|
||||
console.log(res)
|
||||
if (res) {
|
||||
this.redirectToHome();
|
||||
} else {
|
||||
this.setState({failed: true});
|
||||
|
@ -42,17 +44,16 @@ class LoginPageComponent extends React.Component {
|
|||
failed: false
|
||||
};
|
||||
|
||||
this.auth.needsRegistration()
|
||||
.then(result => {
|
||||
if (result) {
|
||||
this.redirectToRegistration()
|
||||
}
|
||||
//this.auth.needsRegistration()
|
||||
// .then(result => {
|
||||
// if (result) {
|
||||
// this.redirectToRegistration()
|
||||
// }
|
||||
// })
|
||||
|
||||
this.auth.loggedIn().then((res) => {
|
||||
if(res){this.redirectToHome();}
|
||||
})
|
||||
|
||||
if (this.auth.loggedIn()) {
|
||||
this.redirectToHome();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import React from 'react';
|
||||
import {Button, Col, Container, Form, Row} from 'react-bootstrap';
|
||||
|
||||
import AuthService from '../../services/AuthService';
|
||||
import monkeyGeneral from '../../images/militant-monkey.svg';
|
||||
import ParticleBackground from '../ui-components/ParticleBackground';
|
||||
import {Redirect} from 'react-router-dom';
|
||||
import {Routes} from '../Main';
|
||||
|
||||
class LogoutPageComponent extends React.Component {
|
||||
|
||||
redirectToLogin = () => {
|
||||
window.location.href = '/login';
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
fetch('/api/logout').then(this.redirectToLogin);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (<p>Logging out</p>);
|
||||
}
|
||||
}
|
||||
|
||||
export default LogoutPageComponent;
|
|
@ -28,13 +28,7 @@ export default class AuthService {
|
|||
})
|
||||
}).then(response => response.json())
|
||||
.then(res => {
|
||||
if (Object.prototype.hasOwnProperty.call(res, 'access_token')) {
|
||||
this._setToken(res['access_token']);
|
||||
return {result: true};
|
||||
} else {
|
||||
this._removeToken();
|
||||
return {result: false};
|
||||
}
|
||||
return res["login"]
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -61,31 +55,8 @@ export default class AuthService {
|
|||
};
|
||||
|
||||
_authFetch = (url, options = {}) => {
|
||||
const headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
if (this.loggedIn()) {
|
||||
headers['Authorization'] = 'Bearer ' + this._getToken();
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(options, 'headers')) {
|
||||
for (let header in headers) {
|
||||
options['headers'][header] = headers[header];
|
||||
}
|
||||
} else {
|
||||
options['headers'] = headers;
|
||||
}
|
||||
|
||||
return fetch(url, options)
|
||||
.then(res => {
|
||||
if (res.status === 401) {
|
||||
res.clone().json().then(res_json => {
|
||||
console.log('Got 401 from server while trying to authFetch: ' + JSON.stringify(res_json));
|
||||
});
|
||||
this._removeToken();
|
||||
}
|
||||
return res;
|
||||
})
|
||||
};
|
||||
|
@ -100,8 +71,12 @@ export default class AuthService {
|
|||
};
|
||||
|
||||
loggedIn() {
|
||||
const token = this._getToken();
|
||||
return ((token !== null) && !this._isTokenExpired(token));
|
||||
return fetch(this.AUTHENTICATION_API_ENDPOINT)
|
||||
.then(response => response.json())
|
||||
.then(res => {
|
||||
console.log(res);
|
||||
return res['authenticated'];
|
||||
})
|
||||
}
|
||||
|
||||
logout = () => {
|
||||
|
|
Loading…
Reference in New Issue