app.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import datetime as datetime
  2. import configparser as configparser
  3. import os
  4. from urllib.parse import urlparse
  5. import webbrowser
  6. from emailtool.emailer import Emailer
  7. from flask import Flask, render_template, request, redirect, url_for, jsonify, session
  8. from flask_httpauth import HTTPBasicAuth
  9. import configparser
  10. from gevent.pywsgi import WSGIServer
  11. import socket
  12. import logging
  13. from peewee import Model, CharField, TextField, DateTimeField, SqliteDatabase, BooleanField
  14. import hashlib
  15. db_name = 'users.db'
  16. db = SqliteDatabase(db_name)
  17. class User(Model):
  18. username = CharField()
  19. password = CharField()
  20. logged_in = BooleanField(default=False)
  21. class Meta:
  22. database = db
  23. class IlsUser(Model):
  24. username = CharField()
  25. email = CharField()
  26. reset_datetime = DateTimeField(default=datetime.datetime.now)
  27. class Meta:
  28. database = db
  29. config = configparser.ConfigParser()
  30. config.read('settings.ini')
  31. application_settings = config['application']
  32. smtp_settings = config['smtp']
  33. http_settings = config['http']
  34. domain_settings = config['domain']
  35. log = logging.getLogger('werkzeug')
  36. log.setLevel(logging.INFO)
  37. if application_settings['debug'].lower() == 'true':
  38. debug = True
  39. else:
  40. debug = False
  41. def send_email(to, subject, body):
  42. # Get settings from smtp_settings
  43. host = smtp_settings['host']
  44. port = smtp_settings['port']
  45. username = smtp_settings['username']
  46. password = smtp_settings['password']
  47. # Create an instance of the Emailer class
  48. emailer = Emailer(host, port, username, password)
  49. # Call the send_email method
  50. emailer.send_email(to, subject, body)
  51. # Encrypt the password with SHA256
  52. def encrypt_password(password):
  53. hash = hashlib.sha256(password.encode('utf-8')).hexdigest()
  54. return hash
  55. def shutdown_session(exception=None):
  56. print('Stopping HTTP Service...')
  57. http_server.stop()
  58. # Get the systems hostname
  59. def get_hostname():
  60. return socket.gethostname()
  61. # Get systems IP address
  62. def get_ip_address():
  63. return socket.gethostbyname(socket.gethostname())
  64. # Method to check if a URL is valid using regex
  65. def is_valid_url(url):
  66. try:
  67. result = urlparse(url)
  68. if all([result.scheme, result.netloc]):
  69. url = '{uri.scheme}://{uri.netloc}/'.format(uri=result)
  70. else:
  71. url = False
  72. return url
  73. except:
  74. return False
  75. def requires_auth():
  76. if 'username' in session:
  77. username = session['username']
  78. user = User.get(User.username == username)
  79. if user.logged_in is True:
  80. return True
  81. else:
  82. return False
  83. else:
  84. return False
  85. # Check for DB tables and create if they don't exist
  86. if db.table_exists('user') is False:
  87. db.create_tables([User, IlsUser])
  88. User.create(username='admin', password=encrypt_password('admin'))
  89. if db.table_exists('ilsuser') is False:
  90. db.create_tables([IlsUser])
  91. db.close()
  92. app = Flask(__name__)
  93. app.secret_key = 'super secret key'
  94. @app.before_request
  95. def before_request():
  96. db.connect()
  97. @app.after_request
  98. def after_request(response):
  99. db.close()
  100. return response
  101. # Create a route for the home page
  102. @app.route('/', methods=['GET', 'POST'])
  103. def index():
  104. # send_email('aday@twinfallspubliclibrary.org', 'TEST', 'This is a test email')
  105. error = None
  106. reset = False
  107. reset_url = is_valid_url(domain_settings['reset_url'])
  108. reset_url_error = False
  109. if reset_url is False:
  110. reset_url_error = True
  111. if request.method == 'POST':
  112. username = request.form.get('username')
  113. # Check for the username in the DB
  114. try:
  115. user = IlsUser.filter(IlsUser.username == username).first()
  116. except Exception as e:
  117. print(e)
  118. user = None
  119. if user:
  120. # Reset login datetime
  121. user.reset_datetime = datetime.datetime.now()
  122. user.save()
  123. # Open the reset URL in a new tab if the URL is valid
  124. if reset_url is not False:
  125. webbrowser.open_new_tab(str(reset_url))
  126. # Set reset to True to pass back to the view to display the correct content back to the user.
  127. reset = True
  128. else:
  129. error = 'Invalid username'
  130. context = {
  131. 'domain': domain_settings['name'],
  132. 'error': error,
  133. 'reset': reset,
  134. 'reset_url': reset_url,
  135. 'reset_url_error': reset_url_error,
  136. }
  137. return render_template('index.html', context=context)
  138. # Create a route for admin page
  139. @app.route('/admin')
  140. def admin():
  141. # Check to see if user is logged in
  142. if not requires_auth():
  143. return redirect(url_for('login'))
  144. return render_template('admin.html')
  145. @app.route('/logout')
  146. def logout():
  147. if 'username' in session:
  148. username = session['username']
  149. user = User.get(User.username == username)
  150. user.logged_in = False
  151. user.save()
  152. session.pop('username', None)
  153. return redirect(url_for('login'))
  154. @app.route('/login', methods=['GET', 'POST'])
  155. def login():
  156. if request.method == 'POST':
  157. username = request.form.get('username')
  158. password = encrypt_password(request.form.get('password'))
  159. try:
  160. user = User.filter(User.username == username and User.password == password).first()
  161. except Exception as e:
  162. print(e)
  163. user = None
  164. session.pop('username', None)
  165. if user:
  166. # Login user
  167. session['username'] = request.form.get('username')
  168. user.logged_in = True
  169. user.save()
  170. return redirect(url_for('admin'))
  171. else:
  172. error = 'Invalid Credentials. Please try again.'
  173. context = {
  174. 'error': error
  175. }
  176. return render_template('login.html', context=context)
  177. context = {
  178. }
  179. return render_template('login.html', context=context)
  180. # on exit of the program make sure the http server is stopped
  181. #@app.teardown_appcontext
  182. if __name__ == "__main__":
  183. print("------------------------- Start up -----------------------------")
  184. print("Starting HTTP Service on port %s..." % http_settings['port'])
  185. if debug is True:
  186. print("Debug mode is enabled.")
  187. http_server = WSGIServer(('0.0.0.0', int(http_settings['port'])), app)
  188. else:
  189. http_server = WSGIServer(('0.0.0.0', int(http_settings['port'])), app, log=log, error_log=log)
  190. print("HTTP Service Started.")
  191. print("--------------------- Application Details ---------------------")
  192. print("Application started at %s" % datetime.datetime.now())
  193. print("System IP Address: %s" % get_ip_address())
  194. print("System Hostname: %s" % get_hostname())
  195. print("Access the Dashboard using a web browser using any of the following:")
  196. print("http://%s:%s or http://%s:%s" % (get_hostname(), http_settings['port'], get_ip_address(), http_settings['port']))
  197. print("---------------------------------------------------------------")
  198. print("To stop the application close this window.")
  199. print("---------------------------------------------------------------")
  200. http_server.serve_forever()