Example #1
0
def create_user(
        username,
        password,
        email,
        auto_verify=False,
        email_required=True,
        prompts=tuple(),
        is_possible_abuser=False,
):
    """
    Creates a regular user, if allowed.
    """
    if not validate_password(password):
        raise InvalidPasswordException(INVALID_PASSWORD_MESSAGE)

    created = create_user_noverify(
        username,
        email,
        email_required=email_required,
        prompts=prompts,
        is_possible_abuser=is_possible_abuser,
    )
    created.password_hash = hash_password(password).decode("ascii")
    created.verified = auto_verify
    created.save()

    return created
Example #2
0
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
Example #3
0
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
Example #4
0
def change_password(user, new_password):
    if not validate_password(new_password):
        raise InvalidPasswordException(INVALID_PASSWORD_MESSAGE)

    pw_hash = hash_password(new_password)
    user.invalid_login_attempts = 0
    user.password_hash = pw_hash.decode("ascii")
    invalidate_all_sessions(user)

    # Remove any password required notifications for the user.
    notification.delete_notifications_by_kind(user, "password_required")
Example #5
0
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