Remote Details Section Added
parent
a5d6dea801
commit
6165103385
|
|
@ -31,6 +31,14 @@ def create_app():
|
||||||
db.session.add(default_category)
|
db.session.add(default_category)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
# Ensure default remote categories exist
|
||||||
|
from app.models import RemoteCategory
|
||||||
|
default_remote_cats = ["RDP", "SSL-VPN", "VPN", "MGMT"]
|
||||||
|
for cat in default_remote_cats:
|
||||||
|
if not RemoteCategory.query.filter_by(name=cat).first():
|
||||||
|
db.session.add(RemoteCategory(name=cat))
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
@event.listens_for(Engine, "connect")
|
@event.listens_for(Engine, "connect")
|
||||||
def set_sqlite_pragma(dbapi_connection, connection_record):
|
def set_sqlite_pragma(dbapi_connection, connection_record):
|
||||||
cursor = dbapi_connection.cursor()
|
cursor = dbapi_connection.cursor()
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,16 @@
|
||||||
from app import db
|
from app import db
|
||||||
|
|
||||||
# Association tables (if not already defined)
|
# Existing models…
|
||||||
client_domains = db.Table('client_domains',
|
|
||||||
db.Column('client_id', db.Integer, db.ForeignKey('client.id', ondelete="CASCADE")),
|
|
||||||
db.Column('domain_id', db.Integer, db.ForeignKey('domain.id'))
|
|
||||||
)
|
|
||||||
|
|
||||||
client_ssl = db.Table('client_ssl',
|
|
||||||
db.Column('client_id', db.Integer, db.ForeignKey('client.id', ondelete="CASCADE")),
|
|
||||||
db.Column('domain_id', db.Integer, db.ForeignKey('domain.id'))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Domain(db.Model):
|
class Domain(db.Model):
|
||||||
__tablename__ = 'domain'
|
__tablename__ = 'domain'
|
||||||
__table_args__ = {'extend_existing': True}
|
__table_args__ = {'extend_existing': True}
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
domain = db.Column(db.String(255), unique=True, nullable=False)
|
domain = db.Column(db.String(255), unique=True, nullable=False)
|
||||||
expiration_date = db.Column(db.String(255)) # WHOIS expiration date
|
expiration_date = db.Column(db.String(255))
|
||||||
ssl_expiration_date = db.Column(db.String(255)) # SSL certificate expiration date
|
ssl_expiration_date = db.Column(db.String(255))
|
||||||
ssl_only = db.Column(db.Boolean, default=False) # True if added via SSL-only form
|
ssl_only = db.Column(db.Boolean, default=False)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Domain {self.domain} | Whois: {self.expiration_date} | SSL: {self.ssl_expiration_date} | ssl_only: {self.ssl_only}>"
|
return f"<Domain {self.domain}>"
|
||||||
|
|
||||||
class Client(db.Model):
|
class Client(db.Model):
|
||||||
__tablename__ = 'client'
|
__tablename__ = 'client'
|
||||||
|
|
@ -30,29 +18,18 @@ class Client(db.Model):
|
||||||
name = db.Column(db.String(255), nullable=False)
|
name = db.Column(db.String(255), nullable=False)
|
||||||
phone = db.Column(db.String(255))
|
phone = db.Column(db.String(255))
|
||||||
address = db.Column(db.String(255))
|
address = db.Column(db.String(255))
|
||||||
|
|
||||||
# Delete all passwords when the client is deleted.
|
|
||||||
passwords = db.relationship('ClientPassword', backref='client', lazy=True,
|
passwords = db.relationship('ClientPassword', backref='client', lazy=True,
|
||||||
cascade="all, delete-orphan")
|
cascade="all, delete-orphan")
|
||||||
|
domains = db.relationship('Domain', secondary='client_domains',
|
||||||
# Many-to-many: Only the associations will be removed (due to ondelete cascade), not the Domain records.
|
|
||||||
domains = db.relationship('Domain', secondary=client_domains,
|
|
||||||
backref=db.backref('clients', lazy='dynamic'))
|
backref=db.backref('clients', lazy='dynamic'))
|
||||||
ssl_domains = db.relationship('Domain', secondary=client_ssl,
|
ssl_domains = db.relationship('Domain', secondary='client_ssl',
|
||||||
backref=db.backref('ssl_clients', lazy='dynamic'))
|
backref=db.backref('ssl_clients', lazy='dynamic'))
|
||||||
|
# New relationship for remotes
|
||||||
|
remotes = db.relationship('ClientRemote', backref='client', lazy=True,
|
||||||
|
cascade="all, delete-orphan")
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Client {self.name}>"
|
return f"<Client {self.name}>"
|
||||||
|
|
||||||
|
|
||||||
class PasswordCategory(db.Model):
|
|
||||||
__tablename__ = 'password_category'
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
name = db.Column(db.String(255), unique=True, nullable=False)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<PasswordCategory {self.name}>"
|
|
||||||
|
|
||||||
class ClientPassword(db.Model):
|
class ClientPassword(db.Model):
|
||||||
__tablename__ = 'client_password'
|
__tablename__ = 'client_password'
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
|
@ -62,6 +39,47 @@ class ClientPassword(db.Model):
|
||||||
client_id = db.Column(db.Integer, db.ForeignKey('client.id'), nullable=False)
|
client_id = db.Column(db.Integer, db.ForeignKey('client.id'), nullable=False)
|
||||||
category_id = db.Column(db.Integer, db.ForeignKey('password_category.id'))
|
category_id = db.Column(db.Integer, db.ForeignKey('password_category.id'))
|
||||||
category = db.relationship('PasswordCategory')
|
category = db.relationship('PasswordCategory')
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<ClientPassword {self.item}>"
|
return f"<ClientPassword {self.item}>"
|
||||||
|
|
||||||
|
class PasswordCategory(db.Model):
|
||||||
|
__tablename__ = 'password_category'
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(255), unique=True, nullable=False)
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<PasswordCategory {self.name}>"
|
||||||
|
|
||||||
|
# New models for Remote Categories and Client Remotes
|
||||||
|
class RemoteCategory(db.Model):
|
||||||
|
__tablename__ = 'remote_category'
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(255), unique=True, nullable=False)
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<RemoteCategory {self.name}>"
|
||||||
|
|
||||||
|
class ClientRemote(db.Model):
|
||||||
|
__tablename__ = 'client_remote'
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
client_id = db.Column(db.Integer, db.ForeignKey('client.id'), nullable=False)
|
||||||
|
remote_category_id = db.Column(db.Integer, db.ForeignKey('remote_category.id'), nullable=False)
|
||||||
|
# Optional fields: depending on category, only some are used.
|
||||||
|
name = db.Column(db.String(255))
|
||||||
|
ip_address = db.Column(db.String(255))
|
||||||
|
port = db.Column(db.String(10))
|
||||||
|
psk = db.Column(db.String(255))
|
||||||
|
address = db.Column(db.String(255))
|
||||||
|
details = db.Column(db.String(255))
|
||||||
|
remote_category = db.relationship('RemoteCategory')
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<ClientRemote {self.id} in {self.remote_category.name}>"
|
||||||
|
|
||||||
|
# Association tables for domains remain unchanged.
|
||||||
|
client_domains = db.Table('client_domains',
|
||||||
|
db.Column('client_id', db.Integer, db.ForeignKey('client.id', ondelete="CASCADE")),
|
||||||
|
db.Column('domain_id', db.Integer, db.ForeignKey('domain.id'))
|
||||||
|
)
|
||||||
|
|
||||||
|
client_ssl = db.Table('client_ssl',
|
||||||
|
db.Column('client_id', db.Integer, db.ForeignKey('client.id', ondelete="CASCADE")),
|
||||||
|
db.Column('domain_id', db.Integer, db.ForeignKey('domain.id'))
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from flask import Blueprint, render_template, request, redirect, url_for, flash
|
from flask import Blueprint, render_template, request, redirect, url_for, flash
|
||||||
from app.models import Client, ClientPassword, Domain, PasswordCategory
|
from app.models import Client, ClientPassword, Domain, PasswordCategory, RemoteCategory
|
||||||
from app import db
|
from app import db
|
||||||
|
|
||||||
clients_bp = Blueprint('clients', __name__)
|
clients_bp = Blueprint('clients', __name__)
|
||||||
|
|
@ -27,18 +27,29 @@ def client_detail(client_id):
|
||||||
available_domains = Domain.query.filter_by(ssl_only=False).all()
|
available_domains = Domain.query.filter_by(ssl_only=False).all()
|
||||||
available_ssl = Domain.query.filter_by(ssl_only=True).all()
|
available_ssl = Domain.query.filter_by(ssl_only=True).all()
|
||||||
available_categories = PasswordCategory.query.all()
|
available_categories = PasswordCategory.query.all()
|
||||||
# Group passwords by category (or "Uncategorized" if none)
|
available_remote_categories = RemoteCategory.query.all()
|
||||||
|
# Group passwords by category.
|
||||||
passwords_by_category = {}
|
passwords_by_category = {}
|
||||||
for p in client.passwords:
|
for p in client.passwords:
|
||||||
cat = p.category.name if p.category else "Uncategorized"
|
cat = p.category.name if p.category else "Uncategorized"
|
||||||
if cat not in passwords_by_category:
|
if cat not in passwords_by_category:
|
||||||
passwords_by_category[cat] = []
|
passwords_by_category[cat] = []
|
||||||
passwords_by_category[cat].append(p)
|
passwords_by_category[cat].append(p)
|
||||||
|
# Group remotes by remote category.
|
||||||
|
remotes_by_category = {}
|
||||||
|
for r in client.remotes:
|
||||||
|
cat_name = r.remote_category.name
|
||||||
|
if cat_name not in remotes_by_category:
|
||||||
|
remotes_by_category[cat_name] = []
|
||||||
|
remotes_by_category[cat_name].append(r)
|
||||||
return render_template('client_detail.html', client=client,
|
return render_template('client_detail.html', client=client,
|
||||||
available_domains=available_domains,
|
available_domains=available_domains,
|
||||||
available_ssl=available_ssl,
|
available_ssl=available_ssl,
|
||||||
available_categories=available_categories,
|
available_categories=available_categories,
|
||||||
passwords_by_category=passwords_by_category)
|
available_remote_categories=available_remote_categories,
|
||||||
|
passwords_by_category=passwords_by_category,
|
||||||
|
remotes_by_category=remotes_by_category)
|
||||||
|
|
||||||
|
|
||||||
@clients_bp.route('/clients/<int:client_id>/update_details', methods=['POST'])
|
@clients_bp.route('/clients/<int:client_id>/update_details', methods=['POST'])
|
||||||
def update_client_details(client_id):
|
def update_client_details(client_id):
|
||||||
|
|
@ -118,3 +129,41 @@ def delete_client(client_id):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash("Client deleted successfully.", "success")
|
flash("Client deleted successfully.", "success")
|
||||||
return redirect(url_for('clients.clients'))
|
return redirect(url_for('clients.clients'))
|
||||||
|
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/add_remote', methods=['POST'])
|
||||||
|
def add_remote(client_id):
|
||||||
|
from app.models import RemoteCategory, ClientRemote
|
||||||
|
client = Client.query.get_or_404(client_id)
|
||||||
|
remote_category_id = request.form.get('remote_category_id')
|
||||||
|
if not remote_category_id:
|
||||||
|
flash("Please select a remote category.", "warning")
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client.id))
|
||||||
|
remote_category = RemoteCategory.query.get(remote_category_id)
|
||||||
|
new_remote = ClientRemote(client_id=client.id, remote_category_id=remote_category.id)
|
||||||
|
# Fill in fields depending on category name.
|
||||||
|
if remote_category.name == "RDP":
|
||||||
|
new_remote.name = request.form.get('remote_name')
|
||||||
|
new_remote.ip_address = request.form.get('ip_address')
|
||||||
|
new_remote.port = request.form.get('port')
|
||||||
|
elif remote_category.name == "SSL-VPN":
|
||||||
|
new_remote.ip_address = request.form.get('ip_address')
|
||||||
|
new_remote.port = request.form.get('port')
|
||||||
|
elif remote_category.name == "VPN":
|
||||||
|
new_remote.ip_address = request.form.get('ip_address')
|
||||||
|
new_remote.psk = request.form.get('psk')
|
||||||
|
elif remote_category.name == "MGMT":
|
||||||
|
new_remote.name = request.form.get('remote_name')
|
||||||
|
new_remote.address = request.form.get('address')
|
||||||
|
else:
|
||||||
|
new_remote.details = request.form.get('details')
|
||||||
|
db.session.add(new_remote)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client.id))
|
||||||
|
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/remove_remote/<int:remote_id>', methods=['POST'])
|
||||||
|
def remove_remote(client_id, remote_id):
|
||||||
|
from app.models import ClientRemote
|
||||||
|
remote = ClientRemote.query.get_or_404(remote_id)
|
||||||
|
db.session.delete(remote)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client_id))
|
||||||
|
|
|
||||||
|
|
@ -3,45 +3,45 @@ import whois
|
||||||
from app.models import Domain
|
from app.models import Domain
|
||||||
from app import db
|
from app import db
|
||||||
from app.utils import get_ssl_expiration, get_whois_expiration
|
from app.utils import get_ssl_expiration, get_whois_expiration
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
domain_bp = Blueprint('domain', __name__)
|
domain_bp = Blueprint('domain', __name__)
|
||||||
|
|
||||||
@domain_bp.route('/')
|
@domain_bp.route('/')
|
||||||
def home():
|
def home():
|
||||||
current_year = datetime.now().year
|
now = datetime.now()
|
||||||
|
three_months_later = now + timedelta(days=90)
|
||||||
all_domains = Domain.query.all()
|
all_domains = Domain.query.all()
|
||||||
domains_expiring = []
|
domains_expiring = []
|
||||||
certs_expiring = []
|
ssl_expiring = []
|
||||||
|
|
||||||
for d in all_domains:
|
for d in all_domains:
|
||||||
# Filter and sort by WHOIS expiration date (expected format: mm/dd/yyyy)
|
# Check WHOIS expiration date (assumed format "mm/dd/yyyy")
|
||||||
try:
|
try:
|
||||||
dt_whois = datetime.strptime(d.expiration_date, "%m/%d/%Y")
|
dt_whois = datetime.strptime(d.expiration_date, "%m/%d/%Y")
|
||||||
if dt_whois.year == current_year:
|
if now <= dt_whois <= three_months_later:
|
||||||
domains_expiring.append((dt_whois, d))
|
domains_expiring.append((dt_whois, d))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Filter and sort by SSL expiration date (expected format: mm/dd/yyyy)
|
# Check SSL expiration date (assumed format "mm/dd/yyyy")
|
||||||
try:
|
try:
|
||||||
dt_ssl = datetime.strptime(d.ssl_expiration_date, "%m/%d/%Y")
|
dt_ssl = datetime.strptime(d.ssl_expiration_date, "%m/%d/%Y")
|
||||||
if dt_ssl.year == current_year:
|
if now <= dt_ssl <= three_months_later:
|
||||||
certs_expiring.append((dt_ssl, d))
|
ssl_expiring.append((dt_ssl, d))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Sort the lists in ascending order by the date
|
# Sort lists in ascending order by date
|
||||||
domains_expiring.sort(key=lambda x: x[0])
|
domains_expiring.sort(key=lambda x: x[0])
|
||||||
certs_expiring.sort(key=lambda x: x[0])
|
ssl_expiring.sort(key=lambda x: x[0])
|
||||||
|
# Extract just the domain objects
|
||||||
# Extract the domain objects from the sorted tuples
|
|
||||||
domains_expiring = [item[1] for item in domains_expiring]
|
domains_expiring = [item[1] for item in domains_expiring]
|
||||||
certs_expiring = [item[1] for item in certs_expiring]
|
ssl_expiring = [item[1] for item in ssl_expiring]
|
||||||
|
|
||||||
return render_template('home.html',
|
return render_template('home.html',
|
||||||
domains_expiring=domains_expiring,
|
domains_expiring=domains_expiring,
|
||||||
certs_expiring=certs_expiring)
|
ssl_expiring=ssl_expiring)
|
||||||
|
|
||||||
@domain_bp.route('/domains')
|
@domain_bp.route('/domains')
|
||||||
def domains():
|
def domains():
|
||||||
|
|
|
||||||
|
|
@ -202,3 +202,29 @@ def import_domains():
|
||||||
flash("No file uploaded", "warning")
|
flash("No file uploaded", "warning")
|
||||||
return redirect(url_for('tools.tools'))
|
return redirect(url_for('tools.tools'))
|
||||||
return render_template('import_domains.html')
|
return render_template('import_domains.html')
|
||||||
|
|
||||||
|
|
||||||
|
@tools_bp.route('/tools/remote_categories', methods=['GET', 'POST'])
|
||||||
|
def remote_categories():
|
||||||
|
from app.models import RemoteCategory
|
||||||
|
if request.method == 'POST':
|
||||||
|
category_name = request.form.get('category_name')
|
||||||
|
if category_name:
|
||||||
|
# Check if it exists
|
||||||
|
if not RemoteCategory.query.filter_by(name=category_name.strip()).first():
|
||||||
|
new_cat = RemoteCategory(name=category_name.strip())
|
||||||
|
db.session.add(new_cat)
|
||||||
|
db.session.commit()
|
||||||
|
categories = RemoteCategory.query.all()
|
||||||
|
return render_template('remote_categories.html', categories=categories)
|
||||||
|
|
||||||
|
@tools_bp.route('/tools/remote_categories/delete/<int:cat_id>', methods=['POST'])
|
||||||
|
def delete_remote_category(cat_id):
|
||||||
|
from app.models import RemoteCategory, ClientRemote
|
||||||
|
cat = RemoteCategory.query.get_or_404(cat_id)
|
||||||
|
# Optional: you might want to prevent deletion of defaults.
|
||||||
|
db.session.query(ClientRemote).filter_by(remote_category_id=cat.id).update({"remote_category_id": None}, synchronize_session=False)
|
||||||
|
db.session.delete(cat)
|
||||||
|
db.session.commit()
|
||||||
|
flash("Remote category deleted.", "success")
|
||||||
|
return redirect(url_for('tools.remote_categories'))
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
<!-- Section 1: Details -->
|
<!-- Section 1: Details -->
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<h2 class="section-title text-center">Details</h2>
|
|
||||||
<div id="detailsDisplay" class="text-center">
|
<div id="detailsDisplay" class="text-center">
|
||||||
{% if client.phone or client.address %}
|
{% if client.phone or client.address %}
|
||||||
<h2>Phone: {{ client.phone or "N/A" }} | Address: {{ client.address or "N/A" }}</h2>
|
<h2>Phone: {{ client.phone or "N/A" }} | Address: {{ client.address or "N/A" }}</h2>
|
||||||
|
|
@ -35,6 +34,142 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<!-- Section: Remote -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<h2 class="section-title">Remote</h2>
|
||||||
|
{% for category, remotes in remotes_by_category.items() %}
|
||||||
|
{% if remotes|length > 0 %}
|
||||||
|
<h3 class="mt-3">{{ category }}</h3>
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
{% if category == 'RDP' %}
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>IP Address</th>
|
||||||
|
<th>Port</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
{% elif category == 'SSL-VPN' %}
|
||||||
|
<tr>
|
||||||
|
<th>IP Address</th>
|
||||||
|
<th>Port</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
{% elif category == 'VPN' %}
|
||||||
|
<tr>
|
||||||
|
<th>IP Address</th>
|
||||||
|
<th>PSK</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
{% elif category == 'MGMT' %}
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Address</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
|
<tr>
|
||||||
|
<th>Details</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for remote in remotes %}
|
||||||
|
<tr>
|
||||||
|
{% if category == 'RDP' %}
|
||||||
|
<td>{{ remote.name }}</td>
|
||||||
|
<td>{{ remote.ip_address }}</td>
|
||||||
|
<td>{{ remote.port }}</td>
|
||||||
|
{% elif category == 'SSL-VPN' %}
|
||||||
|
<td>{{ remote.ip_address }}</td>
|
||||||
|
<td>{{ remote.port }}</td>
|
||||||
|
{% elif category == 'VPN' %}
|
||||||
|
<td>{{ remote.ip_address }}</td>
|
||||||
|
<td>{{ remote.psk }}</td>
|
||||||
|
{% elif category == 'MGMT' %}
|
||||||
|
<td>{{ remote.name }}</td>
|
||||||
|
<td><a href="{{ remote.address }}" target="_blank">{{ remote.address }}</a></td>
|
||||||
|
{% else %}
|
||||||
|
<td>{{ remote.details }}</td>
|
||||||
|
{% endif %}
|
||||||
|
<td>
|
||||||
|
<form action="{{ url_for('clients.remove_remote', client_id=client.id, remote_id=remote.id) }}" method="post" class="d-inline">
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this remote?');">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<!-- Button to toggle remote form -->
|
||||||
|
<button id="toggleRemoteFormBtn" class="btn btn-primary">Add Remote</button>
|
||||||
|
|
||||||
|
<!-- Remote Form: hidden by default -->
|
||||||
|
<div id="remoteForm" style="display: none;" class="mt-4">
|
||||||
|
<h3>Add Remote</h3>
|
||||||
|
<form action="{{ url_for('clients.add_remote', client_id=client.id) }}" method="post" id="remoteFormFields">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="remote_category">Remote Category</label>
|
||||||
|
<select class="form-control" id="remote_category" name="remote_category_id" onchange="changeRemoteFormFields()">
|
||||||
|
{% for rc in available_remote_categories %}
|
||||||
|
<option value="{{ rc.id }}">{{ rc.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div id="remoteFields">
|
||||||
|
<!-- Fields will be dynamically inserted by JavaScript -->
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success">Add Remote</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Toggle the remote form display when the button is clicked
|
||||||
|
document.getElementById("toggleRemoteFormBtn").addEventListener("click", function(){
|
||||||
|
var formDiv = document.getElementById("remoteForm");
|
||||||
|
if(formDiv.style.display === "none"){
|
||||||
|
formDiv.style.display = "block";
|
||||||
|
} else {
|
||||||
|
formDiv.style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeRemoteFormFields() {
|
||||||
|
var select = document.getElementById("remote_category");
|
||||||
|
var categoryName = select.options[select.selectedIndex].text;
|
||||||
|
var container = document.getElementById("remoteFields");
|
||||||
|
container.innerHTML = "";
|
||||||
|
if (categoryName === "RDP") {
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="remote_name">Name</label><input type="text" class="form-control" name="remote_name" placeholder="Name"></div>';
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="ip_address">IP Address</label><input type="text" class="form-control" name="ip_address" placeholder="IP Address"></div>';
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="port">Port</label><input type="text" class="form-control" name="port" placeholder="Port"></div>';
|
||||||
|
} else if (categoryName === "SSL-VPN") {
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="ip_address">IP Address</label><input type="text" class="form-control" name="ip_address" placeholder="IP Address"></div>';
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="port">Port</label><input type="text" class="form-control" name="port" placeholder="Port"></div>';
|
||||||
|
} else if (categoryName === "VPN") {
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="ip_address">IP Address</label><input type="text" class="form-control" name="ip_address" placeholder="IP Address"></div>';
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="psk">PSK</label><input type="text" class="form-control" name="psk" placeholder="Pre-Shared Key"></div>';
|
||||||
|
} else if (categoryName === "MGMT") {
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="remote_name">Name</label><input type="text" class="form-control" name="remote_name" placeholder="Name"></div>';
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="address">Address (URL)</label><input type="text" class="form-control" name="address" placeholder="http://example.com"></div>';
|
||||||
|
} else {
|
||||||
|
container.innerHTML += '<div class="form-group"><label for="details">Details</label><input type="text" class="form-control" name="details" placeholder="Details"></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function(){
|
||||||
|
changeRemoteFormFields();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<!-- Section 2: Passwords -->
|
<!-- Section 2: Passwords -->
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,15 @@
|
||||||
{% block title %}Home{% endblock %}
|
{% block title %}Home{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="my-4">Home</h1>
|
<h1 class="my-4">Expiring in the Next 3 Months</h1>
|
||||||
|
|
||||||
<!-- Domains Expiring this Year -->
|
<h2>Domains:</h2>
|
||||||
<h2 class="mb-3">Domains Expiring this Year</h2>
|
|
||||||
{% if domains_expiring and domains_expiring|length > 0 %}
|
{% if domains_expiring and domains_expiring|length > 0 %}
|
||||||
<table class="table table-bordered table-hover">
|
<table class="table table-bordered table-hover">
|
||||||
<thead class="thead-light">
|
<thead class="thead-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Domain</th>
|
<th>Domain</th>
|
||||||
<th>WHOIS Expiration</th>
|
<th>WHOIS Expiration</th>
|
||||||
<th>SSL Expiration</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -20,18 +18,16 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ d.domain }}</td>
|
<td>{{ d.domain }}</td>
|
||||||
<td>{{ d.expiration_date }}</td>
|
<td>{{ d.expiration_date }}</td>
|
||||||
<td>{{ d.ssl_expiration_date }}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No domains expiring this year.</p>
|
<p>No domains expiring in the next 3 months.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Certs Expiring this Year -->
|
<h2 class="mt-5">SSL Certificates:</h2>
|
||||||
<h2 class="mt-5 mb-3">Certs Expiring this Year</h2>
|
{% if ssl_expiring and ssl_expiring|length > 0 %}
|
||||||
{% if certs_expiring and certs_expiring|length > 0 %}
|
|
||||||
<table class="table table-bordered table-hover">
|
<table class="table table-bordered table-hover">
|
||||||
<thead class="thead-light">
|
<thead class="thead-light">
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -40,7 +36,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for d in certs_expiring %}
|
{% for d in ssl_expiring %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ d.domain }}</td>
|
<td>{{ d.domain }}</td>
|
||||||
<td>{{ d.ssl_expiration_date }}</td>
|
<td>{{ d.ssl_expiration_date }}</td>
|
||||||
|
|
@ -49,7 +45,7 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No certificates expiring this year.</p>
|
<p>No SSL certificates expiring in the next 3 months.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Remote Categories{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="my-4">Remote Categories</h1>
|
||||||
|
<form method="post" class="form-inline mb-4">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category_name" class="sr-only">Category Name:</label>
|
||||||
|
<input type="text" name="category_name" class="form-control" placeholder="Enter remote category">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary ml-2">Add Category</button>
|
||||||
|
</form>
|
||||||
|
{% if categories %}
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th>Category Name</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for cat in categories %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ cat.name }}</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ url_for('tools.delete_remote_category', cat_id=cat.id) }}" method="post" class="d-inline">
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Delete remote category?');">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<p>No remote categories defined.</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
Loading…
Reference in New Issue