async def login(request): token = request.match_info['token'] form = await request.post() username = form.get('username', '').strip() password = form.get('password', '').strip() if not username or not password: raise web.HTTPSeeOther(f'/{token}/?error=Заполните+все+поля') if not re.fullmatch('[a-zA-Z0-9-]{,32}', username): raise web.HTTPSeeOther( f'/{token}/?error=Заполните+поле+username+правильно') password = hashlib.sha512(password.encode()).hexdigest() user = await get_user_by_username(username) if user is None: if not await create_user(username, password): raise web.HTTPSeeOther(f'/{token}/?error=Повторите+запрос') elif user['password'] != password: raise web.HTTPSeeOther(f'/{token}/?error=Пароль+неверный') payload = json.dumps({ 'created': int(time.time()), 'username': username }).encode() encrypted = bytearray([i ^ j for i, j in zip(COOKIE_SECRET, payload)]) session = base64.b64encode(encrypted).decode() raise web.HTTPSeeOther( f'/{token}/passwords', headers={'Set-Cookie': f'session={session}; path=/'})
async def wrapper(request): token = request.match_info['token'] cookie = request.cookies.get('session', '') if not should_login: if cookie == '': return await func(request) else: raise web.HTTPSeeOther(f'/{token}/passwords') if cookie is None and not should_login: return await func(request) user = await get_user_by_cookie(cookie) if user is None: raise web.HTTPSeeOther( f'/{token}/', headers={ 'Set-Cookie': 'session=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT', 'X-Error': 'Invalid cookie' }) request.user = user return await func(request)
async def post(self): data = await self.request.post() user = await get_user_by_api_key(self.request, self.request.cookies['api_key']) # Check if marker is delete album if 'delete' in data: # Get all tracks id by album id result_tr = await delete_tracks_by_album_id( self.request, int(data['delete']), user['id']) result_alb = await delete_album(self.request, int(data['delete']), user['id']) for track in result_tr: os.remove(track[1]) print('DELETE ALBUM', result_alb) print('DELETE TRACKS', result_tr) return web.HTTPSeeOther('/albums') # Create new album title = data['title'] list_of_tracks = list(data.values()) del (list_of_tracks[0]) # Create new album in db row_alb = await create_album(self.request, title, datetime.datetime.now(), user['id']) # Add album id (foreign key) to appropriate tracks await update_add_track_item_to_album(self.request, row_alb[0], list_of_tracks, user['id']) return web.HTTPSeeOther('/albums')
async def post(self) -> web.Response: """Post route function that updates a collection of klasses.""" user = await check_login(self) informasjon = "" action = "" form = await self.request.post() event_id = str(form["event_id"]) logging.debug(f"Form {form}") try: if "generate_startlist" in form.keys(): informasjon = await StartAdapter( ).generate_startlist_for_event(user["token"], event_id) elif "generate_next_race" in form.keys(): informasjon = await TimeEventsService( ).generate_next_race_templates(user["token"], event_id) elif "delete_time_events" in form.keys(): informasjon = await delete_time_events(user["token"], event_id) elif "delete_start_lists" in form.keys(): informasjon = await delete_start_lists(user["token"], event_id) except Exception as e: logging.error(f"Error: {e}") informasjon = f"Det har oppstått en feil - {e.args}." error_reason = str(e) if error_reason.startswith("401"): return web.HTTPSeeOther( location= f"/login?informasjon=Ingen tilgang, vennligst logg inn på nytt. {e}" ) info = f"action={action}&informasjon={informasjon}" return web.HTTPSeeOther(location=f"/tasks?event_id={event_id}&{info}")
async def track_upload(request): reader = await request.multipart() field = await reader.next() assert field.name == 'mp3' filename = field.filename if not filename.endswith('.mp3'): return web.HTTPSeeOther('/track') user = await get_user_by_api_key(request, request.cookies['api_key']) # Check if file with this title exists row = await get_user_track_by_title_and_api_key(request, filename, user['id']) if row: return web.HTTPSeeOther('/tracks') size = 0 filename_for_dir = f'{user["id"]}-{filename}' saved_dir = os.path.join(upload_path, filename_for_dir) with open(saved_dir, 'wb') as f: while True: chunk = await field.read_chunk() if not chunk: break size += len(chunk) f.write(chunk) date_time = datetime.datetime.now() result = await create_track(request, filename, date_time, saved_dir, user[0]) return web.HTTPSeeOther('/tracks')
async def post(self): data = await self.request.post() print(data) # Get user by api_key from request cookie user = await get_user_by_api_key(self.request, self.request.cookies['api_key']) old_title = self.request.match_info['title'] if 'delete' in data: result = await delete_track_from_album(self.request, int(data['delete']), user['id']) print('DELETE TRACK FROM ALBUM', result) return web.HTTPSeeOther( f'/album/{self.request.match_info["title"]}') if 'checked' in data: list_of_tracks = list(data.values()) print(list_of_tracks) # Add album id (foreign key) to appropriate tracks row = await get_user_album_by_title_and_api_key( self.request, old_title, user['id']) await update_add_track_item_to_album(self.request, row[0], list_of_tracks, user['id']) return web.HTTPSeeOther( f'/album/{self.request.match_info["title"]}') # Update album title row = await update_album_name(self.request, data['title'], old_title, user['id']) return web.HTTPSeeOther(f'/album/{data["title"]}')
async def check_register(request): token = request.match_info['token'] form = await request.post() username = form.get('username', '').strip() if not username: raise web.HTTPSeeOther( f'/{token}/register?error=Как+же+Вы+без+логина%3F%3F%3F') user = await get_user_by_username(username) if user is not None: raise web.HTTPSeeOther( f'/{token}/register?error=Такой+логин+уже+есть,+входите+же!!!') try: user_id = await create_user(username) except aiosqlite.IntegrityError: raise web.HTTPSeeOther( f'/{token}/register?error=Ну+что+же+вы+по+два+раза+кнопки-то+нажимаете%3F%3F%3F' ) session = await sessions.get_session(request) session['state'] = 'user' session['user_id'] = user_id raise web.HTTPSeeOther(f'/{token}/users/{user_id}')
async def post(self) -> web.Response: """Get route function that return the index page.""" informasjon = "" result = 0 logging.debug(f"Login: {self}") try: form = await self.request.post() try: event_id = self.request.rel_url.query["event_id"] logging.debug(f"Event: {event_id}") except Exception: event_id = "" # Create new event if "create" in form.keys(): session = await get_session(self.request) token = str(session["token"]) id = await UserAdapter().create_user( token, str(form["newrole"]), str(form["newusername"]), str(form["newpassword"]), session, ) informasjon = f"Ny bruker opprettet med id {id}" return web.HTTPSeeOther( location=f"/login?new=True&informasjon={informasjon}") else: # Perform login session = await new_session(self.request) result = await UserAdapter().login(str(form["username"]), str(form["password"]), session) if result != 200: informasjon = f"Innlogging feilet - {result}" except Exception as e: logging.error(f"Error: {e}") informasjon = f"Det har oppstått en feil - {e.args}." result = 400 if result != 200: event = {"name": "Administrasjon", "organiser": "Ikke valgt"} return await aiohttp_jinja2.render_template_async( "login.html", self.request, { "lopsinfo": "Login resultat", "event": event, "event_id": event_id, "informasjon": informasjon, }, ) elif event_id != "": return web.HTTPSeeOther( location=f"/events?event={event_id}&informasjon={informasjon}") else: return web.HTTPSeeOther(location=f"/?informasjon={informasjon}")
async def post(self) -> web.Response: """Post route function that updates a collection of klasses.""" user = await check_login(self) informasjon = "" action = "edit_mode" try: form = await self.request.post() logging.debug(f"Form {form}") event_id = str(form["event_id"]) # delete_all if "delete_all" in form.keys(): res = await RaceclassesAdapter().delete_all_raceclasses( user["token"], event_id) informasjon = f"Klasser er slettet - {res}" # delete elif "delete_one" in form.keys(): res = await RaceclassesAdapter().delete_raceclass( user["token"], event_id, str(form["id"])) informasjon = f"Klasse er slettet - {res}" # Create classes from list of contestants elif "generate_raceclasses" in form.keys(): informasjon = await EventsAdapter().generate_classes( user["token"], event_id) informasjon += ( " Neste steg: Velg slå sammen klasser eller rediger statrekkefølge." ) return web.HTTPSeeOther( location= f"/raceclasses?event_id={event_id}&action=edit_mode&informasjon={informasjon}" ) elif "merge_ageclasses" in form.keys(): informasjon = await merge_ageclasses(user, event_id, form) # type: ignore elif "refresh_no_of_contestants" in form.keys(): informasjon = "Ikke implementert. Rediger manuelt pr klasse." elif "update_one" in form.keys(): informasjon = await update_one(user, event_id, form) # type: ignore elif "update_order" in form.keys(): informasjon = await update_order(user, event_id, form) # type: ignore return web.HTTPSeeOther( location= f"/tasks?event_id={event_id}&informasjon={informasjon}") except Exception as e: logging.error(f"Error: {e}") informasjon = f"Det har oppstått en feil - {e.args}." error_reason = str(e) if error_reason.startswith("401"): return web.HTTPSeeOther( location= f"/login?informasjon=Ingen tilgang, vennligst logg inn på nytt. {e}" ) info = f"action={action}&informasjon={informasjon}" return web.HTTPSeeOther( location=f"/raceclasses?event_id={event_id}&{info}")
async def post(self): data = await self.request.post() # Check if marker is delete user if 'delete' in data: result = await delete_user(self.request) print('DELETE USER', result) return web.HTTPSeeOther('/') # Else update information about user result = await validate_user_form(self.request, data) print(result) return web.HTTPSeeOther('/user')
async def get(self): if not self.riki_path: raise web.HTTPSeeOther(f'{APP_PATH}page/index') page_fs_path = os.path.join(self.data_dir, self.riki_path) pelms = page_fs_path.rsplit('.', 1) page_suff = None if len(pelms) < 2 else pelms[-1] if self.dir_metadata.directory_type == 'gallery': raise web.HTTPSeeOther(f'{APP_PATH}gallery/{self.riki_path}/index') elif files.page_is_dir(page_fs_path): if self.dir_metadata.directory_type == 'page': raise web.HTTPSeeOther( f'{APP_PATH}page/{self.riki_path}/index') else: raise web.HTTPServerError('Unknown page type') elif page_suff and page_suff in appconf.RAW_FILES: with open(page_fs_path, 'rb') as fr: web.header('Content-Type', appconf.RAW_FILES[page_suff]) return fr.read() else: page_fs_path = f'{page_fs_path}.md' curr_dir = os.path.dirname(self.riki_path) page_name = os.path.basename(self.riki_path) # setup the directory information if curr_dir: path_elms = path_dir_elms(curr_dir) curr_dir_fs = os.path.join(self.data_dir, curr_dir) else: curr_dir = '' path_elms = [] curr_dir_fs = self.data_dir # transform the page if files.page_exists(page_fs_path): page_info = files.get_version_info( self.data_dir, page_fs_path, info_encoding=conf.hg_info_encoding) inner_html = load_markdown(page_fs_path) page_template = 'page.html' else: inner_html = '' page_info = files.RevisionInfo() page_template = 'dummy_page.html' data = dict(html=inner_html, page_list=self.generate_page_list(curr_dir_fs), path_elms=path_elms, page_info=page_info, page_name=page_name, curr_dir_name=self.get_current_dirname(curr_dir)) return self.response_html(page_template, data)
async def _modify_job_phase(self, request): try: with suppress(asyncio.CancelledError): job_id = await asyncio.shield(modify_job_request(request)) return web.HTTPSeeOther(location=f'/vospace/transfers/{job_id}') except InvalidJobStateError: return web.HTTPSeeOther(location=f'/vospace/transfers/{job_id}') except VOSpaceError as f: return web.Response(status=f.code, text=f.error) except Exception as e: return web.Response(status=500)
async def handle_create_password(request): token = request.match_info['token'] form = await request.post() description = form.get('description', '').strip() password = form.get('password', '').strip() if not description or not password: raise web.HTTPSeeOther( f'/{token}/passwords?error=Заполните+все+поля') await create_password(request.user['id'], description, password) raise web.HTTPSeeOther(f'/{token}/passwords')
async def post(self): data = await self.post() # Login existed user and return api_key as cookie if data.get('login', None) is not None \ and data.get('login', None) != '' \ and data.get('password', None) is not None \ and data.get('password', None) != '': try: async with self.app['db'].acquire() as conn: row = await user_login(conn, data.get('login'), data.get('password')) if row: res = web.HTTPSeeOther(self.path) res.cookies['api_key'] = row return res except: e = 'Incorrect username or password' print(e) return aiohttp_jinja2.render_template( 'signup.html', self, { 'error_login': e, 'url': request.path }) # Sign up new user and return api_key as cookie if data.get('username', None) is not None \ and data.get('username', None) != '' \ and data.get('new_password', None) is not None \ and data.get('new_password', None) != '': print(data.get('new_password') == '') date_time = datetime.datetime.now() async with self.app['db'].acquire() as conn: row = await user_signup(conn, data.get('username'), data.get('new_password'), date_time, True) if not row: e = 'This username is used yet. Please, try again' print(e) return aiohttp_jinja2.render_template( 'signup.html', self, { 'error_signup': e, 'url': request.path }) res = web.HTTPSeeOther(self.path) res.cookies['api_key'] = row return res print('ERROR') e = 'Perhaps some field is not filled' return aiohttp_jinja2.render_template('signup.html', self, { 'error': e, 'url': request.path })
async def wrapper(request): token = request.match_info['token'] session = await sessions.get_session(request) if session.setdefault('state', 'login') == state: return await func(request) if session.get('state') == 'user': raise web.HTTPSeeOther( f'/{token}/users/{session["user_id"]}') elif session.get('state') == 'pass': raise web.HTTPSeeOther(f'/{token}/password') else: raise web.HTTPSeeOther(f'/{token}/login')
async def login(self, req: Request) -> Response: """Redirect user to AAI login. :param req: A HTTP request instance :raises: HTTPSeeOther redirect to login AAI """ # Generate a state for callback and save it to session storage state = secrets.token_hex() await self._save_to_session(req, key="oidc_state", value=state) LOG.debug("Start login") # Parameters for authorisation request params = { "client_id": self.client_id, "response_type": "code", "state": state, "redirect_uri": self.callback_url, "scope": self.scope, "nonce": self.nonce, } # Prepare response url = f"{self.auth_url}?{urllib.parse.urlencode(params)}" response = web.HTTPSeeOther(url) response.headers["Location"] = url raise response
async def handle_login_post(request: web.Request): # return web.Response(text='OK', content_type="text/html") if request.method == 'POST': form = await request.post() uid, error = await validate_login(form, request.app) if error: response = aiohttp_jinja2.render_template('login.jinja2', request, {'error': error}) response.headers['Content-Language'] = 'ru' return response else: # login form is valid # make session and set token session = await aiohttp_session.get_session(request) session["username"] = form["username"] session["uid"] = uid if request.app.get('arq_pool'): await request.app['arq_pool'].enqueue_job('build_news_cache', user_id=uid) next_location = form.get('next') location = next_location or request.app.router['index'].url_for() response = web.HTTPSeeOther(location) return response return web.HTTPFound(request.app.router['login'].url_for())
async def handle_delete_password(request): token = request.match_info['token'] password_id = request.match_info['password_id'] await delete_password(request.user['id'], password_id) raise web.HTTPSeeOther(f'/{token}/passwords')
async def get(self) -> web.Response: """Get function that return the index page.""" try: informasjon = self.request.rel_url.query["informasjon"] except Exception: informasjon = "" try: user = await check_login_open(self) event = await get_event(user["token"], "") events = await EventsAdapter().get_all_events(user["token"]) logging.debug(f"Events: {events}") return await aiohttp_jinja2.render_template_async( "index.html", self.request, { "lopsinfo": "Startside", "event": event, "event_id": "", "events": events, "informasjon": informasjon, "username": user["name"], }, ) except Exception as e: logging.error(f"Error: {e}. Redirect to login page.") return web.HTTPSeeOther(location=f"/login?informasjon={e}")
async def get(self) -> web.Response: """Get route function that return the tasks page.""" try: event_id = self.request.rel_url.query["event_id"] except Exception: event_id = "" try: informasjon = self.request.rel_url.query["informasjon"] except Exception: informasjon = "" try: user = await check_login(self) event = await get_event(user["token"], event_id) task_status = await get_task_status(user["token"], event_id) return await aiohttp_jinja2.render_template_async( "tasks.html", self.request, { "lopsinfo": "Rennforberedelser - status", "event": event, "event_id": event_id, "informasjon": informasjon, "task_status": task_status, "username": user["name"], }, ) except Exception as e: logging.error(f"Error: {e}. Redirect to main page.") return web.HTTPSeeOther(location=f"/?informasjon={e}")
async def callback(request): secret_key = getattr(request.app.config, 'session_key', b'') session = await get_session(request) messages = session.pop('flash.messages', []) post = await request.post() form = CallbackForm(session, secret_key, post, prefix='callback') if form.validate(): mail = EmailMultipart(request) mail.callback(form.data) send = await mail.send() if send: messages.append(( 'Сообщение отправлено', 'success', )) else: messages.append(( 'Ошибка отправки сообщения', 'error', )) else: messages.append(( 'Ошибка ввода данных', 'error', )) session['flash.messages'] = messages raise web.HTTPSeeOther(request.app.router['home'].url())
async def add_friend(request): token = request.match_info['token'] session = await sessions.get_session(request) user_id = session['user_id'] try: target_id = int(request.match_info['target_id']) except ValueError: raise web.HTTPBadRequest if user_id == target_id: raise web.HTTPBadRequest async with aiosqlite.connect(DATABASE) as db: await get_user(target_id) await db.execute( 'INSERT INTO friends (source_id, target_id) VALUES (:source_id, :target_id)', { "source_id": user_id, "target_id": target_id }) await db.commit() return web.HTTPSeeOther(f'/{token}/users/{target_id}')
async def initialize_routes(self): self.web_app.add_routes([ web.get('/', lambda r: web.FileResponse("./templates/index.html")), web.get( '/methodology', lambda r: web.FileResponse("./templates/methodology.html")), web.get('/configure', lambda r: web.FileResponse("./templates/configure.html")), web.post('/generate_list', self.generate_list), web.get('/generate_list/{list_id}', self.poll_list_generation_status, allow_head=False), web.post('/notify_email', self.notify_email), web.get( '/list/{list_id}', lambda r: web.HTTPSeeOther( "/list/{}/full".format(r.match_info['list_id']))), web.get('/list/{list_id}/{list_size}', self.list_info), web.get('/download/{list_id}/{list_size}', self.download_list), web.get('/download_latest', self.download_latest), web.get( '/failure', lambda r: web.FileResponse( "./templates/failure.html", status=500) ), # status is ignored for FileResponse ]) self.web_app.router.add_static('/assets/', path="./assets", name='static')
async def delete_user(self, req: Request) -> Response: """Delete user from database. :param req: DELETE request :raises: HTTPUnauthorized if not current user :returns: HTTPNoContent response """ user_id = req.match_info["userId"] if user_id != "current": LOG.info(f"User ID {user_id} delete was requested") raise web.HTTPUnauthorized(reason="Only current user deleteion is allowed") db_client = req.app["db_client"] operator = UserOperator(db_client) current_user = req.app["Session"]["user_info"] user = await operator.delete_user(current_user) LOG.info(f"DELETE user with ID {user} was successful.") req.app["Session"]["access_token"] = None req.app["Session"]["user_info"] = None req.app["Session"]["oidc_state"] = None req.app["Session"] = {} req.app["Cookies"] = set({}) response = web.HTTPSeeOther(f"{aai_config['redirect']}/") response.headers["Location"] = ( "/" if aai_config["redirect"] == aai_config["domain"] else f"{aai_config['redirect']}/" ) LOG.debug("Logged out user ") raise response
async def logout(self, req: Request) -> Response: """Log the user out by revoking tokens. :param req: A HTTP request instance :raises: HTTPBadRequest in case logout failed :returns: HTTPSeeOther redirect to login page """ # Revoke token at AAI try: cookie = decrypt_cookie(req) req.app["OIDC_State"].remove( req.app["Session"][cookie["id"]]["oidc_state"]) except KeyError: pass try: cookie = decrypt_cookie(req) req.app["Session"].pop(cookie["id"]) except KeyError: pass response = web.HTTPSeeOther(f"{self.redirect}/") response.headers[ "Location"] = "/" if self.redirect == self.domain else f"{self.redirect}/" LOG.debug("Logged out user ") raise response
async def login_request(request: web.Request) -> web.Response: """Handle login requests.""" LOG.debug("Handle login request.") # Generate a state for callback state = await generate_state() # Save state to session storage await save_to_session(request, key="oidc_state", value=state) # Create parameters for authorisation request params = { "client_id": CONFIG.aai["client_id"], "response_type": "code", "state": state, "redirect_uri": CONFIG.aai["url_callback"], "scope": " ".join(CONFIG.aai["scope"].split(",")), } # Craft authorisation URL url = f"{CONFIG.aai['url_auth']}?{urllib.parse.urlencode(params)}" # Prepare response response = web.HTTPSeeOther(url) # Redirect user to remote AAI server for authentication, this does a 303 redirect raise response
async def check_login(request: Request, handler: Callable) -> StreamResponse: """Check login if session user is logged in and can access API. :param req: A request instance :param handler: A request handler :raises: HTTPSeeOther in case session does not contain access token and user_info :raises: HTTPUnauthorized in case cookie cannot be found :returns: Successful requests unaffected """ controlled_paths = [ "/schemas", "/drafts", "/validate", "/publish", "/submit", "/folders", "/objects", "/users", "/logout", "/home", "/newdraft", ] main_paths = [ "/aai", "/callback", "/static", "/health", "/error401", "/error403", "/error404", "/error500" ] if (request.path.startswith(tuple(main_paths)) or request.path == "/" or (request.path.startswith("/") and request.path.endswith(tuple([".svg", ".jpg", ".ico", ".json"])))): return await handler(request) if request.path.startswith( tuple(controlled_paths)) and "OIDC_URL" in os.environ and bool( os.getenv("OIDC_URL")): cookie = decrypt_cookie(request) session = request.app["Session"].setdefault(cookie["id"], {}) if not all(x in ["access_token", "user_info", "oidc_state"] for x in session): LOG.debug("checked session parameter") response = web.HTTPSeeOther(f"{aai_config['domain']}/aai") response.headers["Location"] = "/aai" raise response if cookie["id"] in request.app["Cookies"]: LOG.debug("checked cookie session") _check_csrf(request) else: LOG.debug("Cannot find cookie in session") raise web.HTTPUnauthorized( headers={ "WWW-Authenticate": 'OAuth realm="/", charset="UTF-8"' }) return await handler(request) elif "OIDC_URL" in os.environ and bool(os.getenv("OIDC_URL")): LOG.debug(f"not authorised to view this page {request.path}") raise web.HTTPUnauthorized( headers={"WWW-Authenticate": 'OAuth realm="/", charset="UTF-8"'}) else: return await handler(request)
async def login(request, args): admin_id = await SysAdminMod.login(args['username'], args['password']) if not admin_id: raise web.HTTPSeeOther(request.app.router.get('login_fail').url_for()) session = await get_session(request) session['admin_id'] = admin_id session['is_login'] = True return OptSuccess()
async def check_password(request): token = request.match_info['token'] session = await sessions.get_session(request) user_id = session['user_id'] secret = get_otp_secret(user_id) real_password = get_totp_token(secret) form = await request.post() password = form.get('password', '').strip() if password != str(real_password): raise web.HTTPSeeOther( f'/{token}/password?error=И+что+это+за+пароль+такой%3F%3F%3F') session['state'] = 'user' raise web.HTTPSeeOther(f'/{token}/users/{user_id}')
async def logout(request): token = request.match_info['token'] session = await sessions.get_session(request) session['state'] = 'login' session.pop('user_id') raise web.HTTPSeeOther(f'/{token}/login')