A Python content management system designed for kirsle.net featuring a blog, comments and photo albums. https://rophako.kirsle.net/
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.

137 lines
3.8KB

  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals, absolute_import
  3. """Endpoints for user login and out."""
  4. from flask import Blueprint, request, redirect, url_for, session, flash
  5. import re
  6. import rophako.model.user as User
  7. from rophako.utils import template
  8. mod = Blueprint("account", __name__, url_prefix="/account")
  9. @mod.route("/")
  10. def index():
  11. return redirect(url_for(".login"))
  12. @mod.route("/login", methods=["GET", "POST"])
  13. def login():
  14. """Log into an account."""
  15. if request.method == "POST":
  16. username = request.form.get("username", "")
  17. password = request.form.get("password", "")
  18. # Lowercase the username.
  19. username = username.lower()
  20. if User.check_auth(username, password):
  21. # OK!
  22. db = User.get_user(username=username)
  23. session["login"] = True
  24. session["username"] = username
  25. session["uid"] = db["uid"]
  26. session["name"] = db["name"]
  27. session["role"] = db["role"]
  28. # Redirect them to a local page?
  29. url = request.form.get("url", "")
  30. if url.startswith("/"):
  31. return redirect(url)
  32. return redirect(url_for("index"))
  33. else:
  34. flash("Authentication failed.")
  35. return redirect(url_for(".login"))
  36. return template("account/login.html")
  37. @mod.route("/logout")
  38. def logout():
  39. """Log out the user."""
  40. session["login"] = False
  41. session["username"] = "guest"
  42. session["uid"] = 0
  43. session["name"] = "Guest"
  44. session["role"] = "user"
  45. flash("You have been signed out.")
  46. return redirect(url_for(".login"))
  47. @mod.route("/setup", methods=["GET", "POST"])
  48. def setup():
  49. """Initial setup to create the Admin user account."""
  50. # This can't be done if users already exist on the CMS!
  51. if User.exists(uid=1):
  52. flash("This website has already been configured (users already created).")
  53. return redirect(url_for("index"))
  54. if request.method == "POST":
  55. # Submitting the form.
  56. username = request.form.get("username", "")
  57. name = request.form.get("name", "")
  58. pw1 = request.form.get("password1", "")
  59. pw2 = request.form.get("password2", "")
  60. # Default name = username.
  61. if name == "":
  62. name = username
  63. # Lowercase the user.
  64. username = username.lower()
  65. if User.exists(username=username):
  66. flash("That username already exists.")
  67. return redirect(url_for(".setup"))
  68. # Validate the form.
  69. errors = validate_create_form(username, pw1, pw2)
  70. if errors:
  71. for error in errors:
  72. flash(error)
  73. return redirect(url_for(".setup"))
  74. # Create the account.
  75. uid = User.create(
  76. username=username,
  77. password=pw1,
  78. name=name,
  79. role="admin",
  80. )
  81. flash("Admin user created! Please log in now.".format(uid))
  82. return redirect(url_for(".login"))
  83. return template("account/setup.html")
  84. def validate_create_form(username, pw1=None, pw2=None, skip_passwd=False):
  85. """Validate the submission of a create-user form.
  86. Returns a list of error messages if there were errors, otherwise
  87. it returns None."""
  88. errors = list()
  89. if len(username) == 0:
  90. errors.append("You must provide a username.")
  91. if re.search(r'[^A-Za-z0-9-_]', username):
  92. errors.append("Usernames can only contain letters, numbers, dashes or underscores.")
  93. if not skip_passwd:
  94. if len(pw1) < 3:
  95. errors.append("You should use at least 3 characters in your password.")
  96. if pw1 != pw2:
  97. errors.append("Your passwords don't match.")
  98. if len(errors):
  99. return errors
  100. else:
  101. return None