Skip to content
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

Slack Work #3232

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
60 changes: 60 additions & 0 deletions website/management/commands/import_slack_channel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import requests
from django.conf import settings
from django.core.management.base import BaseCommand

from website.models import Project # Replace `website` with the actual app name

SLACK_TOKEN = settings.SLACK_TOKEN
SLACK_API_URL = "https://slack.com/api/conversations.list"
HEADERS = {"Authorization": f"Bearer {SLACK_TOKEN}"}


class Command(BaseCommand):
help = "Fetch Slack channels and associate them with projects"

def fetch_channels(self):
url = SLACK_API_URL
params = {"limit": 1000, "types": "public_channel"} # Fetch only public channels
channels = []

while url:
response = requests.get(url, headers=HEADERS, params=params)
data = response.json()

if not data.get("ok"):
self.stdout.write(f"Error: {data.get('error')}")
break

channels.extend(data.get("channels", []))
cursor = data.get("response_metadata", {}).get("next_cursor")
if cursor:
url = SLACK_API_URL + f"?cursor={cursor}"
else:
url = None

return channels

def handle(self, *args, **kwargs):
self.stdout.write("Fetching Slack channels...")

channels = self.fetch_channels()
for channel in channels:
if channel["name"].startswith("project-"):
project_name = channel["name"].replace("project-", "").capitalize()

# Update or create project with Slack details
project, created = Project.objects.update_or_create(
name=project_name,
defaults={
"slack_channel": channel["name"],
"slack_id": channel["id"],
"slack_url": f"https://OWASP.slack.com/archives/{channel['id']}",
},
)

if created:
self.stdout.write(f"Created new project: {project_name}")
else:
self.stdout.write(f"Updated existing project: {project_name}")

self.stdout.write(f"Processed {len(channels)} Slack channels.")
17 changes: 17 additions & 0 deletions website/migrations/0180_project_slack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.1.4 on 2025-01-12 08:07

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("website", "0179_contributorstats"),
]

operations = [
migrations.AddField(
model_name="project",
name="slack",
field=models.CharField(blank=True, max_length=30, null=True),
),
]
17 changes: 17 additions & 0 deletions website/migrations/0181_alter_project_slack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.1.4 on 2025-01-15 15:51

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("website", "0180_project_slack"),
]

operations = [
migrations.AlterField(
model_name="project",
name="slack",
field=models.URLField(blank=True, null=True),
),
]
12 changes: 12 additions & 0 deletions website/migrations/0182_merge_20250116_0944.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Generated by Django 5.1.4 on 2025-01-16 09:44

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("website", "0180_rename_project_visit_count_repo_repo_visit_count"),
("website", "0181_alter_project_slack"),
]

operations = []
29 changes: 29 additions & 0 deletions website/migrations/0183_slackchannel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 5.1.4 on 2025-01-19 17:57

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("website", "0182_merge_20250116_0944"),
]

operations = [
migrations.CreateModel(
name="SlackChannel",
Copy link
Collaborator

@DonnieBLT DonnieBLT Jan 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think slack channel could link back to the project as some projects have multiple channels and can you squash the migrations to one file please?

fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("slack_channel", models.CharField(max_length=255)),
("slack_id", models.CharField(max_length=255, unique=True)),
("slack_url", models.URLField()),
],
),
]
4 changes: 4 additions & 0 deletions website/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,10 @@ 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="M12 2C6.48 2 2 6.48 2 12c0 4.94 3.63 9.02 8.35 9.8V15.5H7.5v-3h2.85V10.7c0-2.82 1.68-4.38 4.25-4.38 1.23 0 2.55.22 2.55.22v2.82h-1.43c-1.41 0-1.85.87-1.85 1.77v2.13h3l-.3 3h-2.7v6.5C18.37 21.02 22 16.94 22 12c0-5.52-4.48-10-10-10z" />
</svg>
Slack
</a>
{% endif %}
</div>
</div>
</div>
Expand Down
8 changes: 8 additions & 0 deletions website/templates/projects/project_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,14 @@ <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>
<!-- Slack URL -->
<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
13 changes: 13 additions & 0 deletions website/templates/projects/repo_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ <h1 class="text-3xl font-bold text-gray-900">{{ repo.name }}</h1>
Visit Homepage
</a>
{% endif %}
{% if repo.slack %}
<a href="{{ repo.slack }}"
target="_blank"
class="inline-flex items-center px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition-colors">
<svg class="w-5 h-5 mr-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
</svg>
Join on Slack
</a>
{% endif %}
<a href="{{ repo.repo_url }}"
target="_blank"
class="inline-flex items-center px-4 py-2 bg-red-500 hover:bg-red-600 text-white rounded-lg transition-colors">
Expand Down
12 changes: 12 additions & 0 deletions website/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,17 @@ def validate_url(url):
},
status=400,
)
slack = request.POST.get("slack")
if slack:
if slack.startswith(("http://", "https://")):
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[]")
Expand Down Expand Up @@ -444,6 +455,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