init
This commit is contained in:
parent
9ef96b9479
commit
dffa0a86f8
17 changed files with 11 additions and 192 deletions
|
|
@ -1,3 +0,0 @@
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
# Register your models here.
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class ApiConfig(AppConfig):
|
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
|
||||||
name = 'apps.api'
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
from django.db import models
|
|
||||||
from oauth2_provider.models import get_application_model
|
|
||||||
|
|
||||||
from apps.users.models import User
|
|
||||||
|
|
||||||
Application = get_application_model()
|
|
||||||
|
|
||||||
|
|
||||||
class Invoke(models.Model):
|
|
||||||
caller_application = models.ForeignKey(to=Application, on_delete=models.PROTECT)
|
|
||||||
callee_application = models.CharField(to=Application, on_delete=models.PROTECT)
|
|
||||||
caller_user = models.ForeignKey(to=User, on_delete=models.PROTECT)
|
|
||||||
cost = models.DecimalField()
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
# TODO: move to external model
|
|
||||||
request = models.JSONField()
|
|
||||||
response = models.JSONField()
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
from django.urls import path, include
|
|
||||||
from .views import myview
|
|
||||||
app_name = "core"
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
# path('', HomeView.as_view(), name='home'),
|
|
||||||
path('proxy/(?P<path>.*)', myview),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
import re
|
|
||||||
import requests
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.http import QueryDict
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
|
|
||||||
|
|
||||||
def proxy_view(request, url, requests_args=None):
|
|
||||||
"""
|
|
||||||
Forward as close to an exact copy of the request as possible along to the
|
|
||||||
given url. Respond with as close to an exact copy of the resulting
|
|
||||||
response as possible.
|
|
||||||
|
|
||||||
If there are any additional arguments you wish to send to requests, put
|
|
||||||
them in the requests_args dictionary.
|
|
||||||
"""
|
|
||||||
requests_args = (requests_args or {}).copy()
|
|
||||||
headers = get_headers(request.META)
|
|
||||||
params = request.GET.copy()
|
|
||||||
|
|
||||||
if 'headers' not in requests_args:
|
|
||||||
requests_args['headers'] = {}
|
|
||||||
if 'data' not in requests_args:
|
|
||||||
requests_args['data'] = request.body
|
|
||||||
if 'params' not in requests_args:
|
|
||||||
requests_args['params'] = QueryDict('', mutable=True)
|
|
||||||
|
|
||||||
# Overwrite any headers and params from the incoming request with explicitly
|
|
||||||
# specified values for the requests library.
|
|
||||||
headers.update(requests_args['headers'])
|
|
||||||
params.update(requests_args['params'])
|
|
||||||
|
|
||||||
# If there's a content-length header from Django, it's probably in all-caps
|
|
||||||
# and requests might not notice it, so just remove it.
|
|
||||||
for key in list(headers.keys()):
|
|
||||||
if key.lower() == 'content-length':
|
|
||||||
del headers[key]
|
|
||||||
|
|
||||||
requests_args['headers'] = headers
|
|
||||||
requests_args['params'] = params
|
|
||||||
|
|
||||||
response = requests.request(request.method, url, **requests_args)
|
|
||||||
|
|
||||||
proxy_response = HttpResponse(
|
|
||||||
response.content,
|
|
||||||
status=response.status_code)
|
|
||||||
|
|
||||||
excluded_headers = set([
|
|
||||||
# Hop-by-hop headers
|
|
||||||
# ------------------
|
|
||||||
# Certain response headers should NOT be just tunneled through. These
|
|
||||||
# are they. For more info, see:
|
|
||||||
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
|
|
||||||
'connection', 'keep-alive', 'proxy-authenticate',
|
|
||||||
'proxy-authorization', 'te', 'trailers', 'transfer-encoding',
|
|
||||||
'upgrade',
|
|
||||||
|
|
||||||
# Although content-encoding is not listed among the hop-by-hop headers,
|
|
||||||
# it can cause trouble as well. Just let the server set the value as
|
|
||||||
# it should be.
|
|
||||||
'content-encoding',
|
|
||||||
|
|
||||||
# Since the remote server may or may not have sent the content in the
|
|
||||||
# same encoding as Django will, let Django worry about what the length
|
|
||||||
# should be.
|
|
||||||
'content-length',
|
|
||||||
])
|
|
||||||
|
|
||||||
# Treat Set-Cookie header in a special way, as Django uses a cookie jar to
|
|
||||||
# manage cookies instead of the normal headers dict:
|
|
||||||
# https://docs.djangoproject.com/en/5.0/ref/request-response/#django.http.HttpResponse.headers
|
|
||||||
#
|
|
||||||
# Use headers.get instead of headers.pop in case there are users that rely
|
|
||||||
# on the Set-Cookie header value.
|
|
||||||
cookies_header = response.headers.get('set-cookie', '')
|
|
||||||
proxy_response.cookies.load(cookies_header)
|
|
||||||
|
|
||||||
for key, value in response.headers.items():
|
|
||||||
if key.lower() in excluded_headers:
|
|
||||||
continue
|
|
||||||
elif key.lower() == 'location':
|
|
||||||
# If the location is relative at all, we want it to be absolute to
|
|
||||||
# the upstream server.
|
|
||||||
proxy_response[key] = make_absolute_location(response.url, value)
|
|
||||||
else:
|
|
||||||
proxy_response[key] = value
|
|
||||||
|
|
||||||
return proxy_response
|
|
||||||
|
|
||||||
|
|
||||||
def make_absolute_location(base_url, location):
|
|
||||||
"""
|
|
||||||
Convert a location header into an absolute URL.
|
|
||||||
"""
|
|
||||||
absolute_pattern = re.compile(r'^[a-zA-Z]+://.*$')
|
|
||||||
if absolute_pattern.match(location):
|
|
||||||
return location
|
|
||||||
|
|
||||||
parsed_url = urlparse(base_url)
|
|
||||||
|
|
||||||
if location.startswith('//'):
|
|
||||||
# scheme relative
|
|
||||||
return parsed_url.scheme + ':' + location
|
|
||||||
|
|
||||||
elif location.startswith('/'):
|
|
||||||
# host relative
|
|
||||||
return parsed_url.scheme + '://' + parsed_url.netloc + location
|
|
||||||
|
|
||||||
else:
|
|
||||||
# path relative
|
|
||||||
return parsed_url.scheme + '://' + parsed_url.netloc + parsed_url.path.rsplit('/', 1)[0] + '/' + location
|
|
||||||
|
|
||||||
return location
|
|
||||||
|
|
||||||
|
|
||||||
def get_headers(environ):
|
|
||||||
"""
|
|
||||||
Retrieve the HTTP headers from a WSGI environment dictionary. See
|
|
||||||
https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META
|
|
||||||
"""
|
|
||||||
headers = {}
|
|
||||||
for key, value in environ.items():
|
|
||||||
# Sometimes, things don't like when you send the requesting host through.
|
|
||||||
if key.startswith('HTTP_') and key != 'HTTP_HOST':
|
|
||||||
headers[key[5:].replace('_', '-')] = value
|
|
||||||
elif key in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
|
|
||||||
headers[key.replace('_', '-')] = value
|
|
||||||
|
|
||||||
return headers
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
# Create your views here.
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
|
||||||
from .utils.views import proxy_view
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def proxy_view(request, path):
|
|
||||||
extra_requests_args = {...}
|
|
||||||
remoteurl = 'http://<host_name>/' + path
|
|
||||||
return proxy_view(request, remoteurl, extra_requests_args)
|
|
||||||
|
|
||||||
|
|
@ -24,4 +24,4 @@ class OAUTHLoginRequestForm(forms.ModelForm):
|
||||||
class AccountUpdateForm(forms.ModelForm):
|
class AccountUpdateForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserModel
|
model = UserModel
|
||||||
fields = ['iban']
|
fields = []
|
||||||
|
|
@ -91,7 +91,7 @@ class OAuthCode(models.Model):
|
||||||
return code_challenge
|
return code_challenge
|
||||||
|
|
||||||
def generate_login_url(self):
|
def generate_login_url(self):
|
||||||
url = f'''{settings.BASE_OAUTH2_PROVIDER_URL}/oauth2/authorize/?response_type=code&code_challenge={self.generate_code_challenge()}&code_challenge_method=S256&client_id={settings.CLIENT_ID}&scope=wallet.wallet:get_balance+wallet.transaction:list&state={self.uuid}'''
|
url = f'''{settings.BASE_OAUTH2_PROVIDER_URL}/oauth2/authorize/?response_type=code&code_challenge={self.generate_code_challenge()}&code_challenge_method=S256&client_id={settings.CLIENT_ID}&scope={settings.SCOPES}&state={self.uuid}'''
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def validate_code(self):
|
def validate_code(self):
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,5 @@
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
wallet
|
data crud
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
{#{% load jalali_tags %}#}
|
{#{% load jalali_tags %}#}
|
||||||
{#{% load tags %}#}
|
{#{% load tags %}#}
|
||||||
|
|
||||||
{% block title %}wallet: user account{% endblock %}
|
{% block title %}data crud: user account{% endblock %}
|
||||||
{% block page_title %}wallet: user account{% endblock %}
|
{% block page_title %}data crud: user account{% endblock %}
|
||||||
|
|
||||||
{% block page_action %}
|
{% block page_action %}
|
||||||
<div class="me-2">
|
<div class="me-2">
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% load jalali_tags %}
|
{% load jalali_tags %}
|
||||||
|
|
||||||
{% block title %}user account{% endblock %}
|
{% block title %}data crud: user account{% endblock %}
|
||||||
{% block page_title %}user account{% endblock %}
|
{% block page_title %}data crud: user account{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form action="{{ request.get_full_path }}" method="post" enctype="multipart/form-data" novalidate>
|
<form action="{{ request.get_full_path }}" method="post" enctype="multipart/form-data" novalidate>
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
{#{% load jalali_tags %}#}
|
{#{% load jalali_tags %}#}
|
||||||
{#{% load tags %}#}
|
{#{% load tags %}#}
|
||||||
|
|
||||||
{% block title %}wallet: user account{% endblock %}
|
{% block title %}data crud: user account{% endblock %}
|
||||||
{% block page_title %}wallet: user account{% endblock %}
|
{% block page_title %}data crud: user account{% endblock %}
|
||||||
|
|
||||||
{% block page_action %}
|
{% block page_action %}
|
||||||
<div class="me-2">
|
<div class="me-2">
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
{#{% load jalali_tags %}#}
|
{#{% load jalali_tags %}#}
|
||||||
{#{% load tags %}#}
|
{#{% load tags %}#}
|
||||||
|
|
||||||
{% block title %}wallet: user account{% endblock %}
|
{% block title %}data crud: user account{% endblock %}
|
||||||
{% block page_title %}wallet: user account{% endblock %}
|
{% block page_title %}data crud: user account{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form method="post" action="{% url 'users:login_request' %}">
|
<form method="post" action="{% url 'users:login_request' %}">
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue