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.

198 lines
5.2 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
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. user = User("admin", app.config.get("ADMIN_TOKEN"))
  62. g.user = user
  63. return user
  64. else:
  65. return None
  66. @app.route('/')
  67. def index():
  68. return redirect('/register')
  69. @app.route('/register', methods=('GET', 'POST'))
  70. def registration():
  71. form = RegistrationForm()
  72. if form.validate_on_submit():
  73. add_registered_user(form.registration_code.data, form.username.data)
  74. return redirect('/success')
  75. flash_form_errors(form)
  76. if 'registrationCode' in request.values:
  77. form.registration_code.data = request.values['registrationCode']
  78. return render_template('register.html', form=form)
  79. @app.route('/admin')
  80. @login_required
  81. def admin_index():
  82. context = {
  83. 'add_registration_code_form': RegistrationCodeForm(),
  84. 'registration_codes': get_registration_codes(),
  85. 'registered_users': get_registered_users()
  86. }
  87. return render_template('admin.html', **context)
  88. @app.route('/admin/add_registration_code', methods=['POST'])
  89. @login_required
  90. def admin_add_registration_code():
  91. form = RegistrationCodeForm()
  92. if form.validate_on_submit():
  93. expiration_time = form.expiration_time.data
  94. max_usages = form.max_usages.data
  95. add_registration_code(expiration_time, max_usages)
  96. redirect('/admin')
  97. flash_form_errors(form)
  98. return redirect('/admin')
  99. @app.route('/admin/expire_registration_code', methods=['POST'])
  100. @login_required
  101. def admin_expire_registration_code():
  102. form = ExpireRegistrationCodeForm()
  103. if form.validate_on_submit():
  104. if form.expire.data:
  105. expire_registration_code(form.registration_code.data)
  106. elif form.delete.data:
  107. delete_registration_code(form.registration_code.data)
  108. redirect('/admin')
  109. flash_form_errors(form)
  110. return redirect('/admin')
  111. @app.route('/admin/login', methods=('GET', 'POST'))
  112. def admin_login():
  113. form = LoginForm()
  114. tmp = current_user
  115. if form.validate_on_submit():
  116. user = load_user(form.username.data)
  117. if user is not None:
  118. if form.token.data == user.token:
  119. user.authenticated = True
  120. login_user(user)
  121. flask.flash('Logged in successfully.')
  122. next_loc = flask.request.args.get('next')
  123. if not is_safe_url(next_loc):
  124. return flask.abort(400)
  125. else:
  126. if next_loc is not None:
  127. return redirect(next_loc)
  128. else:
  129. return redirect('/admin')
  130. flash_form_errors(form)
  131. return render_template('login.html', form=form)
  132. @app.route("/admin/logout")
  133. @login_required
  134. def admin_logout():
  135. logout_user()
  136. flask.flash('Logged out successfully.')
  137. return redirect('/')
  138. @app.teardown_appcontext
  139. def close_connection(exception):
  140. db = getattr(g, '_database', None)
  141. if db is not None:
  142. db.close()
  143. if __name__ == '__main__':
  144. app.run()