Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions apps/challenges/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3131,10 +3131,33 @@ def invite_users_to_challenge(request, challenge_pk):
response_data = {"error": "Users email can't be blank"}
return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

# Parse emails safely using json.loads instead of dangerous eval()
try:
users_email = eval(users_email)
except Exception:
response_data = {"error": "Invalid format for users email"}
# If users_email is already a list (from JSON request body), use it directly
if isinstance(users_email, list):
parsed_emails = users_email
# Otherwise, parse the JSON string
elif isinstance(users_email, str):
parsed_emails = json.loads(users_email)
else:
response_data = {"error": "Invalid email format. Expected a list of email addresses."}
return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

# Validate that the result is a list
if not isinstance(parsed_emails, list):
response_data = {"error": "Invalid email format. Expected a list of email addresses."}
return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

# Validate that all items in the list are strings
if not all(isinstance(email, str) for email in parsed_emails):
response_data = {"error": "All email addresses must be strings."}
return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

users_email = parsed_emails

except (json.JSONDecodeError, TypeError, ValueError) as e:
logger.error(f"Error parsing email list: {str(e)}")
response_data = {"error": "Invalid JSON format for users email"}
return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

invalid_emails = []
Expand Down
3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"moment-picker": "0.10.2",
"angular-moment-picker": "moment-picker#^0.10.2",
"moment-timezone": "^0.5.25",
"trix": "1.3.1"
"trix": "1.3.1",
"ngMeta": "vinaygopinath/ngMeta"
},
"resolutions": {
"angular": "1.7.0"
Expand Down
6 changes: 4 additions & 2 deletions frontend/app.scripts.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"angular-moment",
"clipboard",
"ngclipboard",
"moment-picker"
"moment-picker",
"ngMeta"
]
},
"paths": {
Expand All @@ -51,6 +52,7 @@
"angular-moment": "bower_components/angular-moment/angular-moment.js",
"clipboard": "bower_components/clipboard/dist/clipboard.min.js",
"ngclipboard": "bower_components/ngclipboard/dist/ngclipboard.min.js",
"moment-picker": "bower_components/angular-moment-picker/dist/angular-moment-picker.js"
"moment-picker": "bower_components/angular-moment-picker/dist/angular-moment-picker.js",
"ngMeta": "bower_components/ngMeta/dest/ngMeta.min.js"
}
}
15 changes: 9 additions & 6 deletions frontend/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@
<html ng-app="evalai" ng-strict-di>

<head>
<title ng-bind="pageTitle + ' - EvalAI'"></title>
<title ng-bind="ngMeta.title + ngMeta.titleSuffix"></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="EvalAI is an open-source web platform for organizing and participating in challenges to push the state of the art on AI tasks.">
<meta name="description" ng-attr-content="{{ngMeta.tag_description}}" content="EvalAI is an open-source web platform for organizing and participating in challenges to push the state of the art on AI tasks.">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--Open Graph Related Stuff-->
<meta property="og:type" content="website" />
<meta property="og:title" content="EvalAI: Evaluating state of the art in AI" />
<meta property="og:url" content="https://eval.ai" />
<meta property="og:image" content="https://eval.ai/dist/images/evalai-cover.png" />
<meta property="og:title" ng-attr-content="{{ngMeta.title}}" content="EvalAI: Evaluating state of the art in AI" />
<meta property="og:url" ng-attr-content="{{ngMeta.tag_url}}" content="https://eval.ai" />
<meta property="og:image" ng-attr-content="{{ngMeta.tag_image}}" content="https://eval.ai/dist/images/evalai-cover.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:site_name" content="EvalAI" />
<meta property="og:description" content="EvalAI is an open-source web platform for organizing and participating in challenges to push the state of the art on AI tasks." />
<meta property="og:description" ng-attr-content="{{ngMeta.tag_description}}" content="EvalAI is an open-source web platform for organizing and participating in challenges to push the state of the art on AI tasks." />
<!--Twitter Card Stuff-->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" ng-attr-content="{{ngMeta.title}}" content="EvalAI: Evaluating state of the art in AI" />
<meta name="twitter:description" ng-attr-content="{{ngMeta.tag_description}}" content="EvalAI is an open-source web platform for organizing and participating in challenges to push the state of the art on AI tasks." />
<meta name="twitter:image" ng-attr-content="{{ngMeta.tag_image}}" content="https://eval.ai/dist/images/evalai-cover.png" />
<!-- Favicon -->
<link rel="shortcut icon" href="dist/images/favicon.ico" type="image/x-icon">
<link rel="icon" href="dist/images/favicon.ico" type="image/x-icon">
Expand Down
11 changes: 10 additions & 1 deletion frontend/src/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ angular
'angularTrix',
'angularMoment',
'ngclipboard',
'moment-picker'
'moment-picker',
'ngMeta'
])
.service('preventTemplateCache', [function() {
var service = this;
Expand All @@ -36,4 +37,12 @@ angular
}])
.config(['$compileProvider', function($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|file|tel|javascript):/);
}])
.config(['ngMetaProvider', function(ngMetaProvider) {
ngMetaProvider.useTitleSuffix(true);
ngMetaProvider.setDefaultTitle('EvalAI');
ngMetaProvider.setDefaultTitleSuffix(' | EvalAI');
ngMetaProvider.setDefaultTag('description', 'EvalAI is an open-source web platform for organizing and participating in challenges to push the state of the art on AI tasks.');
ngMetaProvider.setDefaultTag('image', 'https://eval.ai/dist/images/evalai-cover.png');
ngMetaProvider.setDefaultTag('url', 'https://eval.ai');
}]);
10 changes: 8 additions & 2 deletions frontend/src/js/controllers/challengeCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
.module('evalai')
.controller('ChallengeCtrl', ChallengeCtrl);

ChallengeCtrl.$inject = ['utilities', 'loaderService', '$scope', '$state', '$http', '$stateParams', '$rootScope', '$interval', '$mdDialog', 'moment', '$location', '$anchorScroll', '$timeout'];
ChallengeCtrl.$inject = ['utilities', 'loaderService', '$scope', '$state', '$http', '$stateParams', '$rootScope', '$interval', '$mdDialog', 'moment', '$location', '$anchorScroll', '$timeout', 'ngMeta'];

function ChallengeCtrl(utilities, loaderService, $scope, $state, $http, $stateParams, $rootScope, $interval, $mdDialog, moment, $location, $anchorScroll, $timeout) {
function ChallengeCtrl(utilities, loaderService, $scope, $state, $http, $stateParams, $rootScope, $interval, $mdDialog, moment, $location, $anchorScroll, $timeout, ngMeta) {
var vm = this;
vm.areSubmissionsFailing = false;
vm.getAllEntriesTestOption = "Include private submissions";
Expand Down Expand Up @@ -403,6 +403,12 @@

}

// Update Open Graph / Twitter meta tags for challenge sharing
ngMeta.setTitle(details.title);
ngMeta.setTag('description', details.short_description || details.description || '');
ngMeta.setTag('image', vm.page.image);
ngMeta.setTag('url', window.location.href);


// Get challenge prizes
vm.prizes = [];
Expand Down