示例#1
0
def delete_user(auth, client):
    """
    Delete a user

    :auth: dict
    :client: users_client object
    """

    log("What user you want to delete?")

    user_to_delete = find_user_by_username(auth, client)
    if user_to_delete is False:
        log("Could not find user.", serv="ERROR")
        return False

    confirmation = yes_or_no("You really want to delete %s?" %
                             user_to_delete["username"])

    if confirmation is False:
        log("Aborted...")
        return False

    try:
        client.users_user_id_delete(int(user_to_delete["id"]))
        log("Successfully deleted user %s" % user_to_delete["username"],
            serv="SUCCESS")
        return True
    except:
        log("Could not delete user %s. Error by backend" %
            user_to_delete["username"],
            serv="ERROR")
        return False
示例#2
0
def find_user_by_username(auth, client):
    """
    Helper function that returns a user object that is found
    by searching for a username

    :auth: dict
    :client: users_client object
    :username: str
    :returns: user object
    """

    user_to_find = None
    user_object = None

    user_to_find = input("Username: "******"Username too short (>=3).", serv="Error")
        return False

    # find user id
    users = client.users_get()
    for user in users:
        if user.to_dict()["username"] == user_to_find:
            user_object = user.to_dict()

    if user_object is None:
        log("Could not find user %s. Are you sure about the username?" %
            user_to_find,
            serv="ERROR")
        return False

    return user_object
示例#3
0
def show_item(auth, client, itemid):
    """
    Shows detail of a single item
    :auth: dict
    :client: item_client object
    :returns: bool
    """

    log(client.items_item_id_get(itemid).to_dict())
    return True
示例#4
0
文件: menu.py 项目: blarz/heiko
def welcome_banner():
    """
    Prints a big ascii interpretation from the club mate logo

    :returns: bool
    """
    logo_banner = """
                                    =?I777777II?????II777777?=
                               7777?                           I777?
                          I77I     I77               =777777777+     I77=
                      =77I    ?777777=                I7777777777777+   =77+
                   =77=   I7777777777                  77777777777777777+   77?
                 ?77   I7777777777777                  =7777777777777777777   ?77
               77=  I777777777777777?                   7777777777777777777777   77=
             ?7I  ?77777777777777777                     77777777777777777777777   77
           +77  77777777777777777777                     7777777777777777777777777   77
          77   777777777777777777777                      77777777777777777777777777  +7=
         77  77777777777777777777777                      777777777777777777777777777+  77
       I7   777777777777777777777777                          +7777777777777I+= +777777  77
      =7   77777777777777777777?=                   +?77777777777?             ?77777777  77
      7   7777777777=          =7777777777777777777777777=                  7777777777777  7I
     77  77777+                      ==+????++=                         I7777777777777777?  7
    I7  77777777I+                    ?77    ?777?+?7777+       +I777777777777777777777777  77
    7I  77777777777777777777777777    7777   777777777777  = 777777777777777777777777777777  7
    7  77777777777777777777777777+      ?  7 I=777777777 777 =77777777777777777777777777777  77
   77  77777777777777777777777777=777        =+==   I7777 7+ 777777777777777777777777777777  +7
   77  77777777777777777777777777 I? 77         77777=7777777777777777777777777777777777777?  7
   77  77777777777777777777777777777777=   777777777+?77777777777777I7777777777II7777777777I  7
   77  77777777777777777777777777    I       777777 ?777777777777777+7777777777 77777777777+ =7
   ?7  77777777777777777777777?                 77+ 7777777777777777=7777+7777+777777777777  I7
    7  ?777777777777777777I                     +7   =77777777777777+7777 7777 777777777777  7?
    77  777777777777777                                 77777777777+77777 77 I=77777777777+  7
     7  +777777777777                                     777777777 777=77+77I777777777777  7I
     77  I777777777                                        +7777=77=777?=777 777777777777  I7
      77  7777777                                            7 777=?777777? I77777777777=  7
       77  I777                                              77777777777    77777777777   7
        77  ?                                              ?777777777777I  77777777777   7
         ?7                                               777777777777777I77777777777  77
           77                                             777777777777I==I777777777=  7I
            +7+                                           77777      ?77777777777+  77
              +7+                                         777         ?77777777   77
                77=                                       77           +77777   77=
                   77                                                    7   I7?
                     77I                                                   77
                        +77?                                           77I
                            +77I                                  =777=
                                  7777I+                   ?7777+
                                          ++?IIII7III??+=

                     github.com/k4cg/heiko (v{}) / github.com/k4cg/matomat-service
""".format(pkg_resources.require("heiko")[0].version)
    os.system('clear')
    log(logo_banner)
    return True
示例#5
0
def nfc_detect():
    key = DEFAULT_KEY.copy()
    v, uid, ttype, dat = mnfc.read(1, 1, key, False)
    header = ""
    try:
        header = dat.decode()
    except:
        pass
    if v == 0:
        log("found " + ttype + " with uid " + uid)
        return uid, header
    return None, None
示例#6
0
def create_item(auth, client):
    """
    Asks admin for details and creates new item in the backend

    :auth: dict
    :returns: bool
    """

    name = input("Name of Drink: ")

    # TODO: Remove this? MaaS does not seem to mind non-alphanumerical charaters...
    if name.isalnum() is False:
        log("Item name not valid. Please be alphanumerical.", serv="ERROR")
        return False

    cost = float(input("Price in EUR (i.e. 1 or 1.20): ")) * 100

    if cost < 0:
        log("Negative price is not allowed ;)", serv="ERROR")
        return False

    try:
        client.items_post(name, int(cost))
        log("Successfully added new item with name %.2f and cost %.2f" % (name, float(cost) / 100), serv="SUCCESS")
    except swagger_client.rest.ApiException as api_expception:
        log("Item could not be created in the backend: " + api_expception.body, serv="ERROR")
        return False

    return True
示例#7
0
def reset_user_nfc(auth, auth_client, user_client):
    """
    Gives an admin the capability to reset password for a specific user and write new nfc token.
    It asks for username, trys to find userid by name and then asks for new password.

    :auth: dict
    :client: users_client object
    :returns: bool
    """
    log("What user you want to reset the password for?")
    user_to_reset = find_user_by_username(auth, user_client)

    if user_to_reset is False:
        log("Could not find user.", serv="ERROR")
        return False

    password = "".join(
        random.choice(string.ascii_letters + "0123456789") for i in range(23))

    try:
        user_client.users_user_id_resetpassword_patch(user_to_reset["id"],
                                                      password, password)
        log("Successfully reset password for user %s with id %s." %
            (user_to_reset["username"], user_to_reset["id"]),
            serv="SUCCESS")
    except:
        log("Could not reset password for user %s with id %s. Error by backend"
            % (user_to_reset["username"], user_to_reset["id"]),
            serv="ERROR")
        return False

    return nfc_format_card(auth_client, user_to_reset["username"], password)
示例#8
0
def reset_user_password(auth, client):
    """
    Gives an admin the capability to reset password for a specific user.
    It asks for username, trys to find userid by name and then asks for new password.

    :auth: dict
    :client: users_client object
    :returns: bool
    """
    log("What user you want to reset the password for?")
    user_to_reset = find_user_by_username(auth, client)

    if user_to_reset is False:
        log("Could not find user.", serv="ERROR")
        return False

    passwordnew = getpass.getpass("Password: "******"Repeat password: "******"id"],
                                                 passwordnew, passwordrepeat)
        log("Successfully changed password for user %s with id %s." %
            (user_to_reset["username"], user_to_reset["id"]),
            serv="SUCCESS")
        return True
    except:
        log("Could not reset password for user %s with id %s. Error by backend"
            % (user_to_reset["username"], user_to_reset["id"]),
            serv="ERROR")
        return False
示例#9
0
def add_credits_admin(auth, client):
    """
    Add credits by admin

    :auth: dict
    :client: users_client object
    :returns: bool
    """
    log("What user you want to add the credits for?")
    user = find_user_by_username(auth, client)
    if user is False:
        log("Could not find user.", serv="ERROR")
        return False

    add_credits = float(input("Paid amount (EUR): ")) * 100

    try:
        r = client.users_user_id_credits_add_patch(user["id"],
                                                   int(add_credits))
        auth["user"]["credits"] = r.to_dict()["credits"]
        log("Successfully set the credits for user %s to %.2f Euro" %
            (user["username"], auth["user"]["credits"] / 100),
            serv="SUCCESS")
        return True
    except:
        log("Could not add %.2f Euro credits for user %s. Backend error." %
            (add_credits, user["username"]),
            serv="ERROR")
        return False
示例#10
0
def reset_credits(auth, client):
    """
    Set credits to defined amount by admin

    :auth: dict
    :client: users_client object
    :returns: bool
    """
    log("What user you want to set the credits for?")
    user_to_reset = find_user_by_username(auth, client)
    if user_to_reset is False:
        log("Could not find user.", serv="ERROR")
        return False

    new_credits = float(input("Set new credits (EUR): ")) * 100

    try:
        client.users_user_id_credits_withdraw_patch(user_to_reset["id"],
                                                    user_to_reset["credits"])
        r = client.users_user_id_credits_add_patch(user_to_reset["id"],
                                                   int(new_credits))
        auth["user"]["credits"] = r.to_dict()["credits"]
        log("Successfully set the credits for user %s to %.2f Euro" %
            (user_to_reset["username"], new_credits / 100),
            serv="SUCCESS")
        return True
    except:
        log("Could not set the credits for user %s to %.2f Euro. Backend error."
            % (user_to_reset["username"], new_credits),
            serv="ERROR")
        return False
示例#11
0
def show_user_stats(auth, client):
    """
    Presents consumption statistics to user

    :auth: dict
    :client: users_client object
    :returns: bool
    """

    try:
        stats = client.users_user_id_stats_get(auth["user"]["id"])
    except swagger_client.rest.ApiException:
        log("Could fetch stats from the database.", serv="ERROR")
        return False

    drinks = []
    sum_money = 0
    for drink in stats:
        money = float(drink["consumed"]) * float(drink["cost"]) / 100
        sum_money = sum_money + money
        drinks.append([drink["name"], drink["consumed"], money])

    log("Your consumption statistics:\n")
    log(
        tabulate(drinks,
                 headers=["Name", "Consumptions", "Coins spent (EUR)"],
                 tablefmt="presto",
                 floatfmt=".2f"))

    log("\nCoins spent overall: {:.2f} EUR".format(sum_money))
    return True
示例#12
0
def nfc_write(uid, header, token, key=None):
    if key is None:
        key = DEFAULT_KEY.copy()

    secLen = 3 * 16
    hb = header.encode()
    hb += b"\x00" * (secLen - len(hb))

    datLen = 14 * secLen
    b = token.encode()
    b += b"\x00" * (datLen - len(b))

    v = mnfc.write(1, 15, uid, hb + b, key, False)
    if v == 0:
        log("write successful")
示例#13
0
def change_password(auth, client):
    """
    Gives user the capability to reset password for himself/herself.

    :auth: dict
    :client: users_client object
    :returns: bool
    """

    password = getpass.getpass("Current Password: "******"New Password: "******"Repeat password: "******"user"]["id"], password,
                                            passwordnew, passwordrepeat)
        log("Successfully changed your password!", serv="SUCCESS")
        return True
    except:
        log("Could not set your password. Error by backend", serv="ERROR")
        return False
示例#14
0
def add_credits(auth, client):
    """
    Asks user to input the amount he put into the box and adds this amount of credits to his/her account

    :auth: dict
    :returns: bool
    """

    try:
        credits = float(input("EUR: "))
        if credits < 0 or credits > 100:
            raise ValueError
    except ValueError:
        log("Invalid input. Valid values: 1-100", serv="ERROR")
        return False

    # calc input from eur into cents
    cents = credits * 100

    try:
        # send update request to backend
        r = client.users_user_id_credits_add_patch(str(auth["user"]["id"]),
                                                   int(cents))

        # TODO: Replace hack that updates local auth object to reflect changes into the banner
        auth["user"]["credits"] = r.to_dict()["credits"]

        # notify user
        log("Your credit is now %.2f" % (auth["user"]["credits"] / 100),
            serv="SUCCESS")
        return True
    except:
        log("Updating your credits in the backend was not successful. Ask people for help",
            serv="ERROR")
        return False
示例#15
0
def delete_item(auth, client):
    """
    Deletes an item from the backend
    :auth: dict
    :client: item_client object
    :returns: bool
    """

    itemid = input("What item (ID)?: ")

    item_name = client.items_item_id_get(itemid).to_dict()["name"]

    really_delete = yes_or_no("Do you really want to delete %s?" % item_name)

    if really_delete is False:
        log("Aborted")
        return False

    try:
        client.items_item_id_delete(itemid)
        log("Item with id %s was deleted" % itemid, serv="SUCCESS")
        return True
    except:
        log("Could not delete item with id %s" % itemid, serv="ERROR")
        return False
示例#16
0
def create_user(auth, client):
    """
    Asks administrator for details and
    creates a new user in the database.

    :auth: dict
    :returns: bool
    """

    is_admin = yes_or_no("Admin?")

    if is_admin:
        admin = 1
    else:
        admin = 0

    name = input("Username: "******"Username too short (>=3).", serv="Error")
        return False

    if name.isalnum() is False:
        log("Username not valid. Please be alphanumerical.", serv="Error")
        return False

    password = getpass.getpass("Password: "******"Repeat password: "******"Error creating user", serv="ERROR")
        return False
示例#17
0
文件: menu.py 项目: blarz/heiko
def banner(auth=None):
    """
    Prints a fancy ascii art banner to user and (if already logged in)
    greets the person with username and current credits

    :auth: dict
    :returns: bool
    """

    mate_banner = """
 __  __    _  _____ ___  __  __    _  _____
|  \/  |  / \|_   _/ _ \|  \/  |  / \|_   _|
| |\/| | / _ \ | || | | | |\/| | / _ \ | |
| |  | |/ ___ \| || |_| | |  | |/ ___ \| |
|_|  |_/_/   \_\_| \___/|_|  |_/_/   \_\_|
"""
    os.system('clear')
    log(mate_banner)
    if auth is not None:
        if auth["user"]["admin"] is True:
            log("Hi %s, current credits: %.2f Euro. You are admin!\n" %
                (auth["user"]["username"], auth["user"]["credits"] / 100))
        else:
            log("Hi %s, current credits: %.2f Euro.\n" %
                (auth["user"]["username"], auth["user"]["credits"] / 100))

    return True
示例#18
0
def nfc_format_card(auth_client, username, password):
    uid, header = nfc_detect()
    if uid is not None:
        ans = input("overwrite card? [yN] ")
        if ans != "y":
            return False
        ans = input("token lifetime in days? ")
        if not ans.isnumeric():
            log("invalid lifetime")
            return False
        days = int(ans)
        token = ""
        try:
            auth2 = auth_client.auth_login_post(username,
                                                password,
                                                validityseconds=days * 3600 *
                                                24).to_dict()
            token = auth2["token"]
        except swagger_client.rest.ApiException:
            log("Wrong password!", serv="ERROR")
            return False
        except (ConnectionRefusedError, urllib3.exceptions.MaxRetryError):
            log("Connection to backend was refused!", serv="ERROR")
            return False
        nfc_write(uid, "matomat1:" + username + ":", token)
        return True
    return False
示例#19
0
def list_users(auth, client):
    """
    Shows all users from the database to an successfully authenticated administrator

    :auth: dict
    :returns: bool
    """

    try:
        users = client.users_get()
    except swagger_client.rest.ApiException:
        log("Could fetch users from the database.", serv="ERROR")
        return False

    it = []
    for u in users:
        d = u.to_dict()
        it.append(
            [d["id"], d["username"],
             float(d["credits"]) / 100, d["admin"]])

    log("List of current users in the database:\n")
    log(
        tabulate(it,
                 headers=["ID", "Username", "Credits (EUR)", "Admin?"],
                 tablefmt="presto",
                 floatfmt=".2f"))

    return True
示例#20
0
def consume_item(auth, client, itemid):
    """
    Sends request to the backend that user took 1 item out of the fridge

    :auth: dict
    :itemid: int
    :returns: bool
    """

    # Lets try to be a little funny
    prost_msgs = [
        "Well, drink responsible",
        "Gesondheid (Cheers in Afrikaans)",
        "Gan bay (Cheers in Mandarin)",
        "Na zdravi (Cheers in Czech)",
        "Proost (Cheers in Dutch)",
        "Ah la vo-tre sahn-tay (Cheers in French)",
        "Zum Wohl! (Cheers in German)",
        "Yamas (Cheers in Greek)",
        "Slawn-cha (Cheers in Irish Gaelic)",
        "Salute (Cheers in Italian)",
        "Kanpai (Cheers in Japanese)",
        "Gun bae (Cheers in Korean)",
        "Na zdrowie (Cheers in Polish)",
        "Happy hacking!",
        "Well.. just hackspace things.",
    ]

    try:
        client.items_item_id_consume_patch(itemid)

        # TODO: Temp hack to display correct credits in banner
        cost = float(client.items_item_id_get(itemid).to_dict()["cost"])
        auth["user"]["credits"] = auth["user"]["credits"] - cost

        log(random.choice(prost_msgs), serv="SUCCESS")
        log("Cost: %.2f Euro" % (cost / 100), serv="SUCCESS")

        return True

    except swagger_client.rest.ApiException:
        log("Not enough credits, dude.", serv="ERROR")
        return False
    except:
        log("Something went wrong, contact developer!", serv="ERROR")
        return False
示例#21
0
文件: menu.py 项目: blarz/heiko
def show_help(items_client, admin=False, cfgobj=None):
    """
    Shows the basic navigation to the user.

    :items_client: object
    :admin: bool
    :returns: bool
    """

    if admin is True:
        actions = admin_actions.copy()
    else:
        actions = user_actions.copy()

        try:
            if cfgobj["accounting"]["user_can_add_credits"] is False:
                del actions[USER_KEY_INSERT_COINS]
        except KeyError:
            pass

        # Reset consumables, to avoid stale entries:
        consumables.clear()

        try:
            for item in items_client.items_get():
                item_dict = item.to_dict()
                action_key = str(item_dict["id"])
                consumables.update({action_key: item_dict})
                actions.update({
                    action_key:
                    "Consume {} ({:.2f})".format(item_dict['name'],
                                                 item_dict['cost'] / 100)
                })
        except swagger_client.rest.ApiException:
            log("Could not get items from the database.", serv="ERROR")

    log("Available actions:")
    for key in sorted(actions.keys()):
        log("[%s] %s" % (key, actions[key]))

    return True
示例#22
0
def update_item(auth, client):
    """
    Adjust the name/price of an item

    :auth: dict
    :returns: bool
    """

    item_id = input("ID of item: ")

    if item_id.isalnum() is False:
        return False

    # Ask for new Cost
    try:
        new_cost = float(input("New price in EUR (i.e. 1 or 1.20): ")) * 100
    except ValueError:
        return False

    if new_cost < 0:
        log("Negative price is not allowed ;)", serv="ERROR")
        return False

    # Ask for new Name
    # TODO as not needed

    # get current item name
    current_item = client.items_item_id_get(item_id).to_dict()
    current_cost = current_item["cost"]
    current_name = current_item["name"]

    try:
        client.items_item_id_patch(item_id, name=current_name, cost=int(new_cost))
        log("Successfully modified price of %s from %s to %s" % (current_name, float(current_cost) / 100, float(new_cost) / 100), serv="SUCCESS")
    except swagger_client.rest.ApiException as api_expception:
        log("Item could not be updated in the backend: " + api_expception.body, serv="ERROR")
        return False

    return True
示例#23
0
def transfer_coins(auth, client):
    """
    Transfer credits to another user

    :auth_client: dict
    :user_client: dict
    :returns: bool
    """

    log("What user you want to send credits to?")
    target_user = find_user_by_username(auth, client)

    if target_user is False:
        # error message already printed at this point by find_user_by_username()
        return False

    # Ask for amount to transfer
    try:
        credits_to_transfer = float(
            input("How many credits you want to transfer (i.e. 1 or 1.20): ")
        ) * 100
    except ValueError:
        return False

    try:
        req = client.users_user_id_credits_transfer_patch(
            user_id=target_user['id'], credits=int(credits_to_transfer))
        transferred_credits = float(req.to_dict()['credits']) / 100
        log("Successfully transferred {:.2f} credits to user {}".format(
            transferred_credits, target_user['username']),
            serv="SUCCESS")
        return True
    except:
        log("Error transferring credits to user {}".format(
            target_user['username']),
            serv="ERROR")
        return False
示例#24
0
def create_user_nfc(auth_client, user_client):
    """
    Asks administrator for details and
    creates a new NFC user in the database
    (= user with random dummy password and NFC token).

    :auth: dict
    :returns: bool
    """

    name = input("Username: "******"Username too short (>=3).", serv="Error")
        return False

    if name.isalnum() is False:
        log("Username not valid. Please be alphanumerical.", serv="Error")
        return False

    is_admin = yes_or_no("Admin?")

    if is_admin:
        admin = 1
    else:
        admin = 0

    password = "".join(
        random.choice(string.ascii_letters + "0123456789") for i in range(23))

    try:
        user_client.users_post(name, password, password, admin)
    except:
        log("Error creating user", serv="ERROR")
        return False

    return nfc_format_card(auth_client, name, password)
示例#25
0
def list_items_stats(auth, client):
    """
    Lists stats for all items in the database

    :auth: dict
    :returns: bool
    """

    try:
        items = client.items_stats_get()
    except swagger_client.rest.ApiException:
        log("Could not show items from the database.", serv="ERROR")

    it = []
    revenue = 0.0
    for i in items:
        d = i.to_dict()
        it.append([d["id"], float(d["cost"]) / 100, d["name"], d["consumed"]])
        revenue += float(d["cost"]) / 100 * float(d["consumed"])

    log(tabulate(it, headers=["ID", "Cost (EUR)", "Drink", "Consumptions"], floatfmt=".2f", tablefmt="presto"))
    log("total revenue (EUR): %.2f" % revenue)

    return True
示例#26
0
文件: __init__.py 项目: k4cg/heiko
def sigalrm_handler(signal, frame):
    log("\nAuto-logout timer triggered!")
    sys.exit(1)
示例#27
0
def migrate_user(auth, client, cfgobj):
    """
    Migration function that reads data from old matomat sqlite and creates user in the backend

    :auth: dict
    :client: userauth object
    :cfgobj: config dict
    :returns: bool
    """

    # Check if configured database is there and can be read
    try:
        migration_database = cfgobj["accounting"]["migration_database"]
        if os.access(migration_database, os.R_OK):
            matomat_db = sqlite3.connect(migration_database)
        else:
            raise IOError
    except (IOError, KeyError):
        log("Migration database cannot be found or is not configured. Aborting.", serv="ERROR")
        return False

    # First, ask for Admin yes/no
    is_admin = yes_or_no("Should the migrated user be admin?")
    if is_admin:
        admin = 1
    else:
        admin = 0

    # Search Username
    log("Please give username to look for in sqlite from matomat.db")
    name = input("Username: "******"Username too short (>=3).", serv="Error")
        return False

    if name.isalnum() is False:
        log("Username not valid. Please be alphanumerical.", serv="Error")
        return False

    log("Looking for user %s in given sqlite..." % name)

    # fetch results from sqlite
    cur = matomat_db.cursor()
    cur.execute("SELECT username, credits from user where username = \"%s\";" % name)
    rows = cur.fetchall()
    matomat_db.commit()
    matomat_db.close()

    if len(rows) > 1:
        log("Search resulted in multiple result sets... exitting", serv="ERROR")
        return False

    # assign values
    user_to_migrate, credits_to_migrate = rows[0]

    log("Found user {} with credits {:.2f} Euro!".format(user_to_migrate, int(credits_to_migrate) / 100), serv="SUCCESS")

    confirmation = yes_or_no("Wanna migrate her?")
    if confirmation is False:
        log("Aborting...")
        return False

    log("Please add new credentials!")
    password = getpass.getpass("Password: "******"Repeat password: "******"Successfully created user %s" % user_to_migrate, serv="SUCCESS")
    except:
        log("Error creating user", serv="ERROR")
        return False

    # Adding credits

    try:
        if float(credits_to_migrate) < 0:
            credits_to_migrate = str(int(credits_to_migrate)).replace('-', '')
            client.users_user_id_credits_withdraw_patch(new_user.to_dict()["id"], int(credits_to_migrate))
            log("Set credit to -{:.2f}".format(float(credits_to_migrate) / 100), serv="SUCCESS")
        else:
            client.users_user_id_credits_add_patch(new_user.to_dict()["id"], int(credits_to_migrate))
            log("Set credit to {:.2f}".format(float(credits_to_migrate) / 100), serv="SUCCESS")
    except:
        log("Error setting credits {:.2f}".format(float(credits_to_migrate) / 100), serv="ERROR")
        return False

    return True
示例#28
0
文件: menu.py 项目: blarz/heiko
def user_menu(auth, auth_client, items_client, users_client, service_client,
              cfgobj):
    """
    Shows the menu to the user, clears screen, draws the navigation screen
    This is kind of the main loop of heiko. If you need new options, add them here
    otherwise they are not being executed.

    :auth: dict
    :items_client: object
    :users_client: object
    :service_client: object
    :cfgobj: dict

    :returns: is_logged_in, is_exit (both bool)
    """
    signal.alarm(AUTOLOGOUT_TIME_SECONDS)

    try:
        optionInput = input(">>> ")
        if optionInput not in user_actions.keys(
        ) and optionInput not in consumables.keys():
            option = USER_KEY_HELP
        else:
            option = optionInput
    except EOFError:
        return user_exit(cfgobj)

    if option in consumables.keys():
        consume_item(auth, items_client, consumables[option]['id'])
        say(cfgobj, "cheers")

    if option == USER_KEY_INSERT_COINS:
        add_credits(auth, users_client)
        say(cfgobj, "transaction_success")

    if option == USER_KEY_SHOW_STATS:
        show_user_stats(auth, users_client)

    if option == USER_KEY_TRANSFER_COINS:
        transfer_coins(auth, users_client)

    if option == USER_KEY_ADMINISTRATION:
        is_exit = False
        say(cfgobj, "admin")

        draw_help = True
        while is_exit is False:
            is_exit, draw_help = admin_menu(auth,
                                            auth_client,
                                            items_client,
                                            users_client,
                                            service_client,
                                            cfgobj,
                                            draw_help=draw_help)

        # when exit was executed, draw normal user help again
        option = USER_KEY_HELP

    if option == USER_KEY_CHANGE_PASSWORD:
        change_password(auth, users_client)

    if option == USER_KEY_NFC:
        username = auth["user"]["username"]
        log("Put your card on the reader now.")
        log("Relogin required:")
        password = getpass.getpass('Password: ')
        nfc_format_card(auth_client, username, password)

    if option == USER_KEY_HELP:
        banner(auth)
        show_help(items_client, admin=False, cfgobj=cfgobj)

    if option == USER_KEY_EXIT:
        return user_exit(cfgobj)

    return True, False
示例#29
0
文件: menu.py 项目: blarz/heiko
def login(maas_builder, auth_client, cfgobj):
    """
    Shows banner, asks user to authenticate via username/password
    and creates auth token that we reuse after auth was successful once.

    :returns: tuple
    """
    is_logged_in = False
    auth = None

    welcome_banner()
    log("Please authenticate yourself!")

    token = ""
    user = ""
    password = ""
    try:
        print("User: "******"", flush=True)
        uid = ""
        if cfgobj['nfc']['enable']:
            while sys.stdin not in select.select([sys.stdin], [], [], 0)[0]:
                uid, header = nfc_detect()
                if uid:
                    break
                time.sleep(0.2)
        if uid:
            token = nfc_read(uid)
        else:
            user = sys.stdin.readline().strip()
            password = getpass.getpass('Password: ')
    except EOFError:
        say(cfgobj, "error")
        return is_logged_in, auth

    if token:
        t = token.split(".")[1]
        try:
            userdict = json.loads(
                base64.b64decode(t + "=" * (4 - len(t) % 4)).decode())
        except json.JSONDecodeError:
            say(cfgobj, "error")
            log("Token json error!", serv="ERROR")
            time.sleep(1)
        except binascii.Error:
            say(cfgobj, "error")
            log("Token base64 error!", serv="ERROR")
            time.sleep(1)

        auth = {"token": token, "user": userdict}

        try:
            users_client = maas_builder.build_users_client(auth["token"])
            tmp = users_client.users_user_id_get(userdict["id"]).to_dict()
            for key in tmp:
                auth["user"][key] = tmp[key]
            is_logged_in = True
            greet_user(cfgobj, auth["user"]["username"])
        except swagger_client.rest.ApiException:
            say(cfgobj, "error")
            log("Invalid token!", serv="ERROR")
            time.sleep(1)
        except (ConnectionRefusedError, urllib3.exceptions.MaxRetryError):
            say(cfgobj, "error")
            log("Connection to backend was refused!", serv="ERROR")
            time.sleep(5)
    else:
        try:
            auth = auth_client.auth_login_post(user, password).to_dict()
            is_logged_in = True
            greet_user(cfgobj, auth["user"]["username"])
        except swagger_client.rest.ApiException:
            say(cfgobj, "error")
            log("Wrong username and/or password!", serv="ERROR")
            time.sleep(1)
        except (ConnectionRefusedError, urllib3.exceptions.MaxRetryError):
            say(cfgobj, "error")
            log("Connection to backend was refused!", serv="ERROR")
            time.sleep(5)

    return is_logged_in, auth
示例#30
0
文件: menu.py 项目: blarz/heiko
def admin_exit(cfgobj):
    say(cfgobj, "quit")
    log("Switching back to normal menu, sir.", serv="SUCCESS")
    return True, False