149 lines
4.2 KiB
Python
Executable File
149 lines
4.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os
|
|
import sys
|
|
from getopt import getopt, GetoptError
|
|
from getpass import getpass
|
|
|
|
from srht.config import cfg
|
|
from srht.database import DbSession
|
|
from srht.oauth import UserType
|
|
from srht.validation import Validation
|
|
|
|
from metasrht import auth_validation
|
|
from metasrht.auth import auth_method
|
|
from metasrht.auth.base import get_user
|
|
from metasrht.auth.builtin import hash_password
|
|
from metasrht.types import User
|
|
|
|
USER_TYPES = [x.value for x in UserType]
|
|
|
|
|
|
def print_usage():
|
|
print(f"""Usage:
|
|
{sys.argv[0]} [-fmPps] [-e <EMAIL>] [-t <USER_TYPE>] <USERNAME>
|
|
|
|
Options:
|
|
-e <EMAIL> set user email
|
|
-f perform action even if using different authentication method
|
|
-m modify existing user
|
|
-P clear password
|
|
-p set password (default if creating a new user)
|
|
-s read initial password from stdin (only effective with -p)
|
|
-t <USER_TYPE> set user type to USER_TYPE; USER_TYPE must be one of these
|
|
values: unconfirmed, active_non_paying, active_free,
|
|
active_paying, active_delinquent, admin, unknown, suspended""")
|
|
|
|
|
|
def get_args():
|
|
try:
|
|
opts, args = getopt(sys.argv[1:], "e:fmPpst:")
|
|
except GetoptError as ex:
|
|
print(ex, file=sys.stderr)
|
|
print_usage()
|
|
sys.exit(1)
|
|
|
|
if len(args) == 0:
|
|
print("Username not specified", file=sys.stderr)
|
|
print_usage()
|
|
sys.exit(1)
|
|
|
|
if len(args) > 1:
|
|
print("Too many arguments", file=sys.stderr)
|
|
print_usage()
|
|
sys.exit(1)
|
|
|
|
force = ("-f", "") in opts
|
|
modify_existing = ("-m", "") in opts
|
|
clear_password = ("-P", "") in opts
|
|
set_password = ("-p", "") in opts
|
|
stdin = ("-s", "") in opts
|
|
email = [y for x, y in opts if x == "-e"]
|
|
email = email[0] if email else None
|
|
user_type = [y for x, y in opts if x == "-t"]
|
|
user_type = user_type[0] if user_type else None
|
|
|
|
username = args[0]
|
|
|
|
if clear_password and set_password:
|
|
sys.exit('Only one of -P, -p can be present at the same time')
|
|
|
|
if not modify_existing and not clear_password:
|
|
set_password = True
|
|
|
|
if not modify_existing and email is None:
|
|
sys.exit("Must specify -e when creating a new user!")
|
|
|
|
if user_type and user_type not in USER_TYPES:
|
|
sys.exit(f"-t must be one of {USER_TYPES}")
|
|
|
|
return force, modify_existing, clear_password, set_password, stdin, email, \
|
|
user_type, username
|
|
|
|
|
|
def get_password(stdin):
|
|
if not stdin:
|
|
password1 = getpass("Enter password: ")
|
|
password2 = getpass("Repeat password: ")
|
|
|
|
if password1 != password2:
|
|
sys.exit("Repeated password does not match")
|
|
|
|
return password1
|
|
else:
|
|
return sys.stdin.readline().rstrip(os.linesep)
|
|
|
|
|
|
def error_on_invalid(valid):
|
|
if not valid.ok:
|
|
for error in valid.errors:
|
|
print(error.message, file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
def validate_user(username, email):
|
|
valid = Validation({})
|
|
auth_validation.validate_username(valid, username, check_blacklist=False)
|
|
auth_validation.validate_email(valid, email)
|
|
error_on_invalid(valid)
|
|
|
|
|
|
def validate_password(password):
|
|
valid = Validation({})
|
|
auth_validation.validate_password(valid, password)
|
|
error_on_invalid(valid)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
force, modify_existing, clear_password, set_password, stdin, email, \
|
|
user_type, username = get_args()
|
|
|
|
if not force and auth_method != 'builtin':
|
|
sys.exit("Can't create accounts if not using builtin authentication!")
|
|
|
|
db = DbSession(cfg("meta.sr.ht", "connection-string"))
|
|
db.init()
|
|
|
|
if modify_existing:
|
|
user = get_user(username)
|
|
if user is None:
|
|
sys.exit(f"User {username} not found!")
|
|
else:
|
|
validate_user(username, email)
|
|
user = User(username)
|
|
db.session.add(user)
|
|
|
|
if set_password:
|
|
password = get_password(stdin)
|
|
validate_password(password)
|
|
user.password = hash_password(password)
|
|
elif clear_password:
|
|
user.password = ''
|
|
|
|
if email is not None:
|
|
user.email = email
|
|
|
|
if user_type is not None:
|
|
user.user_type = UserType[user_type]
|
|
|
|
db.session.commit()
|