def sign(user_id, user_type=None, today=None, session=None):
    """Check user id for validity, then sign user in if they are signed
    out, or out if they are signed in.

    :param user_id: The ID of the user to sign in or out.
    :param user_type: (optional) Specify whether user is signing in as a `'student'` or `'tutor'`.
    :param today: (optional) The current date as a `datetime.date` object. Used for testing.
    :param session: (optional) SQLAlchemy session through which to access the database.
    :return: `Status` named tuple object. Information about the sign attempt.
    """ # noqa
    if session is None:
        session = Session()
    else:
        session = session

    if today is None:
        today = date.today()
    else:
        today = today

    user = (
        session
        .query(User)
        .filter(User.user_id == user_id)
        .one_or_none()
    )

    if user:
        signed_in_entries = (
            user
            .entries
            .filter(Entry.date == today)
            .filter(Entry.time_out.is_(None))
            .all()
        )

        if not signed_in_entries:
            new_entry = sign_in(user, user_type=user_type)
            session.add(new_entry)
            status = Status(
                valid=True,
                in_or_out='in',
                user_name=get_user_name(user),
                user_type=new_entry.user_type,
                entry=new_entry
            )

        else:
            for entry in signed_in_entries:
                signed_out_entry = sign_out(entry)
                session.add(signed_out_entry)
                status = Status(
                    valid=True,
                    in_or_out='out',
                    user_name=get_user_name(user),
                    user_type=signed_out_entry.user_type,
                    entry=signed_out_entry
                )

        session.commit()

    else:
        raise UnregisteredUser(
            '{} not registered. Please register at the front desk.'.format(
                user_id
            )
        )

    logger.debug(status)
    return status