@@ 0,0 1,54 @@
+import re
+from jinja2 import Markup
+from metasrht.blacklist import email_blacklist, username_blacklist
+from metasrht.types import User
+from srht.config import cfg
+from zxcvbn import zxcvbn
+
+
+def validate_username(valid, username, check_blacklist=True):
+ user = User.query.filter(User.username == username).first()
+ valid.expect(user is None, "This username is already in use.", "username")
+ valid.expect(2 <= len(username) <= 30,
+ "Username must contain between 2 and 30 characters.",
+ "username")
+ valid.expect(re.match("^[a-z_]", username),
+ "Username must start with a lowercase letter or underscore.",
+ "username")
+ valid.expect(re.match("^[a-z0-9_-]+$", username),
+ "Username may contain only lowercase letters, numbers, "
+ "hyphens and underscores", "username")
+ valid.expect(not check_blacklist or username not in username_blacklist,
+ "This username is not available", "username")
+
+
+def validate_email(valid, email):
+ user = User.query.filter(User.email == email).first()
+ valid.expect(user is None, "This email address is already in use.", "email")
+ valid.expect(len(email) <= 256,
+ "Email must be no more than 256 characters.", "email")
+ valid.expect("@" in email, "This is not a valid email address.", "email")
+ if valid.ok:
+ [user, domain] = email.split("@")
+ valid.expect(domain not in email_blacklist,
+ "This email domain is blacklisted. Disposable email "
+ "addresses are prohibited by the terms of service - we "
+ "must be able to reach you at your account's primary "
+ "email address. Contact support if you believe this "
+ "domain was blacklisted in error.", "email")
+
+
+def validate_password(valid, password):
+ valid.expect(len(password) <= 512,
+ "Password must be no more than 512 characters.", "password")
+
+ if cfg("sr.ht", "environment", default="production") == "development":
+ return
+ strength = zxcvbn(password)
+ time = strength["crack_times_display"]["offline_slow_hashing_1e4_per_second"]
+ valid.expect(strength["score"] >= 3, Markup(
+ "This password is too weak — it could be cracked in " +
+ f"{time} if our database were broken into. Try using " +
+ "a few words instead of random letters and symbols. A " +
+ "<a href='https://www.passwordstore.org/'>password manager</a> " +
+ "is strongly recommended."), field="password")