Skip to content

Commit

Permalink
c1c client & mock
Browse files Browse the repository at this point in the history
  • Loading branch information
Reimirno committed Apr 12, 2024
1 parent d961011 commit 012ae72
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 25 deletions.
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ EMAIL_USE_TLS=
EMAIL_USERNAME=

# Cal1Card API URL
MOCK_C1C=false
C1C_API_DOMAIN=
C1C_API_USERNAME=
C1C_API_PASSWORD=
Expand Down
1 change: 1 addition & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def getenv(key, default: Optional[str] = None, *, optional=False):
EMAIL_PASSWORD = getenv('EMAIL_PASSWORD', optional=True)

# C1C API setup
MOCK_C1C = getenv('MOCK_C1C', 'false').lower() == 'true'
C1C_PROXY_URL = getenv('C1C_PROXY_URL', optional=True)
C1C_API_DOMAIN = getenv('C1C_API_DOMAIN', optional=True)
C1C_API_USERNAME = getenv('C1C_API_USERNAME', optional=True)
Expand Down
2 changes: 1 addition & 1 deletion server/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ def cache_key_photo(canvas_id: str):
return f'student_photo_{canvas_id}'

Check warning on line 12 in server/cache.py

View check run for this annotation

Codecov / codecov/patch

server/cache.py#L12

Added line #L12 was not covered by tests


cache_life_photo = app.config.get('C1C_PHOTO_CACHE_LIFE')
cache_life_photo = int(app.config.get('C1C_PHOTO_CACHE_LIFE'))
43 changes: 43 additions & 0 deletions server/services/c1c/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from server import app
from server.services.c1c import fake_data


def is_mock_c1c() -> bool:
return app.config['MOCK_C1C'] and \
app.config['FLASK_ENV'].lower() != 'production'


class C1C:
def __init__(self, proxy_url, api_domain, username, password):
self.proxy_dict = {
'http': proxy_url,
'https': proxy_url
} if proxy_url else None
self.api_domain = api_domain
self.username = username
self.password = password

def _make_request(self, path, method='GET'):
import requests
url = f'{self.api_domain}{path}'
if self.proxy_dict:
return requests.request(method, url, proxies=self.proxy_dict,
auth=(self.username, self.password))
else:
return requests.request(method, url, auth=(self.username, self.password))

def get_student_photo(self, student_canvas_id):
if is_mock_c1c():
return fake_data.get_fake_photo(student_canvas_id)
try:
r = self._make_request(f'/c1c-api/v1/photo/{student_canvas_id}')
if r.status_code == 200:
return r.content
else:
return None
except:
return None


c1c_client = C1C(app.config['C1C_PROXY_URL'], app.config['C1C_API_DOMAIN'],
app.config['C1C_API_USERNAME'], app.config['C1C_API_PASSWORD'])
18 changes: 18 additions & 0 deletions server/services/c1c/fake_data/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import json

FAKE_PHOTO_DICT = None

if not FAKE_PHOTO_DICT:
with open('server/services/c1c/fake_data/photos.json', 'rb') as f:
FAKE_PHOTO_DICT = json.load(f)


def get_fake_photo(student_canvas_id):
print(FAKE_PHOTO_DICT)
try:
with open(f"server/services/c1c/fake_data/photos/{FAKE_PHOTO_DICT[student_canvas_id]}",
'rb') as f:
return f.read()
except Exception as e:
print(e)
return None
6 changes: 6 additions & 0 deletions server/services/c1c/fake_data/photos.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"123456": "sample1.jpg",
"234567": "sample1.jpg",
"345678": "sample1.jpg",
"456789": "sample1.jpg"
}
Binary file added server/services/c1c/fake_data/photos/sample1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 6 additions & 24 deletions server/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -908,30 +908,12 @@ def student_photo(exam_student):
photo = cache_store.get(cache_key_photo(student_canvas_id))
if photo is not None:
return send_file(io.BytesIO(photo), mimetype='image/jpeg')

proxy_url = app.config.get('C1C_PROXY_URL')
username = app.config.get('C1C_API_USERNAME')
password = app.config.get('C1C_API_PASSWORD')
url = app.config.get('C1C_API_DOMAIN') + '/c1c-api/v1/photo/' + student_canvas_id
import requests
try:
r = None
if proxy_url:
proxy_dict = {
"http": proxy_url,
"https": proxy_url
}
r = requests.get(url, auth=(username, password), proxies=proxy_dict)
else:
r = requests.get(url, auth=(username, password))
if r.status_code == 200:
photo = r.content
cache_store.set(cache_key_photo(student_canvas_id), photo, timeout=cache_life_photo)
return send_file(io.BytesIO(photo), mimetype='image/jpeg')
else:
return jsonify({"error": "Photo not available."}), r.status_code
except requests.exceptions.RequestException as e:
return jsonify({"error": "Failed to fetch the photo due to an internal error:" + e.message}), 500
from server.services.c1c import c1c_client
photo = c1c_client.get_student_photo(student_canvas_id)
if photo is not None:
cache_store.set(cache_key_photo(student_canvas_id), photo, timeout=cache_life_photo)
return send_file(io.BytesIO(photo), mimetype='image/jpeg')
return send_file('static/img/photo-placeholder.png', mimetype='image/png')

Check warning on line 916 in server/views.py

View check run for this annotation

Codecov / codecov/patch

server/views.py#L904-L916

Added lines #L904 - L916 were not covered by tests

# endregion

Expand Down

0 comments on commit 012ae72

Please sign in to comment.