A simple web application that allows invitation based registration to a matrix instance
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
5.1 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. import logging
  2. import os
  3. import uuid
  4. from urllib.parse import urlparse, urljoin
  5. import flask
  6. from flask import Flask, redirect, render_template, request, g, flash
  7. from flask_login import LoginManager, login_required, login_user, logout_user, UserMixin, \
  8. current_user
  9. from flask_wtf import CSRFProtect
  10. from db import get_db, get_registration_codes, add_registration_code, \
  11. expire_registration_code, delete_registration_code, get_registered_users, \
  12. add_registered_user
  13. from forms import RegistrationForm, LoginForm, RegistrationCodeForm, \
  14. ExpireRegistrationCodeForm
  15. csrf = CSRFProtect()
  16. login_manager = LoginManager()
  17. log = logging.getLogger(__name__)
  18. def init_db(flask_app):
  19. with flask_app.app_context():
  20. db = get_db()
  21. with flask_app.open_resource('schema.sql', mode='r') as f:
  22. db.cursor().executescript(f.read())
  23. log.info("Initialized DB")
  24. db.commit()
  25. def create_app():
  26. flask_app = Flask(__name__)
  27. flask_app.config.update(dict(
  28. ADMIN_TOKEN=os.getenv("ADMIN_TOKEN", uuid.uuid4().__str__()),
  29. SECRET_KEY=os.getenv("SECRET_KEY", "changeme"),
  30. WTF_CSRF_SECRET_KEY=os.getenv("CSRF_SECRET_KEY", "csrf_changeme")
  31. ))
  32. print("Admin Token: %s" % flask_app.config.get("ADMIN_TOKEN"))
  33. csrf.init_app(flask_app)
  34. login_manager.init_app(flask_app)
  35. login_manager.login_view = "admin_login"
  36. init_db(flask_app)
  37. return flask_app
  38. app = create_app()
  39. def flash_form_errors(form):
  40. if hasattr(form, 'errors') and len(form.errors) > 0:
  41. for error in form.errors.items():
  42. flash("%s: %s" % (form[error[0]].label.text, error[1]), 'error')
  43. class User(UserMixin):
  44. username: str
  45. token: str
  46. authenticated: bool = False
  47. def __init__(self, username: str, token: str):
  48. self.username = username
  49. self.token = token
  50. def is_authenticated(self):
  51. return self.authenticated
  52. def get_id(self):
  53. return self.username
  54. def is_safe_url(target):
  55. ref_url = urlparse(request.host_url)
  56. test_url = urlparse(urljoin(request.host_url, target))
  57. return test_url.scheme in ('http', 'https') and ref_url.netloc == test_url.netloc
  58. @login_manager.user_loader
  59. def load_user(user_id):
  60. if user_id == "admin":
  61. return User("admin", app.config.get("ADMIN_TOKEN"))
  62. else:
  63. return None
  64. @app.route('/')
  65. def index():
  66. return 'Hello World!'
  67. @app.route('/register', methods=('GET', 'POST'))
  68. def registration():
  69. form = RegistrationForm()
  70. if form.validate_on_submit():
  71. add_registered_user(form.registration_code.data, form.username.data)
  72. return redirect('/success')
  73. flash_form_errors(form)
  74. if 'registrationCode' in request.values:
  75. form.registration_code.data = request.values['registrationCode']
  76. return render_template('register.html', form=form)
  77. @app.route('/admin')
  78. @login_required
  79. def admin_index():
  80. context = {
  81. 'add_registration_code_form': RegistrationCodeForm(),
  82. 'registration_codes': get_registration_codes(),
  83. 'registered_users': get_registered_users()
  84. }
  85. return render_template('admin.html', **context)
  86. @app.route('/admin/add_registration_code', methods=['POST'])
  87. @login_required
  88. def admin_add_registration_code():
  89. form = RegistrationCodeForm()
  90. if form.validate_on_submit():
  91. expiration_time = form.expiration_time.data
  92. max_usages = form.max_usages.data
  93. add_registration_code(expiration_time, max_usages)
  94. redirect('/admin')
  95. flash_form_errors(form)
  96. return redirect('/admin')
  97. @app.route('/admin/expire_registration_code', methods=['POST'])
  98. @login_required
  99. def admin_expire_registration_code():
  100. form = ExpireRegistrationCodeForm()
  101. if form.validate_on_submit():
  102. if form.expire.data:
  103. expire_registration_code(form.registration_code.data)
  104. elif form.delete.data:
  105. delete_registration_code(form.registration_code.data)
  106. redirect('/admin')
  107. flash_form_errors(form)
  108. return redirect('/admin')
  109. @app.route('/admin/login', methods=('GET', 'POST'))
  110. def admin_login():
  111. form = LoginForm()
  112. tmp = current_user
  113. if form.validate_on_submit():
  114. user = load_user(form.username.data)
  115. if user is not None:
  116. if form.token.data == user.token:
  117. user.authenticated = True
  118. login_user(user)
  119. flask.flash('Logged in successfully.')
  120. next_loc = flask.request.args.get('next')
  121. if not is_safe_url(next_loc):
  122. return flask.abort(400)
  123. else:
  124. if next_loc is not None:
  125. return redirect(next_loc)
  126. else:
  127. return redirect('/admin')
  128. flash_form_errors(form)
  129. return render_template('login.html', form=form)
  130. @app.route("/admin/logout")
  131. @login_required
  132. def admin_logout():
  133. logout_user()
  134. flask.flash('Logged out successfully.')
  135. return redirect('/')
  136. @app.teardown_appcontext
  137. def close_connection(exception):
  138. db = getattr(g, '_database', None)
  139. if db is not None:
  140. db.close()
  141. if __name__ == '__main__':
  142. app.run()