-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Include the Monarch link app as a service on IMAGE-server #894
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments within the file, plus the inputs are not checked. I was able to cause an internal server error by omitting or incorrectly entering fields in the POST requests.
services/monarch-link-app/Dockerfile
Outdated
@@ -0,0 +1,19 @@ | |||
FROM python:3.10 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current versions is 3.13 - why are you using 3.10?
services/monarch-link-app/app.py
Outdated
def write_data(svgData): | ||
with open("data.json", "w") as outfile: | ||
json.dump(svgData, outfile) | ||
|
||
|
||
def read_data(): | ||
with open('data.json', 'r') as openfile: | ||
try: | ||
return json.load(openfile) | ||
except Exception: | ||
return dict() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK for quick prototyping, but this should not be used in production. Would suggest something like sqlite3 that may scale better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created #897 to keep track of this
services/monarch-link-app/app.py
Outdated
return dict() | ||
|
||
|
||
@app.route("/create/<id>", methods=["POST"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there restrictions on what "id" can be here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also - any reason why the create
and update
methods were combined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't limited this currently but I typically use a 6-digit numeric code. Flask has options to limit this something generic like 'int' or we can also build custom 'converters' if we want to enforce this.
EDIT: I have added in a custom converter.
services/monarch-link-app/app.py
Outdated
req_data = request.get_json() | ||
svgData = read_data() | ||
if id in svgData: | ||
if (svgData[id])["secret"] == req_data["secret"]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally considered bad practice to save this in plain text...compare using something like bcrypt?
services/monarch-link-app/app.py
Outdated
write_data(svgData) | ||
return jsonify("Graphic in channel "+id+" has been updated!") | ||
else: | ||
return jsonify("Unauthorized access to existing channel!") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unauthorized access should return 401 code.
services/monarch-link-app/app.py
Outdated
"data": req_data["data"], | ||
"layer": req_data["layer"]} | ||
write_data(svgData) | ||
return jsonify("New channel created with code "+id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the model we discussed earlier, the ID and secret was generated on the server and returned to the client. Create only allowed the client to specify a title. Any reason for the changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, it looks like I've somehow completely messed up the implementation here! :')
Will probably need to touch base in person to sort this out.
services/monarch-link-app/app.py
Outdated
return jsonify("New channel created with code "+id) | ||
|
||
|
||
@app.route("/display/<id>", methods=["GET"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for the change in name from receive
? Also should check the ID.
click==8.1.3 | ||
colorama==0.4.6 | ||
Flask==2.2.2 | ||
Flask-Cors==4.0.2 | ||
Flask-Login==0.6.2 | ||
Flask-SQLAlchemy==3.0.2 | ||
greenlet==2.0.1 | ||
itsdangerous==2.1.2 | ||
Jinja2==3.1.2 | ||
MarkupSafe==2.1.1 | ||
six==1.16.0 | ||
SQLAlchemy==1.4.43 | ||
SQLAlchemy-Utils==0.38.3 | ||
Werkzeug==2.2.2 | ||
gunicorn==22.0.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest setting only what you use directly with semver and allowing some newer verisons. pip freeze
output is almost always overly restrictive.
services/monarch-link-app/app.py
Outdated
response.add_etag(hashlib.md5( | ||
(svgData[id]["data"]+svgData[id]["layer"]).encode())) | ||
response.make_conditional(request) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
Co-authored-by: Juliette Regimbal <[email protected]>
I ran additional tests with POST requests with incorrect/ omitted fields. It now returns 400 in these cases. |
while code in svgData: | ||
code = generate_code(svgData) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting a pin in this for later updates.
services/monarch-link-app/app.py
Outdated
@app.route("/create/<id>", methods=["POST"]) | ||
# generate an id that does not already exist | ||
def generate_code(svgData): | ||
code = ''.join([str(random.randint(1, 9)) for i in range(6)]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like randint(a, b)
returns a value n where a <= n <= b. This conflicts with the check for values between 1 and 8 on line 71.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oopsies! I referred numpy randint docs 😶
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, the legally distinct randint. No worries!
services/monarch-link-app/app.py
Outdated
# has six digits between 1 and 8 | ||
pattern = re.compile("[1-8]{6}") | ||
# also has a length of six | ||
if not pattern.match(value) or len(value) != 6: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest updating the pattern to include line start/end (^[1-8]{6}$
) to avoid the separate length check.
services/monarch-link-app/app.py
Outdated
app.url_map.converters['code'] = CodeConverter | ||
|
||
|
||
@app.route("/create/<string:title>", methods=["POST"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't have put the title as part of the path here. This makes more sense as part of the request body.
Made the requested changes. Also, an exception was being raised when 'display/' was called on a valid ID that didn't exist in the JSON since abort() raises an exception. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! We should chat tomorrow during the meeting about merging this.
Marking for deploy on pegasus since I haven't noticed any ill effects on unicorn. @JRegimbal @VenissaCarolQuadros please push back if you think this could cause issues. |
Unless there is already some cleanup happening on Pegasus, we need have a way to clear the .json file this app creates since this could bulk up over time. (It is cleared on Unicorn every time the container is rebuilt) |
Is there a work item for doing this? (If so, please link here, otw it sounds like we should create one?) And I assume deploying this is also blocked on Shared-Reality-Lab/IMAGE-website#73? |
This PR merges a containerized version of the Monarch web application that links the IMAGE-TactileAuthoring tool to the Monarch client.
As per discussions, this application has been made into a service on the IMAGE-server. New channels can be created and existing channels can be updated by the authoring tool by posting to https://monarch.unicorn.cim.mcgill.ca/create/<subscribed_code>. The JSON can be accessed by the Monarch client by getting from https://monarch.unicorn.cim.mcgill.ca/display/<subscribed_code>. Resolves #888.
Testing:
was published on code 123456.
Graphic on 123456 was updated to
and the change was observed on the Monarch
The update failed when the secret key was changed
Required Information
Coding/Commit Requirements
New Component Checklist (mandatory for new microservices)
docker-compose.yml
andbuild.yml
..github/workflows
.README.md
file that describes what the component does and what it depends on (other microservices, ML models, etc.).OR