Client Pages / Passwords
parent
0be541be85
commit
1c83e211e7
|
|
@ -8,6 +8,8 @@ def create_app():
|
||||||
# Create the Flask app and set the template folder (located in app/templates)
|
# Create the Flask app and set the template folder (located in app/templates)
|
||||||
app = Flask(__name__, template_folder='templates')
|
app = Flask(__name__, template_folder='templates')
|
||||||
|
|
||||||
|
app.secret_key = 'your_super_secret_key_here'
|
||||||
|
|
||||||
# Configure the SQLite database
|
# Configure the SQLite database
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(os.path.abspath(os.path.dirname(__file__)), 'domains.db')
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(os.path.abspath(os.path.dirname(__file__)), 'domains.db')
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
|
@ -27,4 +29,10 @@ def create_app():
|
||||||
from app.routes.ssl import ssl_bp
|
from app.routes.ssl import ssl_bp
|
||||||
app.register_blueprint(ssl_bp)
|
app.register_blueprint(ssl_bp)
|
||||||
|
|
||||||
|
from app.routes.tools import tools_bp
|
||||||
|
app.register_blueprint(tools_bp)
|
||||||
|
|
||||||
|
from app.routes.clients import clients_bp
|
||||||
|
app.register_blueprint(clients_bp)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,16 @@
|
||||||
from app import db
|
from app import db
|
||||||
|
|
||||||
|
# Association tables for many-to-many relationships.
|
||||||
|
client_domains = db.Table('client_domains',
|
||||||
|
db.Column('client_id', db.Integer, db.ForeignKey('client.id')),
|
||||||
|
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')),
|
||||||
|
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}
|
||||||
|
|
@ -12,3 +23,30 @@ class Domain(db.Model):
|
||||||
|
|
||||||
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} | Whois: {self.expiration_date} | SSL: {self.ssl_expiration_date} | ssl_only: {self.ssl_only}>"
|
||||||
|
|
||||||
|
class Client(db.Model):
|
||||||
|
__tablename__ = 'client'
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(255), nullable=False)
|
||||||
|
phone = db.Column(db.String(255))
|
||||||
|
address = db.Column(db.String(255))
|
||||||
|
|
||||||
|
# Relationship for storing passwords
|
||||||
|
passwords = db.relationship('ClientPassword', backref='client', lazy=True)
|
||||||
|
# Many-to-many relationships for domains and SSL domains
|
||||||
|
domains = db.relationship('Domain', secondary=client_domains, backref='clients')
|
||||||
|
ssl_domains = db.relationship('Domain', secondary=client_ssl, backref='ssl_clients')
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Client {self.name}>"
|
||||||
|
|
||||||
|
class ClientPassword(db.Model):
|
||||||
|
__tablename__ = 'client_password'
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
item = db.Column(db.String(255), nullable=False)
|
||||||
|
username = db.Column(db.String(255), nullable=False)
|
||||||
|
password = db.Column(db.String(255), nullable=False)
|
||||||
|
client_id = db.Column(db.Integer, db.ForeignKey('client.id'), nullable=False)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<ClientPassword {self.item}>"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
from flask import Blueprint, render_template, request, redirect, url_for
|
||||||
|
from app.models import Client, ClientPassword, Domain
|
||||||
|
from app import db
|
||||||
|
|
||||||
|
clients_bp = Blueprint('clients', __name__)
|
||||||
|
|
||||||
|
# List all clients
|
||||||
|
@clients_bp.route('/clients')
|
||||||
|
def clients():
|
||||||
|
clients_list = Client.query.all()
|
||||||
|
return render_template('clients.html', clients=clients_list)
|
||||||
|
|
||||||
|
# Add multiple clients at once
|
||||||
|
@clients_bp.route('/clients/add', methods=['GET', 'POST'])
|
||||||
|
def add_client():
|
||||||
|
if request.method == 'POST':
|
||||||
|
names = request.form.getlist('name')
|
||||||
|
for name in names:
|
||||||
|
if name.strip():
|
||||||
|
new_client = Client(name=name.strip())
|
||||||
|
db.session.add(new_client)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.clients'))
|
||||||
|
return render_template('add_client.html')
|
||||||
|
|
||||||
|
# Client detail page with all four sections
|
||||||
|
@clients_bp.route('/clients/<int:client_id>')
|
||||||
|
def client_detail(client_id):
|
||||||
|
client = Client.query.get_or_404(client_id)
|
||||||
|
# For the Domains dropdown: only available non-SSL-only domains.
|
||||||
|
available_domains = Domain.query.filter_by(ssl_only=False).all()
|
||||||
|
# For the SSL dropdown: only available SSL-only domains.
|
||||||
|
available_ssl = Domain.query.filter_by(ssl_only=True).all()
|
||||||
|
return render_template('client_detail.html', client=client,
|
||||||
|
available_domains=available_domains,
|
||||||
|
available_ssl=available_ssl)
|
||||||
|
|
||||||
|
# Update client details (phone, address)
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/update_details', methods=['POST'])
|
||||||
|
def update_client_details(client_id):
|
||||||
|
client = Client.query.get_or_404(client_id)
|
||||||
|
client.phone = request.form.get('phone')
|
||||||
|
client.address = request.form.get('address')
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client.id))
|
||||||
|
|
||||||
|
# Add a new password for the client
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/add_password', methods=['POST'])
|
||||||
|
def add_client_password(client_id):
|
||||||
|
client = Client.query.get_or_404(client_id)
|
||||||
|
item = request.form.get('item')
|
||||||
|
username = request.form.get('username')
|
||||||
|
password = request.form.get('password')
|
||||||
|
if item and username and password:
|
||||||
|
new_pass = ClientPassword(item=item, username=username, password=password, client_id=client.id)
|
||||||
|
db.session.add(new_pass)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client.id))
|
||||||
|
|
||||||
|
# Attach a domain (non SSL-only) to the client
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/attach_domain', methods=['POST'])
|
||||||
|
def attach_domain(client_id):
|
||||||
|
client = Client.query.get_or_404(client_id)
|
||||||
|
domain_id = request.form.get('domain_id')
|
||||||
|
if domain_id:
|
||||||
|
domain = Domain.query.get(int(domain_id))
|
||||||
|
if domain and domain not in client.domains:
|
||||||
|
client.domains.append(domain)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client.id))
|
||||||
|
|
||||||
|
# Attach an SSL domain (ssl_only) to the client
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/attach_ssl', methods=['POST'])
|
||||||
|
def attach_ssl(client_id):
|
||||||
|
client = Client.query.get_or_404(client_id)
|
||||||
|
domain_id = request.form.get('ssl_domain_id')
|
||||||
|
if domain_id:
|
||||||
|
domain = Domain.query.get(int(domain_id))
|
||||||
|
if domain and domain not in client.ssl_domains:
|
||||||
|
client.ssl_domains.append(domain)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client.id))
|
||||||
|
|
||||||
|
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/remove_domain/<int:domain_id>', methods=['POST'])
|
||||||
|
def remove_domain(client_id, domain_id):
|
||||||
|
client = Client.query.get_or_404(client_id)
|
||||||
|
domain = Domain.query.get_or_404(domain_id)
|
||||||
|
if domain in client.domains:
|
||||||
|
client.domains.remove(domain)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client.id))
|
||||||
|
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/remove_ssl/<int:domain_id>', methods=['POST'])
|
||||||
|
def remove_ssl(client_id, domain_id):
|
||||||
|
client = Client.query.get_or_404(client_id)
|
||||||
|
domain = Domain.query.get_or_404(domain_id)
|
||||||
|
if domain in client.ssl_domains:
|
||||||
|
client.ssl_domains.remove(domain)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client.id))
|
||||||
|
|
||||||
|
@clients_bp.route('/clients/<int:client_id>/remove_password/<int:password_id>', methods=['POST'])
|
||||||
|
def remove_password(client_id, password_id):
|
||||||
|
password = ClientPassword.query.get_or_404(password_id)
|
||||||
|
db.session.delete(password)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('clients.client_detail', client_id=client_id))
|
||||||
|
|
@ -71,13 +71,14 @@ def add_domain():
|
||||||
return redirect(url_for('domain.domains'))
|
return redirect(url_for('domain.domains'))
|
||||||
return render_template('add_domain.html')
|
return render_template('add_domain.html')
|
||||||
|
|
||||||
@domain_bp.route('/delete/<int:domain_id>', methods=['GET'])
|
@domain_bp.route('/delete/<int:domain_id>', methods=['POST'])
|
||||||
def delete_domain(domain_id):
|
def delete_domain(domain_id):
|
||||||
domain_to_delete = Domain.query.get_or_404(domain_id)
|
domain_to_delete = Domain.query.get_or_404(domain_id)
|
||||||
db.session.delete(domain_to_delete)
|
db.session.delete(domain_to_delete)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for('domain.domains'))
|
return redirect(url_for('domain.domains'))
|
||||||
|
|
||||||
|
|
||||||
@domain_bp.route('/domains/refresh')
|
@domain_bp.route('/domains/refresh')
|
||||||
def refresh_domains():
|
def refresh_domains():
|
||||||
# Refresh only non-SSL-only domains
|
# Refresh only non-SSL-only domains
|
||||||
|
|
@ -88,3 +89,18 @@ def refresh_domains():
|
||||||
d.ssl_expiration_date = get_ssl_expiration(d.domain)
|
d.ssl_expiration_date = get_ssl_expiration(d.domain)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for('domain.domains'))
|
return redirect(url_for('domain.domains'))
|
||||||
|
|
||||||
|
@domain_bp.route('/refresh/<int:domain_id>', methods=['GET'])
|
||||||
|
def refresh_individual(domain_id):
|
||||||
|
domain = Domain.query.get_or_404(domain_id)
|
||||||
|
from app.utils import get_whois_expiration, get_ssl_expiration
|
||||||
|
# Update WHOIS expiration date
|
||||||
|
domain.expiration_date = get_whois_expiration(domain.domain)
|
||||||
|
# Update SSL expiration date
|
||||||
|
domain.ssl_expiration_date = get_ssl_expiration(domain.domain)
|
||||||
|
db.session.commit()
|
||||||
|
# Redirect back to the appropriate page based on the domain type
|
||||||
|
if domain.ssl_only:
|
||||||
|
return redirect(url_for('ssl.ssl_page'))
|
||||||
|
else:
|
||||||
|
return redirect(url_for('domain.domains'))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Add Client(s){% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="my-4">Add Client(s)</h1>
|
||||||
|
<form method="post">
|
||||||
|
<div id="clientFields">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" name="name" class="form-control" placeholder="Enter client name">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-secondary" onclick="addField()">Add Another</button>
|
||||||
|
<br><br>
|
||||||
|
<button type="submit" class="btn btn-success">Add Clients</button>
|
||||||
|
</form>
|
||||||
|
<br>
|
||||||
|
<a href="{{ url_for('clients.clients') }}" class="btn btn-link">Back to Clients</a>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function addField() {
|
||||||
|
var container = document.getElementById("clientFields");
|
||||||
|
var div = document.createElement("div");
|
||||||
|
div.className = "form-group";
|
||||||
|
var input = document.createElement("input");
|
||||||
|
input.type = "text";
|
||||||
|
input.name = "name";
|
||||||
|
input.className = "form-control";
|
||||||
|
input.placeholder = "Enter client name";
|
||||||
|
div.appendChild(input);
|
||||||
|
container.appendChild(div);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -1,27 +1,33 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Add Domain{% endblock %}
|
{% block title %}Add Domain{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Add Domain(s)</h1>
|
<div class="container">
|
||||||
<form method="post">
|
<h1 class="my-4">Add Domain(s)</h1>
|
||||||
|
<form method="post">
|
||||||
<div id="domainFields">
|
<div id="domainFields">
|
||||||
<input type="text" name="domain" placeholder="Enter domain name">
|
<div class="form-group">
|
||||||
|
<input type="text" name="domain" class="form-control" placeholder="Enter domain name">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<button type="button" class="btn btn-secondary" onclick="addField()">Add Another</button>
|
||||||
<button type="button" onclick="addField()">Add Another</button>
|
|
||||||
<br><br>
|
<br><br>
|
||||||
<input type="submit" value="Save">
|
<button type="submit" class="btn btn-success">Save Domains</button>
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
<a href="{{ url_for('domain.domains') }}">Back to Domains</a>
|
<a href="{{ url_for('domain.domains') }}" class="btn btn-link">Back to Domains</a>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
function addField() {
|
function addField() {
|
||||||
var container = document.getElementById("domainFields");
|
var container = document.getElementById("domainFields");
|
||||||
var input = document.createElement("input");
|
var div = document.createElement("div");
|
||||||
input.type = "text";
|
div.className = "form-group";
|
||||||
input.name = "domain";
|
var input = document.createElement("input");
|
||||||
input.placeholder = "Enter domain name";
|
input.type = "text";
|
||||||
container.appendChild(document.createElement("br"));
|
input.name = "domain";
|
||||||
container.appendChild(input);
|
input.className = "form-control";
|
||||||
}
|
input.placeholder = "Enter domain name";
|
||||||
|
div.appendChild(input);
|
||||||
|
container.appendChild(div);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,33 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Add SSL Domain{% endblock %}
|
{% block title %}Add SSL Domain{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Add SSL Domain(s)</h1>
|
<div class="container">
|
||||||
<form method="post">
|
<h1 class="my-4">Add SSL Domain(s)</h1>
|
||||||
|
<form method="post">
|
||||||
<div id="domainFields">
|
<div id="domainFields">
|
||||||
<input type="text" name="domain" placeholder="Enter domain name">
|
<div class="form-group">
|
||||||
|
<input type="text" name="domain" class="form-control" placeholder="Enter domain name">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<button type="button" class="btn btn-secondary" onclick="addField()">Add Another</button>
|
||||||
<button type="button" onclick="addField()">Add Another</button>
|
|
||||||
<br><br>
|
<br><br>
|
||||||
<input type="submit" value="Save">
|
<button type="submit" class="btn btn-success">Save SSL Domains</button>
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
<a href="{{ url_for('ssl.ssl_page') }}">Back to SSL Page</a>
|
<a href="{{ url_for('ssl.ssl_page') }}" class="btn btn-link">Back to SSL Page</a>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
function addField() {
|
function addField() {
|
||||||
var container = document.getElementById("domainFields");
|
var container = document.getElementById("domainFields");
|
||||||
var input = document.createElement("input");
|
var div = document.createElement("div");
|
||||||
input.type = "text";
|
div.className = "form-group";
|
||||||
input.name = "domain";
|
var input = document.createElement("input");
|
||||||
input.placeholder = "Enter domain name";
|
input.type = "text";
|
||||||
container.appendChild(document.createElement("br"));
|
input.name = "domain";
|
||||||
container.appendChild(input);
|
input.className = "form-control";
|
||||||
}
|
input.placeholder = "Enter domain name";
|
||||||
|
div.appendChild(input);
|
||||||
|
container.appendChild(div);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,49 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>{% block title %}My Domain App{% endblock %}</title>
|
<title>{% block title %}My Domain App{% endblock %}</title>
|
||||||
<style>
|
<!-- Bootstrap CSS -->
|
||||||
nav {
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
|
||||||
background-color: #eee;
|
<style>
|
||||||
padding: 10px;
|
.section-title {
|
||||||
margin-bottom: 20px;
|
margin-top: 30px;
|
||||||
}
|
margin-bottom: 15px;
|
||||||
nav a {
|
}
|
||||||
margin-right: 15px;
|
</style>
|
||||||
text-decoration: none;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav>
|
<nav class="navbar navbar-expand-lg navbar-light bg-light mb-4">
|
||||||
<a href="{{ url_for('domain.home') }}">Home</a>
|
<a class="navbar-brand" href="{{ url_for('domain.home') }}">My Domain App</a>
|
||||||
<a href="{{ url_for('domain.domains') }}">Domains</a>
|
<div class="collapse navbar-collapse">
|
||||||
<a href="{{ url_for('ssl.ssl_page') }}">SSL</a>
|
<ul class="navbar-nav mr-auto">
|
||||||
</nav>
|
<li class="nav-item"><a class="nav-link" href="{{ url_for('domain.home') }}">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="{{ url_for('clients.clients') }}">Clients</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="{{ url_for('domain.domains') }}">Domains</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="{{ url_for('ssl.ssl_page') }}">SSL</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="{{ url_for('tools.tools') }}">Tools</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="container">
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if messages %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
|
||||||
|
{{ message }}
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
<!-- Bootstrap JS and dependencies -->
|
||||||
|
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
|
||||||
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
||||||
|
{% block scripts %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}{{ client.name }}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="display-4">{{ client.name }}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Section 1: Details -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<h2 class="section-title text-center">Details</h2>
|
||||||
|
<div id="detailsDisplay" class="text-center">
|
||||||
|
{% if client.phone or client.address %}
|
||||||
|
<h2>Phone: {{ client.phone or "N/A" }} | Address: {{ client.address or "N/A" }}</h2>
|
||||||
|
{% else %}
|
||||||
|
<p>No details available.</p>
|
||||||
|
{% endif %}
|
||||||
|
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#detailsForm" aria-expanded="false" aria-controls="detailsForm">
|
||||||
|
Add/Update Details
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="collapse mt-3" id="detailsForm">
|
||||||
|
<div class="card card-body">
|
||||||
|
<form action="{{ url_for('clients.update_client_details', client_id=client.id) }}" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="phone">Phone Number:</label>
|
||||||
|
<input type="text" class="form-control" name="phone" value="{{ client.phone or '' }}">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="address">Address:</label>
|
||||||
|
<input type="text" class="form-control" name="address" value="{{ client.address or '' }}">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success">Update Details</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<!-- Section 2: Passwords -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<h2 class="section-title">Passwords</h2>
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th>Item</th>
|
||||||
|
<th>Username</th>
|
||||||
|
<th>Password</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for p in client.passwords %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ p.item }}</td>
|
||||||
|
<td>{{ p.username }}</td>
|
||||||
|
<td>{{ p.password }}</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ url_for('clients.remove_password', client_id=client.id, password_id=p.id) }}" method="post" class="d-inline">
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#passwordForm" aria-expanded="false" aria-controls="passwordForm">
|
||||||
|
Add Password
|
||||||
|
</button>
|
||||||
|
<div class="collapse mt-3" id="passwordForm">
|
||||||
|
<div class="card card-body">
|
||||||
|
<form action="{{ url_for('clients.add_client_password', client_id=client.id) }}" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="item">Item:</label>
|
||||||
|
<input type="text" class="form-control" name="item" placeholder="Item">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username">Username:</label>
|
||||||
|
<input type="text" class="form-control" name="username" placeholder="Username">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Password:</label>
|
||||||
|
<input type="text" class="form-control" name="password" placeholder="Password">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success">Add Password</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<!-- Section 3: Domains -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<h2 class="section-title">Domains</h2>
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th>Domain</th>
|
||||||
|
<th>WHOIS Expiration</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for d in client.domains %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ d.domain }}</td>
|
||||||
|
<td>{{ d.expiration_date }}</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ url_for('clients.remove_domain', client_id=client.id, domain_id=d.id) }}" method="post" class="d-inline">
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<form action="{{ url_for('clients.attach_domain', client_id=client.id) }}" method="post" class="form-inline">
|
||||||
|
<div class="form-group mb-2">
|
||||||
|
<label for="domain_id" class="sr-only">Select Domain</label>
|
||||||
|
<select name="domain_id" class="form-control">
|
||||||
|
{% for d in available_domains %}
|
||||||
|
<option value="{{ d.id }}">{{ d.domain }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary mb-2 ml-2">Attach Domain</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<!-- Section 4: SSL -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<h2 class="section-title">SSL</h2>
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th>Domain</th>
|
||||||
|
<th>SSL Expiration</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for d in client.ssl_domains %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ d.domain }}</td>
|
||||||
|
<td>{{ d.ssl_expiration_date }}</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ url_for('clients.remove_ssl', client_id=client.id, domain_id=d.id) }}" method="post" class="d-inline">
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<form action="{{ url_for('clients.attach_ssl', client_id=client.id) }}" method="post" class="form-inline">
|
||||||
|
<div class="form-group mb-2">
|
||||||
|
<label for="ssl_domain_id" class="sr-only">Select SSL Domain</label>
|
||||||
|
<select name="ssl_domain_id" class="form-control">
|
||||||
|
{% for d in available_ssl %}
|
||||||
|
<option value="{{ d.id }}">{{ d.domain }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary mb-2 ml-2">Attach SSL Domain</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Clients{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="my-4">Clients</h1>
|
||||||
|
<div class="mb-3">
|
||||||
|
<a href="{{ url_for('clients.add_client') }}" class="btn btn-primary">Add Client</a>
|
||||||
|
</div>
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th>Client Name</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for client in clients %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ url_for('clients.client_detail', client_id=client.id) }}">{{ client.name }}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -1,28 +1,41 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Domains{% endblock %}
|
{% block title %}Domains{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Domain List</h1>
|
<div class="container">
|
||||||
<button onclick="window.location.href='{{ url_for('domain.refresh_domains') }}'">Refresh Domains</button>
|
<h1 class="my-4">Domains</h1>
|
||||||
<table border="1" cellpadding="5" cellspacing="0">
|
<div class="mb-3">
|
||||||
<thead>
|
<a href="{{ url_for('domain.refresh_domains') }}" class="btn btn-secondary">Refresh Domains (All)</a>
|
||||||
<tr>
|
</div>
|
||||||
<th>Domain</th>
|
<table class="table table-bordered table-hover">
|
||||||
<th>Domain Expiration</th>
|
<thead class="thead-light">
|
||||||
<th>Action</th>
|
<tr>
|
||||||
</tr>
|
<th>Domain</th>
|
||||||
|
<th>WHOIS Expiration</th>
|
||||||
|
<th>SSL Expiration</th>
|
||||||
|
<th>Refresh</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for domain in domains %}
|
{% for domain in domains %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ domain.domain }}</td>
|
<td>{{ domain.domain }}</td>
|
||||||
<td>{{ domain.expiration_date }}</td>
|
<td>{{ domain.expiration_date }}</td>
|
||||||
<td>
|
<td>{{ domain.ssl_expiration_date }}</td>
|
||||||
<a href="{{ url_for('domain.delete_domain', domain_id=domain.id) }}" onclick="return confirm('Are you sure you want to delete this domain?');">X</a>
|
<td>
|
||||||
</td>
|
<a href="{{ url_for('domain.refresh_individual', domain_id=domain.id) }}" class="btn btn-sm btn-primary">Refresh</a>
|
||||||
</tr>
|
</td>
|
||||||
{% endfor %}
|
<td>
|
||||||
|
<form action="{{ url_for('domain.delete_domain', domain_id=domain.id) }}" method="post" class="d-inline">
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Are you sure you want to delete this domain?');">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<br>
|
<div class="mt-3">
|
||||||
<button onclick="window.location.href='{{ url_for('domain.add_domain') }}'">Add Domain</button>
|
<a href="{{ url_for('domain.add_domain') }}" class="btn btn-primary">Add Domain</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,55 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Home{% endblock %}
|
{% block title %}Home{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Domains Expiring this Year</h1>
|
<div class="container">
|
||||||
{% if domains_expiring and domains_expiring|length > 0 %}
|
<h1 class="my-4">Home</h1>
|
||||||
<table border="1" cellpadding="5" cellspacing="0">
|
|
||||||
<thead>
|
<!-- Domains Expiring this Year -->
|
||||||
<tr>
|
<h2 class="mb-3">Domains Expiring this Year</h2>
|
||||||
<th>Domain</th>
|
{% if domains_expiring and domains_expiring|length > 0 %}
|
||||||
<th>WHOIS Expiration</th>
|
<table class="table table-bordered table-hover">
|
||||||
</tr>
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th>Domain</th>
|
||||||
|
<th>WHOIS Expiration</th>
|
||||||
|
<th>SSL Expiration</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for d in domains_expiring %}
|
{% for d in domains_expiring %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ d.domain }}</td>
|
<td>{{ d.domain }}</td>
|
||||||
<td>{{ d.expiration_date }}</td>
|
<td>{{ d.expiration_date }}</td>
|
||||||
</tr>
|
<td>{{ d.ssl_expiration_date }}</td>
|
||||||
{% endfor %}
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No domains expiring this year.</p>
|
<p>No domains expiring this year.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h1>Certs Expiring this Year</h1>
|
<!-- Certs Expiring this Year -->
|
||||||
{% if certs_expiring and certs_expiring|length > 0 %}
|
<h2 class="mt-5 mb-3">Certs Expiring this Year</h2>
|
||||||
<table border="1" cellpadding="5" cellspacing="0">
|
{% if certs_expiring and certs_expiring|length > 0 %}
|
||||||
<thead>
|
<table class="table table-bordered table-hover">
|
||||||
<tr>
|
<thead class="thead-light">
|
||||||
<th>Domain</th>
|
<tr>
|
||||||
<th>SSL Expiration</th>
|
<th>Domain</th>
|
||||||
</tr>
|
<th>SSL Expiration</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for d in certs_expiring %}
|
{% for d in certs_expiring %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ d.domain }}</td>
|
<td>{{ d.domain }}</td>
|
||||||
<td>{{ d.ssl_expiration_date }}</td>
|
<td>{{ d.ssl_expiration_date }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No certificates expiring this year.</p>
|
<p>No certificates expiring this year.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,49 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}SSL Certificates{% endblock %}
|
{% block title %}SSL Certificates{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>SSL Certificates</h1>
|
<div class="container">
|
||||||
<button onclick="window.location.href='{{ url_for('ssl.refresh_ssl') }}'">Refresh SSL</button>
|
<h1 class="my-4">SSL Certificates</h1>
|
||||||
<table border="1" cellpadding="5" cellspacing="0">
|
<div class="mb-3">
|
||||||
<thead>
|
<a href="{{ url_for('ssl.refresh_ssl') }}" class="btn btn-secondary">Refresh SSL (All)</a>
|
||||||
<tr>
|
</div>
|
||||||
<th>Domain</th>
|
<table class="table table-bordered table-hover">
|
||||||
<th>SSL Expiration</th>
|
<thead class="thead-light">
|
||||||
<th>Type</th>
|
<tr>
|
||||||
<th>Action</th>
|
<th>Domain</th>
|
||||||
</tr>
|
<th>WHOIS Expiration</th>
|
||||||
|
<th>SSL Expiration</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Refresh</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for d in domains %}
|
{% for d in domains %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ d.domain }}</td>
|
<td>{{ d.domain }}</td>
|
||||||
<td>{{ d.ssl_expiration_date }}</td>
|
<td>{{ d.expiration_date }}</td>
|
||||||
<td>
|
<td>{{ d.ssl_expiration_date }}</td>
|
||||||
{% if d.ssl_only %}
|
<td>
|
||||||
Email
|
{% if d.ssl_only %}
|
||||||
{% else %}
|
<span class="badge badge-info">SSL Only</span>
|
||||||
Domain
|
{% else %}
|
||||||
{% endif %}
|
<span class="badge badge-secondary">Normal</span>
|
||||||
</td>
|
{% endif %}
|
||||||
<td>
|
</td>
|
||||||
<a href="{{ url_for('domain.delete_domain', domain_id=d.id) }}" onclick="return confirm('Are you sure you want to delete this domain?');">X</a>
|
<td>
|
||||||
</td>
|
<a href="{{ url_for('domain.refresh_individual', domain_id=d.id) }}" class="btn btn-sm btn-primary">Refresh</a>
|
||||||
</tr>
|
</td>
|
||||||
{% endfor %}
|
<td>
|
||||||
|
<form action="{{ url_for('domain.delete_domain', domain_id=d.id) }}" method="post" class="d-inline">
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Are you sure you want to delete this domain?');">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<br>
|
<div class="mt-3">
|
||||||
<button onclick="window.location.href='{{ url_for('ssl.add_ssl_domain') }}'">Add SSL Domain</button>
|
<a href="{{ url_for('ssl.add_ssl_domain') }}" class="btn btn-primary">Add SSL Domain</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,26 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Tools{% endblock %}
|
{% block title %}Tools{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Tools</h1>
|
<div class="container">
|
||||||
|
<h1 class="my-4">Tools</h1>
|
||||||
<div>
|
<div class="card">
|
||||||
<h2>Import / Export Data</h2>
|
<div class="card-header">
|
||||||
<div>
|
Import / Export Data
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="mb-4">
|
||||||
<form action="{{ url_for('tools.import_data') }}" method="post" enctype="multipart/form-data">
|
<form action="{{ url_for('tools.import_data') }}" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="form-group">
|
||||||
<label for="file">Import Data:</label>
|
<label for="file">Import Data:</label>
|
||||||
<input type="file" name="file" id="file">
|
<input type="file" class="form-control-file" name="file" id="file">
|
||||||
<button type="submit">Import</button>
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Import</button>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="{{ url_for('tools.export_data') }}" class="btn btn-secondary">Export Data</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top:20px;">
|
</div>
|
||||||
<a href="{{ url_for('tools.export_data') }}">
|
|
||||||
<button type="button">Export Data</button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue