How to assert response.data with queryset? - django-rest-framework

I am testing my API endpoints based on user roles that I have specified using choices in my models.py.
My problem is, when comparing my response.data with the queryset. I am getting this error:
AssertionError: OrderedDict([('count', 1), ('next', None)[228 chars])])]) != <QuerySet [<Project: New Housing 3>]>
def test_projects_list_only_contractor(self):
response = self.client.get(self.url, format='json')
if self.user.role == Role.CONTRACTOR and self.user.is_authenticated:
current_projects = self.user.contractor.projects.all()
self.assertEqual(response.status_code, status.HTTP_200_OK)
# print(response.data)
# [project for project in current_projects]
self.assertEqual(response.data, current_projects )
I have tried converting my current_projects to list, response.data to response.json()['results']
I have also tried using Projects.objects.filter(contractor=self.contractor) for my queryset

Related

How to create user of elastic using flask

I want to create a user | role | privilege of elastic using API in flask
Documentation for creating user provided an example
it's working fine in elastic Dev Tools
but how can I convert it into a python POST request?
My Code
from flask import Flask, request, jsonify, render_template
from elasticsearch import Elasticsearch
CLOUD_ID = "myfirstdeployment:XXX"
ELASTIC_PASS = 'XXX'
ELASTIC_USER = 'XXX'
client = Elasticsearch(cloud_id=CLOUD_ID, basic_auth=(ELASTIC_USER, ELASTIC_PASS))
app = Flask(__name__)
import requests
from requests.structures import CaseInsensitiveDict
#app.route('/get')
def getting():
data = client.search(index="kibana_sample_data_ecommerce", body={"query" :{"match_all":{}}})
return f'{[x["_source"]["category"] for x in data["hits"]["hits"]]}'
es = Elasticsearch(hosts="https://localhost:9200", basic_auth=('elastic', 'zoU_Ec8JjbPnQNG4b8kY'), verify_certs=False)
#app.route('/local')
def local():
return f'{es.info()}'
#app.route('/users')
def getAllUser():
uri = 'https://localhost:9200/_security/user/'
es = Elasticsearch(hosts=uri, basic_auth=('elastic', 'zoU_Ec8JjbPnQNG4b8kY'), ca_certs="872ee6c0879fc0cfe73054c3ba7afb5902dbb171a2c215af35a5faab1206b924", verify_certs=False)
return f'{es.info()}'
#app.route('/users/<name>')
def getSingleUser(name):
try:
uri = f'https://localhost:9200/_security/user/{name}'
es = Elasticsearch(hosts=uri, basic_auth=('elastic', 'zoU_Ec8JjbPnQNG4b8kY'), ca_certs="872ee6c0879fc0cfe73054c3ba7afb5902dbb171a2c215af35a5faab1206b924", verify_certs=False)
return f'{es.info()}'
except:
content = {'error':'User Not Found'}
return content, 404
#app.route('/create-new-user', methods=['GET','POST'])
def createUser():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
email = request.form.get('email')
fullname = request.form.get('fullname')
role = request.form.getlist('role')
body ={"password":password, "username":username, "email":email, "fullname":fullname, "role":role}
try:
uri = f'https://localhost:9200/_security/user/{username}'
es = Elasticsearch(hosts=uri, basic_auth=('elastic', 'zoU_Ec8JjbPnQNG4b8kY'), ca_certs="872ee6c0879fc0cfe73054c3ba7afb5902dbb171a2c215af35a5faab1206b924", verify_certs=False)
return f'{es.info()}'
except:
content = {'error':'something went wrong'}
return content, 501
return render_template('add_user.html')
if __name__ == "__main__":
app.run(debug=True)
when I create a user from Stack Management > Security > User > Create
POST request send to security/user/new_user_username
post data = {password=password, username=username, email=email, role=[], fullname=fullname
first Thanks to Paulo
Using put_user() method we can easily create user
username, password & email fields are mandatory when creating a user using API
#app.route('/create-new-user', methods=['GET','POST'])
def createUser():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
email = request.form.get('email')
fullname = request.form.get('fullname')
roles = request.form.getlist('role')
body ={"password":password, "username":username, "email":email, "fullname":fullname, "roles":roles}
try:
client = Elasticsearch(hosts=https://localhost:9200/, basic_auth=(ELASTIC_USERNAME, ELASTIC_PASSWORD), ca_certs=CERTIFICATE, verify_certs=False)
es = SecurityClient(client)
es.put_user(**body)
return {'message':'User created'}, 201
except:
return {'message':'something went wrong'}, 501
return render_template('add_user.html')
Remember to pass keyword args of roles in put_user
Edited if someone experimenting can also try perform_request
Edited 2 Simple and better solution
body ={"password":password, "username":username, "email":email, "full_name":fullname, 'enabled':True, 'roles':role}
uri = f'https://localhost:9200/'
client = Elasticsearch(hosts=uri, basic_auth=(ELASTIC_USER, ELASTIC_PASS), ca_certs=CERTIFICATE, verify_certs=False)
client.perform_request(body=body, method='POST', path=f'/_security/user/{username}', headers={'content-type':'application/json', 'accept':'application/json'})

Http 403 Error: Details Request had insufficient authentification scopes Google Classroom Announcements

I am using Python Google Classroom API to retrieve announcements data.
Here is my code.
from fetch import Fetch
from googleapiclient.discovery import build
cred = 'catp.json'
get_credits = Fetch(cred) #fetching credential data
credit = get_credits()
service = build('Classroom', 'v1', credentials=credit)
setup = service.courses()
data = setup.list().execute()['courses']
course_names = []
course_ids = []
for i in range(len(data)):
course_names.append(data[i]['name'])
course_ids.append(data[i]['id'])
announcement_data = setup.announcements().list(courseId=course_ids[0]).execute()
But I receive the following Traceback Error:
Additional Information:
My project is registered under service account.
My role is Owner.
I have students account on Google Classroom.
To check whether the same error would be called if I tried to access announcements from a teachers account I created a Course in Classroom, using my Students account and posted some demo announcements.
The result was the same TracebackError. I also tried getting access to the data using API Explorer from Google, passing the same course ID as an argument. The data was received normally without any errors.
[Edit]
Here is the code for fetching credentials, Fetch(cred):
import os
import pickle
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
class Fetch:
def __init__ (self, credential_filename):
self.scopes = ['https://www.googleapis.com/auth/classroom.courses.readonly',
'https://www.googleapis.com/auth/classroom.announcements',
]
self.path = 'C:/frank/programs/python/google api'
self.credential_file = credential_filename
def __call__(self):
os.chdir(self.path)
token = open('token.pickle', 'rb')
creds = pickle.load(token)
if creds.valid == False:
if creds.expired == True:
creds.refresh(Request())
else:
try:
flow = InstalledAppFlow.from_client_secrets_file(self.credential_file, self.scopes)
creds = flow.run_local_server(port=0)
except FileNotFoundError:
print(f'{self.credential_file} does not exist')
token = open(self.token_file, 'wb')
pickle.dump(creds, token)
return creds

Passing variables to the Ansible httpapi plugin

I am looking for some help to add one additional variable to the HTTP plugin.
I wanted to pass variable 'ansible_domain' from the inventory or variable file.
I am able to pass to the username and password, but additional variables are not accepted from an inventory file or var file.
The end point required one more parameter to log in for few functions, and I am unable to proceed.
How can I fix this?
I am using Ansible 2.8.
options:
domain:
type: str
description:
- Specifies the api token path of the FTD device
env:
- name: ansible_domain
vars:
- name: ansible_domain
"""
import json
from ansible.module_utils.basic import to_text
from ansible.errors import AnsibleConnectionFailure
from ansible.module_utils.six.moves.urllib.error import HTTPError
from ansible.plugins.httpapi import HttpApiBase
from ansible.module_utils.connection import ConnectionError
BASE_HEADERS = {
'Content-Type': 'application/json',
}
DOMAIN1 = 'domain'
class HttpApi(HttpApiBase):
def login(self, username, password ):
if username and password:
payload = {'user': username, 'password': password, 'domain': DOMAIN1}
url = '/web_api/login'
response, response_data = self.send_request(url, payload)
else:
raise AnsibleConnectionFailure('Username and password are required for login')
try:
self.connection._auth = {'X-chkp-sid': response_data['sid']}
self.connection._session_uid = response_data['uid']
except KeyError:
raise ConnectionError(
'Server returned response without token info during connection authentication: %s' % response)
def logout(self):
url = '/web_api/logout'
response, dummy = self.send_request(url, None)
def get_session_uid(self):
return self.connection._session_uid
def send_request(self, path, body_params):
data = json.dumps(body_params) if body_params else '{}'
try:
self._display_request()
response, response_data = self.connection.send(path, data, method='POST', headers=BASE_HEADERS)
value = self._get_response_value(response_data)
return response.getcode(), self._response_to_json(value)
except AnsibleConnectionFailure as e:
return 404, 'Object not found'
except HTTPError as e:
error = json.loads(e.read())
return e.code, error
def _display_request(self):
self.connection.queue_message('vvvv', 'Web Services: %s %s' % ('POST', self.connection._url))
def _get_response_value(self, response_data):
return to_text(response_data.getvalue())
def _response_to_json(self, response_text):
try:
return json.loads(response_text) if response_text else {}
# JSONDecodeError only available on Python 3.5+
except ValueError:
raise ConnectionError('Invalid JSON response: %s' % response_text)

Youtube Data API Making a comment (Ruby)

I'm currently trying to create a new thread using the Youtube API. Here is the example provided:
def comments_insert(service, properties, part, **params)
resource = create_resource(properties) # See full sample for function
params = params.delete_if { |p, v| v == ''}
response = service.insert_comment(part, resource, params)
end
comments_insert(service,
{'snippet.parent_id': 'pS16m0FttKk',
'snippet.text_original': ''},
'snippet')
I'm essentially using their exact sample code but I'm getting an error that reads: ArgumentError - unknown keyword: snippet:
resource = ChannelbackController.create_resource({'snippet.parentId': '123', 'snippet.textOriginal': message})
response = service.insert_comment('snippet', resource).inspect

Custom header is not added into request.META in Django Rest Framework

I implemented custom authentication, as described in docs
# custom_permissions.py
from rest_framework import authentication
from rest_framework import exceptions
class KeyAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
key = request.META.get('Authorization')
print(key)
if not key:
raise exceptions.AuthenticationFailed('Authentication failed.')
try:
key = ApiKey.objects.get(key=key)
except ApiKey.DoesNotExist:
raise exceptions.AuthenticationFailed('Authentication failed.')
return (key, None)
In my settings:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'api_server.apps.api_v1.custom_permissions.KeyAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
}
It works as expected during tests:
def test_1(self):
client = APIClient()
client.credentials(X_SECRET_KEY='INVALID_KEY')
response = client.get('/v1/resource/')
self.assertEqual(response.status_code, 403)
self.assertEqual(response.data, {'detail': 'Authentication failed.'})
def test_2(self):
client = APIClient()
client.credentials(X_SECRET_KEY='FEJ5UI')
response = client.get('/v1/resource/')
self.assertEqual(response.status_code, 200)
However when I test with curl and locally running server, there is no X_SECRET_KEY header found in request.META. It is printing None in terminal, while received key is expected.
$ curl -X GET localhost:8080/v1/resource/ -H "X_SECRET_KEY=FEJ5UI"
{'detail': 'Authentication failed.'}
Could you give a hint, what might be a problem with that?
The headers variables are uppercase and prefixed with "HTTP_". This is general to Django, dunno about other languages / frameworks.
See https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/authentication.py#L23 for example.

Resources