async def logout(request): app = request.app session_id = get_session_id(request) await terminate_session(app, session_id) resp = HTTPFound('/') resp.del_cookie('X-SESSION-ID') return resp
def _serve_content_artifact(self, content_artifact, headers): """ Handle response for a Content Artifact with the file present. Depending on where the file storage (e.g. filesystem, S3, etc) this could be responding with the file (filesystem) or a redirect (S3). Args: content_artifact (:class:`pulpcore.app.models.ContentArtifact`): The Content Artifact to respond with. headers (dict): A dictionary of response headers. Raises: :class:`aiohttp.web_exceptions.HTTPFound`: When we need to redirect to the file NotImplementedError: If file is stored in a file storage we can't handle Returns: The :class:`aiohttp.web.FileResponse` for the file. """ if settings.DEFAULT_FILE_STORAGE == "pulpcore.app.models.storage.FileSystem": filename = content_artifact.artifact.file.name return FileResponse(os.path.join(settings.MEDIA_ROOT, filename), headers=headers) elif settings.DEFAULT_FILE_STORAGE == "storages.backends.s3boto3.S3Boto3Storage": artifact_file = content_artifact.artifact.file content_disposition = f"attachment;filename={content_artifact.relative_path}" parameters = {"ResponseContentDisposition": content_disposition} url = artifact_file.storage.url(artifact_file.name, parameters=parameters) raise HTTPFound(url) elif settings.DEFAULT_FILE_STORAGE == "storages.backends.azure_storage.AzureStorage": artifact_file = content_artifact.artifact.file url = artifact_file.storage.url(artifact_file.name) raise HTTPFound(url) else: raise NotImplementedError()
async def post_user(request: Request): form = await request.post() user_id = form.get('user_id') if not user_id: raise HTTPBadRequest(reason="You need to set a user_id") user_id = int(user_id) if form.get('mark_read'): user_manager.mark_user_read(user_id) elif form.get('mark_unread'): user_manager.mark_user_unread(user_id) elif form.get('reply'): user_manager.message_user(user_id, form.get('message')) user_manager.mark_user_read(user_id) elif form.get('remove_tag'): user_manager.remove_user_tag(user_id, form.get('remove_tag')) elif form.get('add_tag'): user_manager.add_user_tag(user_id, form.get('add_tag')) user_manager.mark_user_read(user_id) else: raise HTTPBadRequest(reason="You have to make some action") if request.query: raise HTTPFound(base_url + "/?" + request.query_string) raise HTTPFound(request.path_qs)
async def login_post(request): # they must have a current session already # - hope this is enough against CSRF # - TODO: some rate limiting here, without DoS attacks ses = await get_session(request) form = await request.post() ok = False if ses.new: logging.warn("Bad login attempt (no cookie)") elif (time.time() - ses.created) > settings.MAX_LOGIN_WAIT_TIME: ses.invalidate() logging.warn("Stale login attempt (cookie too old)") elif ses.get('kiddie', 0): logging.warn("Keeping the kiddies at bay") else: captcha = form.get('captcha', '').lower() pw = form.get('password', None) if not captcha or not pw: # keep same captcha; they just pressed enter ok = False else: expect = BP.get('master_pw', settings.MASTER_PW) # XXX scrypt(pw) expect_code = ses.pop('captcha', None) ok = (pw == expect) and (captcha == expect_code) if not ok: # fail; do nothing visible (but they will get new captcha) dest = URL(request.headers.get('referer', '/login')) return HTTPFound(dest) # SUCCESS accept_user_login(ses) # try to put them back where they were before try: dest = URL(request.headers.get('referer', '')).query.get('u', '/') except: dest = '/' logging.warn(f"Good login from user, sending to: {dest}") return HTTPFound(dest)
async def kiddie_traps(request): # I hate skill-less people running burpsuite! Track them ses = await get_session(request) ses['kiddie'] = ses.get('kiddie', 0) + 1 return HTTPFound("/login")
async def process_form(request): new_message, missing_fields = {}, [] fields = ['username', 'message'] data = await request.post() for f in fields: new_message[f] = data.get(f) if not new_message[f]: missing_fields.append(f) if missing_fields: return 'Invalid form submission, missing fields: {}'.format( ', '.join(missing_fields)) # simple demonstration of sessions by saving the username and pre-populating it in the form next time session = await get_session(request) session['username'] = new_message['username'] # hack: if no database is available we use a plain old file to store messages. # Don't do this kind of thing in production! # This very simple storage uses "|" to split fields so we need to replace "|" in the username new_message['username'] = new_message['username'].replace('|', '') with request.app['settings'].MESSAGE_FILE.open('a') as f: now = datetime.now().isoformat() f.write('{username}|{timestamp}|{message}\n'.format(timestamp=now, **new_message)) raise HTTPFound(request.app.router['messages'].url_for())
def _handle_file_response(self, file, headers): """ Handle response for file. Depending on where the file storage (e.g. filesystem, S3, etc) this could be responding with the file (filesystem) or a redirect (S3). Args: file (:class:`django.db.models.fields.files.FieldFile`): File to respond with headers (dict): A dictionary of response headers. Raises: :class:`aiohttp.web_exceptions.HTTPFound`: When we need to redirect to the file NotImplementedError: If file is stored in a file storage we can't handle Returns: The :class:`aiohttp.web.FileResponse` for the file. """ if settings.DEFAULT_FILE_STORAGE == 'pulpcore.app.models.storage.FileSystem': return FileResponse(os.path.join(settings.MEDIA_ROOT, file.name), headers=headers) elif (settings.DEFAULT_FILE_STORAGE == 'storages.backends.s3boto3.S3Boto3Storage' or settings.DEFAULT_FILE_STORAGE == 'storages.backends.azure_storage.AzureStorage'): raise HTTPFound(file.url, headers=headers) else: raise NotImplementedError()
async def process_form(request): new_job = {} missing_fields = [] fields = ['ontology_id', 'json_content'] data = await request.post() for f in fields: new_job[f] = data.get(f) if not new_job[f]: missing_fields.append(f) if missing_fields: return 'Invalid form submission, missing fields: {}'.format(', '.join(missing_fields)) ontology_id = new_job['ontology_id'] json_content = loads(new_job['json_content']) session = await get_session(request) session['ontology_id'] = ontology_id agent_id = service_klass.find_provider(ontology_id) if not service_klass.can_perform(agent_id, ontology_id): return 'The service indicates that this service cannot be performed at this time' result = service_klass.perform(agent_id, ontology_id, json_content) # TODO Record the result of the perform so we can check on its status redirect_url = request.app.router['jobs'].url() raise HTTPFound(redirect_url)
async def create_view(self, request): assert self.table is not None assert self.form_class is not None assert self.list_display is not None engine = request.app['engine'] if request.method == 'POST': data = await request.post() form = self.form_class(data) if form.validate(): insert_data = self.transform_input_data(form.data.copy()) async with engine.acquire() as conn: await conn.execute( self.table.insert().values(**insert_data)) return HTTPFound(self.list_view_url) else: form = self.form_class() context = await self.get_each_context() context.update({ 'form': form, 'list_view_url': self.list_view_url, 'add_view_url': self.add_view_url, 'verbose_name': self.verbose_name, 'verbose_name_plural': self.verbose_name_plural, }) return aiohttp_jinja2.render_template(self.change_form_template, request, context)
async def delete_view(self, request): engine = request.app['engine'] driver_id = request.match_info['pk'] data = None context = await self.get_each_context() async with engine.acquire() as conn: query = self.table.select().where(self.table.c.id == driver_id) \ .limit(1) async for row in conn.execute(query): data = self.format_to_dict(row) if data is None: context.update({ 'form': None, 'instance': None, }) return aiohttp_jinja2.render_template(self.delete_view_template, request, context) if request.method == 'POST': async with engine.acquire() as conn: await conn.execute( delete(self.table).where(self.table.c.id == driver_id)) return HTTPFound(self.list_view_url) context['instance'] = data return aiohttp_jinja2.render_template(self.delete_view_template, request, context)
async def _iter(self) -> StreamResponse: if DEBUG: return await super()._iter() else: try: return await super()._iter() except MarshmallowValidationError: # TODO: обработчик ошибок marshmallow raise logout( self.request, HTTPFound(location=self.request.app.router['auth-signin']. url_for())) except PydanticValidationError: # TODO: обработчик ошибок pydantic raise logout( self.request, HTTPFound(location=self.request.app.router['auth-signin']. url_for()))
async def add_user(request): data = await request.post() email = data['email'] engine = request.app['engine'] async with engine.acquire() as conn: v = await conn.execute(sa_user.insert().returning(sa_user.c.id).values( {'email': email})) id = (await v.first()).id print('created user, id: {}, email: {}'.format(id, email)) return HTTPFound('/')
async def create_category(request: Request): form = CategoryForm(await request.post()) if request.method == 'POST' and form.validate(): category = Category( name=form.name.data, allowed_roles=form.allowed_roles.data, ) await category_dao.create(request.app, category) raise HTTPFound('/admin/categories') return {'form': form}
async def login(request: Request): if await get_auth_user(request): raise HTTPFound('/') key = random.randint(1, 10) form = LoginForm(await request.post(), key=key) if request.method == 'POST' and form.validate(): app = request.app user = await login_user( app=app, username=form.username.data, password=form.password.data, key=form.key.data, answer=form.answer.data, ) if user: session_id = await create_session(app, user.id) resp = HTTPFound('/') resp.set_cookie('X-SESSION-ID', session_id) raise resp return {'form': form}
async def update_view(self, request): engine = request.app['engine'] object_id = request.match_info['pk'] instance_data = None async with engine.acquire() as conn: query = self.table.select().where(self.table.c.id == object_id) \ .limit(1) async for row in conn.execute(query): instance_data = self.format_to_dict(row) if instance_data is None: return { 'form': None, 'instance': None, 'list_view_url': self.list_view_url, 'add_view_url': self.add_view_url, 'verbose_name': self.verbose_name, 'verbose_name_plural': self.verbose_name_plural } if request.method == 'POST': data = await request.post() form = self.form_class(data=data) if form.validate(): updated_data = self.transform_input_data(form.data.copy()) async with engine.acquire() as conn: query = update(self.table) \ .where(self.table.c.id == object_id).values( **updated_data) await conn.execute(query) return HTTPFound(self.list_view_url) else: output_data = self.transform_output_data(instance_data) form = self.form_class(**output_data) context = await self.get_each_context(object_id=object_id) _, reverse_name = self.get_url_name('delete', with_name=True) context.update({ 'form': form, 'instance': instance_data, 'list_view_url': self.list_view_url, 'add_view_url': self.add_view_url, 'verbose_name': self.verbose_name, 'verbose_name_plural': self.verbose_name_plural, 'delete_url': request.app.router[reverse_name].url(parts={'pk': object_id}) }) return aiohttp_jinja2.render_template(self.change_form_template, request, context)
async def upload_callback(request: web.Request): app = request.app video_id = request.match_info['id'] await app['db'][VIDEO_MONGO_COLLECTION].update_one( {'_id': ObjectId(video_id)}, {'$set': { 'uploaded': True }}) scheduler = aiojobs.aiohttp.get_scheduler_from_app(app) await scheduler.spawn(process_file(app, video_id)) return HTTPFound(app['config'].site.index)
async def wrapper(view_or_request: Union[View, BaseRequest]): request = view_or_request.request if isinstance( view_or_request, View) else view_or_request auth_cookie: Optional[str] = request.cookies.get( AUTH_COOKIE_NAME, None) if auth_cookie is not None: store: VKAccessTokenObjectManager = request.app.stores.access_tokens if await store.exists_access_token(t_key=auth_cookie): return await function(view_or_request) raise HTTPFound( location=request.app.router[redirect_field_name].url_for())
async def auth_everything(request, handler): # during setup, no login needed if STATUS.force_local_mode or STATUS.setup_mode: # bypass security completely ses = await get_session(request) if not ses: ses = await new_session(request) accept_user_login(ses) return await handler(request) # whitelist of pages that do not need login # all other requests will need auth if handler in { login_page, login_post, captcha_image, kiddie_traps, expected_404s }: return await handler(request) # verify auth ses = await get_session(request) if ses: active = ses.get('active', 0) idle = time.time() - active if idle > settings.MAX_IDLE_TIME: # stale / idle timeout logging.warn("Idle timeout") ses.invalidate() ses = None if not ses: # no cookie/stale cookie, so send them to logout/in page u = URL("/login") target = request.path[1:] if target and target != 'logout': u = u.update_query(u=target) return HTTPFound(u) # normal path: continue to page ses['active'] = time.time() resp = await handler(request) # clearly an HTML request, so force no caching if '/static/' not in request.path: resp.headers['Cache-Control'] = 'no-cache' return resp
async def edit_category(request: Request): category_id = request.match_info['id'] category = await category_dao.get(request.app, int(category_id)) if not category: raise HTTPNotFound form = CategoryForm(await request.post(), obj=category) if request.method == 'POST' and form.validate(): category = Category( name=form.name.data, allowed_roles=form.allowed_roles.data, ) await category_dao.update(request.app, category) raise HTTPFound('/admin/categories') return {'form': form}
async def screen_data_reader_handler(request): if request.content_length > 104857600: return web.Response(status=413, text='<h1>Too much data, 100 MiB max</h1>', content_type='text/html') post = await request.post() # read in the input data filedata = post["file"].file.read() post["file"].file.close() # create the job job = JM.create_job(filedata) # redirect to the job status page jobpath = job.id + "/job" raise HTTPFound(location=jobpath)
async def process_form(request): data = dict(await request.post()) try: m = FormModel(**data) except ValidationError as exc: return exc.errors() # simple demonstration of sessions by saving the username and pre-populating it in the form next time session = await get_session(request) session['username'] = m.username await request.app['pg'].execute( 'insert into messages (username, message) values ($1, $2)', m.username, m.message) raise HTTPFound(request.app.router['messages'].url_for())
async def create_note(request: Request): user = await get_auth_user(request) categories = await category_dao.get_by_roles(request.app, user.roles) form = NoteForm(await request.post()) form.category.choices = [(c.id, c.name) for c in categories] if request.method == 'POST' and form.validate(): note = Note( author_id=user.id, category_id=form.category.data, title=form.title.data, text=form.text.data, ) await note_dao.create(request.app, note) category = await category_dao.get(request.app, form.category.data) raise HTTPFound('/notes/{cat}/notes'.format(cat=category.name)) return {'form': form}
async def _dispatch(file, headers): """ Stream a file back to the client. Stream the bits. Args: file (:class:`django.db.models.fields.files.FieldFile`): File to respond with headers (dict): A dictionary of response headers. Raises: :class:`aiohttp.web_exceptions.HTTPFound`: When we need to redirect to the file NotImplementedError: If file is stored in a file storage we can't handle Returns: The :class:`aiohttp.web.FileResponse` for the file. """ full_headers = MultiDict() full_headers["Content-Type"] = headers["Content-Type"] full_headers["Docker-Content-Digest"] = headers[ "Docker-Content-Digest"] full_headers["Docker-Distribution-API-Version"] = "registry/2.0" full_headers["Content-Length"] = str(file.size) full_headers[ "Content-Disposition"] = "attachment; filename={n}".format( n=os.path.basename(file.name)) if settings.DEFAULT_FILE_STORAGE == "pulpcore.app.models.storage.FileSystem": path = os.path.join(settings.MEDIA_ROOT, file.name) file_response = web.FileResponse(path, headers=full_headers) return file_response elif settings.DEFAULT_FILE_STORAGE == "storages.backends.s3boto3.S3Boto3Storage": content_url = file.storage.url( file.name, parameters={ "ResponseContentType": full_headers["Content-Type"], "ResponseContentDisposition": full_headers["Content-Disposition"], }, ) raise HTTPFound(content_url) else: raise NotImplementedError()
async def enqueue_handle(request): params = request.rel_url.query if not params: raise HTTPFound( f'/enqueue?{COUNT}=10&{DELTA}=1&{START}=0&{INTERVAL}=0.5') item = {} item.update(params) item[COUNT] = int(item[COUNT]) item[DELTA] = float(item[DELTA]) item[START] = float(item[START]) item[INTERVAL] = float(item[INTERVAL]) item[CURRENT] = item[START] item[STATUS] = 'pending' task_id = next(GENERATOR) DB[task_id] = item QUEUE.put_nowait(task_id) return web.Response(text=f'accepted task_id: {task_id}\ntask:{item}')
async def login_page(request): # Completely static and plain. # thanks to <https://codepen.io/rizwanahmed19/pen/KMMoEN> # Create a session, if they don't have one. Need this # to establish timing/authencity of login data when its posted ses = await get_session(request) if not ses: ses = await new_session(request) else: if ses.get('login_ok'): # they are already logged in, so send them to homepage return HTTPFound('/') # - cannot leave session empty, so put anything in there. ses['j'] = True ses.changed() return send_static_html('static/html/login.html')
async def process_form(request): new_message, missing_fields = {}, [] fields = ['username', 'message'] data = await request.post() for f in fields: new_message[f] = data.get(f) if not new_message[f]: missing_fields.append(f) if missing_fields: return 'Invalid form submission, missing fields: {}'.format( ', '.join(missing_fields)) async with request.app['pg_engine'].acquire() as conn: await conn.execute(sa_messages.insert().values( username=new_message['username'], message=new_message['message'], )) raise HTTPFound(request.app.router['messages'].url())
async def process_form(request): new_message, missing_fields = {}, [] fields = ['username', 'message'] data = await request.post() for f in fields: new_message[f] = data.get(f) if not new_message[f]: missing_fields.append(f) if missing_fields: return 'Invalid form submission, missing fields: {}'.format( ', '.join(missing_fields)) # {% if session.is_secure %} # simple demonstration of sessions by saving the username and pre-populating it in the form next time session = await get_session(request) session['username'] = new_message['username'] # {% endif %} # {% if database.is_none %} # hack: if no database is available we use a plain old file to store messages. # Don't do this kind of thing in production! # This very simple storage uses "|" to split fields so we need to replace "|" in the username new_message['username'] = new_message['username'].replace('|', '') with request.app['settings'].MESSAGE_FILE.open('a') as f: now = datetime.now().isoformat() f.write('{username}|{timestamp}|{message}\n'.format(timestamp=now, **new_message)) # {% elif database.is_pg_sqlalchemy %} async with request.app['pg_engine'].acquire() as conn: await conn.execute(sa_messages.insert().values( username=new_message['username'], message=new_message['message'], )) # {% else %} # TODO # {% endif %} raise HTTPFound(request.app.router['messages'].url())
async def google_drive_auth_callback(request): session = await get_session(request) state = session.get('google_drive_auth_state', '') cfg = modules_config api_scopes = cfg.get('google_drive', {}).get('scopes', []) flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( google_drive_secrets_file, scopes=api_scopes, state=state) flow.redirect_uri = request.url.parent.join( request.app.router['google_drive_auth_callback'].url_for()).human_repr( ) authorization_response = request.url.human_repr() try: flow.fetch_token(authorization_response=authorization_response) except InvalidGrantError: logging.exception("Error on getting google drive token: ") raise HTTPBadRequest() credentials = flow.credentials if not credentials.valid: raise HTTPBadRequest() # create user here google_plus = build('plus', 'v1', credentials=credentials) profile = google_plus.people().get(userId='me').execute() user = User(email=profile['emails'][0]['value'], username=profile.get('displayName', ''), profile_url=profile.get('url', ''), avatar_url=profile.get('image', {}).get('url', '')) await user.save_to_db(request.app['db']) session['userid'] = user.id tm = GoogleDriveTokenManager( access_token=credentials.token, refresh_token=credentials.refresh_token, expires=credentials.expiry, token_uri=credentials.token_uri, ) raise HTTPFound(request.app.router['main_page'].url_for())
async def process_form(request): new_message, missing_fields = {}, [] fields = ['username', 'message'] data = await request.post() for f in fields: new_message[f] = data.get(f) if not new_message[f]: missing_fields.append(f) if missing_fields: return 'Invalid form submission, missing fields: {}'.format( ', '.join(missing_fields)) # simple demonstration of sessions by saving the username and pre-populating it in the form next time session = await get_session(request) session['username'] = new_message['username'] async with request.app['pg_engine'].acquire() as conn: await conn.execute(sa_messages.insert().values( username=new_message['username'], message=new_message['message'], )) raise HTTPFound(request.app.router['messages'].url_for())
def index_redirect(_): raise HTTPFound("/v1/ui/")