Password setup - backend fixes
This commit is contained in:
parent
c8cf7d52a4
commit
889bf359e1
|
@ -5,7 +5,7 @@ import flask_restful
|
||||||
from flask import Flask, send_from_directory, Response
|
from flask import Flask, send_from_directory, Response
|
||||||
from werkzeug.exceptions import NotFound
|
from werkzeug.exceptions import NotFound
|
||||||
|
|
||||||
from monkey_island.cc.auth import init_jwt
|
from monkey_island.cc.resources.auth.auth import init_jwt
|
||||||
from monkey_island.cc.database import mongo, database
|
from monkey_island.cc.database import mongo, database
|
||||||
from monkey_island.cc.environment.environment_singleton import env
|
from monkey_island.cc.environment.environment_singleton import env
|
||||||
from monkey_island.cc.resources.client_run import ClientRun
|
from monkey_island.cc.resources.client_run import ClientRun
|
||||||
|
|
|
@ -5,7 +5,6 @@ from datetime import timedelta
|
||||||
|
|
||||||
__author__ = 'itay.mizeretz'
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
from common.utils.exceptions import InvalidRegistrationCredentials
|
from common.utils.exceptions import InvalidRegistrationCredentials
|
||||||
from monkey_island.cc.environment.environment_config import EnvironmentConfig
|
from monkey_island.cc.environment.environment_config import EnvironmentConfig
|
||||||
|
@ -25,7 +24,7 @@ class Environment(object, metaclass=ABCMeta):
|
||||||
_testing = False
|
_testing = False
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._config = None
|
self._config = EnvironmentConfig("", "", UserCreds())
|
||||||
self._testing = False # Assume env is not for unit testing.
|
self._testing = False # Assume env is not for unit testing.
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -40,6 +39,9 @@ class Environment(object, metaclass=ABCMeta):
|
||||||
def try_add_user(self, credentials: UserCreds):
|
def try_add_user(self, credentials: UserCreds):
|
||||||
if self._credentials_required:
|
if self._credentials_required:
|
||||||
if credentials:
|
if credentials:
|
||||||
|
if self._is_registered():
|
||||||
|
raise InvalidRegistrationCredentials("User has already been registered. "
|
||||||
|
"Reset credentials or login.")
|
||||||
self._config.add_user(credentials)
|
self._config.add_user(credentials)
|
||||||
else:
|
else:
|
||||||
raise InvalidRegistrationCredentials("Missing part of credentials.")
|
raise InvalidRegistrationCredentials("Missing part of credentials.")
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import monkey_island.cc.auth
|
from monkey_island.cc.resources.auth.auth_user import User
|
||||||
from monkey_island.cc.auth_user import User
|
|
||||||
from monkey_island.cc.environment import Environment
|
from monkey_island.cc.environment import Environment
|
||||||
from common.cloud.aws.aws_instance import AwsInstance
|
from common.cloud.aws.aws_instance import AwsInstance
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,10 @@ import json
|
||||||
import os
|
import os
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
|
|
||||||
from monkey_island.cc.auth_user import User
|
from monkey_island.cc.resources.auth.auth_user import User
|
||||||
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
||||||
from monkey_island.cc.environment.user_creds import UserCreds
|
from monkey_island.cc.environment.user_creds import UserCreds
|
||||||
|
from monkey_island.cc.resources.auth.user_store import UserStore
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentConfig:
|
class EnvironmentConfig:
|
||||||
|
@ -60,6 +61,8 @@ class EnvironmentConfig:
|
||||||
|
|
||||||
def add_user(self, credentials: UserCreds):
|
def add_user(self, credentials: UserCreds):
|
||||||
self.user_creds = credentials
|
self.user_creds = credentials
|
||||||
|
self.save_to_file()
|
||||||
|
UserStore.set_users(self.get_users())
|
||||||
|
|
||||||
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()
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from monkey_island.cc.environment import Environment
|
from monkey_island.cc.environment import Environment
|
||||||
import monkey_island.cc.auth
|
|
||||||
|
|
||||||
__author__ = 'itay.mizeretz'
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
|
@ -10,6 +9,6 @@ class PasswordEnvironment(Environment):
|
||||||
|
|
||||||
def get_auth_users(self):
|
def get_auth_users(self):
|
||||||
if self._is_registered():
|
if self._is_registered():
|
||||||
return self._config.get_users
|
return self._config.get_users()
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from monkey_island.cc.auth_user import User
|
from monkey_island.cc.resources.auth.auth_user import User
|
||||||
from monkey_island.cc.environment import Environment
|
from monkey_island.cc.environment import Environment
|
||||||
|
|
||||||
__author__ = 'itay.mizeretz'
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
|
@ -2,8 +2,10 @@ import json
|
||||||
import os
|
import os
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
from monkey_island.cc.environment import Environment, EnvironmentConfig
|
from common.utils.exceptions import InvalidRegistrationCredentials
|
||||||
|
from monkey_island.cc.environment import Environment, EnvironmentConfig, UserCreds
|
||||||
|
|
||||||
|
|
||||||
def get_server_config_file_path_test_version():
|
def get_server_config_file_path_test_version():
|
||||||
|
@ -57,6 +59,21 @@ class TestEnvironment(TestCase):
|
||||||
"4f2e9b3ca9f484f521d0ce464345cc1aec96779149c14"
|
"4f2e9b3ca9f484f521d0ce464345cc1aec96779149c14"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@patch.object(target=EnvironmentConfig, attribute="save_to_file", new=MagicMock())
|
||||||
|
def test_try_add_user(self):
|
||||||
|
env = TestEnvironment.EnvironmentWithCredentials()
|
||||||
|
credentials = UserCreds(username="test", password_hash="1231234")
|
||||||
|
env.try_add_user(credentials)
|
||||||
|
|
||||||
|
credentials = UserCreds(username="test")
|
||||||
|
with self.assertRaises(InvalidRegistrationCredentials):
|
||||||
|
env.try_add_user(credentials)
|
||||||
|
|
||||||
|
env = TestEnvironment.EnvironmentNoCredentials()
|
||||||
|
credentials = UserCreds(username="test", password_hash="1231234")
|
||||||
|
with self.assertRaises(InvalidRegistrationCredentials):
|
||||||
|
env.try_add_user(credentials)
|
||||||
|
|
||||||
def test_needs_registration(self):
|
def test_needs_registration(self):
|
||||||
env = TestEnvironment.EnvironmentWithCredentials()
|
env = TestEnvironment.EnvironmentWithCredentials()
|
||||||
self._test_bool_env_method("needs_registration", env, TestEnvironment.CONFIG_WITH_CREDENTIALS, False)
|
self._test_bool_env_method("needs_registration", env, TestEnvironment.CONFIG_WITH_CREDENTIALS, False)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from monkey_island.cc.auth_user import User
|
from monkey_island.cc.resources.auth.auth_user import User
|
||||||
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
|
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
|
||||||
from monkey_island.cc.environment.aws import AwsEnvironment
|
from monkey_island.cc.environment.aws import AwsEnvironment
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
import json
|
import json
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from monkey_island.cc.auth_user import User
|
from monkey_island.cc.resources.auth.auth_user import User
|
||||||
|
|
||||||
|
|
||||||
class UserCreds:
|
class UserCreds:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import jsonify, request, json, current_app
|
from flask import jsonify, request, json, current_app
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.attack.attack_config import AttackConfig
|
from monkey_island.cc.services.attack.attack_config import AttackConfig
|
||||||
|
|
||||||
__author__ = "VakarisZ"
|
__author__ = "VakarisZ"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.attack.attack_report import AttackReportService
|
from monkey_island.cc.services.attack.attack_report import AttackReportService
|
||||||
from monkey_island.cc.services.attack.attack_schema import SCHEMA
|
from monkey_island.cc.services.attack.attack_schema import SCHEMA
|
||||||
from flask import json, current_app
|
from flask import json, current_app
|
||||||
|
|
|
@ -5,23 +5,22 @@ from flask_jwt import JWT, _jwt_required, JWTError
|
||||||
from werkzeug.security import safe_str_cmp
|
from werkzeug.security import safe_str_cmp
|
||||||
|
|
||||||
from monkey_island.cc.environment.environment_singleton import env
|
from monkey_island.cc.environment.environment_singleton import env
|
||||||
|
from monkey_island.cc.resources.auth.user_store import UserStore
|
||||||
|
|
||||||
__author__ = 'itay.mizeretz'
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
|
|
||||||
def init_jwt(app):
|
def init_jwt(app):
|
||||||
users = env.get_auth_users()
|
UserStore.set_users(env.get_auth_users())
|
||||||
username_table = {u.username: u for u in users}
|
|
||||||
userid_table = {u.id: u for u in users}
|
|
||||||
|
|
||||||
def authenticate(username, secret):
|
def authenticate(username, secret):
|
||||||
user = username_table.get(username, None)
|
user = UserStore.username_table.get(username, None)
|
||||||
if user and safe_str_cmp(user.secret.encode('utf-8'), secret.encode('utf-8')):
|
if user and safe_str_cmp(user.secret.encode('utf-8'), secret.encode('utf-8')):
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def identity(payload):
|
def identity(payload):
|
||||||
user_id = payload['identity']
|
user_id = payload['identity']
|
||||||
return userid_table.get(user_id, None)
|
return UserStore.userid_table.get(user_id, None)
|
||||||
|
|
||||||
JWT(app, authenticate, identity)
|
JWT(app, authenticate, identity)
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from monkey_island.cc.resources.auth.auth_user import User
|
||||||
|
|
||||||
|
|
||||||
|
class UserStore:
|
||||||
|
users = []
|
||||||
|
username_table = {}
|
||||||
|
userid_table = {}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_users(users: List[User]):
|
||||||
|
UserStore.users = users
|
||||||
|
UserStore.username_table = {u.username: u for u in UserStore.users}
|
||||||
|
UserStore.userid_table = {u.id: u for u in UserStore.users}
|
|
@ -3,7 +3,7 @@ import json
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import request, jsonify, abort
|
from flask import request, jsonify, abort
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.config import ConfigService
|
from monkey_island.cc.services.config import ConfigService
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
|
|
||||||
import flask_restful
|
import flask_restful
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.island_logs import IslandLogService
|
from monkey_island.cc.services.island_logs import IslandLogService
|
||||||
|
|
||||||
__author__ = "Maor.Rayzin"
|
__author__ = "Maor.Rayzin"
|
||||||
|
|
|
@ -4,7 +4,7 @@ import flask_restful
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
from monkey_island.cc.resources.test.utils.telem_store import TestTelemStore
|
from monkey_island.cc.resources.test.utils.telem_store import TestTelemStore
|
||||||
from monkey_island.cc.services.log import LogService
|
from monkey_island.cc.services.log import LogService
|
||||||
|
|
|
@ -3,7 +3,7 @@ import json
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import request, jsonify, abort
|
from flask import request, jsonify, abort
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.config import ConfigService
|
from monkey_island.cc.services.config import ConfigService
|
||||||
|
|
||||||
__author__ = 'Barak'
|
__author__ = 'Barak'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import flask_restful
|
import flask_restful
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.edge import EdgeService
|
from monkey_island.cc.services.edge import EdgeService
|
||||||
from monkey_island.cc.services.node import NodeService
|
from monkey_island.cc.services.node import NodeService
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from flask import request
|
from flask import request
|
||||||
import flask_restful
|
import flask_restful
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.node import NodeService
|
from monkey_island.cc.services.node import NodeService
|
||||||
|
|
||||||
__author__ = 'Barak'
|
__author__ = 'Barak'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import flask_restful
|
import flask_restful
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.utils.node_states import NodeStates as NodeStateList
|
from monkey_island.cc.services.utils.node_states import NodeStates as NodeStateList
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import flask_restful
|
||||||
from flask import request, send_from_directory, Response
|
from flask import request, send_from_directory, Response
|
||||||
from monkey_island.cc.services.config import ConfigService
|
from monkey_island.cc.services.config import ConfigService
|
||||||
from monkey_island.cc.services.post_breach_files import PBA_WINDOWS_FILENAME_PATH, PBA_LINUX_FILENAME_PATH, UPLOADS_DIR
|
from monkey_island.cc.services.post_breach_files import PBA_WINDOWS_FILENAME_PATH, PBA_LINUX_FILENAME_PATH, UPLOADS_DIR
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
import os
|
import os
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
import logging
|
import logging
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Registration(flask_restful.Resource):
|
||||||
credentials = UserCreds.get_from_json(request.data)
|
credentials = UserCreds.get_from_json(request.data)
|
||||||
try:
|
try:
|
||||||
env.try_add_user(credentials)
|
env.try_add_user(credentials)
|
||||||
return make_response({"error": ""}, 300)
|
return make_response({"error": ""}, 200)
|
||||||
except InvalidRegistrationCredentials as e:
|
except InvalidRegistrationCredentials as e:
|
||||||
return make_response({"error": e}, 400)
|
return make_response({"error": str(e)}, 400)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ from botocore.exceptions import NoCredentialsError, ClientError
|
||||||
from flask import request, jsonify, make_response
|
from flask import request, jsonify, make_response
|
||||||
import flask_restful
|
import flask_restful
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService
|
from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService
|
||||||
from common.cloud.aws.aws_service import AwsService
|
from common.cloud.aws.aws_service import AwsService
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import http.client
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.reporting.report import ReportService
|
from monkey_island.cc.services.reporting.report import ReportService
|
||||||
from monkey_island.cc.services.reporting.zero_trust_service import ZeroTrustService
|
from monkey_island.cc.services.reporting.zero_trust_service import ZeroTrustService
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import threading
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import request, make_response, jsonify
|
from flask import request, make_response, jsonify
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
from monkey_island.cc.services.database import Database
|
from monkey_island.cc.services.database import Database
|
||||||
from monkey_island.cc.services.infection_lifecycle import InfectionLifecycle
|
from monkey_island.cc.services.infection_lifecycle import InfectionLifecycle
|
||||||
|
|
|
@ -6,7 +6,7 @@ import dateutil
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
from monkey_island.cc.resources.test.utils.telem_store import TestTelemStore
|
from monkey_island.cc.resources.test.utils.telem_store import TestTelemStore
|
||||||
from monkey_island.cc.services.node import NodeService
|
from monkey_island.cc.services.node import NodeService
|
||||||
|
|
|
@ -6,7 +6,7 @@ import flask_restful
|
||||||
from flask import request
|
from flask import request
|
||||||
import flask_pymongo
|
import flask_pymongo
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
from monkey_island.cc.services.node import NodeService
|
from monkey_island.cc.services.node import NodeService
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
|
|
||||||
import flask_restful
|
import flask_restful
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.attack.attack_report import AttackReportService
|
from monkey_island.cc.services.attack.attack_report import AttackReportService
|
||||||
from monkey_island.cc.services.reporting.report import ReportService
|
from monkey_island.cc.services.reporting.report import ReportService
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from bson import json_util
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.database import mongo, database
|
from monkey_island.cc.database import mongo, database
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from bson import json_util
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import flask_restful
|
import flask_restful
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from monkey_island.cc.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
from monkey_island.cc.services.reporting.zero_trust_service import ZeroTrustService
|
from monkey_island.cc.services.reporting.zero_trust_service import ZeroTrustService
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {BrowserRouter as Router, NavLink, Redirect, Route, Switch} from 'react-router-dom';
|
import {BrowserRouter as Router, NavLink, Redirect, Route, Switch} from 'react-router-dom';
|
||||||
import {Col, Grid, Row} from 'react-bootstrap';
|
import {Col, Grid, Row} from 'react-bootstrap';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
|
||||||
import { faCheck } from '@fortawesome/free-solid-svg-icons/faCheck'
|
import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
|
||||||
import { faUndo } from '@fortawesome/free-solid-svg-icons/faUndo'
|
import {faUndo} from '@fortawesome/free-solid-svg-icons/faUndo'
|
||||||
|
|
||||||
import RunServerPage from 'components/pages/RunServerPage';
|
import RunServerPage from 'components/pages/RunServerPage';
|
||||||
import ConfigurePage from 'components/pages/ConfigurePage';
|
import ConfigurePage from 'components/pages/ConfigurePage';
|
||||||
|
@ -15,6 +15,7 @@ import ReportPage from 'components/pages/ReportPage';
|
||||||
import LicensePage from 'components/pages/LicensePage';
|
import LicensePage from 'components/pages/LicensePage';
|
||||||
import AuthComponent from 'components/AuthComponent';
|
import AuthComponent from 'components/AuthComponent';
|
||||||
import LoginPageComponent from 'components/pages/LoginPage';
|
import LoginPageComponent from 'components/pages/LoginPage';
|
||||||
|
import RegisterPageComponent from 'components/pages/RegisterPage';
|
||||||
import Notifier from 'react-desktop-notification';
|
import Notifier from 'react-desktop-notification';
|
||||||
import NotFoundPage from 'components/pages/NotFoundPage';
|
import NotFoundPage from 'components/pages/NotFoundPage';
|
||||||
|
|
||||||
|
@ -43,6 +44,15 @@ class AppComponent extends AuthComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!res){
|
||||||
|
this.auth.needsRegistration()
|
||||||
|
.then(result => {
|
||||||
|
this.setState({
|
||||||
|
needsRegistration: result
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
this.authFetch('/api')
|
this.authFetch('/api')
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
|
@ -70,10 +80,16 @@ class AppComponent extends AuthComponent {
|
||||||
case true:
|
case true:
|
||||||
return page_component;
|
return page_component;
|
||||||
case false:
|
case false:
|
||||||
return <Redirect to={{pathname: '/login'}}/>;
|
switch (this.state.needsRegistration){
|
||||||
|
case true:
|
||||||
|
return <Redirect to={{pathname: '/register'}}/>
|
||||||
|
case false:
|
||||||
|
return <Redirect to={{pathname: '/login'}}/>;
|
||||||
|
default:
|
||||||
|
return page_component;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return page_component;
|
return page_component;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,8 +101,8 @@ class AppComponent extends AuthComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
redirectTo = (userPath, targetPath) => {
|
redirectTo = (userPath, targetPath) => {
|
||||||
let pathQuery = new RegExp(userPath+'[\/]?$', 'g');
|
let pathQuery = new RegExp(userPath + '[\/]?$', 'g');
|
||||||
if(window.location.pathname.match(pathQuery)){
|
if (window.location.pathname.match(pathQuery)) {
|
||||||
return <Redirect to={{pathname: targetPath}}/>
|
return <Redirect to={{pathname: targetPath}}/>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -100,7 +116,8 @@ class AppComponent extends AuthComponent {
|
||||||
run_monkey: false,
|
run_monkey: false,
|
||||||
infection_done: false,
|
infection_done: false,
|
||||||
report_done: false,
|
report_done: false,
|
||||||
isLoggedIn: undefined
|
isLoggedIn: undefined,
|
||||||
|
needsRegistration: undefined
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -201,19 +218,20 @@ class AppComponent extends AuthComponent {
|
||||||
<Col sm={9} md={10} smOffset={3} mdOffset={2} className='main'>
|
<Col sm={9} md={10} smOffset={3} mdOffset={2} className='main'>
|
||||||
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/login' render={() => (<LoginPageComponent onStatusChange={this.updateStatus}/>)}/>
|
<Route path='/login' render={() => (<LoginPageComponent onStatusChange={this.updateStatus}/>)}/>
|
||||||
{this.renderRoute('/', <RunServerPage onStatusChange={this.updateStatus}/>, true)}
|
<Route path='/register' render={() => (<RegisterPageComponent onStatusChange={this.updateStatus}/>)}/>
|
||||||
{this.renderRoute('/configure', <ConfigurePage onStatusChange={this.updateStatus}/>)}
|
{this.renderRoute('/', <RunServerPage onStatusChange={this.updateStatus}/>, true)}
|
||||||
{this.renderRoute('/run-monkey', <RunMonkeyPage onStatusChange={this.updateStatus}/>)}
|
{this.renderRoute('/configure', <ConfigurePage onStatusChange={this.updateStatus}/>)}
|
||||||
{this.renderRoute('/infection/map', <MapPage onStatusChange={this.updateStatus}/>)}
|
{this.renderRoute('/run-monkey', <RunMonkeyPage onStatusChange={this.updateStatus}/>)}
|
||||||
{this.renderRoute('/infection/telemetry', <TelemetryPage onStatusChange={this.updateStatus}/>)}
|
{this.renderRoute('/infection/map', <MapPage onStatusChange={this.updateStatus}/>)}
|
||||||
{this.renderRoute('/start-over', <StartOverPage onStatusChange={this.updateStatus}/>)}
|
{this.renderRoute('/infection/telemetry', <TelemetryPage onStatusChange={this.updateStatus}/>)}
|
||||||
{this.redirectTo('/report', '/report/security')}
|
{this.renderRoute('/start-over', <StartOverPage onStatusChange={this.updateStatus}/>)}
|
||||||
{this.renderRoute('/report/security', <ReportPage/>)}
|
{this.redirectTo('/report', '/report/security')}
|
||||||
{this.renderRoute('/report/attack', <ReportPage/>)}
|
{this.renderRoute('/report/security', <ReportPage/>)}
|
||||||
{this.renderRoute('/report/zeroTrust', <ReportPage/>)}
|
{this.renderRoute('/report/attack', <ReportPage/>)}
|
||||||
{this.renderRoute('/license', <LicensePage onStatusChange={this.updateStatus}/>)}
|
{this.renderRoute('/report/zeroTrust', <ReportPage/>)}
|
||||||
<Route component={NotFoundPage} />
|
{this.renderRoute('/license', <LicensePage onStatusChange={this.updateStatus}/>)}
|
||||||
|
<Route component={NotFoundPage}/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Col} from 'react-bootstrap';
|
import {Col} from 'react-bootstrap';
|
||||||
|
|
||||||
import AuthService from '../../services/AuthService'
|
import AuthService from '../../services/AuthService';
|
||||||
|
|
||||||
class LoginPageComponent extends React.Component {
|
class LoginPageComponent extends React.Component {
|
||||||
login = () => {
|
login = () => {
|
||||||
|
@ -26,6 +26,10 @@ class LoginPageComponent extends React.Component {
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
redirectToRegistration = () => {
|
||||||
|
window.location.href = '/register';
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.username = '';
|
this.username = '';
|
||||||
|
@ -34,6 +38,13 @@ class LoginPageComponent extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
failed: false
|
failed: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.auth.needsRegistration()
|
||||||
|
.then(result => {
|
||||||
|
if(result){
|
||||||
|
this.redirectToRegistration()
|
||||||
|
}
|
||||||
|
})
|
||||||
this.auth.loggedIn()
|
this.auth.loggedIn()
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res) {
|
if (res) {
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {Col} from 'react-bootstrap';
|
||||||
|
|
||||||
|
import AuthService from '../../services/AuthService';
|
||||||
|
|
||||||
|
class RegisterPageComponent extends React.Component {
|
||||||
|
|
||||||
|
register = () => {
|
||||||
|
this.auth.register(this.username, this.password).then(res => {
|
||||||
|
this.setState({failed: false, error: ""});
|
||||||
|
if (res['result']) {
|
||||||
|
this.redirectToHome();
|
||||||
|
} else {
|
||||||
|
this.setState({failed: true,
|
||||||
|
error: res['error']});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
updateUsername = (evt) => {
|
||||||
|
this.username = evt.target.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
updatePassword = (evt) => {
|
||||||
|
this.password = evt.target.value;
|
||||||
|
};
|
||||||
|
redirectToHome = () => {
|
||||||
|
window.location.href = '/';
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.username = '';
|
||||||
|
this.password = '';
|
||||||
|
this.auth = new AuthService();
|
||||||
|
this.state = {
|
||||||
|
failed: false,
|
||||||
|
loading: false
|
||||||
|
};
|
||||||
|
|
||||||
|
this.auth.needsRegistration()
|
||||||
|
.then(result => {
|
||||||
|
if(!result){
|
||||||
|
this.redirectToHome()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Col xs={12} lg={8}>
|
||||||
|
<h1 className="page-title">First time?</h1>
|
||||||
|
<h3 className="page-title">Let's secure your island</h3>
|
||||||
|
<div className="col-sm-6 col-sm-offset-3" style={{'fontSize': '1.2em'}}>
|
||||||
|
<div className="panel panel-default">
|
||||||
|
<div className="panel-heading text-center">
|
||||||
|
<b>Register</b>
|
||||||
|
</div>
|
||||||
|
<div className="panel-body">
|
||||||
|
<div className="input-group center-block text-center">
|
||||||
|
<input type="text" className="form-control" placeholder="Username"
|
||||||
|
onChange={evt => this.updateUsername(evt)}/>
|
||||||
|
<input type="password" className="form-control" placeholder="Password"
|
||||||
|
onChange={evt => this.updatePassword(evt)}/>
|
||||||
|
<button type="button" className="btn btn-primary btn-lg" style={{margin: '5px'}}
|
||||||
|
onClick={() => {
|
||||||
|
this.register()
|
||||||
|
}}>
|
||||||
|
Lets Go!
|
||||||
|
</button>
|
||||||
|
{
|
||||||
|
this.state.failed ?
|
||||||
|
<div className="alert alert-danger" role="alert">{this.state.error}</div>
|
||||||
|
:
|
||||||
|
''
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RegisterPageComponent;
|
|
@ -8,6 +8,8 @@ export default class AuthService {
|
||||||
'8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557';
|
'8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557';
|
||||||
|
|
||||||
SECONDS_BEFORE_JWT_EXPIRES = 20;
|
SECONDS_BEFORE_JWT_EXPIRES = 20;
|
||||||
|
AUTHENTICATION_API_ENDPOINT = '/api/auth';
|
||||||
|
REGISTRATION_API_ENDPOINT = '/api/registration';
|
||||||
|
|
||||||
login = (username, password) => {
|
login = (username, password) => {
|
||||||
return this._login(username, this.hashSha3(password));
|
return this._login(username, this.hashSha3(password));
|
||||||
|
@ -30,7 +32,7 @@ export default class AuthService {
|
||||||
}
|
}
|
||||||
|
|
||||||
_login = (username, password) => {
|
_login = (username, password) => {
|
||||||
return this._authFetch('/api/auth', {
|
return this._authFetch(this.AUTHENTICATION_API_ENDPOINT, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
username,
|
username,
|
||||||
|
@ -48,6 +50,28 @@ export default class AuthService {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
register = (username, password) => {
|
||||||
|
return this._register(username, this.hashSha3(password));
|
||||||
|
};
|
||||||
|
|
||||||
|
_register = (username, password) => {
|
||||||
|
return this._authFetch(this.REGISTRATION_API_ENDPOINT, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
'user': username,
|
||||||
|
'password_hash': password
|
||||||
|
})
|
||||||
|
}).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
return this._login(username, password)
|
||||||
|
} else {
|
||||||
|
return res.json().then(res_json => {
|
||||||
|
return {result: false, error: res_json['error']};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
_authFetch = (url, options = {}) => {
|
_authFetch = (url, options = {}) => {
|
||||||
const headers = {
|
const headers = {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
|
@ -72,7 +96,16 @@ export default class AuthService {
|
||||||
this._removeToken();
|
this._removeToken();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
});
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
needsRegistration = () => {
|
||||||
|
return fetch(this.REGISTRATION_API_ENDPOINT,
|
||||||
|
{method: 'GET'})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(res => {
|
||||||
|
return res['needs_registration']
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
async loggedIn() {
|
async loggedIn() {
|
||||||
|
|
Loading…
Reference in New Issue