From 702a4df4031a85c407d181c20e7eb91d5fdb7f8d Mon Sep 17 00:00:00 2001 From: Rinkit Adhana Date: Wed, 27 Aug 2025 05:45:52 +0530 Subject: [PATCH 01/17] change MIDDLEWARE from tuple to list for consistency --- blt/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blt/settings.py b/blt/settings.py index 7698bf802f..d642708163 100644 --- a/blt/settings.py +++ b/blt/settings.py @@ -110,7 +110,7 @@ SOCIAL_AUTH_GITHUB_SECRET = os.environ.get("GITHUB_CLIENT_SECRET", "blank") -MIDDLEWARE = ( +MIDDLEWARE = [ "django.contrib.sessions.middleware.SessionMiddleware", "blt.middleware.domain.DomainMiddleware", "django.middleware.locale.LocaleMiddleware", @@ -126,7 +126,7 @@ "tz_detect.middleware.TimezoneMiddleware", "blt.middleware.ip_restrict.IPRestrictMiddleware", "blt.middleware.user_visit_tracking.VisitTrackingMiddleware", -) +] if DEBUG: MIDDLEWARE += ["livereload.middleware.LiveReloadScript"] From 8f24c00e3e90d4bf8031d80f94f652cb0e885bfb Mon Sep 17 00:00:00 2001 From: Rinkit Adhana Date: Wed, 27 Aug 2025 06:10:46 +0530 Subject: [PATCH 02/17] manage domain small ui fix --- .../dashboard/organization_manage_domains.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/website/templates/organization/dashboard/organization_manage_domains.html b/website/templates/organization/dashboard/organization_manage_domains.html index da9c88bf8c..02d7c81e39 100644 --- a/website/templates/organization/dashboard/organization_manage_domains.html +++ b/website/templates/organization/dashboard/organization_manage_domains.html @@ -26,7 +26,7 @@

Manage Domains

Organize and control your domain portfolio

+ class="inline-flex items-center px-4 py-2.5 bg-[#e74c3c] text-white rounded-xl font-medium hover:bg-red-700 transition-all duration-200 select-none"> {{ domain.name|capfirst }} {% else %} -
+
From 2da239cdd720898affbe75bd3c17d01318550d2f Mon Sep 17 00:00:00 2001 From: Rinkit Adhana Date: Tue, 23 Sep 2025 05:53:59 +0530 Subject: [PATCH 03/17] esolve bug bounty form submission and JavaScript errors --- .../static/organization/js/hunt_controller.js | 909 +++++++++++------- .../organization/bughunt/add_bughunt.html | 42 +- 2 files changed, 572 insertions(+), 379 deletions(-) diff --git a/website/static/organization/js/hunt_controller.js b/website/static/organization/js/hunt_controller.js index a4f1f807c0..5396e91dbf 100644 --- a/website/static/organization/js/hunt_controller.js +++ b/website/static/organization/js/hunt_controller.js @@ -1,396 +1,563 @@ - - -let prize_array = []; -let list_prize_container = document.getElementById("list-prize-container"); - -function add_prize(){ - - let prize_name = document.getElementById("prize_name"); - let cash_value = document.getElementById("cash_value"); - let number_of_winning_projects = document.getElementById("number_of_winning_projects"); - let every_valid_submissions = document.getElementById("every_valid_submissions"); - let prize_description = document.getElementById("prize_description"); - let paid_in_cryptocurrency = document.getElementById("paid_in_cryptocurrency"); - - if (prize_name.value.trim() === "" || cash_value.value <= 0 || number_of_winning_projects.value <= 0){ - alert("Please fill in all fields correctly"); - return; - } - - let prize_data = { - id: prize_array.length, - prize_name: prize_name.value, - cash_value: cash_value.value, - number_of_winning_projects: number_of_winning_projects.value, - every_valid_submissions: every_valid_submissions.checked, - prize_description: prize_description.value, - paid_in_cryptocurrency: paid_in_cryptocurrency.checked - } +// Hunt Controller - Fixed Version with Better Error Handling +(function() { + 'use strict'; - - prize_array.push(prize_data) - alert("Prize added successfully"); + console.log('[Hunt Controller] Script loading...'); - prize_name.value = ""; - cash_value.value = 0; - number_of_winning_projects.value = 1; - if(number_of_winning_projects.disabled){ - number_of_winning_projects.disabled = false; - number_of_winning_projects.style.display = "block"; - } - every_valid_submissions.checked = false; - prize_description.value = ""; - paid_in_cryptocurrency.checked = false; - - const prize_container_child_html = document.createElement('div'); - const prize_name_sanitized = prize_data.prize_name.trim().substring(0, 8) + '...'; // Sanitize prize_name - let prize_description_sanitized = prize_data.prize_description.trim().substring(0, 55) + '...'; // Sanitize prize_description - let sanitizedNumberOfWinningProjects = Number(prize_data.number_of_winning_projects); // Sanitize number_of_winning_projects - - // if every_valid_submissions is checked, the number_of_winning_projects will be "all valid submissions" - if (prize_data.every_valid_submissions){ - sanitizedNumberOfWinningProjects = "All Valid Submissions"; + // Add escapeHTML function to prevent XSS attacks + function escapeHTML(str) { + const div = document.createElement('div'); + div.textContent = str; + return div.innerHTML; } - // if the description is empty, the prize_description will be "No Description" - if (prize_description_sanitized === "..."){ - prize_description_sanitized = "No Description"; - } - // Create a container for the prize -const prizeContainer = document.createElement('div'); -prizeContainer.id = `prize-container-${prize_data.id}`; -prizeContainer.classList.add("bg-white", "rounded-lg", "shadow-lg", "p-6", "w-72", "mr-5", "relative"); - -// Create the remove button -const removeBtn = document.createElement('button'); -removeBtn.classList.add("absolute", "top-2", "right-2", "text-red-500"); -removeBtn.textContent = "x"; -removeBtn.addEventListener('click', () => remove_prize(prize_data.id)); -prizeContainer.appendChild(removeBtn); - -// Create the prize name heading -const heading = document.createElement('h2'); -heading.classList.add("text-2xl", "font-bold", "mb-4", "text-gray-800"); -heading.textContent = escapeHTML(prize_name_sanitized); -prizeContainer.appendChild(heading); - -// Create Cash Value section -const cashDiv = document.createElement('div'); -cashDiv.classList.add("mb-4"); -const cashLabel = document.createElement('p'); -cashLabel.classList.add("text-red-500", "font-bold"); -cashLabel.textContent = "Cash Value (USD)"; -cashDiv.appendChild(cashLabel); -const cashValue = document.createElement('p'); -cashValue.classList.add("text-gray-800"); -cashValue.textContent = `$${prize_data.cash_value}`; -cashDiv.appendChild(cashValue); -prizeContainer.appendChild(cashDiv); - -// Create Number of Winning Projects section -const projectsDiv = document.createElement('div'); -projectsDiv.classList.add("mb-4"); -const projectsLabel = document.createElement('p'); -projectsLabel.classList.add("text-gray-800", "font-bold"); -projectsLabel.textContent = "Number of Winning Projects"; -projectsDiv.appendChild(projectsLabel); -const projectsValue = document.createElement('p'); -projectsValue.classList.add("text-gray-600"); -projectsValue.textContent = sanitizedNumberOfWinningProjects; -projectsDiv.appendChild(projectsValue); -prizeContainer.appendChild(projectsDiv); - -// Create Reward All Valid Submission section -const validDiv = document.createElement('div'); -validDiv.classList.add("mb-4"); -const validLabel = document.createElement('p'); -validLabel.classList.add("text-gray-800", "font-bold"); -validLabel.textContent = "Reward All Valid Submission"; -validDiv.appendChild(validLabel); -const validValue = document.createElement('p'); -validValue.classList.add("text-gray-600"); -validValue.textContent = prize_data.every_valid_submissions; -validDiv.appendChild(validValue); -prizeContainer.appendChild(validDiv); - -// Create Prize Description section -const descDiv = document.createElement('div'); -descDiv.classList.add("mb-4"); -const descLabel = document.createElement('p'); -descLabel.classList.add("text-red-500", "font-bold"); -descLabel.textContent = "Prize Description"; -descDiv.appendChild(descLabel); -const descValue = document.createElement('p'); -descValue.classList.add("text-gray-800"); -descValue.textContent = escapeHTML(prize_description_sanitized); -descDiv.appendChild(descValue); -prizeContainer.appendChild(descDiv); - -// Append the complete prize container to the list -list_prize_container.appendChild(prizeContainer); - -} - -function remove_prize(prize_id) { - let confirmDelete = confirm("Are you sure you want to delete this prize?"); - if (!confirmDelete) { - return; - } - prize_array = prize_array.filter(prize => prize.id !== prize_id); - let prize_container = document.getElementById(`prize-container-${prize_id}`); - if (prize_container && prize_container.parentNode) { - let grandParent = prize_container.parentNode; - if (grandParent.parentNode) { - grandParent.parentNode.removeChild(grandParent); + + // Global variables + let prize_array = []; + let list_prize_container = null; + + // Main functions + function add_prize() { + console.log('[add_prize] Function called'); + + try { + // Initialize list_prize_container if not already done + if (!list_prize_container) { + list_prize_container = document.getElementById("list-prize-container"); + if (!list_prize_container) { + console.error('[add_prize] Could not find list-prize-container element'); + alert('Error: Prize container not found. Please refresh the page.'); + return; + } + } + + // Get form elements + const elements = { + prize_name: document.getElementById("prize_name"), + cash_value: document.getElementById("cash_value"), + number_of_winning_projects: document.getElementById("number_of_winning_projects"), + every_valid_submissions: document.getElementById("every_valid_submissions"), + prize_description: document.getElementById("prize_description"), + paid_in_cryptocurrency: document.getElementById("paid_in_cryptocurrency") + }; + + // Check if all elements exist + for (const [key, element] of Object.entries(elements)) { + if (!element) { + console.error(`[add_prize] Could not find element: ${key}`); + alert(`Error: Form element '${key}' not found. Please refresh the page.`); + return; + } + } + + // Set default value for number_of_winning_projects if empty + if (!elements.number_of_winning_projects.value || elements.number_of_winning_projects.value === "") { + elements.number_of_winning_projects.value = 1; + } + + // Validate inputs + if (elements.prize_name.value.trim() === "") { + alert("Please enter a prize name"); + elements.prize_name.focus(); + return; + } + + if (elements.cash_value.value <= 0) { + alert("Please enter a valid cash value greater than 0"); + elements.cash_value.focus(); + return; + } + + if (elements.number_of_winning_projects.value <= 0) { + alert("Number of winning projects must be at least 1"); + elements.number_of_winning_projects.focus(); + return; + } + + // Create prize data object + const prize_data = { + id: prize_array.length, + prize_name: elements.prize_name.value, + cash_value: elements.cash_value.value, + number_of_winning_projects: elements.number_of_winning_projects.value, + every_valid_submissions: elements.every_valid_submissions.checked, + prize_description: elements.prize_description.value, + paid_in_cryptocurrency: elements.paid_in_cryptocurrency.checked + }; + + console.log('[add_prize] Prize data:', prize_data); + + // Add to array + prize_array.push(prize_data); + + // Create prize display element + createPrizeElement(prize_data); + + // Clear form + elements.prize_name.value = ""; + elements.cash_value.value = ""; + elements.number_of_winning_projects.value = 1; + elements.every_valid_submissions.checked = false; + elements.prize_description.value = ""; + elements.paid_in_cryptocurrency.checked = false; + + // Re-enable number_of_winning_projects if it was disabled + if (elements.number_of_winning_projects.disabled) { + elements.number_of_winning_projects.disabled = false; + elements.number_of_winning_projects.style.display = "block"; + } + + alert("Prize added successfully!"); + console.log('[add_prize] Prize added successfully. Total prizes:', prize_array.length); + + } catch (error) { + console.error('[add_prize] Error:', error); + alert('An error occurred while adding the prize. Please check the console for details.'); } } -} - -function cancelForm(){ - let confirmDelete = confirm("Are you sure you want to cancel, your progress would be lost."); - if (confirmDelete === true){ - window.history.back(); - } -} - -function PublishBughunt(is_published){ - const bughuntForm = document.getElementById("add_bughunt_form"); - - if (bughuntForm.checkValidity()){ - const prizeArrayInput = document.createElement('input'); - prizeArrayInput.type = 'text'; - prizeArrayInput.name = 'prizes'; - prizeArrayInput.value = JSON.stringify(prize_array); + function createPrizeElement(prize_data) { + const prize_name_sanitized = prize_data.prize_name.trim().substring(0, 8) + '...'; + let prize_description_sanitized = prize_data.prize_description.trim().substring(0, 55) + '...'; + let sanitizedNumberOfWinningProjects = Number(prize_data.number_of_winning_projects); + + if (prize_data.every_valid_submissions) { + sanitizedNumberOfWinningProjects = "All Valid Submissions"; + } - const publishHunt = document.createElement('input'); - publishHunt.type = "text"; - publishHunt.name = "publish_bughunt"; - publishHunt.value = is_published - - bughuntForm.appendChild(prizeArrayInput); - bughuntForm.appendChild(publishHunt); - - bughuntForm.submit(); + if (prize_description_sanitized === "...") { + prize_description_sanitized = "No Description"; + } + + // Create container + const prizeContainer = document.createElement('div'); + prizeContainer.id = `prize-container-${prize_data.id}`; + prizeContainer.classList.add("bg-white", "rounded-lg", "shadow-lg", "p-6", "w-72", "mr-5", "relative"); + + // Create remove button + const removeBtn = document.createElement('button'); + removeBtn.classList.add("absolute", "top-2", "right-2", "text-red-500", "hover:text-red-700", "font-bold", "text-xl"); + removeBtn.textContent = "×"; + removeBtn.onclick = function() { remove_prize(prize_data.id); }; + prizeContainer.appendChild(removeBtn); + + // Create content + const content = ` +

${escapeHTML(prize_name_sanitized)}

+
+

Cash Value (USD)

+

$${escapeHTML(prize_data.cash_value)}

+
+
+

Number of Winning Projects

+

${escapeHTML(String(sanitizedNumberOfWinningProjects))}

+
+
+

Reward All Valid Submission

+

${prize_data.every_valid_submissions ? 'Yes' : 'No'}

+
+
+

Prize Description

+

${escapeHTML(prize_description_sanitized)}

+
+ `; + + prizeContainer.innerHTML += content; + list_prize_container.appendChild(prizeContainer); } - - else{ - bughuntForm.reportValidity(); + + function remove_prize(prize_id) { + console.log('[remove_prize] Removing prize:', prize_id); + + if (!confirm("Are you sure you want to delete this prize?")) { + return; + } + + // Remove from array + prize_array = prize_array.filter(prize => prize.id !== prize_id); + + // Remove from DOM + const prize_container = document.getElementById(`prize-container-${prize_id}`); + if (prize_container) { + prize_container.remove(); + } + + console.log('[remove_prize] Prize removed. Remaining prizes:', prize_array.length); } - - -} - -function displayLogoPreview() { - var fileInput = document.getElementById("logo"); - var previewDiv = document.getElementById("previewLogoDiv"); - - if (fileInput.files.length > 0) { - var file = fileInput.files[0]; - var reader = new FileReader(); - - reader.onload = function(event) { - var preview = document.createElement("img"); - preview.src = event.target.result; - previewDiv.innerHTML = ""; - previewDiv.appendChild(preview); - }; - - reader.readAsDataURL(file); - } else { - previewDiv.innerHTML = ""; + function PublishBughunt(is_published) { + console.log('[PublishBughunt] Function called with is_published:', is_published); + + try { + const bughuntForm = document.getElementById("add_bughunt_form"); + if (!bughuntForm) { + console.error('[PublishBughunt] Form not found'); + alert('Error: Form not found. Please refresh the page.'); + return; + } + + // Check form validity + if (!bughuntForm.checkValidity()) { + bughuntForm.reportValidity(); + return; + } + + // Validate dates + const startDateInput = document.querySelector('input[name="start_date"]'); + const endDateInput = document.querySelector('input[name="end_date"]'); + + if (startDateInput && endDateInput) { + const startDate = startDateInput.value; + const endDate = endDateInput.value; + + if (startDate && endDate) { + const start = new Date(startDate); + const end = new Date(endDate); + + if (start >= end) { + alert("End date must be after start date!"); + endDateInput.focus(); + return; + } + } + } + + // Validate that at least one prize is added + if (prize_array.length === 0) { + alert("Please add at least one prize before publishing!"); + return; + } + + console.log('[PublishBughunt] Validation passed. Prizes to submit:', prize_array); + + // Create hidden inputs for form submission + const prizeArrayInput = document.createElement('input'); + prizeArrayInput.type = 'hidden'; + prizeArrayInput.name = 'prizes'; + prizeArrayInput.value = JSON.stringify(prize_array); + + const publishHunt = document.createElement('input'); + publishHunt.type = 'hidden'; + publishHunt.name = 'publish_bughunt'; + publishHunt.value = is_published; + + // Remove any existing hidden inputs with same names + const existingPrizes = bughuntForm.querySelector('input[name="prizes"]'); + const existingPublish = bughuntForm.querySelector('input[name="publish_bughunt"]'); + if (existingPrizes) existingPrizes.remove(); + if (existingPublish) existingPublish.remove(); + + // Add new hidden inputs + bughuntForm.appendChild(prizeArrayInput); + bughuntForm.appendChild(publishHunt); + + console.log('[PublishBughunt] Submitting form...'); + bughuntForm.submit(); + + } catch (error) { + console.error('[PublishBughunt] Error:', error); + alert('An error occurred while submitting the form. Please check the console for details.'); + } } -} - -let valid_s = document.getElementById("every_valid_submissions"); -let winning_projects = document.getElementById("number_of_winning_projects"); -valid_s.addEventListener('click',()=>{ - winning_projects.value = 1; - if (valid_s.checked) { - winning_projects.disabled = true; - winning_projects.style.display = "none"; - } else { - winning_projects.disabled = false; - winning_projects.style.display = "block"; + + function cancelForm() { + if (confirm("Are you sure you want to cancel? Your progress will be lost.")) { + window.history.back(); + } } -}) - -function displayBannerPreview() { - var fileInput = document.getElementById("banner"); - var previewDiv = document.getElementById("bannerPreview"); - - if (fileInput.files.length > 0) { - var file = fileInput.files[0]; - var reader = new FileReader(); - - reader.onload = function(event) { - var img = new Image(); - img.src = event.target.result; - - img.onload = function() { - var canvas = document.createElement("canvas"); - var ctx = canvas.getContext("2d"); - - var maxDim = 300; - var scale = Math.min(maxDim / img.width, maxDim / img.height); - - canvas.width = img.width * scale; - canvas.height = img.height * scale; - - ctx.drawImage(img, 0, 0, canvas.width, canvas.height); - + + function displayLogoPreview() { + const fileInput = document.getElementById("logo"); + const previewDiv = document.getElementById("previewLogoDiv"); + + if (!fileInput || !previewDiv) { + console.error('[displayLogoPreview] Required elements not found'); + return; + } + + if (fileInput.files.length > 0) { + const file = fileInput.files[0]; + const reader = new FileReader(); + + reader.onload = function(event) { + const preview = document.createElement("img"); + preview.src = event.target.result; + preview.style.width = "100%"; + preview.style.height = "100%"; + preview.style.objectFit = "cover"; previewDiv.innerHTML = ""; - previewDiv.style.display = "flex"; - previewDiv.style.justifyContent = "center"; - previewDiv.appendChild(canvas); + previewDiv.appendChild(preview); }; - }; - - reader.readAsDataURL(file); - } else { - previewDiv.innerHTML = ""; - } -} - -function removePrize(event, prizeId, organizationId) { - event.preventDefault(); - if (!confirm("Are you sure you want to delete this prize?")) { - return; + + reader.readAsDataURL(file); + } else { + previewDiv.innerHTML = ""; + } } - - // Show loading indicator (you can customize this as needed) - let prizeContainer = document.getElementById(`prize-container-${prizeId}`); - let loadingIndicator = document.createElement('div'); - loadingIndicator.innerText = "Loading..."; - prizeContainer.appendChild(loadingIndicator); - - // Make AJAX call to delete the prize with organization_id - fetch(`/organization/delete_prize/${prizeId}/${organizationId}`, { - method: 'DELETE', - headers: { - 'X-CSRFToken': getCookie('csrftoken') - }, - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - // Remove the prize from the DOM - prizeContainer.parentNode.removeChild(prizeContainer); - alert("Prize deleted successfully!"); + + function displayBannerPreview() { + const fileInput = document.getElementById("banner"); + const previewDiv = document.getElementById("bannerPreview"); + + if (!fileInput || !previewDiv) { + console.error('[displayBannerPreview] Required elements not found'); + return; + } + + if (fileInput.files.length > 0) { + const file = fileInput.files[0]; + const reader = new FileReader(); + + reader.onload = function(event) { + const img = new Image(); + img.src = event.target.result; + + img.onload = function() { + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); + + const maxDim = 300; + const scale = Math.min(maxDim / img.width, maxDim / img.height); + + canvas.width = img.width * scale; + canvas.height = img.height * scale; + + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + + previewDiv.innerHTML = ""; + previewDiv.style.display = "flex"; + previewDiv.style.justifyContent = "center"; + previewDiv.appendChild(canvas); + }; + }; + + reader.readAsDataURL(file); } else { - alert("Failed to delete prize. Please try again."); + previewDiv.innerHTML = ""; } - }) - .catch(error => { - console.error('Error:', error); - alert("An error occurred. Please try again."); - }); -} - -function editPrize(event, prizeId, prizeName, cashValue, noOfProjects, validSubmissions, description, organizationId) { - event.preventDefault(); // Prevent the form from submitting - alert("Edit the prize details in the form above and click the 'Update Prize' button to save changes."); - document.getElementById('prize_name').value = prizeName; - document.getElementById('cash_value').value = cashValue; - document.getElementById('number_of_winning_projects').value = noOfProjects; - // if every_valid_submissions is true then disable the number_of_winning_projects input field and also hide it - if (validSubmissions) { - document.getElementById('number_of_winning_projects').disabled = true; - document.getElementById('number_of_winning_projects').style.display = "none"; } - document.getElementById('prize_description').value = description; - document.getElementById('every_valid_submissions').checked = validSubmissions ? true : false; - document.getElementById('add_prize_button').innerText = 'Update Prize'; - document.getElementById('add_prize_button').setAttribute('onclick', `updatePrize(${prizeId}, ${organizationId})`); - // hive the cryptocurrencyDiv - document.getElementById('cryptocurrencyDiv').style.display = "none"; -} - -function updatePrize(prizeId, organizationId) { - let prize_name = document.getElementById("prize_name"); - let cash_value = document.getElementById("cash_value"); - let number_of_winning_projects = document.getElementById("number_of_winning_projects"); - let every_valid_submissions = document.getElementById("every_valid_submissions"); - let prize_description = document.getElementById("prize_description"); - - if (prize_name.value.trim() === "" || cash_value.value <= 0 || number_of_winning_projects.value <= 0){ - alert("Please fill in all fields correctly"); - return; + + function getCookie(name) { + let cookieValue = null; + if (document.cookie && document.cookie !== '') { + const cookies = document.cookie.split(';'); + for (let i = 0; i < cookies.length; i++) { + const cookie = cookies[i].trim(); + if (cookie.substring(0, name.length + 1) === (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; } - - let prize_data = { - id: prizeId, - prize_name: prize_name.value, - cash_value: cash_value.value, - number_of_winning_projects: number_of_winning_projects.value, - every_valid_submissions: every_valid_submissions.checked, - prize_description: prize_description.value, + + // Initialize event listeners when DOM is ready + function initializeEventListeners() { + console.log('[initializeEventListeners] Setting up event listeners...'); + + const valid_s = document.getElementById("every_valid_submissions"); + const winning_projects = document.getElementById("number_of_winning_projects"); + + if (valid_s && winning_projects) { + valid_s.addEventListener('click', function() { + winning_projects.value = 1; + if (valid_s.checked) { + winning_projects.disabled = true; + winning_projects.style.display = "none"; + } else { + winning_projects.disabled = false; + winning_projects.style.display = "block"; + } + }); + console.log('[initializeEventListeners] Checkbox listener added'); + } } - - // Make AJAX call to update the prize with organization_id - fetch(`/organization/edit_prize/${prizeId}/${organizationId}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': getCookie('csrftoken') - }, - body: JSON.stringify(prize_data) - }) - .then(response => response.json()) - .then(data => { - if (data.success) { - // Update the prize in the DOM - let prizeContainer = document.getElementById(`prize-container-${prizeId}`); - const paragraph = prizeContainer.querySelectorAll('p'); - prize_data.prize_name = prize_data.prize_name.trim().substring(0, 8) + '...'; - prizeContainer.querySelector('h2').innerText = prize_data.prize_name; - paragraph[1].innerText = `$${prize_data.cash_value}`; - if (prize_data.every_valid_submissions){ - prize_data.number_of_winning_projects = "All Valid Submissions"; + + // Additional functions for edit mode + function removePrize(event, prizeId, organizationId) { + event.preventDefault(); + if (!confirm("Are you sure you want to delete this prize?")) { + return; + } + + // Show loading indicator + let prizeContainer = document.getElementById(`prize-container-${prizeId}`); + let loadingIndicator = document.createElement('div'); + loadingIndicator.innerText = "Loading..."; + prizeContainer.appendChild(loadingIndicator); + + // Make AJAX call to delete the prize + fetch(`/organization/delete_prize/${prizeId}/${organizationId}`, { + method: 'DELETE', + headers: { + 'X-CSRFToken': getCookie('csrftoken') + }, + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); } - paragraph[3].innerText = prize_data.number_of_winning_projects; - paragraph[5].innerText = prize_data.every_valid_submissions; - // description slice to 55 characters - prize_data.prize_description = prize_data.prize_description.trim().substring(0, 55) + '...'; - paragraph[7].innerText = prize_data.prize_description; - // we should have to update the edit button to update the editPrize function attributes - prizeContainer.querySelector('#EditPrizeButton').setAttribute('onclick', `editPrize(event, ${prizeId}, '${prize_data.prize_name}', ${prize_data.cash_value}, ${prize_data.number_of_winning_projects}, ${prize_data.every_valid_submissions}, '${prize_data.prize_description}', ${organizationId})`); - // and then reset the form - prize_name.value = ""; - cash_value.value = 0; - number_of_winning_projects.value = 1; - if(number_of_winning_projects.disabled){ - number_of_winning_projects.disabled = false; - number_of_winning_projects.style.display = "block"; + return response.json(); + }) + .then(data => { + if (data.success) { + prizeContainer.parentNode.removeChild(prizeContainer); + alert("Prize deleted successfully!"); + } else { + alert(data.message || "Failed to delete prize. Please try again."); } - every_valid_submissions.checked = false; - prize_description.value = ""; - document.getElementById('add_prize_button').innerText = 'Add Prize'; - document.getElementById('add_prize_button').setAttribute('onclick', 'add_prize()'); - document.getElementById('cryptocurrencyDiv').style.display = "block"; - alert('Prize updated successfully'); - } else { - alert("Failed to update prize. Please try again."); - } - }) - .catch(error => { - console.error('Error:', error); - alert("An error occurred. Please try again."); - }); -} - -function getCookie(name) { - let cookieValue = null; - if (document.cookie && document.cookie !== '') { - const cookies = document.cookie.split(';'); - for (let i = 0; i < cookies.length; i++) { - const cookie = cookies[i].trim(); - // Does this cookie string begin with the name we want? - if (cookie.substring(0, name.length + 1) === (name + '=')) { - cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; + }) + .catch(error => { + console.error('Error:', error); + alert("Network error occurred while deleting the prize. Please check your connection and try again."); + }) + .finally(() => { + if (loadingIndicator && loadingIndicator.parentNode) { + loadingIndicator.remove(); } + }); + } + + function editPrize(event, prizeId, prizeName, cashValue, noOfProjects, validSubmissions, description, organizationId) { + event.preventDefault(); + alert("Edit the prize details in the form above and click the 'Update Prize' button to save changes."); + document.getElementById('prize_name').value = prizeName; + document.getElementById('cash_value').value = cashValue; + document.getElementById('number_of_winning_projects').value = noOfProjects; + + if (validSubmissions) { + document.getElementById('number_of_winning_projects').disabled = true; + document.getElementById('number_of_winning_projects').style.display = "none"; } + + document.getElementById('prize_description').value = description; + document.getElementById('every_valid_submissions').checked = validSubmissions ? true : false; + document.getElementById('add_prize_button').innerText = 'Update Prize'; + document.getElementById('add_prize_button').setAttribute('onclick', `updatePrize(${prizeId}, ${organizationId})`); + document.getElementById('cryptocurrencyDiv').style.display = "none"; + } + + function updatePrize(prizeId, organizationId) { + let prize_name = document.getElementById("prize_name"); + let cash_value = document.getElementById("cash_value"); + let number_of_winning_projects = document.getElementById("number_of_winning_projects"); + let every_valid_submissions = document.getElementById("every_valid_submissions"); + let prize_description = document.getElementById("prize_description"); + + // Set default value for number_of_winning_projects if empty + if (!number_of_winning_projects.value || number_of_winning_projects.value === "") { + number_of_winning_projects.value = 1; + } + + if (prize_name.value.trim() === "" || cash_value.value <= 0 || number_of_winning_projects.value <= 0) { + alert("Please fill in all fields correctly"); + return; + } + + let prize_data = { + id: prizeId, + prize_name: prize_name.value, + cash_value: cash_value.value, + number_of_winning_projects: number_of_winning_projects.value, + every_valid_submissions: every_valid_submissions.checked, + prize_description: prize_description.value, + }; + + // Show loading state + const updateButton = document.getElementById('add_prize_button'); + const originalText = updateButton.innerText; + updateButton.disabled = true; + updateButton.innerText = 'Updating...'; + + // Make AJAX call to update the prize + fetch(`/organization/edit_prize/${prizeId}/${organizationId}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': getCookie('csrftoken') + }, + body: JSON.stringify(prize_data) + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then(data => { + if (data.success) { + // Update the prize in the DOM + let prizeContainer = document.getElementById(`prize-container-${prizeId}`); + const paragraph = prizeContainer.querySelectorAll('p'); + prize_data.prize_name = prize_data.prize_name.trim().substring(0, 8) + '...'; + prizeContainer.querySelector('h2').innerText = prize_data.prize_name; + paragraph[1].innerText = `$${prize_data.cash_value}`; + + if (prize_data.every_valid_submissions) { + prize_data.number_of_winning_projects = "All Valid Submissions"; + } + + paragraph[3].innerText = prize_data.number_of_winning_projects; + paragraph[5].innerText = prize_data.every_valid_submissions; + prize_data.prize_description = prize_data.prize_description.trim().substring(0, 55) + '...'; + paragraph[7].innerText = prize_data.prize_description; + + // Reset the form + prize_name.value = ""; + cash_value.value = 0; + number_of_winning_projects.value = 1; + + if (number_of_winning_projects.disabled) { + number_of_winning_projects.disabled = false; + number_of_winning_projects.style.display = "block"; + } + + every_valid_submissions.checked = false; + prize_description.value = ""; + document.getElementById('add_prize_button').innerText = 'Add Prize'; + document.getElementById('add_prize_button').setAttribute('onclick', 'add_prize()'); + document.getElementById('cryptocurrencyDiv').style.display = "block"; + alert('Prize updated successfully'); + } else { + alert(data.message || "Failed to update prize. Please try again."); + } + }) + .catch(error => { + console.error('Error:', error); + alert("Network error occurred while updating the prize. Please check your connection and try again."); + }) + .finally(() => { + updateButton.disabled = false; + updateButton.innerText = originalText; + }); } - return cookieValue; -} \ No newline at end of file + + // Expose functions globally + window.add_prize = add_prize; + window.PublishBughunt = PublishBughunt; + window.cancelForm = cancelForm; + window.displayLogoPreview = displayLogoPreview; + window.displayBannerPreview = displayBannerPreview; + window.remove_prize = remove_prize; + window.removePrize = removePrize; + window.editPrize = editPrize; + window.updatePrize = updatePrize; + window.escapeHTML = escapeHTML; + window.prize_array = prize_array; + + // Initialize when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initializeEventListeners); + } else { + // DOM is already loaded + initializeEventListeners(); + } + + console.log('[Hunt Controller] Script loaded successfully'); + console.log('[Hunt Controller] Functions available:', { + add_prize: typeof window.add_prize, + PublishBughunt: typeof window.PublishBughunt, + cancelForm: typeof window.cancelForm + }); + +})(); \ No newline at end of file diff --git a/website/templates/organization/bughunt/add_bughunt.html b/website/templates/organization/bughunt/add_bughunt.html index d28250c142..5527ac27ef 100644 --- a/website/templates/organization/bughunt/add_bughunt.html +++ b/website/templates/organization/bughunt/add_bughunt.html @@ -21,7 +21,7 @@

Add Bug Bounty

@@ -67,9 +67,6 @@

Create new online Bu

-
@@ -216,7 +213,7 @@

id="prize_description" class="w-full mt-2 px-2 py-2 mb-2 border-[1px] border-gray-200 outline-none">

-
+

Check below if your prize is paid in cryptocurrency, and list the cash value of the cryptocurrenty and specify the crypto name in Hunt description eg: $100 USD in ETH @@ -231,6 +228,7 @@

@@ -242,7 +240,7 @@

-

{% endblock body %} -{% block js %} +{% block scripts %} + + + + + -{% endblock js %} + + +{% endblock scripts %} From c6485f24195484a9ac5702dd3f23115476eb90a0 Mon Sep 17 00:00:00 2001 From: Rinkit Adhana Date: Tue, 23 Sep 2025 06:42:55 +0530 Subject: [PATCH 04/17] improve the frontend of add bug hunt page similar to add domain page --- .../static/organization/js/hunt_controller.js | 2 + .../organization/bughunt/add_bughunt.html | 321 ++++++++++++++---- 2 files changed, 251 insertions(+), 72 deletions(-) diff --git a/website/static/organization/js/hunt_controller.js b/website/static/organization/js/hunt_controller.js index 5396e91dbf..cde933f4df 100644 --- a/website/static/organization/js/hunt_controller.js +++ b/website/static/organization/js/hunt_controller.js @@ -266,6 +266,8 @@ } function displayLogoPreview() { + // This function is kept for backward compatibility + // The new template uses previewUploadedImage function const fileInput = document.getElementById("logo"); const previewDiv = document.getElementById("previewLogoDiv"); diff --git a/website/templates/organization/bughunt/add_bughunt.html b/website/templates/organization/bughunt/add_bughunt.html index 5527ac27ef..bf8611eee8 100644 --- a/website/templates/organization/bughunt/add_bughunt.html +++ b/website/templates/organization/bughunt/add_bughunt.html @@ -16,18 +16,26 @@ Set up a Bug Bounty contest, add prizes, and upload logos and banners to start the competition. Specify timelines and contest details. {% endblock og_description %} {% block body %} -
-
-

Add Bug Bounty

-
-
+
+
+ +
+

Add Bug Bounty

+

+ Create a new bug bounty program to engage security researchers and strengthen your application security. +

+
+ + +
-

Create new online Bug Bounty

+

Bug Bounty Information

+

Provide details about your bug bounty program and set the timeline for researchers.

-
+
-
+ class="block text-sm font-medium leading-6 text-gray-900"> + Domain (Select the domain for this bug bounty) + +
-
- -
+
+ +
Create new online Bu
- to +
+
+
+ +
Create new online Bu
-
-
-
- - +
+
+

Bug Bounty Assets

+

Upload logo and banner images for your bug bounty program.

+ +
+ +
+
+ +
+ + +
+

Recommended: Square image, JPG/PNG/GIF, max 5MB, at least 128x128px

-
- -
+
+
+ + +
-
{% include "organization/organization_includes/md_editor.html" %}
-
-

Bug Bounty Prizes

-
-

- click on the add prize button after filling the prize details -

+
+
+

Bug Bounty Description

+

Provide a detailed description of your bug bounty program, scope, and rules.

+
+ {% include "organization/organization_includes/md_editor.html" %} +
+
+ +
+

Bug Bounty Prizes

+

Define the prizes and rewards for security researchers who find valid vulnerabilities.

+
+

+ Fill in the prize details below and click "Add Prize" to add it to your bug bounty program. +

+ id="list-prize-container">
-
+ +
+
+ class="text-md font-medium text-gray-600 hover:text-gray-900 transition-colors duration-200"> + Cancel +
- +
+ + + +
{% endblock body %} {% block scripts %} - - + + @@ -284,5 +355,111 @@

}); } }); + + // Image preview functions from add domain page + function previewUploadedImage(input, previewId, defaultIconId, removeButtonId) { + const preview = document.getElementById(previewId); + const defaultIcon = document.getElementById(defaultIconId); + const removeButton = document.getElementById(removeButtonId); + const errorDiv = document.getElementById('logoError'); + + // Clear any previous errors + if (errorDiv) { + errorDiv.style.display = 'none'; + errorDiv.textContent = ''; + } + + if (!preview || !defaultIcon || !removeButton) { + console.error('One or more required elements not found'); + return; + } + + if (input.files && input.files[0]) { + const file = input.files[0]; + + // Validate file type + const validTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp']; + if (!validTypes.includes(file.type)) { + if (errorDiv) { + errorDiv.textContent = 'Please select a valid image file (JPG, PNG, GIF, or WebP)'; + errorDiv.style.display = 'block'; + } + input.value = ''; + return; + } + + // Validate file size (5MB = 5 * 1024 * 1024 bytes) + const maxSize = 5 * 1024 * 1024; + if (file.size > maxSize) { + if (errorDiv) { + errorDiv.textContent = 'File size must be less than 5MB'; + errorDiv.style.display = 'block'; + } + input.value = ''; + return; + } + + const reader = new FileReader(); + + reader.onload = function(e) { + // Set the image source + preview.src = e.target.result; + + // Use style.display for more reliable showing/hiding + preview.style.display = 'block'; + defaultIcon.style.display = 'none'; + removeButton.style.display = 'inline-flex'; + + // Also use classList as backup + preview.classList.remove('hidden'); + defaultIcon.classList.add('hidden'); + removeButton.classList.remove('hidden'); + } + + reader.onerror = function() { + console.error('Error reading file'); + if (errorDiv) { + errorDiv.textContent = 'Error reading the file. Please try again.'; + errorDiv.style.display = 'block'; + } + input.value = ''; + } + + reader.readAsDataURL(file); + } + } + + function removeUploadedImage(inputId, previewId, defaultIconId, removeButtonId) { + const input = document.getElementById(inputId); + const preview = document.getElementById(previewId); + const defaultIcon = document.getElementById(defaultIconId); + const removeButton = document.getElementById(removeButtonId); + const errorDiv = document.getElementById('logoError'); + + if (!input || !preview || !defaultIcon || !removeButton) { + console.error('One or more required elements not found'); + return; + } + + // Clear the file input and preview + input.value = ''; + preview.src = ''; + + // Use style.display for more reliable showing/hiding + preview.style.display = 'none'; + defaultIcon.style.display = 'flex'; + removeButton.style.display = 'none'; + + // Also use classList as backup + preview.classList.add('hidden'); + defaultIcon.classList.remove('hidden'); + removeButton.classList.add('hidden'); + + // Clear any errors + if (errorDiv) { + errorDiv.style.display = 'none'; + errorDiv.textContent = ''; + } + } {% endblock scripts %} From 47008bbd0667b2a30ddb8a7fd12499d5936ba901 Mon Sep 17 00:00:00 2001 From: Rinkit Adhana Date: Tue, 23 Sep 2025 07:34:20 +0530 Subject: [PATCH 05/17] fix and improve add bug bounty page functionality --- .../static/organization/js/hunt_controller.js | 480 +++++++++--------- .../organization/bughunt/add_bughunt.html | 79 ++- 2 files changed, 285 insertions(+), 274 deletions(-) diff --git a/website/static/organization/js/hunt_controller.js b/website/static/organization/js/hunt_controller.js index cde933f4df..31386f514b 100644 --- a/website/static/organization/js/hunt_controller.js +++ b/website/static/organization/js/hunt_controller.js @@ -12,7 +12,7 @@ } // Global variables - let prize_array = []; +let prize_array = []; let list_prize_container = null; // Main functions @@ -70,18 +70,19 @@ if (elements.number_of_winning_projects.value <= 0) { alert("Number of winning projects must be at least 1"); elements.number_of_winning_projects.focus(); - return; - } - + return; + } + // Create prize data object const prize_data = { - id: prize_array.length, + id: prize_array.length, prize_name: elements.prize_name.value, cash_value: elements.cash_value.value, number_of_winning_projects: elements.number_of_winning_projects.value, every_valid_submissions: elements.every_valid_submissions.checked, prize_description: elements.prize_description.value, - paid_in_cryptocurrency: elements.paid_in_cryptocurrency.checked + paid_in_cryptocurrency: elements.paid_in_cryptocurrency.checked, + organization_id: window.organizationId || null }; console.log('[add_prize] Prize data:', prize_data); @@ -116,64 +117,124 @@ } function createPrizeElement(prize_data) { - const prize_name_sanitized = prize_data.prize_name.trim().substring(0, 8) + '...'; - let prize_description_sanitized = prize_data.prize_description.trim().substring(0, 55) + '...'; + const prize_name_sanitized = prize_data.prize_name.trim().length > 12 + ? prize_data.prize_name.trim().substring(0, 12) + '...' + : prize_data.prize_name.trim(); + let prize_description_sanitized = prize_data.prize_description.trim().length > 60 + ? prize_data.prize_description.trim().substring(0, 60) + '...' + : prize_data.prize_description.trim(); let sanitizedNumberOfWinningProjects = Number(prize_data.number_of_winning_projects); if (prize_data.every_valid_submissions) { - sanitizedNumberOfWinningProjects = "All Valid Submissions"; - } + sanitizedNumberOfWinningProjects = "All Valid Submissions"; + } - if (prize_description_sanitized === "...") { - prize_description_sanitized = "No Description"; + if (!prize_description_sanitized || prize_description_sanitized.trim() === "") { + prize_description_sanitized = "No description provided"; } // Create container - const prizeContainer = document.createElement('div'); - prizeContainer.id = `prize-container-${prize_data.id}`; - prizeContainer.classList.add("bg-white", "rounded-lg", "shadow-lg", "p-6", "w-72", "mr-5", "relative"); - - // Create remove button - const removeBtn = document.createElement('button'); - removeBtn.classList.add("absolute", "top-2", "right-2", "text-red-500", "hover:text-red-700", "font-bold", "text-xl"); - removeBtn.textContent = "×"; - removeBtn.onclick = function() { remove_prize(prize_data.id); }; - prizeContainer.appendChild(removeBtn); - - // Create content - const content = ` -

${escapeHTML(prize_name_sanitized)}

-
-

Cash Value (USD)

-

$${escapeHTML(prize_data.cash_value)}

-
-
-

Number of Winning Projects

-

${escapeHTML(String(sanitizedNumberOfWinningProjects))}

-
-
-

Reward All Valid Submission

-

${prize_data.every_valid_submissions ? 'Yes' : 'No'}

-
-
-

Prize Description

-

${escapeHTML(prize_description_sanitized)}

+const prizeContainer = document.createElement('div'); +prizeContainer.id = `prize-container-${prize_data.id}`; + prizeContainer.classList.add( + "bg-white", "border", "border-gray-200", "rounded-xl", "shadow-sm", + "hover:shadow-md", "transition-all", "duration-200", "p-6", "w-80", + "mr-4", "mb-4", "mt-6", "relative", "group" + ); + + // Create header with remove and edit buttons + const headerDiv = document.createElement('div'); + headerDiv.classList.add("flex", "justify-between", "items-start", "mb-4"); + + const titleDiv = document.createElement('div'); + titleDiv.classList.add("flex-1", "pr-2"); + titleDiv.innerHTML = ` +

${escapeHTML(prize_name_sanitized)}

+
+ + + $${escapeHTML(prize_data.cash_value)} + + ${prize_data.every_valid_submissions ? + 'All Valid' : + `${sanitizedNumberOfWinningProjects} Winners` + }
`; - prizeContainer.innerHTML += content; - list_prize_container.appendChild(prizeContainer); - } - - function remove_prize(prize_id) { + const actionDiv = document.createElement('div'); + actionDiv.classList.add("flex", "gap-1", "opacity-0", "group-hover:opacity-100", "transition-opacity", "duration-200"); + + // Edit button + const editBtn = document.createElement('button'); + editBtn.classList.add( + "p-1.5", "text-gray-400", "hover:text-[#e74c3c]", "hover:bg-red-50", + "rounded-md", "transition-all", "duration-150", "text-sm" + ); + editBtn.innerHTML = ''; + editBtn.title = "Edit Prize"; + editBtn.onclick = function() { + editPrize(event, prize_data.id, prize_data.prize_name, prize_data.cash_value, + prize_data.number_of_winning_projects, prize_data.every_valid_submissions, + prize_data.prize_description, prize_data.organization_id); + }; + + // Remove button +const removeBtn = document.createElement('button'); + removeBtn.classList.add( + "p-1.5", "text-gray-400", "hover:text-red-600", "hover:bg-red-50", + "rounded-md", "transition-all", "duration-150", "text-sm" + ); + removeBtn.innerHTML = ''; + removeBtn.title = "Delete Prize"; + removeBtn.onclick = function() { + if(confirm('Are you sure you want to delete this prize?')) { + remove_prize(prize_data.id); + } + }; + + actionDiv.appendChild(editBtn); + actionDiv.appendChild(removeBtn); + headerDiv.appendChild(titleDiv); + headerDiv.appendChild(actionDiv); + prizeContainer.appendChild(headerDiv); + + // Create content body + const bodyDiv = document.createElement('div'); + bodyDiv.classList.add("space-y-3"); + + // Description section + const descDiv = document.createElement('div'); + descDiv.classList.add("text-sm", "text-gray-600", "bg-gray-50", "p-3", "rounded-lg", "border-l-4", "border-[#e74c3c]"); + descDiv.innerHTML = ` +

Description

+

${escapeHTML(prize_description_sanitized)}

+ `; + + bodyDiv.appendChild(descDiv); + prizeContainer.appendChild(bodyDiv); + + // Add subtle border animation on hover + prizeContainer.addEventListener('mouseenter', function() { + this.style.borderColor = '#e74c3c'; + }); + + prizeContainer.addEventListener('mouseleave', function() { + this.style.borderColor = '#e5e7eb'; + }); + +list_prize_container.appendChild(prizeContainer); +} + +function remove_prize(prize_id) { console.log('[remove_prize] Removing prize:', prize_id); if (!confirm("Are you sure you want to delete this prize?")) { - return; - } + return; + } // Remove from array - prize_array = prize_array.filter(prize => prize.id !== prize_id); + prize_array = prize_array.filter(prize => prize.id !== prize_id); // Remove from DOM const prize_container = document.getElementById(`prize-container-${prize_id}`); @@ -201,26 +262,6 @@ return; } - // Validate dates - const startDateInput = document.querySelector('input[name="start_date"]'); - const endDateInput = document.querySelector('input[name="end_date"]'); - - if (startDateInput && endDateInput) { - const startDate = startDateInput.value; - const endDate = endDateInput.value; - - if (startDate && endDate) { - const start = new Date(startDate); - const end = new Date(endDate); - - if (start >= end) { - alert("End date must be after start date!"); - endDateInput.focus(); - return; - } - } - } - // Validate that at least one prize is added if (prize_array.length === 0) { alert("Please add at least one prize before publishing!"); @@ -229,13 +270,22 @@ console.log('[PublishBughunt] Validation passed. Prizes to submit:', prize_array); + // Check if CSRF token exists + const csrfToken = bughuntForm.querySelector('input[name="csrfmiddlewaretoken"]'); + if (!csrfToken) { + console.error('[PublishBughunt] CSRF token not found in form'); + alert('CSRF token missing. Please refresh the page and try again.'); + return; + } + console.log('[PublishBughunt] CSRF token found:', csrfToken.value.substring(0, 10) + '...'); + // Create hidden inputs for form submission - const prizeArrayInput = document.createElement('input'); + const prizeArrayInput = document.createElement('input'); prizeArrayInput.type = 'hidden'; - prizeArrayInput.name = 'prizes'; - prizeArrayInput.value = JSON.stringify(prize_array); - - const publishHunt = document.createElement('input'); + prizeArrayInput.name = 'prizes'; + prizeArrayInput.value = JSON.stringify(prize_array); + + const publishHunt = document.createElement('input'); publishHunt.type = 'hidden'; publishHunt.name = 'publish_bughunt'; publishHunt.value = is_published; @@ -247,11 +297,14 @@ if (existingPublish) existingPublish.remove(); // Add new hidden inputs - bughuntForm.appendChild(prizeArrayInput); - bughuntForm.appendChild(publishHunt); - + bughuntForm.appendChild(prizeArrayInput); + bughuntForm.appendChild(publishHunt); + + console.log('[PublishBughunt] Form elements:', bughuntForm.elements.length); + console.log('[PublishBughunt] Form action:', bughuntForm.action); + console.log('[PublishBughunt] Form method:', bughuntForm.method); console.log('[PublishBughunt] Submitting form...'); - bughuntForm.submit(); + bughuntForm.submit(); } catch (error) { console.error('[PublishBughunt] Error:', error); @@ -275,27 +328,27 @@ console.error('[displayLogoPreview] Required elements not found'); return; } - - if (fileInput.files.length > 0) { + + if (fileInput.files.length > 0) { const file = fileInput.files[0]; const reader = new FileReader(); - - reader.onload = function(event) { + + reader.onload = function(event) { const preview = document.createElement("img"); - preview.src = event.target.result; + preview.src = event.target.result; preview.style.width = "100%"; preview.style.height = "100%"; preview.style.objectFit = "cover"; - previewDiv.innerHTML = ""; - previewDiv.appendChild(preview); - }; - - reader.readAsDataURL(file); - } else { - previewDiv.innerHTML = ""; - } + previewDiv.innerHTML = ""; + previewDiv.appendChild(preview); + }; + + reader.readAsDataURL(file); + } else { + previewDiv.innerHTML = ""; } - +} + function displayBannerPreview() { const fileInput = document.getElementById("banner"); const previewDiv = document.getElementById("bannerPreview"); @@ -304,40 +357,40 @@ console.error('[displayBannerPreview] Required elements not found'); return; } - - if (fileInput.files.length > 0) { + + if (fileInput.files.length > 0) { const file = fileInput.files[0]; const reader = new FileReader(); - - reader.onload = function(event) { + + reader.onload = function(event) { const img = new Image(); - img.src = event.target.result; - - img.onload = function() { + img.src = event.target.result; + + img.onload = function() { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); - + const maxDim = 300; const scale = Math.min(maxDim / img.width, maxDim / img.height); - - canvas.width = img.width * scale; - canvas.height = img.height * scale; - - ctx.drawImage(img, 0, 0, canvas.width, canvas.height); - - previewDiv.innerHTML = ""; - previewDiv.style.display = "flex"; - previewDiv.style.justifyContent = "center"; - previewDiv.appendChild(canvas); - }; + + canvas.width = img.width * scale; + canvas.height = img.height * scale; + + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + + previewDiv.innerHTML = ""; + previewDiv.style.display = "flex"; + previewDiv.style.justifyContent = "center"; + previewDiv.appendChild(canvas); }; - - reader.readAsDataURL(file); - } else { - previewDiv.innerHTML = ""; - } + }; + + reader.readAsDataURL(file); + } else { + previewDiv.innerHTML = ""; } - +} + function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { @@ -376,69 +429,69 @@ } // Additional functions for edit mode - function removePrize(event, prizeId, organizationId) { - event.preventDefault(); - if (!confirm("Are you sure you want to delete this prize?")) { - return; - } - +function removePrize(event, prizeId, organizationId) { + event.preventDefault(); + if (!confirm("Are you sure you want to delete this prize?")) { + return; + } + // Show loading indicator - let prizeContainer = document.getElementById(`prize-container-${prizeId}`); - let loadingIndicator = document.createElement('div'); - loadingIndicator.innerText = "Loading..."; - prizeContainer.appendChild(loadingIndicator); - + let prizeContainer = document.getElementById(`prize-container-${prizeId}`); + let loadingIndicator = document.createElement('div'); + loadingIndicator.innerText = "Loading..."; + prizeContainer.appendChild(loadingIndicator); + // Make AJAX call to delete the prize - fetch(`/organization/delete_prize/${prizeId}/${organizationId}`, { - method: 'DELETE', - headers: { - 'X-CSRFToken': getCookie('csrftoken') - }, - }) + fetch(`/organization/delete_prize/${prizeId}/${organizationId}`, { + method: 'DELETE', + headers: { + 'X-CSRFToken': getCookie('csrftoken') + }, + }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) - .then(data => { - if (data.success) { - prizeContainer.parentNode.removeChild(prizeContainer); - alert("Prize deleted successfully!"); - } else { + .then(data => { + if (data.success) { + prizeContainer.parentNode.removeChild(prizeContainer); + alert("Prize deleted successfully!"); + } else { alert(data.message || "Failed to delete prize. Please try again."); - } - }) - .catch(error => { - console.error('Error:', error); + } + }) + .catch(error => { + console.error('Error:', error); alert("Network error occurred while deleting the prize. Please check your connection and try again."); }) .finally(() => { if (loadingIndicator && loadingIndicator.parentNode) { loadingIndicator.remove(); } - }); - } - - function editPrize(event, prizeId, prizeName, cashValue, noOfProjects, validSubmissions, description, organizationId) { + }); +} + +function editPrize(event, prizeId, prizeName, cashValue, noOfProjects, validSubmissions, description, organizationId) { event.preventDefault(); - alert("Edit the prize details in the form above and click the 'Update Prize' button to save changes."); - document.getElementById('prize_name').value = prizeName; - document.getElementById('cash_value').value = cashValue; - document.getElementById('number_of_winning_projects').value = noOfProjects; - - if (validSubmissions) { - document.getElementById('number_of_winning_projects').disabled = true; - document.getElementById('number_of_winning_projects').style.display = "none"; - } + alert("Edit the prize details in the form above and click the 'Update Prize' button to save changes."); + document.getElementById('prize_name').value = prizeName; + document.getElementById('cash_value').value = cashValue; + document.getElementById('number_of_winning_projects').value = noOfProjects; - document.getElementById('prize_description').value = description; - document.getElementById('every_valid_submissions').checked = validSubmissions ? true : false; - document.getElementById('add_prize_button').innerText = 'Update Prize'; - document.getElementById('add_prize_button').setAttribute('onclick', `updatePrize(${prizeId}, ${organizationId})`); - document.getElementById('cryptocurrencyDiv').style.display = "none"; + if (validSubmissions) { + document.getElementById('number_of_winning_projects').disabled = true; + document.getElementById('number_of_winning_projects').style.display = "none"; } - + + document.getElementById('prize_description').value = description; + document.getElementById('every_valid_submissions').checked = validSubmissions ? true : false; + document.getElementById('add_prize_button').innerText = 'Update Prize'; + document.getElementById('add_prize_button').setAttribute('onclick', `updatePrize(${prizeId}, ${organizationId})`); + document.getElementById('cryptocurrencyDiv').style.display = "none"; +} + function updatePrize(prizeId, organizationId) { let prize_name = document.getElementById("prize_name"); let cash_value = document.getElementById("cash_value"); @@ -463,75 +516,44 @@ number_of_winning_projects: number_of_winning_projects.value, every_valid_submissions: every_valid_submissions.checked, prize_description: prize_description.value, + organization_id: organizationId }; - // Show loading state - const updateButton = document.getElementById('add_prize_button'); - const originalText = updateButton.innerText; - updateButton.disabled = true; - updateButton.innerText = 'Updating...'; - - // Make AJAX call to update the prize - fetch(`/organization/edit_prize/${prizeId}/${organizationId}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': getCookie('csrftoken') - }, - body: JSON.stringify(prize_data) - }) - .then(response => { - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - return response.json(); - }) - .then(data => { - if (data.success) { - // Update the prize in the DOM - let prizeContainer = document.getElementById(`prize-container-${prizeId}`); - const paragraph = prizeContainer.querySelectorAll('p'); - prize_data.prize_name = prize_data.prize_name.trim().substring(0, 8) + '...'; - prizeContainer.querySelector('h2').innerText = prize_data.prize_name; - paragraph[1].innerText = `$${prize_data.cash_value}`; - - if (prize_data.every_valid_submissions) { - prize_data.number_of_winning_projects = "All Valid Submissions"; - } - - paragraph[3].innerText = prize_data.number_of_winning_projects; - paragraph[5].innerText = prize_data.every_valid_submissions; - prize_data.prize_description = prize_data.prize_description.trim().substring(0, 55) + '...'; - paragraph[7].innerText = prize_data.prize_description; - - // Reset the form - prize_name.value = ""; - cash_value.value = 0; - number_of_winning_projects.value = 1; - - if (number_of_winning_projects.disabled) { - number_of_winning_projects.disabled = false; - number_of_winning_projects.style.display = "block"; - } - - every_valid_submissions.checked = false; - prize_description.value = ""; - document.getElementById('add_prize_button').innerText = 'Add Prize'; - document.getElementById('add_prize_button').setAttribute('onclick', 'add_prize()'); - document.getElementById('cryptocurrencyDiv').style.display = "block"; - alert('Prize updated successfully'); - } else { - alert(data.message || "Failed to update prize. Please try again."); - } - }) - .catch(error => { - console.error('Error:', error); - alert("Network error occurred while updating the prize. Please check your connection and try again."); - }) - .finally(() => { - updateButton.disabled = false; - updateButton.innerText = originalText; - }); + console.log('[updatePrize] Updating prize:', prize_data); + + // Update the prize in the prize_array (client-side only for new bounties) + const prizeIndex = prize_array.findIndex(p => p.id == prizeId); + if (prizeIndex !== -1) { + prize_array[prizeIndex] = prize_data; + console.log('[updatePrize] Updated prize_array:', prize_array); + } + + // Remove the old prize element and create a new one with updated data + const oldPrizeContainer = document.getElementById(`prize-container-${prizeId}`); + if (oldPrizeContainer) { + oldPrizeContainer.remove(); + } + + // Create updated prize element + createPrizeElement(prize_data); + + // Reset the form completely + prize_name.value = ""; + cash_value.value = ""; + number_of_winning_projects.value = "1"; + every_valid_submissions.checked = false; + prize_description.value = ""; + + // Reset the "Add Prize" button + const addPrizeButton = document.getElementById('add_prize_button'); + addPrizeButton.innerText = 'Add Prize'; + addPrizeButton.setAttribute('onclick', 'add_prize()'); + addPrizeButton.disabled = false; + + // Show success message + alert('Prize updated successfully!'); + + console.log('[updatePrize] Prize updated successfully'); } // Expose functions globally diff --git a/website/templates/organization/bughunt/add_bughunt.html b/website/templates/organization/bughunt/add_bughunt.html index bf8611eee8..34936b3d8d 100644 --- a/website/templates/organization/bughunt/add_bughunt.html +++ b/website/templates/organization/bughunt/add_bughunt.html @@ -24,13 +24,13 @@

Add Bug Bounty

Create a new bug bounty program to engage security researchers and strengthen your application security.

-
+

-
{% csrf_token %}
@@ -94,10 +94,11 @@

Bug Bounty Information

+ placeholder="MM/DD/YYYY">
@@ -112,20 +113,20 @@

Bug Bounty Information

xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"> - +
+ placeholder="MM/DD/YYYY">
-
-
+

Bug Bounty Assets

Upload logo and banner images for your bug bounty program.

@@ -135,7 +136,7 @@

Bug Bounty Assets

Bug Bounty Assets
-
@@ -317,44 +318,32 @@

Bug Bounty Prizes

- +
{% endblock body %} {% block scripts %} - - - + - + -
- -
+
+ +
Create new online Bu
- + {% if hunt.is_published %}disabled{% endif %} + class="block w-full rounded-md border-0 py-1.5 pl-10 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-[#e74c3c] sm:text-sm sm:leading-6" + placeholder="MM/DD/YYYY">
- to +
+
+
+ +
Create new online Bu
+ class="block w-full rounded-md border-0 py-1.5 pl-10 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-[#e74c3c] sm:text-sm sm:leading-6" + placeholder="MM/DD/YYYY">
-
-
- -