def change_username(user_id, new_username): (username_valid, username_issue) = validate_username(new_username) if not username_valid: raise InvalidUsernameException("Invalid username %s: %s" % (new_username, username_issue)) with db_transaction(): # Reload the user for update user = db_for_update(User.select().where(User.id == user_id)).get() # Rename the robots for robot in db_for_update( _list_entity_robots(user.username, include_metadata=False, include_token=False)): _, robot_shortname = parse_robot_username(robot.username) new_robot_name = format_robot_username(new_username, robot_shortname) robot.username = new_robot_name robot.save() # Rename the user user.username = new_username user.save() # Remove any prompts for username. remove_user_prompt(user, "confirm_username") return user
def create_robot(robot_shortname, parent, description="", unstructured_metadata=None): (username_valid, username_issue) = validate_username(robot_shortname) if not username_valid: raise InvalidRobotException( "The name for the robot '%s' is invalid: %s" % (robot_shortname, username_issue) ) username = format_robot_username(parent.username, robot_shortname) try: User.get(User.username == username) msg = "Existing robot with name: %s" % username logger.info(msg) raise InvalidRobotException(msg) except User.DoesNotExist: pass service = LoginService.get(name="quayrobot") try: with db_transaction(): created = User.create(username=username, email=str(uuid.uuid4()), robot=True) token = random_string_generator(length=64)() RobotAccountToken.create(robot_account=created, token=token, fully_migrated=True) FederatedLogin.create( user=created, service=service, service_ident="robot:%s" % created.id ) RobotAccountMetadata.create( robot_account=created, description=description[0:255], unstructured_json=unstructured_metadata or {}, ) return created, token except Exception as ex: raise DataModelException(ex.message)
def create_user_noverify( username, email, email_required=True, prompts=tuple(), is_possible_abuser=False ): if email_required: if not validate_email(email): raise InvalidEmailAddressException("Invalid email address: %s" % email) else: # If email addresses are not required and none was specified, then we just use a unique # ID to ensure that the database consistency check remains intact. email = email or str(uuid.uuid4()) (username_valid, username_issue) = validate_username(username) if not username_valid: raise InvalidUsernameException("Invalid namespace %s: %s" % (username, username_issue)) try: existing = User.get((User.username == username) | (User.email == email)) logger.info("Existing user with same username or email.") # A user already exists with either the same username or email if existing.username == username: assert not existing.robot msg = ( "Username has already been taken by an organization and cannot be reused: %s" % username ) if not existing.organization: msg = "Username has already been taken by user cannot be reused: %s" % username raise InvalidUsernameException(msg) raise InvalidEmailAddressException("Email has already been used: %s" % email) except User.DoesNotExist: # This is actually the happy path logger.debug("Email and username are unique!") # Create the user. try: default_expr_s = _convert_to_s(config.app_config["DEFAULT_TAG_EXPIRATION"]) default_max_builds = config.app_config.get("DEFAULT_NAMESPACE_MAXIMUM_BUILD_COUNT") threat_max_builds = config.app_config.get("THREAT_NAMESPACE_MAXIMUM_BUILD_COUNT") if is_possible_abuser and threat_max_builds is not None: default_max_builds = threat_max_builds new_user = User.create( username=username, email=email, removed_tag_expiration_s=default_expr_s, maximum_queued_builds_count=default_max_builds, ) for prompt in prompts: create_user_prompt(new_user, prompt) return new_user except Exception as ex: raise DataModelException(ex.message)
def change_personal_info(db): """ A resource for changing user info. Update request can contain 0 or more fields to change the user. Missing fields will not be updated. JSON body with all fields is: { "username": <string>, "password": <string>, "first_name": <string>, "last_name": <string>, } :param db: The database session :returns: Error JSON on failure or updated user JSON on success. """ # Get User info from request environment. user = request.environ.get('user_info') if user is None: raise RuntimeError('change_personal_info should always have user_info') # Get Update JSON from body. Return unchanged user if no body. data = request.json if data is None: return UserJSON.from_db(user).json # Validate JSON body try: if 'username' in data and not validate_username(data['username']): raise ValueError if 'password' in data and not validate_password(data['username']): raise ValueError if 'first_name' in data and not validate_name(data['first_name']): raise ValueError if 'last_name' in data and not validate_name(data['last_name']): raise ValueError except ValueError: response.status = 400 return Error("Update contains invalid data").json # Check username for originality if changing username = data.get('username', user.username) if username != user.username: count = db.query(User).filter(User.username == username).count() if count != 0: response.status = 400 return Error("'%s' already exists" % username).json # Update fields and send to database user.username = username user.password_hash = data.get('password', user.password_hash) user.first_name = data.get('first_name', user.first_name) user.last_name = data.get('last_name', user.last_name) db.commit() return UserJSON.from_db(user).json
def create_new_user(db): """ Create a new User. JSON must include all fields. JSON body with all fields is: { "username": <string>, "password": <string>, "first_name": <string>, "last_name": <string>, } :param db: The database session :returns: JSON containing the created user info if successful Otherwise, returns error information in JSON format. """ try: # Access and validate new user info from JSON body data = request.json if data is None: raise ValueError if 'username' not in data or not validate_username(data['username']): raise ValueError if 'password' not in data or not validate_password(data['username']): raise ValueError if 'first_name' not in data or not validate_name(data['first_name']): raise ValueError if 'last_name' not in data or not validate_name(data['last_name']): raise ValueError username = data['username'] password = data['password'] first_name = data['first_name'] last_name = data['last_name'] except ValueError: response.status = 400 # Bad Request return Error("Missing JSON with valid username, password, " + "first_name, last_name").json # Check that the username doesn't already exist count = db.query(User).filter(User.username == username).count() if count != 0: response.status = 400 return Error("'%s' already exists" % username).json # Insert User into database user = User(username=username, password_hash=password, first_name=first_name, last_name=last_name) db.add(user) db.commit() return UserJSON.from_db(user).json
def handle_quick_replies(payload, text, db, timezone): db_response = None user_err_msg = None err = None if payload == "qr_check_daily_goal": db_response, err = db.Check_daily_goal() elif payload == "qr_disable_reminder": db_response, err = db.Disable_reminder() elif payload == "qr_set_username": user_err_msg, valid, err = validation.validate_username(text) if valid: db_response, err = db.Set_username(text) elif payload == "qr_set_reminder": user_err_msg, valid, err, reminder_time = validation.validate_reminder( text, timezone) if valid: db_response, err = db.Set_reminder(reminder_time) elif payload == "qr_set_daily_goal": user_err_msg, valid, err = validation.validate_daily_goal(text) if valid: db_response, err = db.Set_daily_goal(text) return db_response, user_err_msg, err
def test_validate_username(username, is_valid): valid, _ = validate_username(username) assert valid == is_valid
def login(db): """ Generate a session with the server. Session generation performed according to the following steps. 1. Client presents username and password 2. Server authenticates username and password. 3. Server generates cryptographically secure random token if session doesn't already exist and send to client. 4. Server sends previously generated random token if session already exists. This session token must be provided with each future request in an HTTP header called 'Authentication'. Login request must contain JSON body: { "username": <string>, "password": <string>, } :param db: The database session :returns: Error JSON on fail or Session token JSON on success. """ try: data = request.json if data is None: raise ValueError # validate data if 'username' not in data or not validate_username(data['username']): raise ValueError if 'password' not in data or not validate_password(data['password']): raise ValueError username = data['username'] password = data['password'] except ValueError: response.status = 400 return Error("Missing valid username or password").json # Verify username/password combo with database try: user = db.query(User) \ .filter(User.username == username, User.password_hash == password) \ .one() except NoResultFound: response.status = 401 return Error("Username/Password combo is invalid").json except MultipleResultsFound: response.status = 500 return Error( "Somehow multiple users exist with that username/password") try: # Try to revieve old session token session = db.query(Session) \ .filter(Session.user_id == user.id) \ .one() except NoResultFound: # No previous session so generate new token while True: # Make sure session token doesn't already exist. token = generate_token() if db.query(Session) \ .filter(Session.session_hash == token).count() == 0: break session = Session(session_hash=token, user_id=user.id, expires=datetime.now() + timedelta(weeks=2)) db.add(session) return Token(session.session_hash).json