Set cookie in GraphQL mutation - python

I need to update a cookie in GraphQL mutation using graphene and Django.
My first idea was to add cookie to context (which is request) and then set it in middleware.
I have a very simple mutation that looks like that:
class SetWantedCookieMutation(graphene.Mutation):
class Arguments:
wanted_cookie = graphene.String(required=True)
ok = graphene.Boolean(required=True)
def mutate(self, info, wanted_cookie):
# set cookie here
info.context.wanted_cookie = wanted_cookie
return SetWantedCookieMutation(ok=True)
And Django Middleware is that:
class CookieMiddleware(MiddlewareMixin):
def process_response(self, request, response):
if (hasattr(request, 'wanted_cookie')):
response.set_cookie('wanted_cookie', request.wanted_cookie)
return response
But I cannot get wanted_cookie in my CookieMiddleware.
Any ideas how to set cookie in mutation/moddlewere?
Or what are other ways to set cookie through graphene mutation?

One way to do this is to check the operation name in the json of the request:
class CookieMiddleware(MiddlewareMixin):
def generate_cookie(self, user):
# Generate a cookie (probably with the user)
def request_has_cookie_mutation(self, request):
# Returns true if the request's operation is SetWantedCookieMutation
if len(request.body) != 0 and 'operationName' in json.loads(request.body):
return json.loads(request.body)['operationName'] == 'SetWantedCookieMutation'
return False
def process_response(self, request, response):
if (self.request_has_cookie_mutation(request)):
new_cookie = self.generate_cookie(request.user)
response.set_cookie('wanted_cookie', new_cookie)
return response
Note that it looks like you're using a version of Django pre-1.10 and should consider upgrading.

Related

How to get request host in django?

How to get request host in django ?
how will I get host URL/name from request
class StoreLocations(APIView):
"""
GET : For fetching store locations
Returns : Store Locations
---------------
json
"""
permission_classes = []
http_method_names = ["get"]
def get(self, request, format=None):
"""
Want to check from where request is coming from and allow requests coming from specific urls only
"""
Use HttpRequest.get_host(...)
class StoreLocations(APIView):
def get(self, request, *args, **kwargs):
host = request.get_host()
You can use the below code snippet to see which host is used.
print(request.environ.get("HTTP_ORIGIN"))
To see the additional details present in request.
print(request.__dict__)
django request have META dictionary:https://docs.djangoproject.com/en/4.0/ref/request-response/#django.http.HttpRequest.META
I think you search for:
request.META['REMOTE_ADDR'] # e.g. '1.1.1.1'
request.META['REMOTE_HOST'] # e.g. '1.1.1.1'
request.META['HTTP_REFERER'] # this show url from where was made request

How can i route request to specific views according to parameters in Django?

I created an API with Django and i am trying to route requests to different views for optimization purposes.
Here is what i'm trying to do: if the GET request is 127.0.0.1:8000/api/sales/?key=<KEY>&some_query=<some_value>&... that query should be handled by a view called sales. If the GET request contains a specific parameter called sale_value the request should be routed to another view called large_sales, for example 127.0.0.1:8000/api/sales/?key=<KEY>&sale_value=<INT>... should be handled from the large_sales view.
Here is what i tried:
urlpatterns = [
path('sales/', views.sales, name="sales"),
path('sales/sale_value<int:num>', views.large_sales, name="large_sales"),
]
This will route all the requests to sales. How can i do this? Maybe with regex?
Edit: i can't handle this logic directly in the view because i want to cache these two queries with different TTL. Example:
#cache_page(1.5)
def sales(request):
...
#cache_page(10)
def large_sales(request):
...
def sales(request):
try:
sale_value = request.GET['sale_value']
except:
return redirect(large_sales, num=11) # replace 11 with your number.
or try to use if condition (if sale_value != None:)
You can write a view which accesses request.GET and redirects accordingly.
You may also need to put defensive code in the view that you redirect to, to make sure that a user (or attacer) is not getting creative with completely insecure GET parameters!
With a class-based view you can subclass get ...
class SalesView( some_CBV_class):
...
def get( self, request, *args, **kwargs):
if request.GET.get( 'sale_value', None):
target = reverse('app:large_sales', kwargs={...}
) + '?' + request.GET.urlencode()
return HttpResponseRedirect( target)
return super().get( request, *args, **kwargs)
and for safety, maybe
class LargeSalesView( ...)
def get( self, request, *args, **kwargs):
if request.GET.get( 'sale_value', None) is None
target = reverse('app:sales', kwargs={...}
) + '?' + request.GET.urlencode()
return HttpResponseRedirect( target)
return super().get( request, *args, **kwargs)

Django rest framework - including an api key for access authorization

I'm creating a Restful API using Django Rest Framework, i'm not serving sensitive data but still i wanted to add some sort of authorization system for viewing my API endpoints.
Basically each user has an API key assigned, and in order to view any endpoint, the user needs to provide the key when performing any request. All the endpoints use only GET to retrieve the data, so what i did is the following:
The API key is provided in the GET params, so something like myURL/api/endpoint/?key=1234&filter=test
A middleware checks if that API key exists in my database, and if it does the user is able to get the data.
Here is my middleware:
TOKEN_QUERY = "key"
class TokenMiddleware(AuthenticationMiddleware):
def process_request(self, request):
if request.user.is_authenticated:
return None
else:
try:
token = request.GET[TOKEN_QUERY]
except Exception as e:
# A token isn't included in the query params
return JsonResponse({'error': 'Missing parameter: make sure to include your key.'})
try:
query = API_keys.objects.get(api_token=token)
except:
token = None
if token != None:
return None
else:
return JsonResponse({'error': 'Authentication failed. Make sure to provid a valid API key.'})
This system works without any problem, but i'm concerned about safety. How safe is this? Should i not use a GET request (of course i'll make sure to use HTTPS and SSL) ? Or is there a de facto way to create this kind of system? Any kind of advice is appreciated.
You can try this
from rest_framework import permissions
TOKEN_QUERY = "key"
# guest token validation class
class GuestTokenPermission(permissions.BasePermission):
def __init__(self, allowed_methods):
self.allowed_methods = allowed_methods
def has_permission(self, request, view):
token = request.META.get('HTTP_GUEST_TOKEN', None)
if token == TOKEN_QUERY:
return request.method in self.allowed_methods
else:
if request.user.is_superuser:
return request.method in self.allowed_methods
# put where you want to set permission
permission_classes = (partial(GuestTokenPermission, ['GET', 'POST', 'HEAD']),)
Refer https://www.django-rest-framework.org/api-guide/permissions/

twisted render_GET redirect to function

I can't seem to find any documentation on how to use twisted.web.util.Redirect to redirect to another function.
For more information see below.
I have the following code:
class Login(Resource):
isLeaf = True
def getChild(self, name, request):
if name == '':
return self
return Resource.getChild(self, name, request)
def render_GET(self, request):
saml = SamlRequest(request)
print('redirecting to sso')
return Redirect(saml.sso())
class SamlRequest(object):
self.auth = OneLogin_Saml2_Auth(self.request, custom_base_path=settings_path)
def sso(self):
return self.auth.login()
I need to redirect to page login to the login function inside OneLogin_Saml2_Auth.
When I try to redirect as-is I receive the error
raise TypeError("Unicode object not allowed as URL")
Is there a way to accomplish this?
twisted.web.util.Redirect is a kind of Resource, not something you return from a render method. It's most suitable if you have a "static" redirect that exists in your URL structure and redirects to a fixed location.
If you want to write a custom resource that redirects to a dynamic URL, use twisted.web.util.redirectTo(url, request), which you can call from your render_GET method just like you tried to do with Redirect.

How to make a python decorator stop a user flow entering a function?

I currently have a authorization header:
def authorize(allowed_groups=None, debug=False):
# Do your auth here...
headers = cherrypy.request.headers
return
if 'consumer_key' in headers:
if check_consumer_key(headers['consumer_key']):
if 'access_token' in headers:
cherryPy.accept = check_access_token['access_token']
else:
cherrypy.accept = False
I'm using it here:
#cherrypy.tools.authorize()
def GET(self, id=None):
#return the order list for this account type
if cherrypy.accept:
print "Accepted"
user = User()
usermodel = user.get_all()
return json.dumps(usermodel, cls=AlchemyEncoder)
So, rather than doing a cherrpy.accept = True, how can I return an error page in the decorator itself when the authorization isn't right?
You could just make another decorator that will only call the original function if the authorization succeeds and otherwise just displays an error page instead. This way you can avoid changing the other decorator.
def rejectNotAuthorized (f):
def inner ():
if cherrypy.accept:
f()
else:
displayErrorPage()
return inner
#cherrypy.tools.authorize()
#rejectNotAuthorized
def GET(self, id=None):
pass
Of course you could also integrate that into the original decorator. You just need to make sure to return a function that, depending on the authentication result, either runs the real function or shows the error.

Categories