-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add s3 storage support and waffle flag #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
Changes from all commits
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 | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |||||||
|
|
||||||||
| This module contains handlers that work across all game types. | ||||||||
| """ | ||||||||
|
|
||||||||
| import hashlib | ||||||||
|
|
||||||||
| from django.core.files.base import ContentFile | ||||||||
|
|
@@ -16,23 +17,24 @@ | |||||||
| GAME_TYPE, | ||||||||
| UPLOAD, | ||||||||
| ) | ||||||||
| from games.utils import get_gamesxblock_storage, delete_image | ||||||||
|
|
||||||||
|
|
||||||||
| class CommonHandlers: | ||||||||
| """Handlers that work across all game types.""" | ||||||||
|
|
||||||||
| @staticmethod | ||||||||
| def expand_game(xblock, data, suffix=''): | ||||||||
| def expand_game(xblock, data, suffix=""): | ||||||||
| """A handler to expand the game from its title block.""" | ||||||||
| description = _("ERR: self.game_type not defined or invalid") | ||||||||
| if xblock.game_type == GAME_TYPE.FLASHCARDS: | ||||||||
| description = _("Click each card to reveal the definition") | ||||||||
| elif xblock.game_type == GAME_TYPE.MATCHING: | ||||||||
| description = _("Match each term with the correct definition") | ||||||||
| return { | ||||||||
| 'title': xblock.title, | ||||||||
| 'description': description, | ||||||||
| 'game_type': xblock.game_type | ||||||||
| "title": xblock.title, | ||||||||
| "description": description, | ||||||||
| "game_type": xblock.game_type, | ||||||||
| } | ||||||||
|
|
||||||||
| @staticmethod | ||||||||
|
|
@@ -46,26 +48,63 @@ def get_settings(xblock, data, suffix=""): | |||||||
|
|
||||||||
| @staticmethod | ||||||||
| def upload_image(xblock, request, suffix=""): | ||||||||
| """Upload an image file and return the URL.""" | ||||||||
| """ | ||||||||
| Upload an image file to configured storage (S3 if set) and return URL. | ||||||||
| """ | ||||||||
| asset_storage = get_gamesxblock_storage() | ||||||||
| try: | ||||||||
| upload_file = request.params["file"].file | ||||||||
| file_name = request.params["file"].filename | ||||||||
| file_hash = hashlib.md5(upload_file.read()).hexdigest() | ||||||||
| upload_file.seek(0) | ||||||||
| _, ext = ( | ||||||||
| file_name.rsplit(".", 1) if "." in file_name else (file_name, UPLOAD.DEFAULT_EXTENSION) | ||||||||
| ) | ||||||||
| if "." not in file_name: | ||||||||
| return Response( | ||||||||
| json_body={ | ||||||||
| "success": False, | ||||||||
| "error": "File must have an extension", | ||||||||
| }, | ||||||||
| status=400, | ||||||||
| ) | ||||||||
| _, ext = file_name.rsplit(".", 1) | ||||||||
| ext = ext.lower() | ||||||||
| allowed_exts = ["jpg", "jpeg", "png", "gif", "webp", "svg"] | ||||||||
|
||||||||
| allowed_exts = ["jpg", "jpeg", "png", "gif", "webp", "svg"] | |
| allowed_exts = UPLOAD.ALLOWED_EXTENSIONS |
Copilot
AI
Nov 21, 2025
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.
MD5 is cryptographically weak and should not be used for security purposes. While this appears to be used for file deduplication rather than security, consider using a stronger hash like SHA256 to avoid potential collision attacks. Use hashlib.sha256(blob).hexdigest() instead.
| file_hash = hashlib.md5(blob).hexdigest() | |
| file_hash = hashlib.sha256(blob).hexdigest() |
Copilot
AI
Nov 21, 2025
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 method signature is inconsistent with other static methods in this class. It has self as the first parameter while being marked as @staticmethod. This will cause a runtime error when called. Change self to xblock to match the pattern used by other static methods like upload_image and save_settings.
Copilot
AI
Nov 21, 2025
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.
References self.asset_storage which doesn't exist. The storage should be obtained via get_gamesxblock_storage() as done in the upload_image method. Change to asset_storage = get_gamesxblock_storage() and then use delete_image(asset_storage, key).
| is_deleted = delete_image(self.asset_storage, key) | |
| asset_storage = get_gamesxblock_storage() | |
| is_deleted = delete_image(asset_storage, key) |
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.
Calls the wrong method name. The handler is defined as
delete_image_handlerin common.py but called asdelete_imagehere. Change toCommonHandlers.delete_image_handler(self, data, suffix)to match the actual method name.