From 82e534f4d3753f2b4f3bb78118ee4e67228da623 Mon Sep 17 00:00:00 2001 From: Simon Cloutier Date: Wed, 2 Apr 2025 00:42:37 -0400 Subject: [PATCH] getting there --- app/__pycache__/app.cpython-39.pyc | Bin 1545 -> 1384 bytes app/__pycache__/config.cpython-39.pyc | Bin 1765 -> 1297 bytes app/__pycache__/database.cpython-39.pyc | Bin 1214 -> 848 bytes app/__pycache__/wsgi.cpython-39.pyc | Bin 174 -> 127 bytes app/app.py | 17 +- app/config.py | 35 +- app/database.py | 38 +- app/db_interface.py | 272 ++++++++++++++ app/templates/base.html | 349 +++++++----------- app/templates/group_list.html | 197 ++-------- app/templates/index.html | 18 +- app/templates/stats.html | 16 +- app/templates/user_list.html | 216 +++-------- .../__pycache__/group_views.cpython-39.pyc | Bin 5886 -> 1348 bytes .../__pycache__/index_views.cpython-39.pyc | Bin 5561 -> 2511 bytes .../__pycache__/user_views.cpython-39.pyc | Bin 7531 -> 1827 bytes app/views/group_views.py | 216 ++--------- app/views/index_views.py | 193 +++------- app/views/user_views.py | 297 ++------------- app/wsgi.py | 3 +- docker-compose.yml | 1 - radius/main.py | 2 +- 22 files changed, 643 insertions(+), 1227 deletions(-) create mode 100644 app/db_interface.py diff --git a/app/__pycache__/app.cpython-39.pyc b/app/__pycache__/app.cpython-39.pyc index c8cda552d7a8bd5cbd2d1aa366a68dcd0cf1996a..77c12e50d3e8fd84b3c59edff3db0d0293460ea1 100644 GIT binary patch delta 604 zcmZut%}(1u5cb;nF~)W_Hijg)X`m`nKtf!&RH#x_sfwz?fr^VSQN)Z~TP8;9AkhS(> zZng#&I+H+xT4Z=extpFzdp&BLaE~(y88*K$&q6C)%xu)BjIbhK0(Hv7&w0K8+En%& zG{a?DD_IMjDT77OuVvzMbie=;8rO=~#&*_0BV3(1U4(A-0^4(2_vumA#o8S2q6!?E zrI{6WQ3LC~%3gv^t(L&Kl<1;8v)dd zO1zfWquBT9`nen@IiDBXUuF+Ugmzo)rJL2$fmOKMMJUwbxsK}INepKZzGcKnb||!% TKAQ?>x~$UD)4OU%si^E9w|9&> delta 807 zcmZ`%O;6N781A&NTX(x3-CYX1z@mTx(QwlPAtuH^FhnHCX)cqp^HRI^V>2y@keEHJ z7ZXV&{R7>^AK?%2)Polfdhkd1cK8S;+NSS3&+~rGJJVmKk4Dw5R7wgy?^k|18iKJ&!nbY8?=F|?lt`uZ4m`3BZV43U}{9D1y;YD zPJ=Nf=xL-gIp=rU%9u!0+Ekzh*62UpA-eMdZC)Oe&qQ>un87P!m3F}F&*C?i&O>KR zc$L@ARczCO4zF{QH_kQMg>Je4_5NMC0jqy6U4-rpzU4`mpm3!xfzF$}g|&9`_DfLW zQ<5S}m$`+lruobV1?Rgjl{P9JJ}Z?6Qkg?#o_D3P!i%q!wS~kZ^vN2@bT@EgW)B8? zNSX&>Y{zckY`Y%p*a7!IP~+MDK0AEza*Mv&+oI|rO}>+F1ru*an8{alv9gRXQuFIl zMKk%SZfqNl2u}v<(ng{#L;p4nq?ze~WA{#(jANb~#j7Y^mue+%wdap7``jeUys8^; zc*g{AS3oa*bSue1ytbPB(83`#dSP(vI;`i}QABla$M%sOfyn=?tmuV~gOg@z7}1Hr zX?&K|ucY-imy<`LoJZ=61-1{2Wf~q6Egy@}XW>yFJ7;?A`fwHokZBIYRL2VJ7|$-# z{p8C8J7{77(aKG}G4Zcq^i4nHCmuW{7!hrtnIXpYt0LA4s*c DQH~L0K`W>}H4hBx zY31?)_==i)ya>Fcd5M>Smo=~O6I1iBG9}#KG3g0yo8$A~_cdSOi@@hJU*gNa=Z|Wg zpHbw?^(NBKX#0xG}Y0q+LM6hX3?tHY;Ur#%{Cg%Ksj4coC;-Uaw1e2J!pnZ z;lus8YBU~K<77KUvI;~M+x-TsbsDVSZSG%tk!9obZWX-4)!k?iC&|uayo!tVZdJjM zR^Pn+wFLfI5w&!jq1kxS2w5lS;+ZJpmRdOW)N76AbEf^&xp@PID%Cn27B=87+O0rY z{cydtvaDRjM$xWdOnHp$CVUbjFERFV62(Uzrye}$Z>oG4^uk7KQ<+Jsa@!&kqdn#Q zx(#VT&nas-%A^BK<`D7-E;^hzc_pMQprM3NMyMe82=fRF03V3Fh#cX2MIYcmcfjiS zwKTzqb0_wLuJR54K!_Xt|7V65$lW&t1;gCA3`zI0rMujk<=`|GfvlBjF|n*)SO$^?plU!R-I4 zcoiIIKdy+H7G_T+XgyWl_-C?}oIHbRaBq5N5`*Pg0Odi?vDrEQtBi8*&AQ`09$<FQhLm%iRekj%|9z zK{44=_E&JSkNgvULti-|@e4Rn-IIseE)v#G6Ve@JDq znV{@Kk1zkpxe{|-BG&9w3$Uyb41hU zI&U!(+e4EX*ruqh72Q8!eXZV;a_U%z1;I3osD^clumRnKZZUi2$WzR9oKhIh zFxO}4IqZI}V^`T6*jL9Hh11jp>?xd~9^fp?DJ@HLbNvS4rCWW8=9QjT-U3~Qu?4m~ zTVaJc!mD(JuD;dq8eN0)KN5CjG(7E}?c@A@t=v8$ZNJj;LvrMwOjjv8?M?>q^Zqbm zy$NT}&)Jp8)EWmQY>@q+<_qhzJBXMtV?JRbD?QRon&t3tTG;50#~XvuStLOTfXFmD z0Vy{F(rMMEPk)HxarD&&c>AS`Zf`IeolnLkIq7nH0}Ro|FK-^Ez=?z=*6voQ1;;^1 zntn^3SfFjOa_6a*gW3sEer#=RLK9xO*(70b?Bhn=7e*(n^biE*uIT_|##Eq3pMi+A z8KQ{lbNvmvM%NnAV`FAsqq)Qu)qpvp&a*I*=Rg!~p^qYApRt$?FO^-GG`r8|Ee0tkcUT7(Ffkc$zW3?%jl`DxM}+4<25Y}MyGvnNlPI)NqNRg7mjQ%j@vLv}D zg<_^4(XtdPQpmfg>n?~#(k9uLYetVjq>!mT&sasC;lZ`@C=Y*ESL5C*wEIG@!sLGy znvP9o&1`B=6AHjl*rGPzl)_1Ir4>$!%cU6ztS1UpcF6{#@dX>k3E|Vn3#KPYpeDQ< z_eaB0DBR-{;FBCS+Tk>}^=iAc^>U~5aRqVak`?B*re!X*f#rN*K)pA(gE4O`|cgGpE~X84D2U%oDdq)j-4 z&{2;N{*g4@$B%z1RhiQKb19xmA#-j)s31H6+sDu&8NVb5l6((w>3NTK8LwUF(GG}3 z+L;Njr4H|mt&jo8QOE?8Qpf_7rZ!ORhdV`c;GD~NwzHTt>~Ae Zi`3Uiy?!GfBgK4P&#mWE`BVEgZ#_m=`WmcZgV|!*i-+1$G_W__h`}%7(qyRsRu_?F)hdAU5R16rY zASH;jqDv=rmTu}2U=DMyAoZBXd_W=l(ow8rqN_pnDtEw(0GMI zj!-e8;4={eMHY17D0ks8x(61W7Tp%T7X3Y7!8cDq<||nEm^+L$Wz#emz06*Zleczq zJf7T6-X%wqw1Zp6!z6h>o{a2vJbZH$dD{KJrP6N01?rV7g$|os%2O_w4q2}9X)ens z5Ds2dd&_hAsY$(mf#8^E@j05rDOkDS|*orX8sD=LmGP`y>26=kF5ytaq_RVW@| zY~8cxvX&D()iY^*R6rkMX&2Au_1r#-{z1iyypn_deV2&nT~+3S@zdHoAPlC;Glj_= zw8SpPx}P?@i)t8?rd%K{5swk0Al$jKULYN;wdnZ*cKian0LM_|YWh1(6psg%C TSaPebGS$M$%>Z^mJ{TtF}mzW?m}vJm>AC$j^5=n4Gd zIS7gHcoCzkIf(a3&iL&3NLMpo_7*}2v3UQorsyrIX zuoVjC+uVj+g2l}~q_UPK32RF@w*&DxffePp)8sJfd_%klQzQP&-v_SlU&dI<`l=Kq zk!;ddQ>Wm()|Mi)1=XHp;JaMMGzhqEFmrEE=>Ri;X9|*6^vV^iiB$rha`i^q zx&gK@{R!z8a0$<2J_o)w25~v`MS70`@EQz>M!GT3n4IDv=pN>KgVGR>$QWU?kCF#A zl2(5gqf>&>;I_0W8ImvPD>=h@{Q&y;lzbvdVWOAOGI$I~lkwo*oAuS&TFk4_Dji7R4fMJyv3YY YP~ca@1mZ9hu>h$emWgfhte-*B0KW_n^Z)<= delta 126 zcmb= daily_limit: + break + + try: + url = url_template.format(prefix) + response = requests.get(url, headers=headers) + if response.status_code == 200: + data = response.json() + vendor_name = data.get("company", "not found") + status = "found" + elif response.status_code == 404: + vendor_name = "not found" + status = "not_found" + else: + print(f"Error {response.status_code} for {prefix}") + continue # skip insert on unexpected status + + cursor.execute(""" + INSERT INTO mac_vendors (mac_prefix, vendor_name, status, last_checked, last_updated) + VALUES (%s, %s, %s, NOW(), NOW()) + ON DUPLICATE KEY UPDATE + vendor_name = VALUES(vendor_name), + status = VALUES(status), + last_checked = NOW(), + last_updated = NOW() + """, (prefix, vendor_name, status)) + conn.commit() + inserted += 1 + + except Exception as e: + print(f"Error fetching vendor for {prefix}: {e}") + continue + + time.sleep(1.0 / rate_limit) + + cursor.close() + conn.close() diff --git a/app/templates/base.html b/app/templates/base.html index 2507dc5..a97dbe4 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -1,245 +1,152 @@ - - - - - - - - - {% block title %}FreeRADIUS Manager{% endblock %} - + .styled-table th { + background-color: var(--card-bg); + color: var(--fg); + } + - + -
- {% block content %}{% endblock %} -
+ {% block content %} + {% endblock %} -
+
- - - - + if (userPref) { + document.documentElement.setAttribute('data-theme', userPref); + } + + toggleBtn.addEventListener('click', () => { + const current = document.documentElement.getAttribute('data-theme'); + const next = current === 'light' ? 'dark' : 'light'; + document.documentElement.setAttribute('data-theme', next); + localStorage.setItem('theme', next); + }); + + // Toast display function + function showToast(message, duration = 3000) { + const toast = document.getElementById('toast'); + toast.textContent = message; + toast.classList.add('show'); + setTimeout(() => toast.classList.remove('show'), duration); + } + + // Make toast function globally available + window.showToast = showToast; + diff --git a/app/templates/group_list.html b/app/templates/group_list.html index 46ebb36..6f349cf 100644 --- a/app/templates/group_list.html +++ b/app/templates/group_list.html @@ -1,183 +1,52 @@ {% extends 'base.html' %} -{% block title %}Group List{% endblock %} +{% block title %}VLAN Groups{% endblock %} {% block content %} -

Group List

+

VLAN Groups

- + + + + + + +
- - - - + + + - - - - - - - - - - - {% for groupname, attributes in grouped_results.items() %} + + {% for group in groups %} - - + + + - {% for attribute in attributes %} - - - - - - {% endfor %} {% endfor %}
Group NameAttributeOpValueVLAN IDDescriptionUser Count Actions
- - - - -
{{ group.vlan_id }} - - - - 🗑️ - +
+ + + +
+
{{ group.user_count }} +
+ + +
-
- + {% endblock %} diff --git a/app/templates/index.html b/app/templates/index.html index ec8c902..8b58fa3 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -1,36 +1,36 @@ {% extends 'base.html' %} -{% block title %}FreeRADIUS Manager{% endblock %} +{% block title %}RadMac{% endblock %} {% block content %} -

FreeRADIUS Manager

+

RadMac

- Total Users + Total MAC Addresses

{{ total_users }}

- Total Groups + Total VLAN Groups

{{ total_groups }}

-

Recent Access Accepts

+

Recent Access-Accept

    {% for entry in latest_accept %}
  • - {{ entry.username }} + {{ entry.mac_address }} {% if entry.description %} ({{ entry.description }}){% endif %} — {{ entry.ago }}
  • {% endfor %}
-

Recent Access Rejects

+

Recent Access-Reject