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.

224 lines
6.3 KiB

4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. import ldap as l
  2. from ldap3 import Server, Connection
  3. from ldap3.core.exceptions import LDAPBindError
  4. from flask import Flask, g, request, redirect, url_for, render_template, flash
  5. from flask_sqlalchemy import SQLAlchemy
  6. from flask_login import LoginManager, login_manager, current_user, login_user, \
  7. logout_user, login_required
  8. from flask_wtf import FlaskForm
  9. from flask_cache_buster import CacheBuster
  10. from wtforms import StringField, PasswordField, BooleanField, SubmitField
  11. from wtforms.validators import DataRequired
  12. from flask_bootstrap import Bootstrap
  13. import short_url
  14. import os
  15. import sqlite3
  16. app = Flask(__name__)
  17. Bootstrap(app)
  18. app.secret_key = 'asdf'
  19. app.debug = True
  20. app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
  21. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
  22. app.config['WTF_CSRF_SECRET_KEY'] = 'asdf'
  23. # Base
  24. app.config['LDAP_REALM_NAME'] = 'OpenLDAP Authentication'
  25. app.config['LDAP_HOST'] = os.environ.get('LDAP_HOST')
  26. app.config['LDAP_BASE_DN'] = os.environ.get('LDAP_BASE_DN')
  27. app.config['LDAP_USERNAME'] = os.environ.get('LDAP_USERNAME')
  28. app.config['LDAP_PASSWORD'] = os.environ.get('LDAP_PASSWORD')
  29. # OpenLDAP
  30. app.config['LDAP_OBJECTS_DN'] = 'dn'
  31. app.config['LDAP_OPENLDAP'] = True
  32. app.config['LDAP_USER_OBJECT_FILTER'] = '(&(objectclass=posixAccount)(uid=%s))'
  33. # Login cookies
  34. app.config['SESSION_COOKIE_DOMAIN'] = os.environ.get('COOKIE_DOMAIN')
  35. app.config['REMEMBER_COOKIE_DOMAIN'] = os.environ.get('COOKIE_DOMAIN')
  36. short_domain = os.environ.get('SHORT_DOMAIN')
  37. db = SQLAlchemy(app)
  38. login_manager = LoginManager(app)
  39. login_manager.init_app(app)
  40. login_manager.login_view = 'login'
  41. db.create_all()
  42. config = {
  43. 'extensions': ['.js', '.css', '.csv'],
  44. 'hash_size': 10
  45. }
  46. cache_buster = CacheBuster(config=config)
  47. cache_buster.register_cache_buster(app)
  48. server = Server(app.config['LDAP_HOST'])
  49. conn = Connection(server, app.config['LDAP_USERNAME'], app.config['LDAP_PASSWORD'], auto_bind=True)
  50. class User(db.Model):
  51. __tablename__ = 'user'
  52. id = db.Column(db.Integer, primary_key=True)
  53. username = db.Column(db.String(100))
  54. authenticated = db.Column(db.Boolean, default=False)
  55. def __init__(self, username):
  56. self.username = username
  57. @staticmethod
  58. def try_login(username, password):
  59. conn.search(app.config['LDAP_BASE_DN'], app.config['LDAP_USER_OBJECT_FILTER'] % username, attributes=['*'])
  60. if len(conn.entries) > 0:
  61. Connection(app.config['LDAP_HOST'], conn.entries[0].entry_dn, password, auto_bind=True)
  62. return
  63. raise LDAPBindError
  64. def is_authenticated(self):
  65. return self.authenticated
  66. def is_active(self):
  67. return True
  68. def is_anonymous(self):
  69. return False
  70. def get_id(self):
  71. return self.id
  72. def get_user_dict(self):
  73. user = {'dn': '',
  74. 'firstName': '',
  75. 'lastName': '',
  76. 'email': '',
  77. 'userName': self.username,
  78. }
  79. conn.search(app.config['LDAP_BASE_DN'], app.config['LDAP_USER_OBJECT_FILTER'] % self.username, attributes=['*'])
  80. user['dn'] = conn.entries[0].entry_dn
  81. user['firstName'] = conn.entries[0].givenName.value
  82. user['lastName'] = conn.entries[0].sn.value
  83. user['email'] = conn.entries[0].mail.value
  84. return user
  85. class LoginForm(FlaskForm):
  86. username = StringField('Username', validators=[DataRequired()])
  87. password = PasswordField('Password', validators=[DataRequired()])
  88. remember_me = BooleanField('Remember Me')
  89. submit = SubmitField('Sign In')
  90. @login_manager.user_loader
  91. def load_user(id):
  92. return User.query.get(int(id))
  93. @app.before_request
  94. def get_current_user():
  95. g.user = current_user
  96. @app.route('/')
  97. @login_required
  98. def index():
  99. return render_template('profile.j2', user = current_user.get_user_dict(), short_domain = short_domain)
  100. @app.route('/login', methods=['GET', 'POST'])
  101. def login():
  102. if current_user.is_authenticated:
  103. flash('You are already logged in.')
  104. return redirect(url_for('index'))
  105. form = LoginForm(request.form)
  106. print(form)
  107. print(request.method)
  108. if request.method == 'POST' and form.validate():
  109. username = request.form.get('username')
  110. password = request.form.get('password')
  111. print(username)
  112. print(password)
  113. try:
  114. User.try_login(username, password)
  115. except LDAPBindError:
  116. flash(
  117. 'Invalid username or password. Please try again.',
  118. 'danger')
  119. return render_template('login.j2', form=form)
  120. user = User.query.filter(User.username == username).first()
  121. print(user)
  122. if user is None:
  123. user = User(username, password)
  124. db.session.add(user)
  125. user.authenticated = True
  126. db.session.commit()
  127. login_user(user, remember=form.remember_me.data)
  128. print('You have successfully logged in.')
  129. return redirect(url_for('index'))
  130. if form.errors:
  131. flash(form.errors, 'danger')
  132. return render_template('login.j2', form=form)
  133. @app.route('/shorten', methods=['POST'])
  134. @login_required
  135. def shorten_url():
  136. if request.method == 'POST':
  137. url = request.form['url']
  138. conn = sqlite3.connect('links/links.db')
  139. c = conn.cursor()
  140. if url is not None and len(url) > 0:
  141. c.execute("INSERT INTO links (url) VALUES (?)", (url,))
  142. c.execute("SELECT * FROM links WHERE url=?", (url,))
  143. row = c.fetchone()
  144. print(row[0])
  145. conn.commit()
  146. conn.close()
  147. url_fragment = short_url.encode_url(row[0])
  148. return "Your shortened link is <a href='{}/{}'>{}/{}</a>".format(short_domain, url_fragment, short_domain, url_fragment)
  149. conn.commit()
  150. conn.close()
  151. return 'Error'
  152. @app.route('/l/<url>')
  153. def expand_url(url):
  154. idx = short_url.decode_url(url)
  155. conn = sqlite3.connect('links/links.db')
  156. c = conn.cursor()
  157. c.execute("SELECT * FROM links WHERE id=?", (idx,))
  158. out_link = c.fetchone()[1]
  159. return redirect(out_link)
  160. @app.route('/logout')
  161. @login_required
  162. def logout():
  163. user = current_user
  164. user.authenticated = False
  165. db.session.add(user)
  166. db.session.commit()
  167. logout_user()
  168. return redirect(url_for('game'))
  169. if __name__ == '__main__':
  170. app.run()