-
Notifications
You must be signed in to change notification settings - Fork 3
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
Placeholder pull request for project-wide code review #30
base: initial
Are you sure you want to change the base?
Changes from 70 commits
2e4c603
c24815b
27a8962
5241435
48b8eed
d3eefab
31e87e4
7a4f929
844f849
2a9fc3a
490144d
6d24c65
f6fa332
9252092
6639d04
86289a5
7158bf0
a91f0e0
c85d44b
3d7864b
3c09e44
b60a656
906e073
6e4b776
4851cc6
48f3a55
18ebc9a
2047dab
031e9ab
4ab60f2
d435184
e1a7cbe
7662aac
3fd75fa
b1877e9
32a335d
cf9494a
ddc8c9f
4b76aaa
ea5a8f2
74ed106
4c5814f
c8a6579
1012008
6b9b2b7
6ec3e60
eb46fd5
9554b2e
fe75465
84b77cd
b2bf0ba
ab2c28b
d6be48b
8a83e3d
1f7d7ed
1e3090a
50a4585
d700854
b84b149
e9d0b18
7e50874
02da69a
5e92102
6f4a796
0d8401d
f43bb48
886aff0
627a291
a6bb274
7a31a8d
6dd4565
f743050
4f80277
3fe59ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
#### | ||
# Vue.js environment variables and modes: https://cli.vuejs.org/guide/mode-and-env.html | ||
# Only variables that start with 'VUE_APP_' will be statically embedded into the client bundle. | ||
# Only variables that start with 'VITE_APP_' will be statically embedded into the client bundle. | ||
#### | ||
|
||
VUE_APP_API_BASE_URL='' | ||
VUE_APP_DEBUG=false | ||
VITE_APP_API_BASE_URL='' | ||
VITE_APP_DEBUG=false |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
#### | ||
# Vue.js environment variables and modes: https://cli.vuejs.org/guide/mode-and-env.html | ||
# Only variables that start with 'VUE_APP_' will be statically embedded into the client bundle. | ||
# Only variables that start with 'VITE_APP_' will be statically embedded into the client bundle. | ||
#### | ||
|
||
VUE_APP_API_BASE_URL='http://localhost:5000' | ||
VUE_APP_DEBUG=true | ||
VITE_APP_API_BASE_URL='http://localhost:5000' | ||
VITE_APP_DEBUG=true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/bin/bash | ||
sudo mv /tmp/hartsfield.conf /etc/httpd/conf.d/hartsfield.conf | ||
sudo mv /tmp/ssl.conf /etc/httpd/conf.d/ssl.conf | ||
sudo /bin/systemctl restart httpd.service |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/bash | ||
|
||
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json -s |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
version: 0.2 | ||
|
||
phases: | ||
install: | ||
runtime-versions: | ||
nodejs: 20 | ||
gmerritt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
python: 3.11 | ||
commands: | ||
- node -v | ||
- npm install | ||
pre_build: | ||
commands: | ||
- echo "pre_build phase" | ||
build: | ||
commands: | ||
- npm run build-vue | ||
post_build: | ||
commands: | ||
- ./scripts/codebuild/create-build-summary.sh | ||
artifacts: | ||
files: | ||
- '.ebextensions/**/*' | ||
- 'dist/**/*' | ||
- 'requirements.txt' | ||
- 'hartsfield/**/*' | ||
- 'scripts/**/*' | ||
- 'application.py' | ||
- 'consoler.py' | ||
- 'config/**/*' | ||
- '.platform/**/*' | ||
- 'Procfile' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
""" | ||
Copyright ©2022. The Regents of the University of California (Regents). All Rights Reserved. | ||
|
||
Permission to use, copy, modify, and distribute this software and its documentation | ||
for educational, research, and not-for-profit purposes, without fee and without a | ||
signed licensing agreement, is hereby granted, provided that the above copyright | ||
notice, this paragraph and the following two paragraphs appear in all copies, | ||
modifications, and distributions. | ||
|
||
Contact The Office of Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, | ||
Suite 510, Berkeley, CA 94720-1620, (510) 643-7201, otl@berkeley.edu, | ||
http://ipira.berkeley.edu/industry-info for commercial licensing opportunities. | ||
|
||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, | ||
INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF | ||
THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED | ||
OF THE POSSIBILITY OF SUCH DAMAGE. | ||
|
||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE | ||
SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED | ||
"AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, | ||
ENHANCEMENTS, OR MODIFICATIONS. | ||
""" | ||
|
||
from functools import wraps | ||
|
||
from flask import current_app as app, request | ||
from flask_login import current_user | ||
from hartsfield.api.errors import UnauthorizedRequestError | ||
from hartsfield.models.user import find_by_uid | ||
|
||
|
||
def auth_required(f): | ||
@wraps(f) | ||
def decorated(*args, **kwargs): | ||
if not current_user.is_authenticated: | ||
auth = request.authorization | ||
if not auth or not valid_worker_credentials(auth.username, auth.password): | ||
raise UnauthorizedRequestError('Invalid credentials.') | ||
return f(*args, **kwargs) | ||
return decorated | ||
|
||
|
||
def authorzied_user_required(f): | ||
@wraps(f) | ||
def decorated(*args, **kwargs): | ||
uid = current_user.uid | ||
user = find_by_uid(uid) | ||
if user is None: | ||
auth = request.authorization | ||
if not auth: | ||
raise UnauthorizedRequestError('Invalid credentials.') | ||
return f(*args, **kwargs) | ||
return decorated | ||
|
||
|
||
def valid_worker_credentials(username, password): | ||
return username == app.config['API_USERNAME'] and password == app.config['API_PASSWORD'] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,79 +22,72 @@ | |
"AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, | ||
ENHANCEMENTS, OR MODIFICATIONS. | ||
""" | ||
from collections import OrderedDict | ||
import json | ||
|
||
from flask import current_app as app | ||
from hartsfield import __version__ as version | ||
from hartsfield.configs import load_configs | ||
from hartsfield.api.config_controller import load_json | ||
from hartsfield.lib.http import tolerant_jsonify | ||
from hartsfield.lib.util import get_eb_environment | ||
|
||
import requests | ||
import datetime | ||
import json | ||
import re | ||
|
||
from google.oauth2 import service_account | ||
from flask import current_app as app, request | ||
from google.cloud import storage | ||
from google.oauth2 import service_account | ||
from hartsfield.api.auth_helper import authorzied_user_required | ||
from hartsfield.lib.http import tolerant_jsonify | ||
import hartsfield.api.read_aws_secret | ||
|
||
PUBLIC_CONFIGS = [ | ||
'DEV_AUTH_ENABLED', | ||
'HARTSFIELD_ENV', | ||
'TIMEZONE', | ||
] | ||
|
||
gcp_json_credentials = app.config['GCP_JSON_CREDENTIALS'] | ||
gcp_json_credentials_dict = json.loads(gcp_json_credentials) | ||
AWS_SECRETS_NAME_GCP_JSON_CREDENTIALS = app.config['AWS_SECRETS_NAME_GCP_JSON_CREDENTIALS'] | ||
|
||
# TODO: pass in gs url as input value to @app.route('/api/fetch_url_direct') from form user front-end form submission | ||
gs_source_url="gs://ucb-datahub-archived-homedirs/spring-2021/datahub.berkeley.edu/peterphu-2edo.tar.gz" | ||
# This will probably be request.args['gs_source_url'] in the def block...but that whole "request" business needs to be brought in etc. | ||
|
||
@app.route('/api/fetch_url_direct') | ||
gcp_json_credentials_from_aws = hartsfield.api.read_aws_secret.read_aws_secret(AWS_SECRETS_NAME_GCP_JSON_CREDENTIALS) | ||
gcp_json_credentials_dict = json.loads(gcp_json_credentials_from_aws) | ||
|
||
@app.route('/api/fetch_url_direct', methods=['POST']) | ||
@authorzied_user_required | ||
def fetch_url_direct(): | ||
|
||
# parse the input gs url to get bucket and blob names | ||
bucket_and_blob_string = gs_source_url.replace("gs://", "") | ||
bucket_and_blob_list = bucket_and_blob_string.split("/") | ||
params = request.get_json() | ||
gs_source_url = params.get('gs_source_url') | ||
gs_source_url = gs_source_url.strip() | ||
if not re.match(r'gs://.{3,}/.+', gs_source_url): | ||
error_message = 'The submitted data \"' + gs_source_url + '\" is not a valid gs_source_url.' | ||
v = {'response': error_message, 'status': 'error'} | ||
return tolerant_jsonify(v) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The above looks good. Although I suggest the following for line 58:
This will make for more standard front-end code (eg, checking HTTP status code). |
||
|
||
bucket_and_blob_string = gs_source_url.replace('gs://', '') | ||
bucket_and_blob_list = bucket_and_blob_string.split('/') | ||
bucket_name = bucket_and_blob_list.pop(0) | ||
blob_name = "/".join(bucket_and_blob_list) | ||
blob_name = '/'.join(bucket_and_blob_list) | ||
|
||
# instantiate gcp storage client plus with bucket and blob objects | ||
credentials = service_account.Credentials.from_service_account_info(gcp_json_credentials_dict) | ||
storage_client = storage.Client(project=gcp_json_credentials_dict['project_id'], credentials=credentials) | ||
bucket = storage_client.bucket(bucket_name) | ||
blob = bucket.blob(blob_name) | ||
|
||
# do some checks to confirm that the bucket and blob exist | ||
try: | ||
stats = storage.Blob(bucket=bucket, name=blob_name).exists(storage_client) | ||
except Exception as e: | ||
error_message = "There was a problem trying to get stats on the requested blob \"" + blob_name + "\" in the requested bucket \"" + bucket_name +"\":\n\n " + str(e) | ||
error_message = 'There was an exception trying to do the GCP storage operation with the submitted data \"' + \ | ||
gs_source_url + \ | ||
'\'. When GCP tried, it told us: \"' + \ | ||
str(e) + '\"' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor code style concern: Use f-string with triple quotes when string is multi-line.
|
||
v = {'response': error_message, 'status': 'error'} | ||
return tolerant_jsonify(v) | ||
if stats: | ||
# if the bucket and blob exist, generate a signed url for the blob... | ||
# ...and package it as a Hartsfield back-end internal response | ||
gcp_response = blob.generate_signed_url( | ||
version="v4", | ||
version='v4', | ||
expiration=datetime.timedelta(days=7), | ||
method="GET", | ||
method='GET', | ||
) | ||
v = {'response': gcp_response, 'status': 'success'} | ||
else: | ||
gcp_response = "File \"" + blob_name + "\"does not exist in bucket \"" + bucket_name + "\"" | ||
gcp_response = 'GCP tried, but could not locate a file \"' + blob_name + '\" in a bucket called \"' + bucket_name + '\".' | ||
v = {'response': gcp_response, 'status': 'error'} | ||
|
||
return tolerant_jsonify(v) | ||
|
||
""" | ||
To make/fix/clean: | ||
|
||
- Make the Web request form / wire up web front end portion of app | ||
|
||
- CalNet auth in front of web app | ||
|
||
- All of the other ignorant/non-ideal coding practices I've done...! | ||
""" | ||
|
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.
source .env.development
seems unnecessary in both instances above. Vite should pick it up automatically whennpm run serve-vue