From b59f037a1865f0f9d17edf9fd739115618f04051 Mon Sep 17 00:00:00 2001 From: Vasek Sraier Date: Sat, 23 Mar 2019 11:24:49 +0100 Subject: [PATCH] introduced Pipenv, downgraded to Python3.5 :(, added password reset feature --- Makefile | 10 +++--- Pipfile | 18 ++++++++++ Pipfile.lock | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 8 ++--- register.py | 65 +++++++++++++++++++++++++---------- 5 files changed, 171 insertions(+), 26 deletions(-) create mode 100644 Pipfile create mode 100644 Pipfile.lock diff --git a/Makefile b/Makefile index 1ff0618..b4e4ffd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ GITEA_URL=https://git.vakabus.cz/swagger.v1.json BUILDDIR=tmp -build: swagger_client click clean_builddir +build: swagger_client clean_builddir pipenv_sync swagger_client: mkdir -p "${BUILDDIR}" @@ -14,10 +14,9 @@ swagger_client: sed -i 's/from swagger_client\.models\.gpg_key import GPGKey/#from swagger_client.models.gpg_key import GPGKey/' swagger_client/models/gpg_key.py sed -i 's/from swagger_client\.models\.repository import Repository/#from swagger_client.models.repository import Repository/' swagger_client/models/repository.py -click: - mkdir -p "${BUILDDIR}" - cd ${BUILDDIR}; git clone --depth=1 https://github.com/pallets/click.git - mv ${BUILDDIR}/click/click click +.PHONY: pipenv_sync +pipenv_sync: + pipenv sync .PHONY: clean_builddir clean_builddir: @@ -27,5 +26,6 @@ clean_builddir: clean: rm -rf swagger_client/ rm -rf click/ + pipenv --rm diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..49df204 --- /dev/null +++ b/Pipfile @@ -0,0 +1,18 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +requests = "*" +click = "*" +beautifulsoup4 = "*" +six = "*" +termcolor = "*" +secrets = "*" +python2-secrets = "*" + +[requires] +python_version = "3.5" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..60e1766 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,96 @@ +{ + "_meta": { + "hash": { + "sha256": "20373be879178f1bb02ee758f0f2d2d3b9a471d92c583b09a1896b833125c1c2" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.5" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "beautifulsoup4": { + "hashes": [ + "sha256:034740f6cb549b4e932ae1ab975581e6103ac8f942200a0e9759065984391858", + "sha256:945065979fb8529dd2f37dbb58f00b661bdbcbebf954f93b32fdf5263ef35348", + "sha256:ba6d5c59906a85ac23dadfe5c88deaf3e179ef565f4898671253e50a78680718" + ], + "index": "pypi", + "version": "==4.7.1" + }, + "certifi": { + "hashes": [ + "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", + "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae" + ], + "version": "==2019.3.9" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "click": { + "hashes": [ + "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", + "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + ], + "index": "pypi", + "version": "==7.0" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "requests": { + "hashes": [ + "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", + "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" + ], + "index": "pypi", + "version": "==2.21.0" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "index": "pypi", + "version": "==1.12.0" + }, + "soupsieve": { + "hashes": [ + "sha256:afa56bf14907bb09403e5d15fbed6275caa4174d36b975226e3b67a3bb6e2c4b", + "sha256:eaed742b48b1f3e2d45ba6f79401b2ed5dc33b2123dfe216adb90d4bfa0ade26" + ], + "version": "==1.8" + }, + "termcolor": { + "hashes": [ + "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b" + ], + "index": "pypi", + "version": "==1.1.0" + }, + "urllib3": { + "hashes": [ + "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", + "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" + ], + "version": "==1.24.1" + } + }, + "develop": {} +} diff --git a/README.md b/README.md index 77f5a84..1f31008 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,16 @@ Určeno pro registraci organizátorů seminářů na MFF UK. Build má následující závislosti: * Make * swagger-codegen -* git +* pipenv Spustí se prostým zavoláním `make` ## Spousteni -Vyzaduje rozumne novou verzi Pythonu 3. +Vyzaduje nejmene Pythonu 3.5 ```sh -python3 register.py --help +pipenv run python register.py --help ``` -Zbytek by mel byt samovysvetlujici. \ No newline at end of file +Zbytek by mel byt samovysvetlujici. Staci vymenovat argumenty dle napovedy na misto `--help` \ No newline at end of file diff --git a/register.py b/register.py index e9c726b..5018a65 100644 --- a/register.py +++ b/register.py @@ -1,14 +1,21 @@ from swagger_client.api.admin_api import AdminApi from swagger_client.api.user_api import UserApi -from swagger_client.api.organization_api import OrganizationApi +from swagger_client.api.organization_api import OrganizationApi from swagger_client.api_client import ApiClient from swagger_client.models import CreateUserOption, Team, User, Organization from swagger_client.rest import ApiException from sys import stderr -from typing import * import click import secrets import termcolor +import requests +from bs4 import BeautifulSoup as bs +import random +import string + + +def rand_str(n) -> str: + return ''.join([random.choice(string.ascii_lowercase) for _ in range(n)]) def text_red(text) -> str: @@ -25,7 +32,7 @@ def text_orange(text) -> str: def does_user_exist(user_api: UserApi, username: str) -> bool: try: - user: User = user_api.user_get(username) + user = user_api.user_get(username) return user is not None except ApiException as e: if e.status == 404: @@ -37,7 +44,7 @@ def does_user_exist(user_api: UserApi, username: str) -> bool: def does_organization_exist(org_api: OrganizationApi, orgname: str) -> bool: try: - org: Organization = org_api.org_get(orgname) + org = org_api.org_get(orgname) return org is not None except ApiException as e: if e.status == 404: @@ -48,15 +55,15 @@ def does_organization_exist(org_api: OrganizationApi, orgname: str) -> bool: def does_organization_have_org_team(org_api: OrganizationApi, orgname: str) -> bool: - teams: List[Team] = org_api.org_list_teams(orgname) + teams = org_api.org_list_teams(orgname) for t in teams: if 'org' == t.name: return True return False -def get_org_team_id(org_api: OrganizationApi, orgname: str) -> int: - teams: List[Team] = org_api.org_list_teams(orgname) +def get_org_team_id(org_api: OrganizationApi, orgname: str) -> int: + teams = org_api.org_list_teams(orgname) for t in teams: if 'org' == t.name: return t.id @@ -81,7 +88,7 @@ def validate(func_check, message: str): def checked_api_action(func_action, message: str): - print(message, end='') + print(message, end=' ') try: res = func_action() print(text_green('[OK]')) @@ -93,6 +100,25 @@ def checked_api_action(func_action, message: str): exit(1) +def reset_password(email: str): + url = HOST.replace('api/v1', 'user/forgot_password') + with requests.session() as session: + # ziskani formulare + resp = session.get(url) + + # vyplneni formulare + soup = bs(resp.text, features='lxml') + form = {n['name']: n['value'] for n in soup.find_all('input')} + form['email'] = email + + # submit form + resp = session.post(url, data=form) + + # simulate being standard api call + if resp.status_code != 200: + raise ApiException(status=resp.status_code, reason=resp.reason, http_resp='Form submission failed.') + + if __name__ == '__main__': # default configuration HOST = "https://git.vakabus.cz/api/v1" @@ -105,12 +131,12 @@ if __name__ == '__main__': @click.command() -@click.option('-a', '--admin-token', help=f'Admin access token', required=True) -@click.option('-h', '--host', help=f'Gitea URL (default: {HOST})') -@click.option('-e','--email', help='Emailova adresa noveho uzivatele.', required=True) -@click.option('-u','--username', help='Uzivatelske jmeno noveho uzivatele.', required=True) -@click.option('-f','--fullname', help='Plne jmeno noveho uzivatele.') -@click.option('-s','--seminar', help='Seminar, kde uzivatel orguje.', required=True) +@click.option('-a', '--admin-token', help='Admin access token', required=True) +@click.option('-h', '--host', help='Gitea URL (default: {})'.format(HOST)) +@click.option('-e', '--email', help='Emailova adresa noveho uzivatele.', required=True) +@click.option('-u', '--username', help='Uzivatelske jmeno noveho uzivatele.', required=True) +@click.option('-f', '--fullname', help='Plne jmeno noveho uzivatele.') +@click.option('-s', '--seminar', help='Seminar, kde uzivatel orguje.', required=True) def register(username: str, seminar: str, fullname: str, email: str, host, admin_token): """ Nastroj pro automatizaci zakladani uctu na serveru Gitea. @@ -132,19 +158,24 @@ def register(username: str, seminar: str, fullname: str, email: str, host, admin # kontrola predpokladu o stavu systemu validate(lambda: not does_user_exist(user_api, username), "Uzivatelske jmeno je volne...") validate(lambda: does_organization_exist(org_api, seminar), "Organizace pro seminar existuje...") - validate(lambda: does_organization_have_org_team(org_api, seminar), "Team se jmenem 'org' v danem seminari existuje...") + validate(lambda: does_organization_have_org_team(org_api, seminar), "V danem seminari existuje team 'org'...") print(text_green('Zakladni predpoklady pro uspesne zalozeni uctu splneny!\n')) # nasbirame vsechny potrebne informace org_team_id = get_org_team_id(org_api, seminar) # pripravime si uzivatele na zalozeni - create_user_req = CreateUserOption(email=email, full_name=fullname, username=username, password=secrets.token_urlsafe(20)) + create_user_req = CreateUserOption(email=email, full_name=fullname, username=username, + password=rand_str(20)) # provedeme zmeny v systemu user = checked_api_action(lambda: admin_api.admin_create_user(body=create_user_req), "Zakladam noveho uzivatele...") - checked_api_action(lambda: org_api.org_add_team_member(org_team_id, username), f"Pridavam do teamu 'org' v seminari {seminar}...") + checked_api_action(lambda: org_api.org_add_team_member(org_team_id, username), + "Pridavam do teamu 'org' v seminari {}...".format(seminar)) print(text_green('Uzivatel zalozen!')) + print() + + checked_api_action(lambda: reset_password(email), "Resetuji heslo...") if __name__ == '__main__':