From 37e7bcd112e35848ae537cc7fc2ef25302714f62 Mon Sep 17 00:00:00 2001 From: Dave Cavaletto Date: Wed, 6 Jul 2022 14:56:23 -0600 Subject: [PATCH] support rejecting entitlements (#10) Co-authored-by: Dave Cavaletto --- backend-ui/README.md | 10 +++--- backend-ui/api.py | 53 +++++++++++++++++++++++++++++--- backend-ui/static/approve.js | 35 +++++++++++++++++++-- backend-ui/templates/noauth.html | 6 ++-- schema.yaml | 2 +- 5 files changed, 91 insertions(+), 15 deletions(-) diff --git a/backend-ui/README.md b/backend-ui/README.md index 7be84b5..1c1bfc7 100644 --- a/backend-ui/README.md +++ b/backend-ui/README.md @@ -2,8 +2,10 @@ This is a User Interface for the backend integration API. +## Environment Variables -# TODO -- [ ] Code up this solution - - [ ] show an approve button for each requested entitlement - - [ ] drop-down filter to show different status entitlements (active, cancelled, etc) \ No newline at end of file +|Variable Name|Platform|Description| Example| +|--|--|---|--| +|PORT|GKE|The port the container should run on |8080| +|API_URL|GKE|The URL for the backend integration API|http://doit-easily-api.prod.svc.cluster.local:8080| +|URL_PREFIX|GKE|The prefix to append to all routes, should match path rules in your ingress|/be| diff --git a/backend-ui/api.py b/backend-ui/api.py index c693f37..c51f281 100644 --- a/backend-ui/api.py +++ b/backend-ui/api.py @@ -2,12 +2,25 @@ import requests from flask import Flask, request, render_template -app = Flask(__name__, static_folder="static", static_url_path="/be") - API_URL = os.environ["API_URL"] assert API_URL +URL_PREFIX = os.environ.get("URL_PREFIX", "") + +# :embarassed: don't look at me, I'm ugly +# this is super hacky and lets us set the url prefix on the static js code. we should not do this. +# this entire app should become an SPA and the backend should the backend API rather than a separate server. +# for now this hack lets us set the url prefix to whatever the customer needs based on their ingress settings +with open("static/approve.js", 'r') as file: + filedata = file.read() +filedata = filedata.replace('{URL_PREFIX}', URL_PREFIX) +with open("static/approve.js", 'w') as file: + file.write(filedata) + +app = Flask(__name__, static_folder="static", static_url_path=URL_PREFIX) +# assert URL_PREFIX starts with a / + def get_entitlements(state): try: query_string = f'?state={state}' if state else '' @@ -22,7 +35,7 @@ def get_entitlements(state): # NOTE: we could just make this an SPA...then we don't need a server at all -@app.route("/be/entitlements") +@app.route(f"{URL_PREFIX}/entitlements") def entitlements(): try: state = request.args.get('state', "ACTIVATION_REQUESTED") @@ -30,10 +43,40 @@ def entitlements(): print("loading index") entitlement_response = get_entitlements(state=state) print(f"entitlements: {entitlement_response}") - page_context["entitlements"] = list(entitlement_response['entitlements']) if 'entitlements' in entitlement_response else [] + page_context["entitlements"] = list( + entitlement_response['entitlements']) if 'entitlements' in entitlement_response else [] return render_template("noauth.html", **page_context) - except Exception: + except Exception as e: + print(e) + return {"error": "Loading failed"}, 500 + + +@app.route(f"{URL_PREFIX}/approve", methods=["POST"]) +def approve(): + try: + # call the backend api /entitlement/approve endpoint + msg_json = request.json + response = requests.post(f"{API_URL}/entitlement/approve", json={"entitlement_id": msg_json['entitlement_id']}) + return {}, response.status_code + except Exception as e: + print(e) + return {"error": "Loading failed"}, 500 + + +@app.route(f"{URL_PREFIX}/reject", methods=["POST"]) +def reject(): + try: + # call the backend api /entitlement/reject endpoint + msg_json = request.json + print(f"rejecting: {msg_json['entitlement_id']}") + response = requests.post(f"{API_URL}/entitlement/reject", + json={"entitlement_id": msg_json['entitlement_id'], + "reason": msg_json["reason"]}) + print(f"response: {response}") + return {}, response.status_code + except Exception as e: + print(e) return {"error": "Loading failed"}, 500 diff --git a/backend-ui/static/approve.js b/backend-ui/static/approve.js index 1036462..2b60aea 100644 --- a/backend-ui/static/approve.js +++ b/backend-ui/static/approve.js @@ -2,7 +2,7 @@ async function approve(entitlement_id) { try { // const token = await firebase.auth().currentUser.getIdToken(); //no auth because the entire site needs to be secured behind IAP - const response = await fetch('/approve', { + const response = await fetch('{URL_PREFIX}/approve', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -12,15 +12,46 @@ async function approve(entitlement_id) { }); if (response.ok) { const text = await response.json(); - window.alert(text); + console.log(text) + // window.alert(text); window.location.reload(); } + else { + window.alert('Something went wrong... Please try again!'); + } } catch (err) { console.log(`Error when submitting approval: ${err}`); window.alert('Something went wrong... Please try again!'); } } +async function reject(entitlement_id, reason) { + try { + // const token = await firebase.auth().currentUser.getIdToken(); + //no auth because the entire site needs to be secured behind IAP + const response = await fetch('{URL_PREFIX}/reject', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + // Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({entitlement_id, reason}) + }); + if (response.ok) { + const text = await response.json(); + console.log(text) + // window.alert(text); + window.location.reload(); + } + else { + window.alert('Something went wrong... Please try again!'); + } + } catch (err) { + console.log(`Error when submitting rejection: ${err}`); + window.alert('Something went wrong... Please try again!'); + } +} + // function go() { // console.log('here we go') // const elem = document.querySelector('select') diff --git a/backend-ui/templates/noauth.html b/backend-ui/templates/noauth.html index 06bef35..80793b7 100644 --- a/backend-ui/templates/noauth.html +++ b/backend-ui/templates/noauth.html @@ -38,7 +38,6 @@

Entitlement Requests

- @@ -50,7 +49,7 @@

Entitlement Requests

- + @@ -67,7 +66,8 @@

Entitlement Requests

- + {% endfor %} diff --git a/schema.yaml b/schema.yaml index afa2b55..1bd5f76 100644 --- a/schema.yaml +++ b/schema.yaml @@ -3,7 +3,7 @@ x-google-marketplace: applicationApiVersion: v1beta1 # The published version is required and MUST match the tag # of the deployer image - publishedVersion: '0.1.2' + publishedVersion: '0.2.0' publishedVersionMetadata: releaseNote: >- Initial Release of Doit Easily backend integration.
Account ID Create Time State Update Time Usage Reporting IDApprovalApprove/Reject
{{ entity['state'] }} {{ entity['updateTime'] }} {{ entity['usageReportingId'] }} +