def adduser(argv): import auth parser = argparse.ArgumentParser( description="Critic administration interface: adduser", prog="criticctl [options] adduser") parser.add_argument("--name", help="user name") parser.add_argument("--email", "-e", help="email address") parser.add_argument("--fullname", "-f", help="full name") parser.add_argument("--password", "-p", help="password") arguments = parser.parse_args(argv) name = use_argument_or_ask(arguments.name, "Username:"******"Full name:") email = use_argument_or_ask(arguments.email, "Email address:") if arguments.password is None: password = inpututils.password("Password:"******"%s: user added" % name
def process(self, db, user, user_id, new_pw, current_pw=None): import auth if (user.id != user_id or current_pw is None) and not user.hasRole(db, "administrator"): raise OperationFailure(code="notallowed", title="Not allowed!", message="Operation not permitted.") subject = dbutils.User.fromId(db, user_id) if current_pw is not None: try: auth.checkPassword(db, subject.name, current_pw) except auth.WrongPassword: raise OperationFailure(code="wrongpassword", title="Wrong password!", message="The provided current password is not correct.") if not new_pw: raise OperationFailure(code="emptypassword", title="Empty password!", message="Setting an empty password is not allowed.") cursor = db.cursor() cursor.execute("UPDATE users SET password=%s WHERE id=%s", (auth.hashPassword(new_pw), user_id)) db.commit() return OperationResult()
def process(self, db, user, new_pw, subject=None, current_pw=None): import auth if subject is None: user_id = user.id elif isinstance(subject, basestring): user_id = dbutils.User.fromName(db, subject).id else: user_id = subject if user.id != user_id or current_pw is None: Operation.requireRole(db, "administrator", user) subject = dbutils.User.fromId(db, user_id) if current_pw is not None: try: auth.checkPassword(db, subject.name, current_pw) except auth.WrongPassword: raise OperationFailure(code="wrongpassword", title="Wrong password!", message="The provided current password is not correct.") if not new_pw: raise OperationFailure(code="emptypassword", title="Empty password!", message="Setting an empty password is not allowed.") cursor = db.cursor() cursor.execute("UPDATE users SET password=%s WHERE id=%s", (auth.hashPassword(new_pw), user_id)) db.commit() return OperationResult()
def adduser(argv): class NoEmail: pass class NoPassword: pass parser = argparse.ArgumentParser( description="Critic administration interface: adduser", prog="criticctl [options] adduser") parser.add_argument("--name", help="user name") parser.add_argument("--email", "-e", help="email address") parser.add_argument("--no-email", dest="email", action="store_const", const=NoEmail, help="create user without email address") parser.add_argument("--fullname", "-f", help="full name") parser.add_argument("--password", "-p", help="password") parser.add_argument("--no-password", dest="password", action="store_const", const=NoPassword, help="create user without password") arguments = parser.parse_args(argv) name = use_argument_or_ask(arguments.name, "Username:"******"Full name:") if arguments.email is NoEmail: email = None else: email = use_argument_or_ask(arguments.email, "Email address:") if not email.strip(): email = None if arguments.password is NoPassword: hashed_password = None else: if arguments.password is None: password = inpututils.password("Password:"******"%s: user added" % name
def install(data): global password import psycopg2 def adapt(value): return psycopg2.extensions.adapt(value).getquoted() if password is not None: try: import auth except ImportError: password = installation.process.check_input( [sys.executable, "-c", "import sys, auth; sys.stdout.write(auth.hashPassword(sys.stdin.read()))"], stdin=password, stdout=subprocess.PIPE, env={ "PYTHONPATH": ":".join([os.path.join(installation.paths.etc_dir, "main"), installation.paths.install_dir]) }) else: password = auth.hashPassword(password) installation.process.check_input( ["su", "-s", "/bin/sh", "-c", "psql -q -v ON_ERROR_STOP=1 -f -", installation.system.username], stdin=("""INSERT INTO users (name, email, password, fullname, status) VALUES (%s, %s, %s, %s, 'current');""" % (adapt(username), adapt(email), adapt(password), adapt(fullname)))) for role in ["administrator", "repositories", "newswriter"]: installation.process.check_input( ["su", "-s", "/bin/sh", "-c", "psql -q -v ON_ERROR_STOP=1 -f -", installation.system.username], stdin=("""INSERT INTO userroles (uid, role) SELECT id, %s FROM users WHERE name=%s;""" % (adapt(role), adapt(username)))) return True
def passwd(argv): parser = argparse.ArgumentParser( description="Critic administration interface: passwd", prog="criticctl [options] passwd") class NoPassword: pass parser.add_argument("--name", help="user name") parser.add_argument("--password", help="password") parser.add_argument("--no-password", dest="password", action="store_const", const=NoPassword, help="delete the user's password") arguments = parser.parse_args(argv) name = use_argument_or_ask(arguments.name, "Username:"******"Password:"******"""UPDATE users SET password=%s WHERE name=%s""", (hashed_password, name)) db.commit() if hashed_password: print "%s: password changed" % name else: print "%s: password deleted" % name
def changePassword(self, db, user, current_pw, new_pw): # If |current_pw| is True, then this is an administrator changing # another user's password. The usual rules do not apply. if current_pw is not True: cursor = db.readonly_cursor() cursor.execute("SELECT password FROM users WHERE id=%s", (user.id,)) hashed_pw, = cursor.fetchone() if current_pw is not None: auth.checkPassword(db, user.name, current_pw) elif hashed_pw is not None: # This is mostly a sanity check; the only way to trigger this is # if the user has no password when he loads /home, sets a # password in another tab or using another browser, and then # tries to set (rather than change) the password using the old # stale /home. raise auth.WrongPassword with db.updating_cursor("users") as cursor: cursor.execute("UPDATE users SET password=%s WHERE id=%s", (auth.hashPassword(new_pw), user.id))
def process(self, db, user, new_pw, subject=None, current_pw=None): if subject is None: subject = user cursor = db.cursor() if user != subject: Operation.requireRole(db, "administrator", user) elif current_pw is None: cursor.execute("SELECT password FROM users WHERE id=%s", (subject.id,)) if cursor.fetchone()[0] is not None: # This is mostly a sanity check; the only way to trigger this is # if the user has no password when he loads /home, sets a # password in another tab or using another browser, and then # tries to set (rather than change) the password using the old # stale /home. raise OperationFailure(code="wrongpassword", title="Wrong password!", message="No current password provided.") if current_pw is not None: try: auth.checkPassword(db, subject.name, current_pw) except auth.WrongPassword: raise OperationFailure(code="wrongpassword", title="Wrong password!", message="The provided current password is not correct.") if not new_pw: raise OperationFailure(code="emptypassword", title="Empty password!", message="Setting an empty password is not allowed.") cursor.execute("UPDATE users SET password=%s WHERE id=%s", (auth.hashPassword(new_pw), subject.id)) db.commit() return OperationResult()
db = dbutils.Database() db.cursor().execute( """INSERT INTO systemidentities (key, name, anonymous_scheme, authenticated_scheme, hostname, description, installed_sha1) VALUES ('main', 'main', 'http', 'http', 'localhost', 'Main', ?)""", (subprocess.check_output("git rev-parse HEAD", shell=True).strip(), )) admin = dbutils.User.create(db, name=arguments.admin_username, fullname=arguments.admin_fullname, email=arguments.admin_email, email_verified=None, password=auth.hashPassword( arguments.admin_password)) if not arguments.testing: if not quiet: print print("Created administrator user %r with password '1234'" % data["installation.admin.username"]) db.cursor().execute( """INSERT INTO userroles (uid, role) SELECT %s, name FROM roles""", (admin.id, )) db.commit() db.close()
import auth db = dbutils.Database() db.cursor().execute("""INSERT INTO systemidentities (key, name, anonymous_scheme, authenticated_scheme, hostname, description, installed_sha1) VALUES ('main', 'main', 'http', 'http', 'localhost', 'Main', ?)""", (subprocess.check_output("git rev-parse HEAD", shell=True).strip(),)) admin = dbutils.User.create( db, name=arguments.admin_username, fullname=arguments.admin_fullname, email=arguments.admin_email, email_verified=None, password=auth.hashPassword(arguments.admin_password)) if not arguments.testing: if not quiet: print print ("Created administrator user %r with password '1234'" % data["installation.admin.username"]) db.cursor().execute("""INSERT INTO userroles (uid, role) SELECT %s, name FROM roles""", (admin.id,)) db.commit() db.close()
def process(self, db, user, req, username, fullname, email, password=None, external=None): cursor = db.cursor() if not fullname: fullname = username if not email: email = None if not password: # Empty password => disabled. password = None if external: provider_config = configuration.auth.PROVIDERS[ external["provider"]] provider = auth.PROVIDERS[external["provider"]] # Check that user registration is actually enabled. This would also # disable the UI for user registration, of course, but the UI could be # bypassed, so we should check here as well. if not configuration.base.ALLOW_USER_REGISTRATION: if not external or not provider_config["allow_user_registration"]: return OperationResult( message="User registration is not enabled.") # Check that the user name is valid. try: auth.validateUserName(username) except auth.InvalidUserName as error: return OperationResult(message="<u>Invalid user name</u><br>" + str(error), focus="#newusername") # Check that the user name is not already taken. cursor.execute("SELECT 1 FROM users WHERE name=%s", (username, )) if cursor.fetchone(): return OperationResult( message="A user named '%s' already exists!" % username, focus="#newusername") # Check that the email address has some hope of being valid. if email and not checkEmailAddressSyntax(email): return OperationResult( message=("<u>Invalid email address</u><br>" "Please provide an address on the form user@host!"), focus="#email") # Check that we have either a password or an external authentication # provider. If we have neither, the user wouldn't be able to sign in. if password is None and external is None: return OperationResult(message="Empty password.", focus="#password1") if password: password = auth.hashPassword(password) verify_email_address = configuration.base.VERIFY_EMAIL_ADDRESSES if external: # Check that the external authentication token is valid. if not provider.validateToken(db, external["account"], external["token"]): return OperationResult( message="Invalid external authentication state.") cursor.execute( """SELECT id, uid, email FROM externalusers WHERE provider=%s AND account=%s""", (external["provider"], external["account"])) # Note: the token validation above implicitly checks that there's a # matching row in the 'externalusers' table. external_user_id, existing_user_id, external_email = cursor.fetchone( ) # Check that we don't already have a Critic user associated with # this external user. if existing_user_id is not None: existing_user = dbutils.User.fromId(db, existing_user_id) return OperationResult( message=("There is already a Critic user ('%s') connected " "to the %s '%s'" % (existing_user.name, provider.getTitle(), external["account"]))) if email == external_email: verify_email_address = provider.configuration[ "verify_email_addresses"] # Reset 'email' column in 'externalusers': we only need it to detect # if the user changed the email address in the "Create user" form. # Also reset the 'token' column, which serves no further purpose # beyond this point. cursor.execute( """UPDATE externalusers SET email=NULL, token=NULL WHERE id=%s""", (external_user_id, )) email_verified = False if email and verify_email_address else None user = dbutils.User.create(db, username, fullname, email, email_verified, password) if external: cursor.execute( """UPDATE externalusers SET uid=%s WHERE id=%s""", (user.id, external_user_id)) auth.startSession(db, req, user) if email_verified is False: sendVerificationMail(db, user) db.commit() user.sendUserCreatedMail("wsgi[registeruser]", external) return OperationResult()
def process(self, db, user, req, username, fullname, email, password=None, external=None): cursor = db.cursor() if not fullname: fullname = username if not email: email = None if not password: # Empty password => disabled. password = None if external: provider_config = configuration.auth.PROVIDERS[external["provider"]] provider = auth.PROVIDERS[external["provider"]] # Check that user registration is actually enabled. This would also # disable the UI for user registration, of course, but the UI could be # bypassed, so we should check here as well. if not configuration.base.ALLOW_USER_REGISTRATION: if not external or not provider_config["allow_user_registration"]: return OperationResult( message="User registration is not enabled.") # Check that the user name is valid. try: auth.validateUserName(username) except auth.InvalidUserName as error: return OperationResult( message="<u>Invalid user name</u><br>" + str(error), focus="#newusername") # Check that the user name is not already taken. cursor.execute("SELECT 1 FROM users WHERE name=%s", (username,)) if cursor.fetchone(): return OperationResult( message="A user named '%s' already exists!" % username, focus="#newusername") # Check that the email address has some hope of being valid. if email and not checkEmailAddressSyntax(email): return OperationResult( message=("<u>Invalid email address</u><br>" "Please provide an address on the form user@host!"), focus="#email") # Check that we have either a password or an external authentication # provider. If we have neither, the user wouldn't be able to sign in. if password is None and external is None: return OperationResult( message="Empty password.", focus="#password1") if password: password = auth.hashPassword(password) verify_email_address = configuration.base.VERIFY_EMAIL_ADDRESSES if external: # Check that the external authentication token is valid. if not provider.validateToken(db, external["account"], external["token"]): return OperationResult( message="Invalid external authentication state.") cursor.execute("""SELECT id, uid, email FROM externalusers WHERE provider=%s AND account=%s""", (external["provider"], external["account"])) # Note: the token validation above implicitly checks that there's a # matching row in the 'externalusers' table. external_user_id, existing_user_id, external_email = cursor.fetchone() # Check that we don't already have a Critic user associated with # this external user. if existing_user_id is not None: existing_user = dbutils.User.fromId(db, existing_user_id) return OperationResult( message=("There is already a Critic user ('%s') connected " "to the %s '%s'" % (existing_user.name, provider.getTitle(), external["account"]))) if email == external_email: verify_email_address = provider.configuration["verify_email_addresses"] # Reset 'email' column in 'externalusers': we only need it to detect # if the user changed the email address in the "Create user" form. # Also reset the 'token' column, which serves no further purpose # beyond this point. with db.updating_cursor("externalusers") as cursor: cursor.execute("""UPDATE externalusers SET email=NULL, token=NULL WHERE id=%s""", (external_user_id,)) email_verified = False if email and verify_email_address else None user = dbutils.User.create( db, username, fullname, email, email_verified, password, external_user_id=external_user_id) if email_verified is False: sendVerificationMail(db, user) user.sendUserCreatedMail("wsgi[registeruser]", external) auth.createSessionId(db, req, user) return OperationResult()