Comments (4)
Once the API Browser has the schema definition, we can overload the UI Template and extends that with some code that will help the API Browser put the JWT Token in the Authorization header. For example,
app.py
browse = JSONRPCBrowe(
extensions = ['myst_parser'],
parser = 'markdown',
....,
template_index='./templates/index.html'
)
app = Flask('docstring')
jsonrpc_v1 = JSONRPC(app, '/api/v1', browse=browse)
./templates/index.html
{% extends "index.html" %}
{% block include_script %}
<script src="//unpkg.com/something@x/some-jwt-bundle.js"></script>
<script>
let JWTToken = {};
// Create an adapter to use the JWT Flask, seems like keycloak-adapter-js
window.JSONRPCBrowse = JSONRPCBrowse({
requestInterceptor: (request) => {
request.headers['Authorization'] = JWTToken.accessToken;
return request;
}
});
</script>
{% endblock %}
{% endblock %}
It is the generic form, but the API Browse can support the specific provider by extensions, as simple as is:
app.py
browse = JSONRPCBrowe(
extensions = ['myst_parser', 'flask-jwt'],
parser = 'markdown',
....,
{'flask_jwt': {
public_key: '...',
secret_key: '...',
....,
}}
)
app = Flask('docstring')
jsonrpc_v1 = JSONRPC(app, '/api/v1', browse=browse)
What do you think about that?
from flask-jsonrpc.
It's a bit hard to get grok of your suggestion, but I guess generally ability to extend templates might work, I guess.
This is some quick-and-dirty hack (without understanding how AngularJS magic works) to make it work, by adding authentication form fields and modifying controllers:
diff --git a/src/flask_jsonrpc/contrib/browse/static/js/apps/browse/controllers.js b/src/flask_jsonrpc/contrib/browse/static/js/apps/browse/controllers.js
index 5fcd9f3..4df5d7a 100644
--- a/src/flask_jsonrpc/contrib/browse/static/js/apps/browse/controllers.js
+++ b/src/flask_jsonrpc/contrib/browse/static/js/apps/browse/controllers.js
@@ -20,6 +20,10 @@
$scope.response = responseExample;
$scope.response_object = responseObjectExample;
+ window.username = "";
+ window.password = "";
+ window.customer = "";
+
$scope.$on('App:displayFakeIntro', function(event, display) {
$scope.showFakeIntro = display;
});
@@ -108,31 +112,56 @@
};
}]);
- App.controller('ResponseObjectCtrl', ['$scope', '$window', '$modal', 'RPC', 'module', function($scope, $window, $modal, RPC, module) {
+ App.controller('ResponseObjectCtrl', ['$scope', '$window', '$modal', 'RPC', 'module', 'serviceUrl', function($scope, $window, $modal, RPC, module, serviceUrl) {
$scope.module = module;
+ $scope.module.username = $window.username;
+ $scope.module.password = $window.password;
+ $scope.module.customer = $window.customer;
$scope.$emit('App:displayToolbar', true);
$scope.$emit('App:breadcrumb', module.name);
var RPCCall = function(module) {
- var payload = RPC.payload(module);
- $scope.request_object = payload;
- $scope.response = undefined;
- $scope.response_object = undefined;
- RPC.callWithPayload(payload).success(function(response_object, status, headers, config) { // success
- var headers_pretty = headers();
- headers_pretty.data = config.data;
-
- $scope.response = {status: status, headers: headers_pretty, config: config};
- $scope.response_object = response_object;
- $scope.$emit('App:displayContentLoaded', false);
- }).error(function(response_object, status, headers, config) { // error
- var headers_pretty = headers();
- headers_pretty.data = config.data;
- $scope.response = {status_code: status, headers: headers_pretty, config: config};
- $scope.response_object = response_object;
- $scope.$emit('App:displayContentLoaded', false);
+ window.username = module.username;
+ window.password = module.password;
+ window.customer = module.customer;
+
+ RPC.generateJWT(module.username, module.password, module.customer).success(function(response_object, status, headers, config) {
+
+ const jwt = response_object['access_token'];
+ console.log("JWT:", jwt);
+
+ var payload = RPC.payload(module);
+ $scope.request_object = payload;
+ $scope.response = undefined;
+ $scope.response_object = undefined;
+
+ RPC.callWithPayload(payload, {method: 'POST', url: serviceUrl, headers: { 'Authorization': "JWT " + jwt }} ).success(function(response_object, status, headers, config) { // success
+ var headers_pretty = headers();
+ headers_pretty.data = config.data;
+
+ $scope.response = {status: status, headers: headers_pretty, config: config};
+ $scope.response_object = response_object;
+ $scope.$emit('App:displayContentLoaded', false);
+
+ }).error(function(response_object, status, headers, config) { // error
+ var headers_pretty = headers();
+ headers_pretty.data = config.data;
+
+ $scope.response = {status_code: status, headers: headers_pretty, config: config};
+ $scope.response_object = response_object;
+ $scope.$emit('App:displayContentLoaded', false);
+ });
+
+ }).error(function(response_object, status, headers, config) { // JWT error
+ var headers_pretty = headers();
+ headers_pretty.data = config.data;
+
+ $scope.response = {status_code: status, headers: headers_pretty, config: config};
+ $scope.response_object = response_object;
+ $scope.$emit('App:displayContentLoaded', false);
});
+
},
RPCCallModal = function(module) {
$modal.open({
diff --git a/src/flask_jsonrpc/contrib/browse/static/js/apps/browse/services.js b/src/flask_jsonrpc/contrib/browse/static/js/apps/browse/services.js
index 9b0b287..7a45e59 100644
--- a/src/flask_jsonrpc/contrib/browse/static/js/apps/browse/services.js
+++ b/src/flask_jsonrpc/contrib/browse/static/js/apps/browse/services.js
@@ -116,6 +116,14 @@
return payload;
},
+ generateJWT: function(username, password, customer) {
+ const options = {
+ method: 'POST',
+ url: '/auth',
+ data: { "username" : customer + ";" + username, "password" : password },
+ };
+ return $http(options);
+ },
callWithPayload: function(data, options) {
var options = options || {method: 'POST', url: serviceUrl};
options.data = data;
diff --git a/src/flask_jsonrpc/contrib/browse/templates/browse/partials/response_object.html b/src/flask_jsonrpc/contrib/browse/templates/browse/partials/response_object.html
index 9b57a5e..b8075bc 100644
--- a/src/flask_jsonrpc/contrib/browse/templates/browse/partials/response_object.html
+++ b/src/flask_jsonrpc/contrib/browse/templates/browse/partials/response_object.html
@@ -9,7 +9,14 @@
<div class="modal-body">
<h5><b>Summary:</b> <span ng-if="!module.summary">None</span><span style="white-space: pre-wrap;">{{module.summary}}</span></h5>
<ng-form name="nameDialog" novalidate role="form">
- <div class="form-group input-group-lg">
+ <div class="form-group input-group-sm">
+ <label for="username">Username</label>
+ <input type="text" class="form-control" autocomplete="on" name="username" id="username" ng-model="module.username" ng-keyup="hitEnter($event)" required>
+ <label for="password">Password</label>
+ <input type="password" class="form-control" autocomplete="on" name="password" id="password" ng-model="module.password" ng-keyup="hitEnter($event)" required>
+ <label for="customer">Customer</label>
+ <input type="text" class="form-control" autocomplete="on" name="customer" id="customer" ng-model="module.customer" ng-keyup="hitEnter($event)" required>
+ <hr/>
<span ng-repeat="param in module.params">
<label class="control-label" for="course">{{param.name}} -> {{param.type}}: </label><input type="text" class="form-control" name="{{param.name}}" id="{{param.name}}" ng-model="param.value" ng-keyup="hitEnter($event)" required>
<span class="help-block"></span>
from flask-jsonrpc.
It seems to work. One question, Is every request the client needs to ask for a new JWT Token?
For your example, I think the good decision is the approach of API Browser extension to support that.
from flask-jsonrpc.
It seems to work. One question, Is every request the client needs to ask for a new JWT Token?
No, it does need new token for each request. Simply in order not to check for JWT expiration error (and re-generate transparenlty), I've just made it get a new one on every request. This behavior is only in the Browser of course, not in production. Again, it's a quick-and-very-dirty hack :) .
from flask-jsonrpc.
Related Issues (20)
- App.wellcome() is visible in Dashboard but unaccessible? HOT 2
- Directories in API browser HOT 8
- Feature reqest: do not allow to invoke method as JSON-RPC "Notification" HOT 2
- API browser does not support more complex type anotations
- Default values for parameters in API Browser HOT 3
- Feature request: package description and package documentation page
- Feature request: Markdown/HTML support for descriptions HOT 2
- Allow to use custom error codes for unexpected errors HOT 1
- Feature request: use Annotated type hint for per-field documentation HOT 2
- Feature request: allow deeper view nesting in API Browser HOT 2
- Feature request: function (view) overloading? HOT 6
- The API Browser doesn't support method without types hints
- Unified API Browser in case of using modular server
- Add support to Python 3.11
- Goodbye Python 3.6
- JSON Schema Service Descriptor
- Can not import in windows HOT 1
- remove support for 3.7 and 3.8 and add 3.12 HOT 7
- New major library version HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flask-jsonrpc.