How to allow CORS in odoo 10 - python

is there any solution to add CORS in odoo 10?, i want to access this restful API:
#validate_token
#http.route("/api/survey.survey/all", type="http", auth="none", methods=["GET", "OPTIONS"], csrf=False, cors='*') #Keperluan Web
def get_survey_survey_all(self, id=None, **payload):
model = "v.survey.survey"
ioc_name = model
_model = request.env[self._model].sudo().search([("model", "=", model)], limit=1)
custFields = ['id', 'title', 'stage_id', 'date_start', 'date_end', 'narasi', 'tot_comp_survey', 'department_id', 'responden'
, 'jenis_penelitian_id', 'polda_id', 'polres_id', 'fungsi', 'tahun', 'public_url', 'result_url']
custDomain = [("public_publish", "=", "1")]
if _model:
domain, fields, offset, limit, order = extract_arguments(payload)
fields = custFields
domain = custDomain
data = (request.env[_model.model].sudo().search_read(
domain = domain,
fields = fields,
offset = offset,
limit = limit,
order = order
))
if data:
return valid_response(data)
else:
return valid_response(data)
return invalid_response(
"Invalid object model",
"The model %s is not available in the registry." % ioc_name
)
i've add cors='*' but it's still got an error because access_token not allowed from header Access-Control-Allow-Headers
and this is my valid response code
def valid_response(data, status=200):
"""Valid Response
This will be return when the http request was successfully processed."""
data = {"count": len(data), "data": data}
return werkzeug.wrappers.Response(
status=status,
content_type="application/json; charset=utf-8;",
headers=[
("Access-Control-Allow-Headers", "access_token")
],
response=json.dumps(data),
)

Related

Can I grab some specific third api data as an additional property to my django api view?

I have an api view which fetches data from its model. I want this api view to have an additional value from third party api. Here is views.py which grabs all of its model properties.
#api_view(
["GET"],
)
def business_asset_risk_details(request):
res = models.BusinessImpact.objects.all().values(
"hierarchy",
"business_assets",
"asset_name",
"vendors",
"product",
"version",
"cpe",
"asset_type",
"asset_categorization",
"_regulations",
"asset_risk",
)
return Response({"business_impact_details": res})
Here is third party api view fetching a specific values of it's own.
#api_view(
["GET"],
)
def cve_summery(request, key):
r = requests.get(
"https://services.nvd.nist.gov/rest/json/cves/1.0?cpeMatchString={}".format(
key)
)
if r.status_code == 200:
result = []
res = r.json().get("result").get("CVE_Items")
for rs in res:
data = {
"VulnID": rs.get("cve").get("CVE_data_meta").get("ID"),
"Summery": rs.get("cve").get("description").get("description_data"),
"exploitabilityScore": rs.get("impact")
.get("baseMetricV2")
.get("exploitabilityScore"),
"severity": rs.get("impact").get("baseMetricV2").get("severity"),
"impactScore": rs.get("impact").get("baseMetricV2").get("impactScore"),
}
result.append(data)
return Response(result)
return Response("error happend", r.status_code)
The logic here is, I want business_asset_risk_details view to return "severity": rs.get("impact").get("baseMetricV2").get("severity"), from cve_summery view.
NB: THE KEY parameter in cve_summery view IS cpe of business_asset_risk_details
Thanks.

Checking the payment status from an payment APi

Am trying to verify user transaction on paystack. After a user makes payment, I want what to append the reference to the Api URL to check if the payment was succcessful. If the payment is successful then save the model.
import requests
from django.conf import settings
class Paystack:
PAYSTACK_SECRET_KEY = "sk_test_3cd83d64a1de3a7334bdad47e3fdfa01bf16a059"
base_url = "https://api.paystack.co"
def verify_payment(self, reference, *args, **kwargs):
path = f'/transaction/verify/{reference}'
headers ={
"Authorization": f"Bearer {self.PAYSTACK_SECRET_KEY}",
"Content-Type":'application/json'
}
url = self.base_url + path
response = requests.get(url, headers=headers)
if response.status_code == 200:
response_data = response.json()
return response_data['status'], response_data['data']
response_data = response.json()
return response_data["status"], response_data["message"]
def process_payment(request, slug, amount, award, votes):
reason = request.GET.get('reason')
transaction_id = request.GET.get('reference')
amount = (str(int(amount) / 100))
paystack = Paystack()
status = paystack.process_payment(self.reference)
if status == "success":
transaction = SuccessfulTransactionHistory(
nominee_name=slug,
transaction_id=transaction_id,
amount=amount,
award=award
)
transaction.save()
Nomination.objects.filter(slug=slug).update(votes=F('votes') + votes)
Award.objects.filter(slug=award).update(amount=F('amount') + amount)
return redirect('vote:paymentsuccess', slug=slug)
else:
context = {
'error': reason
}
transaction = FailedTransactionHistory(
nominee_name=slug,
transaction_id=transaction_id,
amount=amount,
award=award
)
transaction.save()
return render(request, 'payment_error.html', context=context)
This is the eeror i get
AttributeError at /payment/Paul/000000000020/halotech-award-8/1/
'Paystack' object has no attribute 'process_payment'
verify_payment vs process_payment.
def verify_payment(self, reference, *args, **kwargs):
status = paystack.process_payment(self.reference)

Django Access Token Matching Query Does Not Exist

I have the following code I am trying to test:
def customer_add_order(request):
"""
params:
access_token
restaurant_id
address
order_details(json format), example:
[{"meal_id": 1, "quantity":2}, {"meal_id": 2, "quantity":3}]
stripe_token
return:
{"status": "success"}
"""
if request.method == "POST":
#Get token
access_token = AccessToken.objects.get(token = request.POST.get("access_token"),
expires__gt = timezone.now())
#Get profile
customer = access_token.user.customer
# Check if customer has a order that is not delivered
if Order.objects.filter(customer = customer).exclude(status = Order.DELIVERED):
return JsonResponse({"status": "fail", "error": "Your Last Order must be completed"})
# Check Address
if not request.POST("address"):
return JsonResponse({"status": "failed", "error": "Address is required."})
# Ger Order Details
order_details = json.load(request.POST["order_details"])
order_total = 0
for meal in order_details:
order_total += Meal.objects.get(id = meal["meal_id"]).price * meal[quantity]
if len(order_details)>0:
# Step 1 - Create an Order
order = Order.objects.create(
customer = customer,
restaurant_id = request.POST["restaurant_id"],
total = order_total,
status = Order.PENDING,
address = request.POST["address"]
)
# Step 2 - Create Order details
for meal in order_details:
OrderDetails.objects.create(
order = order,
meal_id = meal["meal_id"],
quantity = meal["quantity"],
sub_total = Meal.objects.get(id = meal["meal_id"]).price * meal["quantity"]
)
return JsonResponse({"status": "success"})
I enter the params in Postman, and use an access token that shows valid in django, and it hasn't expired. I am using the rest framework and the function is for API.
I use the following function for creating Access Token:
def create_user_by_type(backend, user, response, *args, **kwargs):
request = backend.strategy.request_data()
if backend.name == 'facebook':
avatar = 'https://graph.facebook.com/%s/picture?type=large' % response['id']
if request.get("user_type") == "driver" and not Driver.objects.filter(user_id=user.id):
Driver.objects.create(user_id=user.id, avatar = avatar)
elif not Customer.objects.filter(user_id=user.id):
Customer.objects.create(user_id=user.id, avatar = avatar)
Also, the line if request.get("user_type") == "driver" and not Driver.objects.filter(user_id=user.id): previously had an error because I had it in an outdated format request["user_type"]. Not sure if this is correct syntax for what I want to do, but I can create Access Tokens through Postman.
The issue was I was using the params in Postman to enter the Access Token and other information, instead it should in in 'body' with form-data selected.

How do I structure my view for sending an api get request in Django?

I am sending a get request in my view and then using the response to fill my database and I need some confirmation on the following:
should i make an api call inside of a view?
what should that view response be?
if i have done it wrong then what would be the right way to send get requests in Django?
my_app/views.py
class api(APIView):
template_name = 'payment/api.html'
def get(self, request):
#I SEND THE GET REQUEST HERE
config = configparser.ConfigParser()
config.read('config.ini')
r = requests.get(config['DEFAULT']['api'])
response = r.json()
#HERE I FILTER THE RESPONSE AND PUT IN A DB
for item in response:
if 'Covered Recipient Physician' in item.values():
person, _ = models.Person.objects.get_or_create(
profile_id = int(item['physician_profile_id']),
first_name = item['physician_first_name'].lower(),
last_name = item['physician_last_name'].lower()
)
address, _ = models.Address.objects.get_or_create(
business_street =
item['recipient_primary_business_street_address_line1'].lower(),
city = item['recipient_city'].lower(),
state = item['recipient_state'].lower(),
country = item['recipient_country'].lower()
)
business, _ = models.Business.objects.get_or_create(
business = item['submitting_applicable_manufacturer_or_applicable_gpo_name'].lower(),
)
business_address_link = models.Business_address_link.objects.create(
business = business,
address = address
)
business_address_link.save()
payment = models.Payment.objects.create(
record_id = int(item['record_id']),
amount = float(item['total_amount_of_payment_usdollars']),
date = item['date_of_payment'],
number_of_payments = int(item['number_of_payments_included_in_total_amount']),
payment_form = item['form_of_payment_or_transfer_of_value'],
nature_of_payment = item['nature_of_payment_or_transfer_of_value']
)
payment.save()
person_payment_information = models.Person_payment_information.objects.create(
person = person,
business_address_link = business_address_link,
payment = payment
)
person_payment_information.save()
Try to use this function for GET request -
#require_http_methods(['GET'])
def get_persons(request):
try:
data = list(Message.objects.all.values())
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})
Once you get the response and send it to template.html, you can display it in any way you want.
If you want to add information to the DB you better use POST request, for example -
#require_http_methods(['POST'])
def add_person(request):
try:
data = json.loads(request.body)
new_person = Person(**data)
new_person.save()
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})

tastypie PUT works but POST doesn't

I'm trying to implement a simple Django service with a RESTful API using tastypie. My problem is that when I try to create a WineResource with PUT, it works fine, but when I use POST, it returns a HTTP 501 error. Reading the tastypie documentation, it seems like it should just work, but it's not.
Here's my api.py code:
class CustomResource(ModelResource):
"""Provides customizations of ModelResource"""
def determine_format(self, request):
"""Provide logic to provide JSON responses as default"""
if 'format' in request.GET:
if request.GET['format'] in FORMATS:
return FORMATS[request.GET['format']]
else:
return 'text/html' #Hacky way to prevent incorrect formats
else:
return 'application/json'
class WineValidation(Validation):
def is_valid(self, bundle, request=None):
if not bundle.data:
return {'__all__': 'No data was detected'}
missing_fields = []
invalid_fields = []
for field in REQUIRED_WINE_FIELDS:
if not field in bundle.data.keys():
missing_fields.append(field)
for key in bundle.data.keys():
if not key in ALLOWABLE_WINE_FIELDS:
invalid_fields.append(key)
errors = missing_fields + invalid_fields if request.method != 'PATCH' \
else invalid_fields
if errors:
return 'Missing fields: %s; Invalid fields: %s' % \
(', '.join(missing_fields), ', '.join(invalid_fields))
else:
return errors
class WineProducerResource(CustomResource):
wine = fields.ToManyField('wines.api.WineResource', 'wine_set',
related_name='wine_producer')
class Meta:
queryset = WineProducer.objects.all()
resource_name = 'wine_producer'
authentication = Authentication() #allows all access
authorization = Authorization() #allows all access
class WineResource(CustomResource):
wine_producer = fields.ForeignKey(WineProducerResource, 'wine_producer')
class Meta:
queryset = Wine.objects.all()
resource_name = 'wine'
authentication = Authentication() #allows all access
authorization = Authorization() #allows all access
validation = WineValidation()
filtering = {
'percent_new_oak': ('exact', 'lt', 'gt', 'lte', 'gte'),
'percentage_alcohol': ('exact', 'lt', 'gt', 'lte', 'gte'),
'color': ('exact', 'startswith'),
'style': ('exact', 'startswith')
}
def hydrate_wine_producer(self, bundle):
"""Use the provided WineProducer ID to properly link a PUT, POST,
or PATCH to the correct WineProducer instance in the db"""
#Workaround since tastypie has bug and calls hydrate more than once
try:
int(bundle.data['wine_producer'])
except ValueError:
return bundle
bundle.data['wine_producer'] = '/api/v1/wine_producer/%s/' % \
bundle.data['wine_producer']
return bundle
Any help is greatly appreciated! :-)
This usually means that you are sending the POST to a detail uri, e.g. /api/v1/wine/1/. Since POST means treat the enclosed entity as a subordinate, sending the POST to the list uri, e.g. /api/v1/wine/, is probably what you want.

Categories

Resources