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")
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)
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
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
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
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)
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
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)
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))
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)
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))
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))
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])
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)
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'))
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)
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))
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())
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))
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
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'))
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)
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'))
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
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
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) """
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)
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)
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))
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