Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
114 changes: 114 additions & 0 deletions project_channels.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
slack_channel,slack_id,slack_url
project-zap,C04SX2GAS,https://OWASP.slack.com/archives/C04SX2GAS
project-xenotix,C04T4HY7U,https://OWASP.slack.com/archives/C04T4HY7U
project-railsgoat,C04THC44W,https://OWASP.slack.com/archives/C04THC44W
project-o2,C04TJNC8M,https://OWASP.slack.com/archives/C04TJNC8M
project-nodegoat,C04TQK9UF,https://OWASP.slack.com/archives/C04TQK9UF
project-hackademic,C050BRC9M,https://OWASP.slack.com/archives/C050BRC9M
project-scg,C050V7CNL,https://OWASP.slack.com/archives/C050V7CNL
project-sec-shepherd,C051M1G3A,https://OWASP.slack.com/archives/C051M1G3A
project-dotnet,C053H58SK,https://OWASP.slack.com/archives/C053H58SK
project-zap-notify,C061VMC87,https://OWASP.slack.com/archives/C061VMC87
project-asvs,C06MNF14M,https://OWASP.slack.com/archives/C06MNF14M
project-webgoat,C0948GVLM,https://OWASP.slack.com/archives/C0948GVLM
project-webgoat-notif,C09H06VFA,https://OWASP.slack.com/archives/C09H06VFA
project-zsc,C09HKQ0D7,https://OWASP.slack.com/archives/C09HKQ0D7
project-devops,C09MLAY8P,https://OWASP.slack.com/archives/C09MLAY8P
project-wafec,C0BBA9FM0,https://OWASP.slack.com/archives/C0BBA9FM0
project-hacakdemic,C0BR2NMUG,https://OWASP.slack.com/archives/C0BR2NMUG
project-skf,C0F7L9X6V,https://OWASP.slack.com/archives/C0F7L9X6V
project-csrfguard,C0H1KR347,https://OWASP.slack.com/archives/C0H1KR347
project-glue,C0HVCFDP0,https://OWASP.slack.com/archives/C0HVCFDP0
project-appsensor,C0KJ7JMCJ,https://OWASP.slack.com/archives/C0KJ7JMCJ
project-samm,C0VF1EJGH,https://OWASP.slack.com/archives/C0VF1EJGH
project-virtualvillag,C18A8EGKH,https://OWASP.slack.com/archives/C18A8EGKH
project-mobile-app-security,C1M6ZVC6S,https://OWASP.slack.com/archives/C1M6ZVC6S
project-vicnum,C1MAN1B08,https://OWASP.slack.com/archives/C1MAN1B08
project-top-10,C1QBMGU69,https://OWASP.slack.com/archives/C1QBMGU69
project-embeddedappsec,C1TJMUNG3,https://OWASP.slack.com/archives/C1TJMUNG3
project-juiceshop,C255XSY04,https://OWASP.slack.com/archives/C255XSY04
project-igoat,C2BKNP7DZ,https://OWASP.slack.com/archives/C2BKNP7DZ
project-blt,C2FF0UVHU,https://OWASP.slack.com/archives/C2FF0UVHU
project-olg-github,C3F2F9TMY,https://OWASP.slack.com/archives/C3F2F9TMY
project-riskrating,C56GPPD6Z,https://OWASP.slack.com/archives/C56GPPD6Z
project-riskrating_mp,C56GQ0ZHT,https://OWASP.slack.com/archives/C56GQ0ZHT
project-owtf,C5M114999,https://OWASP.slack.com/archives/C5M114999
project-blt-github,C5QAK3Q9G,https://OWASP.slack.com/archives/C5QAK3Q9G
project-securityrat,C76U4TNFJ,https://OWASP.slack.com/archives/C76U4TNFJ
project-malware,C9G489878,https://OWASP.slack.com/archives/C9G489878
project-securetea,C9GAF53NK,https://OWASP.slack.com/archives/C9GAF53NK
project-devslop,CA1PNFZSR,https://OWASP.slack.com/archives/CA1PNFZSR
project-mobile-app-security-dev,CCBAP0CGN,https://OWASP.slack.com/archives/CCBAP0CGN
project-sls-top-10,CD9D8J41E,https://OWASP.slack.com/archives/CD9D8J41E
project-scvs,CGH5X9NQ0,https://OWASP.slack.com/archives/CGH5X9NQ0
project-packman,CHKT6HKTK,https://OWASP.slack.com/archives/CHKT6HKTK
project-security-bot,CLMA4F01J,https://OWASP.slack.com/archives/CLMA4F01J
project-mobile_tm,CLW9F9F0X,https://OWASP.slack.com/archives/CLW9F9F0X
project-integration,CPMEWT342,https://OWASP.slack.com/archives/CPMEWT342
project-nettacker,CQZGG24FQ,https://OWASP.slack.com/archives/CQZGG24FQ
project-threat-dragon,CURE8PQ68,https://OWASP.slack.com/archives/CURE8PQ68
project-pygoat,C013HSLMTFE,https://OWASP.slack.com/archives/C013HSLMTFE
project-blt-gsoc-rehndndup,C0145BH2P70,https://OWASP.slack.com/archives/C0145BH2P70
project-samuraiwtf,C01524KH43G,https://OWASP.slack.com/archives/C01524KH43G
project-isvs,C01600RMP9P,https://OWASP.slack.com/archives/C01600RMP9P
project-off,C016U8XQ95H,https://OWASP.slack.com/archives/C016U8XQ95H
project-curriculum,C017AC06QV7,https://OWASP.slack.com/archives/C017AC06QV7
project-sponsorship,C018P1JUPUH,https://OWASP.slack.com/archives/C018P1JUPUH
project-committee,C01930CGW23,https://OWASP.slack.com/archives/C01930CGW23
project-how-to-get-into-appsec,C01KF26B1UH,https://OWASP.slack.com/archives/C01KF26B1UH
project-purpleteam,C01LARX6WP8,https://OWASP.slack.com/archives/C01LARX6WP8
project-html-sanitizer,C0250DKTFCP,https://OWASP.slack.com/archives/C0250DKTFCP
project-developeroutreach,C02CXL4USFM,https://OWASP.slack.com/archives/C02CXL4USFM
project-cre,C02EAS3MY84,https://OWASP.slack.com/archives/C02EAS3MY84
project-snow,C02EX68P1UJ,https://OWASP.slack.com/archives/C02EX68P1UJ
project-wrongsecrets,C02KQ7D9XHR,https://OWASP.slack.com/archives/C02KQ7D9XHR
project-pytm,C02KRQ0CATB,https://OWASP.slack.com/archives/C02KRQ0CATB
project-secure-code-review-guide,C02QDREE0M7,https://OWASP.slack.com/archives/C02QDREE0M7
project-podcast,C02U3MTA13K,https://OWASP.slack.com/archives/C02U3MTA13K
project-iot-top10,C034JK2BFGW,https://OWASP.slack.com/archives/C034JK2BFGW
project-wrongsecrets-dev,C039L78LSER,https://OWASP.slack.com/archives/C039L78LSER
project-wrongsecrets-callback,C03BCJ1BXNK,https://OWASP.slack.com/archives/C03BCJ1BXNK
project-security-culture,C03CHLJ1YLR,https://OWASP.slack.com/archives/C03CHLJ1YLR
project-k8s-top10,C03FV6MSRCM,https://OWASP.slack.com/archives/C03FV6MSRCM
project-safetypes,C0432Q430Q3,https://OWASP.slack.com/archives/C0432Q430Q3
project-continuous-penetration-testing-framework,C0484CAPBE0,https://OWASP.slack.com/archives/C0484CAPBE0
project-domain-protect,C04BPJ5B2P4,https://OWASP.slack.com/archives/C04BPJ5B2P4
project-secure-coding-practices,C04DZ254HFG,https://OWASP.slack.com/archives/C04DZ254HFG
project-go-scp,C04FG14MN5B,https://OWASP.slack.com/archives/C04FG14MN5B
project-ai-community,C04FV0D1GES,https://OWASP.slack.com/archives/C04FV0D1GES
project-devsecops-verification-standard,C04HD8ES72M,https://OWASP.slack.com/archives/C04HD8ES72M
project-mlsec-top-10,C04PESBUWRZ,https://OWASP.slack.com/archives/C04PESBUWRZ
project-developer-guide,C04QN6CMNAC,https://OWASP.slack.com/archives/C04QN6CMNAC
project-vulnerability-maturity-sig,C04QWA7R3C7,https://OWASP.slack.com/archives/C04QWA7R3C7
project-blt-flutter-github,C04SCC5Q3RT,https://OWASP.slack.com/archives/C04SCC5Q3RT
project-committee-github,C0506NPJ2EM,https://OWASP.slack.com/archives/C0506NPJ2EM
project-asvs-nuclei,C052939BZ43,https://OWASP.slack.com/archives/C052939BZ43
project-blt-codemagic,C052AAELH3P,https://OWASP.slack.com/archives/C052AAELH3P
project-new-projects,C052TF4AA84,https://OWASP.slack.com/archives/C052TF4AA84
project-raider,C053YNZNEFP,https://OWASP.slack.com/archives/C053YNZNEFP
project-api-top10,C0558AF1QQM,https://OWASP.slack.com/archives/C0558AF1QQM
project-top10-for-llm,C05956H7R8R,https://OWASP.slack.com/archives/C05956H7R8R
project-osib,C05DPB4M1Q8,https://OWASP.slack.com/archives/C05DPB4M1Q8
project-blt-prs,C05FBSPALLS,https://OWASP.slack.com/archives/C05FBSPALLS
project-nightingale,C05JPRM5GP8,https://OWASP.slack.com/archives/C05JPRM5GP8
project-sweeper,C0607RP8MS8,https://OWASP.slack.com/archives/C0607RP8MS8
project-securecodebox,C062TQANH3N,https://OWASP.slack.com/archives/C062TQANH3N
project-modsecurity,C069PCXSW12,https://OWASP.slack.com/archives/C069PCXSW12
project-blockchain-appsec-standard,C06A53BF0QY,https://OWASP.slack.com/archives/C06A53BF0QY
project-security-c4po,C06ECA5U8SY,https://OWASP.slack.com/archives/C06ECA5U8SY
project-common-lifecycle-enumeration,C06GUKY03NC,https://OWASP.slack.com/archives/C06GUKY03NC
project-pscf,C06HQQF04CU,https://OWASP.slack.com/archives/C06HQQF04CU
project-sdrf,C06J07ZG7DE,https://OWASP.slack.com/archives/C06J07ZG7DE
project-llmvs,C06MDJG0KBK,https://OWASP.slack.com/archives/C06MDJG0KBK
project-blt-lettuce,C06R1H90JKV,https://OWASP.slack.com/archives/C06R1H90JKV
project-blt-lettuce-deploys,C06RBJ779CH,https://OWASP.slack.com/archives/C06RBJ779CH
project-blt-bacon,C06RNAENB4P,https://OWASP.slack.com/archives/C06RNAENB4P
project-flop-10,C072N37N82Z,https://OWASP.slack.com/archives/C072N37N82Z
project-ai-masteraisecurity,C077YSV1D7C,https://OWASP.slack.com/archives/C077YSV1D7C
project-netryx,C07D6R13URM,https://OWASP.slack.com/archives/C07D6R13URM
project-ot-top-10,C07HDTYRA6R,https://OWASP.slack.com/archives/C07HDTYRA6R
project-nest,C07JLLG2GFQ,https://OWASP.slack.com/archives/C07JLLG2GFQ
project-top10-proactive-controls,C07KNHZAN1H,https://OWASP.slack.com/archives/C07KNHZAN1H
project-actions,C07PMR5RV1A,https://OWASP.slack.com/archives/C07PMR5RV1A
project-aibom-community,C07UZUAJTL4,https://OWASP.slack.com/archives/C07UZUAJTL4
project-scstg,C083UNMMVMH,https://OWASP.slack.com/archives/C083UNMMVMH
66 changes: 66 additions & 0 deletions website/management/commands/import_slack_channels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import csv
import os

from django.core.management.base import BaseCommand

from website.models import Project


class Command(BaseCommand):
help = "Import slack channels from CSV file and associate them with projects"

def add_arguments(self, parser):
parser.add_argument(
"--csv-file",
type=str,
default="project_channels.csv",
help="Path to the CSV file containing the slack channel data",
)

def handle(self, *args, **kwargs):
csv_file_path = kwargs["csv_file"]

self.stdout.write(f"Importing slack channels from CSV file: {csv_file_path}")

if not os.path.exists(csv_file_path):
self.stdout.write(self.style.ERROR(f"CSV file not found: {csv_file_path}"))
return

updated_count = 0

with open(csv_file_path, "r") as file:
reader = csv.DictReader(file)
for row in reader:
slack_channel = row.get("slack_channel", "").strip()
slack_id = row.get("slack_id", "").strip()
slack_url = row.get("slack_url", "").strip()

if not slack_channel or not slack_channel.startswith("project-"):
continue

project_name = slack_channel.replace("project-", "").replace("-", " ").title()

project = Project.objects.filter(name__iexact=project_name).first()

if project:
updated = False
if project.slack_channel != slack_channel:
project.slack_channel = slack_channel
updated = True

if project.slack_id != slack_id:
project.slack_id = slack_id
updated = True

if project.slack != slack_url:
project.slack = slack_url
updated = True

if updated:
project.save()
updated_count += 1
self.stdout.write(f"Updated project: {project_name}")
else:
self.stdout.write(self.style.WARNING(f"No project found with name: {project_name}"))

self.stdout.write(self.style.SUCCESS(f"Successfully processed CSV. Updated {updated_count} projects."))
28 changes: 28 additions & 0 deletions website/migrations/0247_add_slack_fields_to_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 5.1.8 on 2025-10-05 13:30

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("website", "0246_add_user_progress_models"),
]

operations = [
migrations.AddField(
model_name="project",
name="slack",
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name="project",
name="slack_channel",
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name="project",
name="slack_id",
field=models.CharField(blank=True, max_length=255, null=True, unique=True),
),
]
3 changes: 3 additions & 0 deletions website/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,9 @@ class Project(models.Model):
url = models.URLField(unique=True, null=True, blank=True) # Made url nullable in case of no website
project_visit_count = models.IntegerField(default=0)
twitter = models.CharField(max_length=30, null=True, blank=True)
slack = models.URLField(null=True, blank=True)
slack_channel = models.CharField(max_length=255, blank=True, null=True)
slack_id = models.CharField(max_length=255, unique=True, blank=True, null=True)
facebook = models.URLField(null=True, blank=True)
logo = models.ImageField(upload_to="project_logos", null=True, blank=True)
created = models.DateTimeField(auto_now_add=True) # Standardized field name
Expand Down
11 changes: 11 additions & 0 deletions website/templates/projects/project_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ <h1 class="text-3xl font-bold text-white mb-2">{{ project.name }}</h1>
Facebook
</a>
{% endif %}
{% if project.slack %}
<a href="{{ project.slack }}"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center px-4 py-2 bg-white/10 hover:bg-white/20 rounded-lg text-white transition">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 24 24">
<path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zM18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zM15.165 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z" />
</svg>
Slack
</a>
{% endif %}
</div>
</div>
</div>
Expand Down
7 changes: 7 additions & 0 deletions website/templates/projects/project_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,13 @@ <h3 class="text-xl font-bold text-gray-900">Add New Project</h3>
class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-red-500"
placeholder="https://facebook.com/..." />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Slack URL</label>
<input type="url"
name="slack"
class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-red-500"
placeholder="https://slack.com/..." />
</div>
</div>
<!-- Repositories Section -->
<div>
Expand Down
20 changes: 20 additions & 0 deletions website/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,25 @@ def validate_url(url):
status=400,
)

slack = request.POST.get("slack")
if slack:
if not slack.startswith(("http://", "https://")):
return JsonResponse(
{
"error": "Slack URL must start with http:// or https://",
"code": "INVALID_SLACK_URL",
},
status=400,
)
if not validate_url(slack):
return JsonResponse(
{
"error": "Slack URL is not accessible",
"code": "INVALID_SLACK_URL",
},
status=400,
)

# Validate repository URLs
repo_urls = request.POST.getlist("repo_urls[]")
for url in repo_urls:
Expand Down Expand Up @@ -458,6 +477,7 @@ def validate_url(url):
"url": project_url,
"twitter": request.POST.get("twitter"),
"facebook": request.POST.get("facebook"),
"slack": request.POST.get("slack"),
}

# Handle logo file
Expand Down
Loading