diff --git a/.dockerignore b/.dockerignore
index d259ec7..6ea5688 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,3 +1,4 @@
*.pyc
.git/
-Dockerfile
\ No newline at end of file
+Dockerfile
+__pycache__/*
\ No newline at end of file
diff --git a/app/__init__.py b/app/__init__.py
new file mode 100644
index 0000000..cf00692
--- /dev/null
+++ b/app/__init__.py
@@ -0,0 +1,10 @@
+from flask import Flask, render_template
+from . import reset
+
+def create_app():
+ app = Flask(__name__, instance_relative_config=True, template_folder="ui/templates", static_folder="ui/static")
+ app.config.from_object("instance.config.DebugConfig")
+
+ app.register_blueprint(reset.bp)
+
+ return app
\ No newline at end of file
diff --git a/app/reset.py b/app/reset.py
new file mode 100644
index 0000000..204c2e1
--- /dev/null
+++ b/app/reset.py
@@ -0,0 +1,39 @@
+import functools
+
+from flask import (
+ Blueprint, flash, g, redirect, render_template, request, session, url_for
+)
+from flask_wtf import FlaskForm
+from wtforms import StringField, PasswordField, BooleanField, \
+ SubmitField
+from wtforms.validators import ValidationError, DataRequired, \
+ Email, EqualTo, Length
+from werkzeug.security import check_password_hash, generate_password_hash
+
+
+bp = Blueprint('reset', __name__, url_prefix='/reset')
+
+class ResetPasswordForm(FlaskForm):
+ username = StringField(label=('Username'),
+ validators=[DataRequired(),
+ Length(max=64)])
+ currentpassword = PasswordField(label=('Current password'),
+ validators=[DataRequired()])
+ newpassword = PasswordField(label=('New password'),
+ validators=[DataRequired(),
+ Length(min=8, message='Password should be at least %(min)d characters long')],
+ render_kw={"onkeyup": "validate_form()"})
+ confirm_password = PasswordField(
+ label=('Confirm Password'),
+ validators=[DataRequired(message='* Required'),
+ EqualTo('newpassword', message='Both password fields must be equal!')],
+ render_kw={"onkeyup": "validate_confirm()"})
+
+ submit = SubmitField(label=('Change my password'), render_kw={"onclick": "validate_form()"})
+
+@bp.route('/', methods=('GET', 'POST'))
+def reset():
+ form = ResetPasswordForm()
+ if form.validate_on_submit():
+ return f'''
Welcome {form.username.data}
'''
+ return render_template('reset.html', form=form)
\ No newline at end of file
diff --git a/app/ui/static/css/main.css b/app/ui/static/css/main.css
new file mode 100644
index 0000000..0e5b919
--- /dev/null
+++ b/app/ui/static/css/main.css
@@ -0,0 +1,84 @@
+html,
+body {
+ margin: 0;
+ height: 100%;
+ min-width: 310px;
+}
+
+body {
+ min-height: 100%;
+ font-family: 'Roboto Mono', monospace;
+ color: white;
+ background: rgb(0, 0, 0);
+ background: linear-gradient(8deg, rgb(35, 155, 21) 0%, rgba(14, 47, 11, 1) 40%, rgba(0, 0, 0, 1) 70%);
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+}
+
+.vcenter {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ -webkit-transform: translateX(-50%) translateY(-50%);
+ transform: translateX(-50%) translateY(-50%);
+}
+
+.container {
+ animation: fadein ease 3s;
+ animation-iteration-count: 1;
+ animation-fill-mode: forwards;
+}
+
+a {
+ text-decoration: none;
+}
+
+a:link>span {
+ color: rgb(216, 216, 216);
+}
+
+a:visited>span {
+ color: rgb(216, 216, 216);
+}
+
+a:hover>span {
+ color: rgb(255, 255, 255);
+}
+
+.icon2x {
+ height: 32px;
+ width: 32px;
+ font-size: 32px;
+}
+
+.errorinput {
+ border-color: #f44246 !important;
+}
+
+#confirm-msg,
+#password-msg {
+ color: #f44246;
+ opacity: 0;
+ transition: opacity 225ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
+}
+
+.errorinput:focus {
+ box-shadow: 0 0 0 .10rem rgba(244, 66, 70, 0.50) !important;
+ -webkit-box-shadow: 0 0 0 .10rem rgba(244, 66, 70, 0.50) !important;
+}
+
+.form-control:focus {
+ border-color: #5cb85c;
+ box-shadow: 0 0 0 .10rem rgba(92, 184, 92, 0.50);
+ -webkit-box-shadow: 0 0 0 .10rem rgba(92, 184, 92, 0.50);
+}
+
+#reset-form {
+ background: #4e4e4e;
+ border-radius: .50rem;
+}
+
+.fade {
+ opacity: 1 !important;
+ transition: opacity 300ms cubic-bezier(0.55, 0.085, 0.68, 0.53);
+}
\ No newline at end of file
diff --git a/app/ui/static/js/validate.js b/app/ui/static/js/validate.js
new file mode 100644
index 0000000..3f90df1
--- /dev/null
+++ b/app/ui/static/js/validate.js
@@ -0,0 +1,37 @@
+function validate_form() {
+ var pass = validate_password();
+
+ return validate_confirm() && pass;
+}
+
+function validate_confirm() {
+ var password = document.getElementById("newpassword");
+ var confirm = document.getElementById("confirm_password");
+
+ if (password.value != confirm.value) {
+ confirm.classList.add("errorinput");
+ document.getElementById("confirm-msg").classList.add("fade");
+ return false;
+ }
+
+ confirm.classList.remove("errorinput");
+ document.getElementById("confirm-msg").classList.remove("fade");
+
+ return true;
+}
+
+function validate_password() {
+ var password = document.getElementById("newpassword");
+ var reg = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}/;
+
+ if (reg.test(password.value) != true) {
+ password.classList.add("errorinput");
+ document.getElementById("password-msg").classList.add("fade");
+ return false;
+ }
+
+ password.classList.remove("errorinput");
+ document.getElementById("password-msg").classList.remove("fade");
+
+ return true;
+}
\ No newline at end of file
diff --git a/app/ui/templates/base.html b/app/ui/templates/base.html
new file mode 100644
index 0000000..b640b1b
--- /dev/null
+++ b/app/ui/templates/base.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+ AlxCzl - LDAP Interface
+
+
+
+
+
+
+
+
+ {% for message in get_flashed_messages() %}
+ {{ message }}
+ {% endfor %}
+
+ {% block main_block %}{% endblock main_block %}
+
+ {% block script_block %}{% endblock script_block %}
+
+
+
diff --git a/app/ui/templates/reset.html b/app/ui/templates/reset.html
new file mode 100644
index 0000000..dcd0031
--- /dev/null
+++ b/app/ui/templates/reset.html
@@ -0,0 +1,42 @@
+{% extends 'base.html' %}
+
+{% block main_block %}
+
+{% endblock main_block %}
+
+{% block script_block %}
+
+{% endblock script_block %}
\ No newline at end of file
diff --git a/app/entrypoint.sh b/entrypoint.sh
similarity index 100%
rename from app/entrypoint.sh
rename to entrypoint.sh
diff --git a/requirements.txt b/requirements.txt
index 9c6a7e4..03fa1b2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,4 +8,5 @@ MarkupSafe==2.0.1
typing_extensions==4.0.0
Werkzeug==2.0.2
zipp==3.6.0
-python-ldap
\ No newline at end of file
+python-ldap
+Flask-WTF==1.0.0
\ No newline at end of file
diff --git a/wsgi.py b/wsgi.py
new file mode 100644
index 0000000..3f0abc1
--- /dev/null
+++ b/wsgi.py
@@ -0,0 +1,6 @@
+import os, sys
+app_path = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, app_path)
+
+from app import create_app
+application = create_app()