Hello,
I’m trying to develop an user application which is going to have access to some routes in the server, like chronos and timesheet do.
This is my first time developing something on Tryton werkzeug/wsgi/web - you call it - related, so bear with me please.
Setup
-
Blank database initialized with a main module simulating a future client module.
This module installs a second module calledautoventa
which is going to be my user application module. -
Basic configuration of the admin user on Tryton, the party for the company and the company itself.
-
autoventa
installsres
module. and adds the following code to append my application to the application selection, alongside some routes which I intended to use in a future to check the workflow.
user.py
from trytond.pool import PoolMeta
class UserApplication(metaclass=PoolMeta):
__name__ = 'res.user.application'
@classmethod
def __setup__(cls):
super().__setup__()
cls.application.selection.append(('autoventa', 'Autoventa'))
routes.py
from werkzeug.wrappers import Response
from trytond.wsgi import app
from trytond.protocols.wrappers import user_application
autoventa_application = user_application('autoventa')
url_start = '/<database_name>/autoventa'
@app.route(f'{url_start}/healthcheck', methods=['GET'])
@autoventa_application
def health_check(request):
return Response(None, 200)
@app.route(f'{url_start}/hello_world', methods=['GET'])
@autoventa_application
def hello_world(request):
return {'text': 'Hello World'}
Configuration / Environment variables
DB_NAME=ingsys
TRYTOND_DATABASE__URI=postgresql://
TRYTOND_WEB__LISTEN=0.0.0.0:8121
TRYTOND_WEB__ROOT=/home/hodei/ingsys/tryton/6.0/sao/
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
#register-form h1 {
margin: 0;
padding: 0;
text-align: center;
}
#register-form hr {
margin: 20px;
}
#form-inputs {
display: grid;
grid-template-columns: 25%;
justify-content: center;
row-gap: 10px;
}
</style>
</head>
<body>
<form id="register-form">
<h1>Settings</h1>
<hr />
<div id="form-inputs">
<label for="inputURL">URL</label>
<input type="text" name="inputURL" placeholder="URL" />
<label for="inputDatabase">Database</label>
<input
type="text"
name="inputDatabase"
placeholder="Database"
/>
<label for="inputApplication">Application</label>
<input
type="text"
name="inputApplication"
value="autoventa"
disabled
/>
<label for="inputUser">User</label>
<input type="text" name="inputUser" placeholder="User" />
<button type="submit">Send</button>
</div>
</form>
</body>
</html>
SAO runs on 0.0.0.0:8121 and the HTML runs on a live-server by the vscode extension on 127.0.0.1:5500.
I’m writing the following data on the form:
- URL: http://0.0.0.0:8121
- Database: ingsys
- Application: autoventa
- User: admin
On form submit I’m trying to access the route /<database_name>/user/application/
as User Application — trytond latest documentation indicates, but I’m getting the following errors:
Client Side
XHR OPTIONS http://0.0.0.0:8121/ingsys/user/application
CORS Missing Allow Origin
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://0.0.0.0:8121/ingsys/user/application. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://0.0.0.0:8121/ingsys/user/application. (Reason: CORS request did not succeed).
Server side
17370 140689018676800 [2021-08-29 12:53:47,122] INFO werkzeug 127.0.0.1 - - [29/Aug/2021 12:53:47] "OPTIONS /ingsys/user/application HTTP/1.1" 500 -
17370 140689018676800 [2021-08-29 12:53:47,122] ERROR werkzeug Error on request:
Traceback (most recent call last):
File "/home/hodei/ingsys/clients/ingsys/.venv/lib/python3.9/site-packages/werkzeug/serving.py", line 323, in run_wsgi
execute(self.server.app)
File "/home/hodei/ingsys/clients/ingsys/.venv/lib/python3.9/site-packages/werkzeug/serving.py", line 312, in execute
application_iter = app(environ, start_response)
File "/home/hodei/ingsys/clients/ingsys/.venv/lib/python3.9/site-packages/trytond/wsgi.py", line 204, in __call__
return self.wsgi_app(environ, start_response)
File "/home/hodei/ingsys/clients/ingsys/.venv/lib/python3.9/site-packages/trytond/wsgi.py", line 210, in __call__
return self.app(environ, start_response)
File "/home/hodei/ingsys/clients/ingsys/.venv/lib/python3.9/site-packages/trytond/wsgi.py", line 176, in wsgi_app
abort(HTTPStatus.FORBIDDEN)
File "/home/hodei/ingsys/clients/ingsys/.venv/lib/python3.9/site-packages/werkzeug/exceptions.py", line 822, in abort
return _aborter(status, *args, **kwargs)
File "/home/hodei/ingsys/clients/ingsys/.venv/lib/python3.9/site-packages/werkzeug/exceptions.py", line 807, in __call__
raise self.mapping[code](*args, **kwargs)
werkzeug.exceptions.Forbidden: 403 Forbidden: You don't have the permission to access the requested resource. It is either read-protected or not readable by the server.
I’ve tried my own code then copied chronos: settings.js (tryton.org) but I’m getting the same error on the client side.
JavaScript
Method #1
<script>
const $ = (selector) => document.getElementById(selector);
const form = $('register-form');
const handleFormSubmit = async function (event) {
event.preventDefault();
const url = form.elements.inputURL.value;
const database = form.elements.inputDatabase.value;
const application = form.elements.inputApplication.value;
const user = form.elements.inputUser.value;
const fetchUrl = `${url}/${database}/user/application`;
const data = { user: user, application: application };
const headers = { 'Content-Type': 'application/json' };
const fetchSettings = {
method: 'POST',
body: data,
headers: headers,
};
const request = await fetch(fetchUrl, fetchSettings);
};
form.addEventListener('submit', handleFormSubmit);
</script>
Method #2
<script>
const $ = (selector) => document.getElementById(selector);
const form = $('register-form');
const handleFormSubmit = async function (event) {
event.preventDefault();
const url = form.elements.inputURL.value;
const database = form.elements.inputDatabase.value;
const application = form.elements.inputApplication.value;
const user = form.elements.inputUser.value;
const fetchUrl = `${url}/${database}/user/application`;
const data = { user: user, application: application };
jQuery
.ajax({
url: fetchUrl,
contentType: 'application/json',
data: JSON.stringify(data),
dataType: 'json',
type: 'POST',
})
.done(function (data) {
console.log(data);
})
.fail(function (request, status, error) {
console.log(request);
console.log(status);
console.log(error);
});
};
form.addEventListener('submit', handleFormSubmit);
</script>
I’ve read some posts and responses in some places but I didn’t get it to work, like I said it’s my first time. Any pointers will be appreciated.
Thank you