diff --git a/README.md b/README.md index de6f5bb..1f2ba5d 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ It also manages the FSM. As you can see this file is set up to start with the container in `solvable/supervisor/tfw_server.conf`. `event_handler_main.py` contains example usage of our pre-defined event handlers written in Python3. -As you can see they run in a separate process (set up in `solvable/supervisor/event_handlers.conf`). +As you can see they run in a separate process (set up in `solvable/supervisor/event_handler_main.conf`). These event handlers could be implemented in any language that has ZMQ bindings. Note that you don't have to use all our event handlers. @@ -204,7 +204,7 @@ When creating your own challenge the process should be the following: - Set it up to run: `solvable/supervisor/tfw_server.conf` 4. Create event handlers connecting to the `TFWServer` handling events you want to process: - Create an event handler server: `solvable/src/event_handler_main.py` - - Set it up to run: `solvable/supervisor/event_handlers.conf` + - Set it up to run: `solvable/supervisor/event_handler_main.conf` 5. Modify the frontend in `solvable/frontend` to fit your challenge - This usually involves using our pre-made components - And perhaps doing some of your own stuff, like: diff --git a/solvable/src/event_handler_main.py b/solvable/src/event_handler_main.py index 2950235..297f132 100644 --- a/solvable/src/event_handler_main.py +++ b/solvable/src/event_handler_main.py @@ -2,7 +2,8 @@ from ast import literal_eval from tornado.ioloop import IOLoop -from tfw.components import IdeEventHandler, TerminalEventHandler, ProcessManagingEventHandler, BashMonitor +from tfw.components import IdeEventHandler, TerminalEventHandler +from tfw.components import ProcessManagingEventHandler, BashMonitor from tfw.components import TerminalCommands, LogMonitoringEventHandler from tfw.networking import MessageSender, TFWServerConnector from tfw.config import TFWENV @@ -13,6 +14,10 @@ LOG = logging.getLogger(__name__) def cenator(history): + """ + Logs commands executed in terminal to messages. + !! Please remove from production code. !! + """ LOG.debug('User executed command: "%s"', history[-1]) MessageSender().send('JOHN CENA', f'You\'ve executed "{history[-1]}"') @@ -20,7 +25,7 @@ def cenator(history): class TestCommands(TerminalCommands): """ Some example commands useful for debugging. - Please remove from production code and inherit your own + !! Please remove from production code !! and inherit your own class from TerminalCommands if you need to define custom commands in your challenge. """ @@ -38,7 +43,7 @@ class TestCommands(TerminalCommands): 'key': 'shell', 'data': { 'command': 'write', - 'shellcmd': f'sendmessage {message_template}' + 'value': f'sendmessage {message_template}' } }) else: @@ -50,20 +55,22 @@ class TestCommands(TerminalCommands): This can speed up development when combined with mounting volumes from host to container. """ - seppuku = ('nohup sh -c "supervisorctl restart tfwserver event_handler_main" &> /dev/null & ' - 'clear && echo "Committed seppuku! :)" && sleep infinity') + seppuku = ( + 'nohup sh -c "supervisorctl restart tfwserver event_handler_main" &> /dev/null & ' + 'clear && echo "Committed seppuku! :)" && sleep infinity' + ) uplink = TFWServerConnector() uplink.send_to_eventhandler({ 'key': 'shell', 'data': { 'command': 'write', - 'shellcmd': f'{seppuku}\n' + 'value': f'{seppuku}\n' } }) uplink.send({ 'key': 'dashboard', 'data': { - 'command': 'reload_frontend' + 'command': 'reloadFrontend' } }) @@ -73,8 +80,7 @@ if __name__ == '__main__': key='ide', allowed_directories=[TFWENV.IDE_WD, TFWENV.WEBSERVICE_DIR], directory=TFWENV.IDE_WD, - exclude=['*.pyc'], - additional_watched_directories=[TFWENV.WEBSERVICE_DIR] + exclude=['*.pyc'] ) terminal = TerminalEventHandler( # Web shell backend key='shell', @@ -92,10 +98,9 @@ if __name__ == '__main__': ) eventhandlers = {ide, terminal, processmanager, logmonitor} - terminal.historymonitor.subscribe_callback(cenator) - commands = TestCommands(bashrc=f'/home/{TAOENV.USER}/.bashrc') terminal.historymonitor.subscribe_callback(commands.callback) + terminal.historymonitor.subscribe_callback(cenator) try: IOLoop.instance().start() diff --git a/solvable/src/webservice/model.py b/solvable/src/webservice/model.py index f135b25..2439684 100644 --- a/solvable/src/webservice/model.py +++ b/solvable/src/webservice/model.py @@ -6,9 +6,11 @@ from sqlalchemy.orm import sessionmaker engine = create_engine('sqlite:///db.db', convert_unicode=True) -session_factory = sessionmaker(autocommit=False, - autoflush=False, - bind=engine) +session_factory = sessionmaker( + autocommit=False, + autoflush=False, + bind=engine +) @contextmanager diff --git a/solvable/src/webservice/server.py b/solvable/src/webservice/server.py index cc84ecb..6f4aab7 100644 --- a/solvable/src/webservice/server.py +++ b/solvable/src/webservice/server.py @@ -10,7 +10,9 @@ BASEURL = getenv('BASEURL', '') init_db() app = Flask(__name__) app.secret_key = urandom(32) -app.jinja_env.globals.update(get_url=lambda endpoint: f'{BASEURL}{url_for(endpoint)}') # pylint: disable=no-member +app.jinja_env.globals.update( # pylint: disable=no-member + get_url=lambda endpoint: f'{BASEURL}{url_for(endpoint)}' +) def get_db_session(): @@ -47,22 +49,33 @@ def index(): @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': - if not all([request.form.get('username'), - request.form.get('password'), - request.form.get('passwordconfirm')]): + form_filled_out = all([ + request.form.get('username'), + request.form.get('password'), + request.form.get('passwordconfirm') + ]) + + if not form_filled_out: return render_template('register.html', alert='You need to fill everything.') if request.form['password'] != request.form['passwordconfirm']: return render_template('register.html', alert='Passwords do not match! Please try again.') try: - UserOps(request.form.get('username'), - request.form.get('password'), - get_db_session()).register() + UserOps( + request.form.get('username'), + request.form.get('password'), + get_db_session() + ).register() except UserExistsError: return render_template('register.html', alert='Username already in use.') - return render_template('login.html', success=('Account "{}" successfully registered. ' - 'You can log in now!'.format(request.form['username']))) + return render_template( + 'login.html', + success=( + 'Account "{}" successfully registered. ' + 'You can log in now!'.format(request.form['username']) + ) + ) return render_template('register.html') diff --git a/solvable/src/webservice/user_ops.py b/solvable/src/webservice/user_ops.py index ac59294..c9107a6 100644 --- a/solvable/src/webservice/user_ops.py +++ b/solvable/src/webservice/user_ops.py @@ -23,9 +23,16 @@ class UserOps: :raises InvalidCredentialsError: User does not exist or password provided is invalid """ - user = self.db_session.query(User).filter(User.username == self.username).first() + user = self.db_session.query(User).filter( + User.username == self.username + ).first() - if not user or not PasswordHasher.verify(self.password, user.passwordhash): + passw_is_correct = PasswordHasher.verify( + self.password, + user.passwordhash + ) + + if not user or not passw_is_correct: self.log(f'Invalid credentials for user "{self.username}"!') raise InvalidCredentialsError @@ -39,11 +46,17 @@ class UserOps: :raises UserExistsError: A user with the provided username already exists """ - if self.db_session.query(User).filter(User.username == self.username).all(): + existing_users = self.db_session.query(User).filter( + User.username == self.username + ).all() + + if existing_users: raise UserExistsError - user = User(username=self.username, - passwordhash=PasswordHasher.hash(self.password)) + user = User( + username=self.username, + passwordhash=PasswordHasher.hash(self.password) + ) self.db_session.add(user) self.db_session.commit() diff --git a/solvable/supervisor/event_handlers.conf b/solvable/supervisor/event_handler_main.conf similarity index 100% rename from solvable/supervisor/event_handlers.conf rename to solvable/supervisor/event_handler_main.conf