Ejemplo n.º 1
0
Archivo: door.py Proyecto: bitraf/p2k16
    def open_doors(self, account: Account, doors):
        can_open_door = authz_management.can_haz_door_access(account, doors)
        if not can_open_door:
            f = "{} does not have an active membership, or lacks door circle membership"
            raise P2k16UserException(f.format(account.display_name()))

        if not event_management.has_opened_door(account):
            system = Account.find_account_by_username("system")
            logger.info("First door opening for {}".format(account))
            badge_management.create_badge(account, system,
                                          "first-door-opening")

        for door in doors:
            lf = "Opening door. username={}, door={}, open_time={}"
            logger.info(lf.format(account.username, door.key, door.open_time))

            event_management.save_event(OpenDoorEvent(door.key))

        # Make sure everything has been written to the database before actually opening the door.
        db.session.flush()

        # TODO: move this to a handler that runs after the transaction is done
        # TODO: we can look at the responses and see if they where successfully sent/received.
        for door in doors:
            if isinstance(door, DlockDoor):
                self.dlock.open(door)
            elif isinstance(door, MqttDoor):
                self.mqtt.open(door)
            else:
                P2k16TechnicalException("Unknown kind of door")
Ejemplo n.º 2
0
    def open_doors(self, account: Account, doors: List[Door]):

        can_open_door = authz_management.can_haz_door_access(account)

        if not can_open_door:
            raise P2k16UserException(
                '{} does not have an active membership, or lack door circle membership'
                .format(account.display_name()))

        publishes = []

        if not event_management.has_opened_door(account):
            system = Account.find_account_by_username("system")
            logger.info("First door opening for {}".format(account))
            badge_management.create_badge(account, system,
                                          "first-door-opening")

        for door in doors:
            logger.info(
                'Opening door. username={}, door={}, open_time={}'.format(
                    account.username, door.key, door.open_time))
            event_management.save_event(OpenDoorEvent(door.key))
            publishes.append((self.prefix + door.topic, str(door.open_time)))

        # Make sure everything has been written to the database before actually opening the door.
        db.session.flush()

        # TODO: move this to a handler that runs after the transaction is done
        # TODO: we can look at the responses and see if they where successfully sent/received.
        for topic, open_time in publishes:
            logger.info("Sending message: {}: {}".format(topic, open_time))
            self._client.publish(topic, open_time)
Ejemplo n.º 3
0
def start_reset_password(username: string) -> Optional[Account]:
    logger.info('Resetting password for {}'.format(username))

    account = Account.find_account_by_username(username)

    if account is None:
        account = Account.find_account_by_email(username)

    if account is None:
        logger.info(
            'Could not find account by username or email: {}'.format(username))
        return None

    account.create_new_reset_token()

    # Setting scheme to https here is a bit silly, but flask doesn't auto-detect the correct scheme without more work
    url = flask.url_for('core.reset_password_form',
                        reset_token=account.reset_token,
                        _external=True,
                        _scheme="https")
    logger.info('Reset URL: {}'.format(url))

    mail.send_password_recovery(account, url)

    return account
Ejemplo n.º 4
0
def _load_circle_admin(account_id, circle_id, admin_id):
    account = Account.find_account_by_id(account_id)
    admin = Account.find_account_by_id(admin_id)
    circle = Circle.find_by_id(circle_id)

    if account is None or admin is None or circle is None:
        raise P2k16UserException('Bad values')

    return account, admin, circle
Ejemplo n.º 5
0
def register_account(username: str, email: str, name: str, password: str,
                     phone: str) -> Account:
    account = Account.find_account_by_username(username)
    if account:
        raise P2k16UserException("Username is taken")

    account = Account.find_account_by_email(email)
    if account:
        raise P2k16UserException("Email is already registered")

    account = Account(username, email, name, phone, password)
    db.session.add(account)
    return account
Ejemplo n.º 6
0
    def open_doors(self, account: Account, doors: List[Door]):
        door_circle = Circle.get_by_name('door')

        can_open_door = False

        if account_management.is_account_in_circle(
                account,
                door_circle) and membership_management.active_member(account):
            can_open_door = True

        if len(Company.find_active_companies_with_account(account.id)) > 0:
            can_open_door = True

        if not can_open_door:
            # Only non-office users may fail here
            if not membership_management.active_member(account):
                raise P2k16UserException(
                    '{} does not have an active membership'.format(
                        account.display_name()))

            if not account_management.is_account_in_circle(
                    account, door_circle):
                raise P2k16UserException('{} is not in the door circle'.format(
                    account.display_name()))

        publishes = []

        if not event_management.has_opened_door(account):
            system = Account.find_account_by_username("system")
            logger.info("First door opening for {}".format(account))
            badge_management.create_badge(account, system,
                                          "first-door-opening")

        for door in doors:
            logger.info(
                'Opening door. username={}, door={}, open_time={}'.format(
                    account.username, door.key, door.open_time))
            event_management.save_event(OpenDoorEvent(door.key))
            publishes.append((self.prefix + door.topic, str(door.open_time)))

        # Make sure everything has been written to the database before actually opening the door.
        db.session.flush()

        # TODO: move this to a handler that runs after the transaction is done
        # TODO: we can look at the responses and see if they where successfully sent/received.
        for topic, open_time in publishes:
            logger.info("Sending message: {}: {}".format(topic, open_time))
            self._client.publish(topic, open_time)
Ejemplo n.º 7
0
def passwd_php():
    # IP check is done by the frontend webserver

    # $res = pg_query(
    #     "SELECT ac.id + 100000 AS id, ac.name, au.data, am.full_name FROM auth au INNER JOIN accounts ac ON ac.id =
    #     au.account INNER JOIN active_members am ON am.account = ac.id WHERE au.realm = 'login'");
    #
    # header('Content-Type: text/plain; charset=utf-8');
    #
    # while ($row = pg_fetch_assoc($res))
    # {
    #     echo
    # "{$row['name']}:{$row['data']}:{$row['id']}:{$row['id']}:{$row['full_name']}:/bitraf/home/{$row['name']}:/bin/bash\n";

    accounts = Account.all_user_accounts()

    s = io.StringIO()
    for a in accounts:
        s.write("{}:{}:{}:{}:{}:/bitraf/home/{}:/bin/bash\n".format(
            a.username, a.password, a.id, a.id, a.name, a.username))

    r = flask.make_response()  # type: flask.Response
    r.content_type = 'text/plain;charset=utf-8'
    r.data = s.getvalue()
    return r
Ejemplo n.º 8
0
def data_account_summary(account_id):
    account = Account.find_account_by_id(account_id)

    if account is None:
        abort(404)

    badges = badge_management.badges_for_account(account.id)

    open_door_event = event_management.last_door_open(account)

    # Add to response
    from .badge_blueprint import badge_to_json
    summary = {
        "account": account_to_json(account),
        "badges": [badge_to_json(b) for b in badges],
        "lastDoorOpen": open_door_event.to_dict() if open_door_event else None,
    }

    # Add information about membership if current user is in a circle
    admin_circle = Circle.get_by_name('insight-fee')
    if account_management.is_account_in_circle(
            flask_login.current_user.account, admin_circle):
        membership = get_membership(account)
        membership_details = {}
        if membership is not None:
            membership_details['fee'] = membership.fee
            membership_details[
                'first_membership'] = membership.first_membership
            membership_details[
                'start_membership'] = membership.start_membership
        else:
            membership_details['fee'] = 0
        summary['membership'] = membership_details

    return jsonify(summary)
Ejemplo n.º 9
0
def _data_company_change_employee(company_id, add: bool):
    check_is_in_circle("admin")

    company = Company.find_by_id(company_id)

    if company is None:
        abort(404)

    account_id = request.json["account_id"]
    account = Account.find_account_by_id(account_id)
    if account is None:
        abort(404)

    if add:
        db.session.add(CompanyEmployee(company, account))
    else:
        ce = CompanyEmployee.find_by_company_and_account(
            company_id, account_id)
        if ce is None:
            abort(404)
        db.session.delete(ce)

    employees = CompanyEmployee.list_by_company(company_id)
    db.session.commit()

    return jsonify(company_to_json(company, employees))
Ejemplo n.º 10
0
def data_account(account_id):
    account = Account.find_account_by_id(account_id)

    if account is None:
        abort(404)

    circles = account_management.get_circles_for_account(account.id)

    # Get current membership
    membership = get_membership(account)
    membership_details = {}
    if membership is not None:
        membership_details['fee'] = membership.fee
        membership_details['first_membership'] = membership.first_membership
        membership_details['start_membership'] = membership.start_membership
    else:
        membership_details['fee'] = 0

    # Export payments
    payments = []
    for pay in get_membership_payments(account):
        payments.append({
            'id': pay.id,
            'start_date': pay.start_date,
            'end_date': pay.end_date,
            'amount': float(pay.amount),
            'payment_date': pay.payment_date
        })
    membership_details['payments'] = payments

    detail = account_to_json(account, circles, None)
    detail['membership'] = membership_details

    return jsonify(detail)
Ejemplo n.º 11
0
def _data_company_save():
    contact_id = request.json["contact"]
    contact = Account.find_account_by_id(contact_id)
    if not contact:
        raise P2k16UserException("No such account: {}".format(contact_id))

    _id = request.json.get("id", None)

    if _id:
        company = Company.find_by_id(_id)

        if company is None:
            abort(404)

        logger.info("Updating company: {}".format(company))
        company.name = request.json["name"]
        company.contact_id = contact.id
        company.active = request.json["active"]
    else:
        name = request.json["name"]
        active = request.json["active"]
        logger.info("Registering new company: {}".format(name))
        company = Company(name, contact, active)

    db.session.add(company)
    db.session.commit()

    return jsonify(company_to_json(company, include_employees=True))
Ejemplo n.º 12
0
def set_password(account: Account,
                 new_password: str,
                 old_password: Optional[str] = None,
                 reset_token: Optional[str] = None):
    if reset_token is not None:
        if not account.is_valid_reset_token(reset_token):
            raise P2k16TechnicalException("Invalid reset token")
    elif old_password is not None:
        if not account.valid_password(old_password):
            raise P2k16TechnicalException("Bad password")
    else:
        raise P2k16TechnicalException(
            "Either old_password or reset_token has to be set.")

    account.password = new_password
    logger.info('Updating password for account={}'.format(account))
Ejemplo n.º 13
0
def badges_for_user(account_id):
    account = Account.find_account_by_id(account_id)

    badges = AccountBadge.query. \
        filter(AccountBadge.account == account). \
        all()  # type: List[AccountBadge]
    return jsonify([badge_to_json(b) for b in badges])
Ejemplo n.º 14
0
def _data_profile_list(full):
    accounts = {a.id: a
                for a in Account.all_user_accounts()
                }  # type:Mapping[int, Account]
    account_ids = [a for a in accounts]
    from itertools import groupby

    account_badges = AccountBadge.query.filter(
        AccountBadge.account_id.in_(account_ids))
    account_badges = sorted(account_badges, key=lambda ab: ab.account_id)
    badges_by_account = {
        _id: list(abs)
        for _id, abs in groupby(account_badges, lambda ab: ab.account_id)
    }  # type: Mapping[int, List[AccountBadge]]

    cms = CircleMember.query.filter(CircleMember.account_id.in_(account_ids))
    cms = sorted(cms, key=lambda cm: cm.account_id)
    cms_by_account = groupby(
        cms,
        lambda cm: cm.account_id)  # type: Iterable[(int, List[CircleMember])]

    circles_by_account = {
        _id: {cm.circle
              for cm in cms}
        for _id, cms in cms_by_account
    }  # type: Mapping[int, Set[Circle]]

    profiles = [
        profile_to_json(a,
                        circles_by_account.get(id, []),
                        badges_by_account.get(id, []),
                        full=full) for id, a in accounts.items()
    ]

    return jsonify(profiles)
Ejemplo n.º 15
0
def reset_password_form():
    reset_token = flask.request.args['reset_token']
    account = Account.find_account_by_reset_token(reset_token)

    if account and account.is_valid_reset_token(reset_token):
        return render_template("reset-password.html", reset_token=reset_token, account=account_to_json(account, [], []))

    return flask.redirect(flask.url_for('.login', show_message='recovery-invalid-request'))
Ejemplo n.º 16
0
    def checkout_tool(self, account: Account, tool: ToolDescription):
        # Check that user has correct circle and is paying member
        if not account_management.is_account_in_circle(account, tool.circle):
            raise P2k16UserException('{} is not in the {} circle'.format(
                account.display_name(), tool.circle.name))

        if not membership_management.active_member(account) \
                and len(Company.find_active_companies_with_account(account.id)) == 0:
            raise P2k16UserException(
                '{} does not have an active membership and is not employed in an active company'
                .format(account.display_name()))

        logger.info('Checking out tool. username={}, tool={}'.format(
            account.username, tool.name))

        # Verify that tool is not checked out by someone else. Check in first if it is.
        checkout = ToolCheckout.find_by_tool(tool)
        if checkout:
            if checkout.account is account:
                raise P2k16UserException('Tools can only be checked out once.')

            logger.info(
                'Tool checked out by someone else. Assuming control: username={}, tool={}, old_username={}'
                .format(account.username, tool.name, checkout.account.name))
            self.checkin_tool(checkout.account, checkout.tool_description)

        # Make a new checkout reservation
        event_management.save_event(
            ToolCheckoutEvent(tool.name, datetime.now(), account))
        checkout = ToolCheckout(tool, account, datetime.now())
        db.session.add(checkout)

        # Make sure everything has been written to the database before actually opening the door.
        db.session.flush()

        # TODO: move this to a handler that runs after the transaction is done
        # TODO: we can look at the responses and see if they where successfully sent/received.
        #        for topic, open_time in publishes:
        #            logger.info("Sending message: {}: {}".format(topic, open_time))
        #            self._client.publish(topic, open_time)

        topic = self._mqtt_topic(tool=tool.name, action='unlock')
        payload = 'true'
        logger.info("Sending message: {}: {}".format(topic, payload))
        self._client.publish(topic, payload)
Ejemplo n.º 17
0
def data_account(account_id):
    account = Account.find_account_by_id(account_id)

    if account is None:
        abort(404)

    circles = account_management.get_circles_for_account(account.id)

    return jsonify(account_to_json(account, circles, None))
Ejemplo n.º 18
0
def print_box_label():
    a = flask_login.current_user.account

    client = flask.current_app.config.label_client  # type: LabelClient

    user = Account.find_account_by_id(request.json["user"])

    client.print_box_label(user)

    return jsonify(dict())
Ejemplo n.º 19
0
def _manage_circle_membership(create: bool):
    username = request.json.get("accountUsername", None)

    if username is not None:
        account = Account.get_by_username(username)
    else:
        account = Account.get_by_id(request.json["accountId"])

    circle = Circle.get_by_id(request.json["circleId"])

    admin = flask_login.current_user.account

    if create:
        comment = request.json.get("comment", "")
        account_management.add_account_to_circle(account, circle, admin, comment)
    else:
        account_management.remove_account_from_circle(account, circle, admin)

    db.session.commit()
    return jsonify(circle_to_json(circle, include_members=True))
Ejemplo n.º 20
0
def find_account_from_stripe_customer(stripe_customer_id) -> Optional[Account]:
    """
    Get account from stripe customer
    :param stripe_customer_id:
    :return: account
    """
    sc = StripeCustomer.query.filter(
        StripeCustomer.stripe_id == stripe_customer_id).one_or_none()

    return Account.find_account_by_id(
        sc.created_by_id) if sc is not None else None
Ejemplo n.º 21
0
def set_new_password():
    reset_token = flask.request.form['reset_token']
    account = Account.find_account_by_reset_token(reset_token)

    if not account or not account.is_valid_reset_token(reset_token):
        return flask.redirect(flask.url_for('.login', show_message='recovery-invalid-request'))

    new_password = flask.request.form['password']
    account_management.set_password(account, new_password, reset_token=reset_token)
    db.session.commit()
    return flask.redirect(flask.url_for('core.index'))
Ejemplo n.º 22
0
def find_account_from_stripe_customer(stripe_customer_id):
    """
    Get account from stripe customer
    :param customer_id:
    :return: account
    """
    id = StripeCustomer.query.filter(
        StripeCustomer.stripe_id == stripe_customer_id).one_or_none()
    if id is None:
        return None

    return Account.find_account_by_id(id.created_by_id)
Ejemplo n.º 23
0
def set_new_password():
    reset_token = flask.request.form['reset_token']
    account = Account.find_account_by_reset_token(reset_token)

    if not account or not account.is_valid_reset_token(reset_token):
        return flask.redirect(
            flask.url_for('.login', show_message='recovery-invalid-request'))

    password = flask.request.form['password']
    account.password = password
    logger.info('Updating password for account={}'.format(account))
    db.session.commit()
    return flask.redirect(flask.url_for('core.index'))
Ejemplo n.º 24
0
def register_account(username: str, email: str, name: str, password: str,
                     phone: str) -> Account:
    account = Account.find_account_by_username(username)
    if account:
        raise P2k16UserException("Username is taken")

    account = Account.find_account_by_email(email)
    if account:
        raise P2k16UserException("Email is already registered")

    if name is None:
        raise P2k16UserException("Name cannot be empty.")

    if " " in username:
        raise P2k16UserException("Username cannot contain spaces")

    if not re.match(r"^[a-zA-Z0-9@._+-]+", username):
        raise P2k16UserException(
            "Username can only contain a-z, 0-9, @, ., _, + and -.")

    account = Account(username, email, name, phone, password)
    db.session.add(account)
    return account
Ejemplo n.º 25
0
def start_reset_password(username: string) -> Optional[Account]:
    logger.info('Resetting password for {}'.format(username))

    account = Account.find_account_by_username(username)

    if account is None:
        account = Account.find_account_by_email(username)

    if account is None:
        logger.info(
            'Could not find account by username or email: {}'.format(username))
        return None

    account.create_new_reset_token()

    url = flask.url_for('core.reset_password_form',
                        reset_token=account.reset_token,
                        _external=True)
    logger.info('Reset URL: {}'.format(url))

    mail.send_password_recovery(account, url)

    return account
Ejemplo n.º 26
0
def handle_session_completed(event):
    customer_id = event.data.object.customer

    account = Account.find_account_by_id(event.data.object.metadata.accountId)

    stripe_customer = get_stripe_customer(account)

    # Customer not registered with p2k16
    if stripe_customer is None:
        with model_support.run_as(account):
            stripe_customer = StripeCustomer(customer_id)
            db.session.add(stripe_customer)
            db.session.commit()

    mail.send_new_member(account)
    """
Ejemplo n.º 27
0
def account_loader(account_id):
    # logger.info("login_manager.user_loader: Loading account_id={}".format(account_id))

    account = Account.find_account_by_id(account_id)

    if account is None:
        logger.info(
            "login_manager.user_loader: no such account".format(account_id))
        return

    # logger.info("login_manager.user_loader: Loaded account.id={}, account.username={}".
    #             format(account.id, account.username))

    circles = account_management.get_circles_for_account(account.id)

    return AuthenticatedAccount(account, circles)
Ejemplo n.º 28
0
def data_account_summary(account_id):
    account = Account.find_account_by_id(account_id)

    if account is None:
        abort(404)

    circles = account_management.get_circles_for_account(account.id)
    badges = badge_management.badges_for_account(account.id)

    open_door_event = event_management.last_door_open(account)

    from .badge_blueprint import badge_to_json
    summary = {
        "account": account_to_json(account, circles, None),
        "badges": [badge_to_json(b) for b in badges],
        "lastDoorOpen": open_door_event.to_dict() if open_door_event else None
    }
    return jsonify(summary)
Ejemplo n.º 29
0
def login():
    if flask.request.method == 'GET':
        show_message = flask.request.args.get('show_message') or ''
        username = flask.request.args.get('username') or ''
        return render_template("login.html", show_message=show_message, username=username)

    username = flask.request.form['username']
    account = Account.find_account_by_username(username)
    password = flask.request.form['password']

    if account.valid_password(password):
        circles = account_management.get_circles_for_account(account.id)
        logger.info("User {} logged in, circles={}".format(username, circles))
        authenticated_account = auth.AuthenticatedAccount(account, circles)
        flask_login.login_user(authenticated_account)
        return flask.redirect(flask.url_for('core.index'))

    return flask.redirect(flask.url_for('.login', show_message='bad-login', username=username))
Ejemplo n.º 30
0
def core_ldif():
    from ldif3 import LDIFWriter
    import io
    f = io.BytesIO()
    writer = LDIFWriter(f)

    for a in Account.all_user_accounts():
        dn = "uid={},ou=People,dc=bitraf,dc=no".format(a.username)

        writer.unparse(dn, {"changetype": ["delete"]})

        object_class = ["top", "inetOrgPerson"]

        d = {
            "objectClass": object_class,
            "changetype": ["add"],
        }

        parts = a.name.split() if a.name is not None else []

        if len(parts) < 1:
            # bad name
            continue

        d["cn"] = [a.name]
        d["sn"] = [parts[-1]]
        if a.email:
            d["mail"] = [a.email]

        # posixAccount: http://ldapwiki.com/wiki/PosixAccount
        object_class.append("posixAccount")
        d["uid"] = [a.username]
        d["uidNumber"] = ["1000"]
        d["gidNumber"] = ["1000"]
        d["homeDirectory"] = ["/home/{}".format(a.username)]
        if a.password is not None:
            d["userPassword"] = [a.password]
        d["gecos"] = [a.name]

        writer.unparse(dn, d)

    s = f.getvalue()
    print(str(s))
    return s