Skip to content

Commit

Permalink
Merge branch 'fasterFront' into 'development'
Browse files Browse the repository at this point in the history
Faster front

See merge request hosting/api!79
  • Loading branch information
Valentin Lantigny committed May 6, 2024
2 parents ba550cf + 0a1c4e0 commit 449e1f0
Show file tree
Hide file tree
Showing 20 changed files with 520 additions and 332 deletions.
2 changes: 1 addition & 1 deletion backend/proxmox_api/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ def create_app():
app = connexion.App(__name__, specification_dir='./swagger/')
app.app.json_encoder = encoder.JSONEncoder
app.app.config['SQLALCHEMY_DATABASE_URI'] = config.DATABASE_URI
CORS(app.app)
scheduler = APScheduler()
app.add_api('swagger.yaml', arguments={'title': 'Proxmox'}, pythonic_params=True)
CORS(app.app)
return app, scheduler


Expand Down
28 changes: 14 additions & 14 deletions backend/proxmox_api/controllers/default_controller.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
from logging import error
from proxmox_api import proxmox

import connexion
import requests
import json
from threading import Thread
from requests.api import head
from slugify import slugify
from proxmox_api.models.dns_entry_item import DnsEntryItem # noqa: E501
from proxmox_api.models.dns_item import DnsItem # noqa: E501
from proxmox_api.models.vm_id_item import VmIdItem # noqa: E501
from proxmox_api.models.vm_item import VmItem # noqa: E501
from proxmox_api import util
from proxmox_api.db.db_functions import *
from datetime import datetime
import proxmox_api.db.db_functions as dbfct
from proxmox_api.proxmox import is_admin
from proxmox_api.db import db_models
Expand Down Expand Up @@ -57,11 +50,10 @@ def validate_dns(): # noqa: E501

try:
userid = update_body['userid']
except:
except KeyError:
return {"error": "Bad userid"}, 400


return proxmox.accept_user_dns(update_body['userid'], update_body['dnsentry'], update_body['dnsip'])
return proxmox.accept_user_dns(userid, update_body['dnsentry'], update_body['dnsip'])

def create_dns(body=None): # noqa: E501
"""create dns entry
Expand Down Expand Up @@ -652,7 +644,6 @@ def renew_ip():


def delete_dns_id(dnsid): # noqa: E501
print("delete dns entry")
"""delete dns entry by id
# noqa: E501
Expand All @@ -666,6 +657,9 @@ def delete_dns_id(dnsid): # noqa: E501
dnsid = int(dnsid)
except:
return {"status": "error not an integer"}, 500

# Get the sendMail parameter from the request
sendMail = connexion.request.args.get('sendMail', default=False, type=bool)

headers = {"Authorization": connexion.request.headers["Authorization"]}
status_code, cas = util.check_cas_token(headers)
Expand Down Expand Up @@ -697,14 +691,20 @@ def delete_dns_id(dnsid): # noqa: E501
return {"status": "cotisation expired"}, 403

user_id = cas['sub']

# print(update_body)
# try:
# sendMail = bool(update_body['sendMail'])
# except KeyError:
# return {"error": "Not a boolean"}, 400

if "attributes" in cas:
if "memberOf" in cas["attributes"]:
if is_admin(cas["attributes"]["memberOf"]):
return proxmox.del_user_dns(dnsid)
return proxmox.del_user_dns(dnsid, sendMail)

if dnsid in map(int, proxmox.get_user_dns(user_id)[0]):
return proxmox.del_user_dns(dnsid)
return proxmox.del_user_dns(dnsid, sendMail)
else:
return {"status": "error"}, 500

Expand Down
2 changes: 1 addition & 1 deletion backend/proxmox_api/db/db_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def get_entry_host_and_validation(id):
if domainName is None:
return {"dns": "not found"}, 404
else:
return {"host": domainName.entry, "validated" : domainName.validated}, 201
return {"host": domainName.entry, "validated" : domainName.validated, "ip" : domainName.ip, "userId" : domainName.userId}, 201


def get_entry_userid(dnsid):
Expand Down
6 changes: 5 additions & 1 deletion backend/proxmox_api/ddns.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ def delete_dns_record(entry):
""" Delete a record with ddns protocole in configuration.MAIN_DNS_SERVER_IP DNS server """
print("Deleting entry: " + str(entry))
dns_domain = "%s." % configuration.HOSTING_DOMAIN
print(keyring)

update = dns.update.Update(dns_domain, keyring=keyring)
print(update)
update.present(entry)
update.delete(entry)
response = dns.query.tcp(update, configuration.MAIN_DNS_SERVER_IP, timeout=5)
print(response)
if response.rcode() == 0:
return {"dns": "entry deleted"}, 201
if response.rcode() == 3:
return {"dns": "entry does not exist"}, 201 #C'est très crade, mais c'est dans le cas ou l'entrée n'a pas été validée, mais l'appel à ddns se fais quand même.
logging.error("Problem in get_vm_status(" + str(vmid) + ") when getting VM status: " + str(e))
logging.error("Problem in delete_dns_id(" + entry + ")")
return {"dns": "error occured"}, 500
29 changes: 28 additions & 1 deletion backend/proxmox_api/proxmox.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
def add_user_dns(user_id, entry, ip):
database.add_dns_entry(user_id, entry, ip, validated=False)
logging.info("DNS entry added: " + str(user_id) + " " + str(entry) + "=> " + str(ip))
logging.info("send a notification to [email protected]")
mailBody = util.mailHTMLBureau(user_id, entry, ip)
try :
util.sendMailBureau(mailBody, user_id)
except Exception as e:
print("ERROR : the mail to " + str(user_id) + " failed to be sent : " + str(e))
return {"dns": "added"}, 201


Expand All @@ -42,8 +48,21 @@ def accept_user_dns(user_id, entry, ip):

rep_msg, rep_code = ddns.create_entry(entry, ip)
if rep_code == 201:

database.validate_dns_entry(user_id, entry, ip)
logging.info("DNS entry validated: " + str(user_id) + " " + str(entry) + "=> " + str(ip))
logging.info("send a notification to " + str(user_id))
print("send a notification to " + str(user_id))
mailBody = util.mailHTMLAdherent(user_id, entry, ip, "acceptée")
account, status = util.get_adh6_account(user_id)
if (account is None):
return {"error": "Impossible to retrieve the user info"}, 404
try :
util.sendMailAdherent(account["email"], mailBody, entry, True)
except Exception as e:
print("ERROR : the mail to " + str(user_id) + " failed to be sent : " + str(e))
return rep_msg, rep_code

return rep_msg, rep_code

def isDnsEntryExistingInDatabase(entry):
Expand All @@ -63,7 +82,7 @@ def get_user_dns(user_id = ""):



def del_user_dns(dnsid):
def del_user_dns(dnsid, sendMail:bool = False):
db_result = database.get_entry_host_and_validation(dnsid)
if db_result is None:
return {"dns": "not found"}, 404
Expand All @@ -83,6 +102,14 @@ def del_user_dns(dnsid):
else:
database.del_dns_entry(dnsid)
logging.info("DNS entry deleted: " + str(dnsid))
if sendMail:
user_id = db_result[0]['userId']
ip = db_result[0]['ip']
mailBody = util.mailHTMLAdherent(user_id, entry, ip, "refusée")
try :
util.sendMailAdherent(mailBody, user_id, entry, False)
except Exception as e:
print("ERROR : the mail to " + str(user_id) + " failed to be sent : " + str(e))
return {"dns": "entry deleted"}, 201


Expand Down
7 changes: 7 additions & 0 deletions backend/proxmox_api/swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,13 @@ paths:
schema:
type: string
example: "3"
- name: sendMail
in: query
description: do we send an email to the user
required: false
schema:
type: string
example: "sendMail: true"
responses:
"201":
description: deleted dns entry by id
Expand Down
90 changes: 88 additions & 2 deletions backend/proxmox_api/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
import connexion
import tempfile
import subprocess
from flask_apscheduler import APScheduler
from flask_cors import CORS
import proxmox_api.config.configuration as config
import proxmox_api.config.configuration as config
from proxmox_api import encoder
from proxmox_api.db.db_models import db
from email.message import EmailMessage
import smtplib


if not bool(config.ADH6_API_KEY):
raise Exception("NO ADH6 API KEY GIVEN")
Expand Down Expand Up @@ -344,3 +345,88 @@ def subscribe_to_hosting_ML(username):
return status, response.status_code

return {"error" : "the user " + username + " failed to be retrieved"}, 404

def sendMailBureau(htmlbody, username):
msg = EmailMessage()
msg['From'] = "[email protected]"
msg['To'] = "[email protected]"
# msg['Bcc'] = "[email protected]"
msg['subject'] = f"[Hosting]" + {username} + " veut créer un nom de domaine !"
msg.add_header('Content-Type','text/html')
msg.set_payload(htmlbody.encode('utf-8'))
server = smtplib.SMTP("192.168.102.18:25")
server.send_message(msg)
server.set_debuglevel(1)
server.quit()
print("OK email")
return 0

def sendMailAdherent(usermail: str, htmlbody: str, entry: str, accepted: bool):
msg = EmailMessage()
msg['From'] = "[email protected]"
print(usermail)
msg['To'] = usermail
# msg['Bcc'] = "[email protected]"
if accepted:
msg['subject'] = f"[Hosting] : {entry} a été accepté comme nom de domaine!"
else:
msg['subject'] = f"[Hosting] : {entry} a été refusé comme nom de domaine!"

msg.add_header('Content-Type','text/html')
msg.set_payload(htmlbody.encode('utf-8'))
server = smtplib.SMTP("192.168.102.18:25")
server.send_message(msg)
server.set_debuglevel(1)
server.quit()
print("OK email")
return 0

def mailHTMLBureau(username, entry, ip):

header="""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<style>
body{
font-family: Helvetica, sans-serif;
font-size: 14px;
font-color:black;
}
</style>"""
msg = f"""
<body>
&#128680; Une personne souhaite ajouter une nouvelle entrée DNS sur hosting : {username} qui veut mettre en ligne {entry} pour l'IP {ip}.<br>
Un admin Hosting doit la valider sur <a href="https://hosting.minet.net">hosting.minet.net</a>
</body></html>
"""
return header+msg

def mailHTMLAdherent(username: str, entry: str, ip: str, accepted:str):

header="""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<style>
body{
font-family: Helvetica, sans-serif;
font-size: 14px;
font-color:black;
}
</style>""".replace('\n', ' ').replace('\r', ' ')
msg = f"""
<body>
Bonjour {username}, <br>
Ton entrée DNS <strong>{entry}</strong> pour ta machine d'IP <strong>{ip}</strong> a été {accepted} par un admin sur <a href="https://hosting.minet.net">hosting</a>.<br>
Cordialement,<br>
<table style="font-size: medium; font-family: Arial; background:white; width:vw;" class="sc-gPEVay eQYmiW" cellspacing="0" cellpadding="0"><tbody><tr><td><table style="font-size: medium; font-family: Arial;" class="sc-gPEVay eQYmiW" cellspacing="0" cellpadding="0"><tbody><tr><td style="vertical-align: middle;" width="150"><span style="margin-right: 20px; display: block;" class="sc-kgAjT cuzzPp"><img src="https://www.minet.net/res/img/minet.png" role="presentation" style="max-width: 130px;" class="sc-cHGsZl bHiaRe" width="130"></span></td><td style="vertical-align: middle;"><font color="#000000" size="4"><span style="caret-color: rgb(0, 0, 0);"><b>L'équipe MINET</b></span></font><p color="#000000" font-size="medium" style="margin: 0px; color: rgb(0, 0, 0); font-size: 14px; line-height: 22px;" class="sc-fMiknA bxZCMx"><span></span></p><p color="#000000" font-size="medium" style="margin: 0px; font-weight: 500; color: rgb(0, 0, 0); font-size: 14px; line-height: 22px;" class="sc-dVhcbM fghLuF"><span></span></p></td><td width="30"><div style="width: 30px;"></div></td><td color="#6fa3e8" direction="vertical" style="width: 1px; border-bottom: medium none; border-left: 1px solid rgb(111, 163, 232);" class="sc-jhAzac hmXDXQ" width="1"></td><td width="30"><div style="width: 30px;"></div></td><td style="vertical-align: middle;"><table style="font-size: medium; font-family: Arial;" class="sc-gPEVay eQYmiW" cellspacing="0" cellpadding="0"><tbody><tr><td style="padding: 0px;"><a href="https://tickets.minet.net" color="#000000" style="text-decoration: none; color: rgb(0, 0, 0); font-size: 12px;" class="sc-gipzik iyhjGb"><span style="margin-left:1px; font-family: Arial;">&#128735; tickets.minet.net</span></a></td></tr><tr><td style="padding: 0px;"><a href="//www.minet.net" color="#000000" style="text-decoration: none; color: rgb(0, 0, 0); font-size: 12px;" class="sc-gipzik iyhjGb"><span style="margin-left:1px; font-family: Arial;">&#127760; www.minet.net</span></a></td></tr><tr style="vertical-align: middle;" height="25"><td style="padding: 0px;"><span color="#000000" style="font-size: 12px; color: rgb(0, 0, 0);" class="sc-csuQGl CQhxV"><span style="margin-left:1px; font-family: Arial;"> &#128235; 9 rue Charles Fourier, 91000, Evry</span></span></td></tr></tbody></table></td></tr></tbody></table></td></tr><tr><td></td></tr><tr><td></td></tr></tbody></table>
</body></html>
""".replace('\n', ' ').replace('\r', ' ')
return header+msg

17 changes: 12 additions & 5 deletions backend/swagger_client/api/default_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def create_vm_with_http_info(self, **kwargs): # noqa: E501
collection_formats=collection_formats)


def delete_dns_id(self, dnsid, **kwargs): # noqa: E501
def delete_dns_id(self, dnsid, sendMail, **kwargs): # noqa: E501
"""delete dns entry by id # noqa: E501
This method makes a synchronous HTTP request by default. To make an
Expand All @@ -227,12 +227,12 @@ def delete_dns_id(self, dnsid, **kwargs): # noqa: E501
"""
kwargs['_return_http_data_only'] = True
if kwargs.get('async_req'):
return self.delete_dns_id_with_http_info(dnsid, **kwargs) # noqa: E501
return self.delete_dns_id_with_http_info(dnsid, sendMail, **kwargs) # noqa: E501
else:
(data) = self.delete_dns_id_with_http_info(dnsid, **kwargs) # noqa: E501
(data) = self.delete_dns_id_with_http_info(dnsid, sendMail, **kwargs) # noqa: E501
return data

def delete_dns_id_with_http_info(self, dnsid, **kwargs): # noqa: E501
def delete_dns_id_with_http_info(self, dnsid, sendMail, **kwargs): # noqa: E501
"""delete dns entry by id # noqa: E501
This method makes a synchronous HTTP request by default. To make an
Expand All @@ -247,7 +247,7 @@ def delete_dns_id_with_http_info(self, dnsid, **kwargs): # noqa: E501
returns the request thread.
"""

all_params = ['dnsid'] # noqa: E501
all_params = ['dnsid', 'sendMail'] # noqa: E501
all_params.append('async_req')
all_params.append('_return_http_data_only')
all_params.append('_preload_content')
Expand All @@ -266,12 +266,19 @@ def delete_dns_id_with_http_info(self, dnsid, **kwargs): # noqa: E501
if ('dnsid' not in params or
params['dnsid'] is None):
raise ValueError("Missing the required parameter `dnsid` when calling `delete_dns_id`") # noqa: E501

if ('sendMail' not in params or
params['sendMail'] is None):
raise ValueError("Missing the required parameter `sendMail` when calling `delete_dns_id`") # noqa: E501

collection_formats = {}

path_params = {}
if 'dnsid' in params:
path_params['dnsid'] = params['dnsid'] # noqa: E501

if 'sendMail' in params:
path_params['sendMail'] = params['sendMail'] # noqa: E501

query_params = []

Expand Down
1 change: 0 additions & 1 deletion frontend/src/app/cancel-update.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export class CancelUpdateGuard implements CanActivate {
const url = route.url.join('/');
if (url === 'dns' || url.startsWith('vms/') || url === 'history') {
this.vmsService.cancelUpdateVms();
console.log(route.url);
}
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/common/services/dns.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export class DnsService {
dns.ip = response.body['ip'];
dns.user = response.body['user'];
dns.validated = response.body['validated'];

dns.status = 'created';
if (dns.validated) {
this.ActiveDNSCount++;
}
Expand Down
Loading

0 comments on commit 449e1f0

Please sign in to comment.