diff --git a/backend/db.sqlite3 b/backend/db.sqlite3
index 2f7556b6683597ac5991d9b012d338917534fe75..2640fc9a9b2d3bcc229cdaa25a55f92addba7a93 100644
Binary files a/backend/db.sqlite3 and b/backend/db.sqlite3 differ
diff --git a/backend/rssfeeds/__init__.py b/backend/rssfeeds/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/backend/rssfeeds/admin.py b/backend/rssfeeds/admin.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e
--- /dev/null
+++ b/backend/rssfeeds/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/backend/rssfeeds/apps.py b/backend/rssfeeds/apps.py
new file mode 100644
index 0000000000000000000000000000000000000000..88e2c6b492b6ef43641f629ba30d2fd10cb5b192
--- /dev/null
+++ b/backend/rssfeeds/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class RssfeedsConfig(AppConfig):
+ default_auto_field = "django.db.models.BigAutoField"
+ name = "rssfeeds"
diff --git a/backend/rssfeeds/models.py b/backend/rssfeeds/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..71a836239075aa6e6e4ecb700e9c42c95c022d91
--- /dev/null
+++ b/backend/rssfeeds/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/backend/rssfeeds/tests.py b/backend/rssfeeds/tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6
--- /dev/null
+++ b/backend/rssfeeds/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/backend/rssfeeds/urls.py b/backend/rssfeeds/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..0e74e03e30853d996df27da6dddf81f4c1987eff
--- /dev/null
+++ b/backend/rssfeeds/urls.py
@@ -0,0 +1,9 @@
+# rssfeeds/urls.py
+from django.urls import path
+from . import views
+from .views import fetch_cve_updates
+
+urlpatterns = [
+ path('api/news/', views.fetch_security_news, name='security-news'),
+ path('api/cve-updates/', fetch_cve_updates, name='cve-updates'),
+]
\ No newline at end of file
diff --git a/backend/rssfeeds/views.py b/backend/rssfeeds/views.py
new file mode 100644
index 0000000000000000000000000000000000000000..fa3c8892d3b8489b85d588741eab0506c1c127ac
--- /dev/null
+++ b/backend/rssfeeds/views.py
@@ -0,0 +1,29 @@
+# rssfeeds/views.py
+import feedparser, requests
+from django.http import JsonResponse
+from datetime import datetime, timedelta
+
+def fetch_security_news(request):
+ feed_url = 'https://www.bleepingcomputer.com/feed/' # Replace with actual RSS feed URL
+ feed = feedparser.parse(feed_url)
+ news_items = [{'title': entry.title, 'link': entry.link, 'description': entry.description} for entry in feed.entries]
+ return JsonResponse(news_items, safe=False)
+
+def fetch_cve_updates(request):
+ # Get the current date and date 14 days ago
+ current_date = datetime.now().isoformat()
+ start_date = (datetime.now() - timedelta(days=14)).isoformat()
+
+ # Construct the URL with the date information
+ url = f"https://services.nvd.nist.gov/rest/json/cves/2.0/?pubStartDate={start_date}&pubEndDate={current_date}&resultsPerPage=10"
+ print(url)
+
+ # Fetch data from the URL
+ response = requests.get(url)
+ data = response.json()
+
+ # Extract the first five CVEs
+ recent_cves = data.get('vulnerabilities', [])[:5]
+
+ # Return the recent CVEs as JSON response
+ return JsonResponse(recent_cves, safe=False)
\ No newline at end of file
diff --git a/backend/shodan_scan/utils.py b/backend/shodan_scan/utils.py
index 478daa8c7a27ac3923f7c24a018a4c13170aed03..e2a359fb9b2101e15ace77637264d731952c8d20 100644
--- a/backend/shodan_scan/utils.py
+++ b/backend/shodan_scan/utils.py
@@ -28,8 +28,7 @@ def shodan_scan(api_key, ips):
for cve in vulns_info:
if isinstance(cve, str):
scan_result['vulnerabilities'].append({
- 'cve': cve,
- 'summary': 'Details not provided by Shodan' # Placeholder text
+ 'cve': cve
})
else:
print(f"Unexpected format for vulnerability detail: {cve}")
diff --git a/backend/watchstone_backend/settings.py b/backend/watchstone_backend/settings.py
index 05cc913ddedef184eb7b4ed6a23dbdc8a7a8677f..0e378714144cd6b16ff5e80115ea91f06b93f097 100644
--- a/backend/watchstone_backend/settings.py
+++ b/backend/watchstone_backend/settings.py
@@ -35,7 +35,8 @@ INSTALLED_APPS = [
"rest_framework_simplejwt",
"breach_check",
"shodan_scan",
- "network_scanner"
+ "network_scanner",
+ "rssfeeds"
]
diff --git a/backend/watchstone_backend/urls.py b/backend/watchstone_backend/urls.py
index 168d007780dffa43b2c5263057f0b9b8ceb31f8a..e8a725864349c8cae5c1054b8ecbbbce64553f6e 100644
--- a/backend/watchstone_backend/urls.py
+++ b/backend/watchstone_backend/urls.py
@@ -13,5 +13,6 @@ urlpatterns = [
path('haveibeenpwned/passwords/<str:identifier>/', breached_password_info, name='breached_password_info'),
path('', include('shodan_scan.urls')),
path('api/networkscanner/', include('network_scanner.urls')),
+ path('', include('rssfeeds.urls')), # Include the rssfeeds app URLs
# Add other URL patterns as needed
]
diff --git a/frontend/src/views/dashboard/CVEUpdates.js b/frontend/src/views/dashboard/CVEUpdates.js
new file mode 100644
index 0000000000000000000000000000000000000000..6df254345a1342d3f14df8f7ba4034689fa43f0f
--- /dev/null
+++ b/frontend/src/views/dashboard/CVEUpdates.js
@@ -0,0 +1,48 @@
+import React, { useState, useEffect } from 'react'
+import axios from 'axios'
+import { CCard, CCardBody, CCardTitle } from '@coreui/react'
+
+const CVEUpdates = () => {
+ const [cveItems, setCveItems] = useState([])
+
+ useEffect(() => {
+ const fetchCve = async () => {
+ try {
+ const response = await axios.get('http://localhost:8000/api/cve-updates/')
+ setCveItems(response.data)
+ } catch (error) {
+ console.error('Failed to fetch CVE updates:', error)
+ }
+ }
+
+ fetchCve()
+ }, [])
+
+ return (
+ <div>
+ {cveItems.length > 0 ? (
+ <div>
+ {cveItems.map((cveItem, index) => (
+ <CCard key={index} className="mb-3">
+ <CCardBody>
+ <CCardTitle>ID: {cveItem.cve.id}</CCardTitle>
+ <p>Date: {cveItem.cve.published}</p>
+ <p>Summary: {cveItem.cve.descriptions[0].value}</p>
+ <p>
+ Details:{' '}
+ <a href={cveItem.cve.references[0].url} target="_blank" rel="noopener noreferrer">
+ View More
+ </a>
+ </p>
+ </CCardBody>
+ </CCard>
+ ))}
+ </div>
+ ) : (
+ <p>No CVE data available.</p>
+ )}
+ </div>
+ )
+}
+
+export default CVEUpdates
diff --git a/frontend/src/views/dashboard/Dashboard.js b/frontend/src/views/dashboard/Dashboard.js
index 0aeeeee951b68ea97fffb8dea86bf437c821e90e..b3d8832b33dfeb6c28d31f4fefcea0929d3bf8ed 100644
--- a/frontend/src/views/dashboard/Dashboard.js
+++ b/frontend/src/views/dashboard/Dashboard.js
@@ -1,312 +1,31 @@
import React from 'react'
-
-import {
- CAvatar,
- CButton,
- CButtonGroup,
- CCard,
- CCardBody,
- CCardFooter,
- CCardHeader,
- CCol,
- CProgress,
- CRow,
- CTable,
- CTableBody,
- CTableDataCell,
- CTableHead,
- CTableHeaderCell,
- CTableRow,
-} from '@coreui/react'
-import { CChartLine } from '@coreui/react-chartjs'
-import { getStyle, hexToRgba } from '@coreui/utils'
-import CIcon from '@coreui/icons-react'
-import {
- cibCcAmex,
- cibCcApplePay,
- cibCcMastercard,
- cibCcPaypal,
- cibCcStripe,
- cibCcVisa,
- cibGoogle,
- cibFacebook,
- cibLinkedin,
- cifBr,
- cifEs,
- cifFr,
- cifIn,
- cifPl,
- cifUs,
- cibTwitter,
- cilCloudDownload,
- cilPeople,
- cilUser,
- cilUserFemale,
-} from '@coreui/icons'
-
-import avatar1 from 'src/assets/images/avatars/1.jpg'
-import avatar2 from 'src/assets/images/avatars/2.jpg'
-import avatar3 from 'src/assets/images/avatars/3.jpg'
-import avatar4 from 'src/assets/images/avatars/4.jpg'
-import avatar5 from 'src/assets/images/avatars/5.jpg'
-import avatar6 from 'src/assets/images/avatars/6.jpg'
-
-import WidgetsBrand from '../widgets/WidgetsBrand'
+import { CCard, CCardBody, CCol, CRow } from '@coreui/react'
import WidgetsDropdown from '../widgets/WidgetsDropdown'
+import SecurityNews from './SecurityNews'
+import CVEUpdates from './CVEUpdates'
const Dashboard = () => {
- const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min)
-
- const progressExample = [
- { title: 'Visits', value: '29.703 Users', percent: 40, color: 'success' },
- { title: 'Unique', value: '24.093 Users', percent: 20, color: 'info' },
- { title: 'Pageviews', value: '78.706 Views', percent: 60, color: 'warning' },
- { title: 'New Users', value: '22.123 Users', percent: 80, color: 'danger' },
- { title: 'Bounce Rate', value: 'Average Rate', percent: 40.15, color: 'primary' },
- ]
-
- const progressGroupExample1 = [
- { title: 'Monday', value1: 34, value2: 78 },
- { title: 'Tuesday', value1: 56, value2: 94 },
- { title: 'Wednesday', value1: 12, value2: 67 },
- { title: 'Thursday', value1: 43, value2: 91 },
- { title: 'Friday', value1: 22, value2: 73 },
- { title: 'Saturday', value1: 53, value2: 82 },
- { title: 'Sunday', value1: 9, value2: 69 },
- ]
-
- const progressGroupExample2 = [
- { title: 'Male', icon: cilUser, value: 53 },
- { title: 'Female', icon: cilUserFemale, value: 43 },
- ]
-
- const progressGroupExample3 = [
- { title: 'Organic Search', icon: cibGoogle, percent: 56, value: '191,235' },
- { title: 'Facebook', icon: cibFacebook, percent: 15, value: '51,223' },
- { title: 'Twitter', icon: cibTwitter, percent: 11, value: '37,564' },
- { title: 'LinkedIn', icon: cibLinkedin, percent: 8, value: '27,319' },
- ]
-
- const tableExample = [
- {
- avatar: { src: avatar1, status: 'success' },
- user: {
- name: 'Yiorgos Avraamu',
- new: true,
- registered: 'Jan 1, 2021',
- },
- country: { name: 'USA', flag: cifUs },
- usage: {
- value: 50,
- period: 'Jun 11, 2021 - Jul 10, 2021',
- color: 'success',
- },
- payment: { name: 'Mastercard', icon: cibCcMastercard },
- activity: '10 sec ago',
- },
- {
- avatar: { src: avatar2, status: 'danger' },
- user: {
- name: 'Avram Tarasios',
- new: false,
- registered: 'Jan 1, 2021',
- },
- country: { name: 'Brazil', flag: cifBr },
- usage: {
- value: 22,
- period: 'Jun 11, 2021 - Jul 10, 2021',
- color: 'info',
- },
- payment: { name: 'Visa', icon: cibCcVisa },
- activity: '5 minutes ago',
- },
- {
- avatar: { src: avatar3, status: 'warning' },
- user: { name: 'Quintin Ed', new: true, registered: 'Jan 1, 2021' },
- country: { name: 'India', flag: cifIn },
- usage: {
- value: 74,
- period: 'Jun 11, 2021 - Jul 10, 2021',
- color: 'warning',
- },
- payment: { name: 'Stripe', icon: cibCcStripe },
- activity: '1 hour ago',
- },
- {
- avatar: { src: avatar4, status: 'secondary' },
- user: { name: 'Enéas Kwadwo', new: true, registered: 'Jan 1, 2021' },
- country: { name: 'France', flag: cifFr },
- usage: {
- value: 98,
- period: 'Jun 11, 2021 - Jul 10, 2021',
- color: 'danger',
- },
- payment: { name: 'PayPal', icon: cibCcPaypal },
- activity: 'Last month',
- },
- {
- avatar: { src: avatar5, status: 'success' },
- user: {
- name: 'Agapetus Tadeáš',
- new: true,
- registered: 'Jan 1, 2021',
- },
- country: { name: 'Spain', flag: cifEs },
- usage: {
- value: 22,
- period: 'Jun 11, 2021 - Jul 10, 2021',
- color: 'primary',
- },
- payment: { name: 'Google Wallet', icon: cibCcApplePay },
- activity: 'Last week',
- },
- {
- avatar: { src: avatar6, status: 'danger' },
- user: {
- name: 'Friderik Dávid',
- new: true,
- registered: 'Jan 1, 2021',
- },
- country: { name: 'Poland', flag: cifPl },
- usage: {
- value: 43,
- period: 'Jun 11, 2021 - Jul 10, 2021',
- color: 'success',
- },
- payment: { name: 'Amex', icon: cibCcAmex },
- activity: 'Last week',
- },
- ]
-
return (
<>
<WidgetsDropdown />
- <CCard className="mb-4">
- <CCardBody>
- <CRow>
- <CCol sm={5}>
- <h4 id="traffic" className="card-title mb-0">
- Traffic
- </h4>
- <div className="small text-medium-emphasis">January - July 2021</div>
- </CCol>
- <CCol sm={7} className="d-none d-md-block">
- <CButton color="primary" className="float-end">
- <CIcon icon={cilCloudDownload} />
- </CButton>
- <CButtonGroup className="float-end me-3">
- {['Day', 'Month', 'Year'].map((value) => (
- <CButton
- color="outline-secondary"
- key={value}
- className="mx-0"
- active={value === 'Month'}
- >
- {value}
- </CButton>
- ))}
- </CButtonGroup>
- </CCol>
- </CRow>
- <CChartLine
- style={{ height: '300px', marginTop: '40px' }}
- data={{
- labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
- datasets: [
- {
- label: 'My First dataset',
- backgroundColor: hexToRgba(getStyle('--cui-info'), 10),
- borderColor: getStyle('--cui-info'),
- pointHoverBackgroundColor: getStyle('--cui-info'),
- borderWidth: 2,
- data: [
- random(50, 200),
- random(50, 200),
- random(50, 200),
- random(50, 200),
- random(50, 200),
- random(50, 200),
- random(50, 200),
- ],
- fill: true,
- },
- {
- label: 'My Second dataset',
- backgroundColor: 'transparent',
- borderColor: getStyle('--cui-success'),
- pointHoverBackgroundColor: getStyle('--cui-success'),
- borderWidth: 2,
- data: [
- random(50, 200),
- random(50, 200),
- random(50, 200),
- random(50, 200),
- random(50, 200),
- random(50, 200),
- random(50, 200),
- ],
- },
- {
- label: 'My Third dataset',
- backgroundColor: 'transparent',
- borderColor: getStyle('--cui-danger'),
- pointHoverBackgroundColor: getStyle('--cui-danger'),
- borderWidth: 1,
- borderDash: [8, 5],
- data: [65, 65, 65, 65, 65, 65, 65],
- },
- ],
- }}
- options={{
- maintainAspectRatio: false,
- plugins: {
- legend: {
- display: false,
- },
- },
- scales: {
- x: {
- grid: {
- drawOnChartArea: false,
- },
- },
- y: {
- ticks: {
- beginAtZero: true,
- maxTicksLimit: 5,
- stepSize: Math.ceil(250 / 5),
- max: 250,
- },
- },
- },
- elements: {
- line: {
- tension: 0.4,
- },
- point: {
- radius: 0,
- hitRadius: 10,
- hoverRadius: 4,
- hoverBorderWidth: 3,
- },
- },
- }}
- />
- </CCardBody>
- <CCardFooter>
- <CRow xs={{ cols: 1 }} md={{ cols: 5 }} className="text-center">
- {progressExample.map((item, index) => (
- <CCol className="mb-sm-2 mb-0" key={index}>
- <div className="text-medium-emphasis">{item.title}</div>
- <strong>
- {item.value} ({item.percent}%)
- </strong>
- <CProgress thin className="mt-2" color={item.color} value={item.percent} />
- </CCol>
- ))}
- </CRow>
- </CCardFooter>
- </CCard>
+ <CRow>
+ <CCol sm="6">
+ <CCard className="mb-5">
+ {' '}
+ <CCardBody>
+ <h4 className="card-title mb-3">Security News</h4> <SecurityNews />
+ </CCardBody>
+ </CCard>
+ </CCol>
+ <CCol sm="6">
+ <CCard className="mb-5">
+ {' '}
+ <CCardBody>
+ <h4 className="card-title mb-3">CVE Updates</h4> <CVEUpdates />
+ </CCardBody>
+ </CCard>
+ </CCol>
+ </CRow>
</>
)
}
diff --git a/frontend/src/views/dashboard/SecurityNews.js b/frontend/src/views/dashboard/SecurityNews.js
new file mode 100644
index 0000000000000000000000000000000000000000..243ab25921bbec86d1aab544edb8359e30629798
--- /dev/null
+++ b/frontend/src/views/dashboard/SecurityNews.js
@@ -0,0 +1,43 @@
+import React, { useState, useEffect } from 'react'
+import axios from 'axios'
+import ReactMarkdown from 'react-markdown'
+import { CCard, CCardBody, CCardTitle } from '@coreui/react'
+
+const SecurityNews = () => {
+ const [newsItems, setNewsItems] = useState([])
+
+ useEffect(() => {
+ const fetchNews = async () => {
+ try {
+ const response = await axios.get('http://localhost:8000/api/news')
+ setNewsItems(response.data)
+ } catch (error) {
+ console.error('Failed to fetch news:', error)
+ }
+ }
+
+ fetchNews()
+ }, [])
+
+ return (
+ <div>
+ {newsItems.map((item, index) => (
+ <CCard key={index} className="mb-3">
+ <CCardBody>
+ <a
+ href={item.link}
+ target="_blank"
+ rel="noopener noreferrer"
+ style={{ textDecoration: 'none', color: 'inherit' }}
+ >
+ <CCardTitle>{item.title}</CCardTitle>
+ </a>
+ <ReactMarkdown>{item.content}</ReactMarkdown>
+ </CCardBody>
+ </CCard>
+ ))}
+ </div>
+ )
+}
+
+export default SecurityNews