Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b806425d9 | ||
|
|
e741fe47b1 | ||
|
|
5614a714bc |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,8 +1,13 @@
|
||||
from django.contrib import admin
|
||||
from .models import Ticket
|
||||
from .models import Application, Vulnerability
|
||||
|
||||
@admin.register(Ticket)
|
||||
class TicketAdmin(admin.ModelAdmin):
|
||||
list_display = ('subject', 'status', 'priority', 'requester_email', 'created_at')
|
||||
list_filter = ('status', 'priority')
|
||||
search_fields = ('subject', 'requester_email', 'description')
|
||||
@admin.register(Application)
|
||||
class ApplicationAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'version', 'vendor')
|
||||
search_fields = ('name', 'vendor')
|
||||
|
||||
@admin.register(Vulnerability)
|
||||
class VulnerabilityAdmin(admin.ModelAdmin):
|
||||
list_display = ('cve_id', 'application', 'severity', 'status', 'discovered_at')
|
||||
list_filter = ('severity', 'status', 'application__name')
|
||||
search_fields = ('cve_id', 'description')
|
||||
@ -1,7 +1,8 @@
|
||||
from django import forms
|
||||
from .models import Ticket
|
||||
|
||||
class TicketForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Ticket
|
||||
fields = ['subject', 'requester_email', 'priority', 'description']
|
||||
class UploadFileForm(forms.Form):
|
||||
file = forms.FileField()
|
||||
|
||||
class VulnerabilitySearchForm(forms.Form):
|
||||
application_name = forms.CharField(max_length=100, label="Application Name")
|
||||
application_website = forms.URLField(label="Application Website", required=False)
|
||||
@ -0,0 +1,39 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-27 12:23
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Application',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('version', models.CharField(max_length=100)),
|
||||
('vendor', models.CharField(max_length=255)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Vulnerability',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('cve_id', models.CharField(max_length=50, unique=True)),
|
||||
('description', models.TextField()),
|
||||
('severity', models.CharField(choices=[('Critical', 'Critical'), ('High', 'High'), ('Medium', 'Medium'), ('Low', 'Low')], max_length=10)),
|
||||
('status', models.CharField(choices=[('New', 'New'), ('Acknowledged', 'Acknowledged'), ('In-Progress', 'In-Progress'), ('Resolved', 'Resolved')], default='New', max_length=20)),
|
||||
('discovered_at', models.DateTimeField(auto_now_add=True)),
|
||||
('last_updated', models.DateTimeField(auto_now=True)),
|
||||
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vulnerabilities', to='core.application')),
|
||||
],
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Ticket',
|
||||
),
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,25 +1,34 @@
|
||||
from django.db import models
|
||||
|
||||
class Ticket(models.Model):
|
||||
STATUS_CHOICES = [
|
||||
('open', 'Open'),
|
||||
('in_progress', 'In Progress'),
|
||||
('closed', 'Closed'),
|
||||
]
|
||||
|
||||
PRIORITY_CHOICES = [
|
||||
('low', 'Low'),
|
||||
('medium', 'Medium'),
|
||||
('high', 'High'),
|
||||
]
|
||||
|
||||
subject = models.CharField(max_length=255)
|
||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='open')
|
||||
priority = models.CharField(max_length=20, choices=PRIORITY_CHOICES, default='medium')
|
||||
requester_email = models.EmailField()
|
||||
description = models.TextField()
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
class Application(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
version = models.CharField(max_length=100)
|
||||
vendor = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return self.subject
|
||||
return f"{self.name} {self.version}"
|
||||
|
||||
class Vulnerability(models.Model):
|
||||
SEVERITY_CHOICES = [
|
||||
('Critical', 'Critical'),
|
||||
('High', 'High'),
|
||||
('Medium', 'Medium'),
|
||||
('Low', 'Low'),
|
||||
]
|
||||
STATUS_CHOICES = [
|
||||
('New', 'New'),
|
||||
('Acknowledged', 'Acknowledged'),
|
||||
('In-Progress', 'In-Progress'),
|
||||
('Resolved', 'Resolved'),
|
||||
]
|
||||
|
||||
cve_id = models.CharField(max_length=50, unique=True)
|
||||
description = models.TextField()
|
||||
severity = models.CharField(max_length=10, choices=SEVERITY_CHOICES)
|
||||
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='vulnerabilities')
|
||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='New')
|
||||
discovered_at = models.DateTimeField(auto_now_add=True)
|
||||
last_updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.cve_id
|
||||
|
||||
69
core/templates/base.html
Normal file
69
core/templates/base.html
Normal file
@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}{{ project_name|default:"Vulnerability Scanner" }}{% endblock %}</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
{% load static %}
|
||||
<link rel="stylesheet" href="{% static 'css/custom.css' %}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="d-flex" id="wrapper">
|
||||
<!-- Sidebar -->
|
||||
<div class="bg-light border-right" id="sidebar-wrapper">
|
||||
<div class="sidebar-heading">
|
||||
<a class="text-decoration-none text-dark" href="/">
|
||||
<i class="bi bi-shield-shaded"></i> {{ project_name|default:"Vulnerability Scanner" }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="list-group list-group-flush">
|
||||
<a href="/" class="list-group-item list-group-item-action bg-light"><i class="bi bi-speedometer2 me-2"></i>Dashboard</a>
|
||||
<a href="#" class="list-group-item list-group-item-action bg-light"><i class="bi bi-file-earmark-arrow-up me-2"></i>Upload Inventory</a>
|
||||
<a href="#" class="list-group-item list-group-item-action bg-light"><i class="bi bi-bug me-2"></i>Vulnerabilities</a>
|
||||
<a href="#" class="list-group-item list-group-item-action bg-light"><i class="bi bi-gear me-2"></i>Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /#sidebar-wrapper -->
|
||||
|
||||
<!-- Page Content -->
|
||||
<div id="page-content-wrapper">
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom">
|
||||
<div class="container-fluid">
|
||||
<button class="btn btn-primary" id="menu-toggle"><i class="bi bi-list"></i></button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav ms-auto mt-2 mt-lg-0">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-person-circle"></i> Admin
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<li><a class="dropdown-item" href="#">Profile</a></li>
|
||||
<li><a class="dropdown-item" href="#">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="container-fluid p-4">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</div>
|
||||
<!-- /#page-content-wrapper -->
|
||||
</div>
|
||||
<!-- /#wrapper -->
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
document.getElementById("menu-toggle").addEventListener("click", function(e) {
|
||||
e.preventDefault();
|
||||
document.getElementById("wrapper").classList.toggle("toggled");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
14
core/templates/core/article_detail.html
Normal file
14
core/templates/core/article_detail.html
Normal file
@ -0,0 +1,14 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}{{ article.title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-5">
|
||||
<h1>{{ article.title }}</h1>
|
||||
<p class="text-muted">Published on {{ article.created_at|date:"F d, Y" }}</p>
|
||||
<hr>
|
||||
<div>
|
||||
{{ article.content|safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -1,157 +1,122 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ project_name }}</title>
|
||||
{% if project_description %}
|
||||
<meta name="description" content="{{ project_description }}">
|
||||
<meta property="og:description" content="{{ project_description }}">
|
||||
<meta property="twitter:description" content="{{ project_description }}">
|
||||
{% endif %}
|
||||
{% if project_image_url %}
|
||||
<meta property="og:image" content="{{ project_image_url }}">
|
||||
<meta property="twitter:image" content="{{ project_image_url }}">
|
||||
{% endif %}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.08);
|
||||
--card-border-color: rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
{% block title %}Dashboard - {{ project_name }}{% endblock %}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
{% block content %}
|
||||
<div class="container-fluid">
|
||||
<h1 class="mt-4">Dashboard</h1>
|
||||
<p>Overview of application vulnerabilities.</p>
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(130deg, var(--bg-color-start), var(--bg-color-end));
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-6 mb-4">
|
||||
<div class="card text-white bg-primary">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<div class="fs-4 fw-bold">{{ total_applications }}</div>
|
||||
<div>Total Applications</div>
|
||||
</div>
|
||||
<i class="bi bi-box-fill fs-1"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6 mb-4">
|
||||
<div class="card text-white bg-warning">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<div class="fs-4 fw-bold">{{ total_vulnerabilities }}</div>
|
||||
<div>Total Vulnerabilities</div>
|
||||
</div>
|
||||
<i class="bi bi-bug-fill fs-1"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6 mb-4">
|
||||
<div class="card text-white bg-danger">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<div class="fs-4 fw-bold">{{ critical_vulnerabilities }}</div>
|
||||
<div>Critical Vulnerabilities</div>
|
||||
</div>
|
||||
<i class="bi bi-exclamation-octagon-fill fs-1"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6 mb-4">
|
||||
<div class="card text-white bg-info">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<div class="fs-4 fw-bold">{{ new_vulnerabilities }}</div>
|
||||
<div>New Vulnerabilities</div>
|
||||
</div>
|
||||
<i class="bi bi-patch-plus-fill fs-1"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140' viewBox='0 0 140 140'><path d='M-20 20L160 20M20 -20L20 160' stroke-width='1' stroke='rgba(255,255,255,0.05)'/></svg>");
|
||||
animation: bg-pan 24s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<i class="bi bi-search me-2"></i>
|
||||
Vulnerability Search
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{% url 'vulnerability_search' %}" method="get">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="application_name" placeholder="Enter application name...">
|
||||
<button class="btn btn-primary" type="submit">Search</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@keyframes bg-pan {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(-140px, -140px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
padding: clamp(2rem, 4vw, 3rem);
|
||||
width: min(640px, 92vw);
|
||||
}
|
||||
|
||||
.card {
|
||||
background: var(--card-bg-color);
|
||||
border: 1px solid var(--card-border-color);
|
||||
border-radius: 20px;
|
||||
padding: clamp(2rem, 4vw, 3rem);
|
||||
backdrop-filter: blur(24px);
|
||||
-webkit-backdrop-filter: blur(24px);
|
||||
box-shadow: 0 20px 60px rgba(15, 23, 42, 0.35);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 1.2rem;
|
||||
font-weight: 700;
|
||||
font-size: clamp(2.2rem, 3vw + 1.3rem, 3rem);
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0.6rem 0;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.7;
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.loader {
|
||||
margin: 1.5rem auto;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border: 4px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
code {
|
||||
background: rgba(15, 23, 42, 0.35);
|
||||
padding: 0.2rem 0.6rem;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 2.4rem;
|
||||
font-size: 0.86rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<i class="bi bi-box-seam me-2"></i>
|
||||
Application Inventory
|
||||
</div>
|
||||
<a href="{% url 'upload_inventory' %}" class="btn btn-primary">Upload Inventory</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Version</th>
|
||||
<th>Vendor</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for app in applications %}
|
||||
<tr>
|
||||
<td>{{ app.name }}</td>
|
||||
<td>{{ app.version }}</td>
|
||||
<td>{{ app.vendor }}</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-primary">Details</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="4" class="text-center">No applications found.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<p>Appwizzy AI is collecting your requirements and applying the first changes.</p>
|
||||
<p>This page will refresh automatically as the plan is implemented.</p>
|
||||
<p>
|
||||
Runtime: Django <code>{{ django_version }}</code> · Python <code>{{ python_version }}</code> —
|
||||
UTC <code>{{ current_time|date:"Y-m-d H:i:s" }}</code>
|
||||
</p>
|
||||
</div>
|
||||
<footer>
|
||||
Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC)
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
13
core/templates/core/upload_inventory.html
Normal file
13
core/templates/core/upload_inventory.html
Normal file
@ -0,0 +1,13 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h2>Upload Application Inventory</h2>
|
||||
<p>Upload a CSV file with the following columns: Name, Version, Vendor.</p>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
25
core/templates/core/vulnerability_search.html
Normal file
25
core/templates/core/vulnerability_search.html
Normal file
@ -0,0 +1,25 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h2>Vulnerability Search</h2>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<button type="submit" class="btn btn-primary">Search</button>
|
||||
</form>
|
||||
|
||||
{% if results %}
|
||||
<hr>
|
||||
<h3>Search Results</h3>
|
||||
<div class="list-group">
|
||||
{% for result in results %}
|
||||
<div class="list-group-item">
|
||||
<h5 class="mb-1">{{ result.cve_id }}</h5>
|
||||
<p class="mb-1">{{ result.description }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -1,7 +1,9 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import home
|
||||
from .views import dashboard, upload_inventory, vulnerability_search
|
||||
|
||||
urlpatterns = [
|
||||
path("", home, name="home"),
|
||||
path("", dashboard, name="dashboard"),
|
||||
path("upload/", upload_inventory, name="upload_inventory"),
|
||||
path("search/", vulnerability_search, name="vulnerability_search"),
|
||||
]
|
||||
@ -1,37 +1,72 @@
|
||||
import os
|
||||
import platform
|
||||
from django.shortcuts import render, redirect
|
||||
from .models import Application, Vulnerability
|
||||
from .forms import UploadFileForm, VulnerabilitySearchForm
|
||||
import csv
|
||||
import io
|
||||
import requests
|
||||
|
||||
from django import get_version as django_version
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.views.generic.edit import CreateView
|
||||
|
||||
from .forms import TicketForm
|
||||
from .models import Ticket
|
||||
|
||||
|
||||
def home(request):
|
||||
"""Render the landing screen with loader and environment details."""
|
||||
host_name = request.get_host().lower()
|
||||
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
|
||||
now = timezone.now()
|
||||
def dashboard(request):
|
||||
# Placeholder data
|
||||
total_apps = Application.objects.count()
|
||||
total_vulns = Vulnerability.objects.count()
|
||||
critical_vulns = Vulnerability.objects.filter(severity='Critical').count()
|
||||
new_vulns = Vulnerability.objects.filter(status='New').count()
|
||||
applications = Application.objects.all()
|
||||
|
||||
context = {
|
||||
"project_name": "New Style",
|
||||
"agent_brand": agent_brand,
|
||||
"django_version": django_version(),
|
||||
"python_version": platform.python_version(),
|
||||
"current_time": now,
|
||||
"host_name": host_name,
|
||||
"project_description": os.getenv("PROJECT_DESCRIPTION", ""),
|
||||
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
|
||||
'total_applications': total_apps,
|
||||
'total_vulnerabilities': total_vulns,
|
||||
'critical_vulnerabilities': critical_vulns,
|
||||
'new_vulnerabilities': new_vulns,
|
||||
'applications': applications,
|
||||
"project_name": "Vulnerability Scanner",
|
||||
}
|
||||
return render(request, "core/index.html", context)
|
||||
|
||||
def upload_inventory(request):
|
||||
if request.method == 'POST':
|
||||
form = UploadFileForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
try:
|
||||
csv_file = request.FILES['file']
|
||||
decoded_file = io.TextIOWrapper(csv_file.file, encoding='utf-8', newline='', errors='ignore')
|
||||
reader = csv.reader(decoded_file)
|
||||
# Skip header row
|
||||
next(reader)
|
||||
for row in reader:
|
||||
if row and len(row) == 3:
|
||||
print(f"Processing row: {row}")
|
||||
Application.objects.create(
|
||||
name=row[0],
|
||||
version=row[1],
|
||||
vendor=row[2],
|
||||
)
|
||||
return redirect('dashboard')
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
form.add_error(None, f"An error occurred: {e}")
|
||||
else:
|
||||
form = UploadFileForm()
|
||||
return render(request, 'core/upload_inventory.html', {'form': form})
|
||||
|
||||
class TicketCreateView(CreateView):
|
||||
model = Ticket
|
||||
form_class = TicketForm
|
||||
template_name = "core/ticket_create.html"
|
||||
success_url = reverse_lazy("home")
|
||||
def vulnerability_search(request):
|
||||
form = VulnerabilitySearchForm()
|
||||
results = []
|
||||
if request.method == 'POST':
|
||||
form = VulnerabilitySearchForm(request.POST)
|
||||
if form.is_valid():
|
||||
application_name = form.cleaned_data['application_name']
|
||||
# Basic search using NVD API
|
||||
url = f"https://services.nvd.nist.gov/rest/json/cves/1.0?keyword={application_name}"
|
||||
try:
|
||||
response = requests.get(url)
|
||||
data = response.json()
|
||||
if 'result' in data:
|
||||
for cve_item in data['result']['CVE_Items']:
|
||||
cve_id = cve_item['cve']['CVE_data_meta']['ID']
|
||||
description = cve_item['cve']['description']['description_data'][0]['value']
|
||||
results.append({'cve_id': cve_id, 'description': description})
|
||||
except requests.exceptions.RequestException as e:
|
||||
form.add_error(None, f"Error fetching data from NVD: {e}")
|
||||
|
||||
return render(request, 'core/vulnerability_search.html', {'form': form, 'results': results})
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
Django==5.2.7
|
||||
mysqlclient==2.2.7
|
||||
python-dotenv==1.1.1
|
||||
requests
|
||||
|
||||
46
static/css/custom.css
Normal file
46
static/css/custom.css
Normal file
@ -0,0 +1,46 @@
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#sidebar-wrapper {
|
||||
min-height: 100vh;
|
||||
margin-left: -15rem;
|
||||
transition: margin .25s ease-out;
|
||||
}
|
||||
|
||||
#sidebar-wrapper .sidebar-heading {
|
||||
padding: 0.875rem 1.25rem;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#sidebar-wrapper .list-group {
|
||||
width: 15rem;
|
||||
}
|
||||
|
||||
#page-content-wrapper {
|
||||
min-width: 100vw;
|
||||
}
|
||||
|
||||
#wrapper.toggled #sidebar-wrapper {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
#sidebar-wrapper {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
#page-content-wrapper {
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#wrapper.toggled #sidebar-wrapper {
|
||||
margin-left: -15rem;
|
||||
}
|
||||
}
|
||||
|
||||
.card-body .fs-1 {
|
||||
opacity: 0.7;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user