From 149487195b2adaaacd2c556013fd91d7c1f9516f Mon Sep 17 00:00:00 2001 From: Kobe Date: Tue, 27 May 2025 15:13:36 +0200 Subject: [PATCH] enforce password change if password is changeme --- routes/__pycache__/auth.cpython-313.pyc | Bin 4087 -> 6359 bytes routes/__pycache__/contacts.cpython-313.pyc | Bin 15739 -> 15720 bytes .../__pycache__/conversations.cpython-313.pyc | Bin 21692 -> 21950 bytes routes/__pycache__/main.cpython-313.pyc | Bin 35291 -> 35391 bytes routes/__pycache__/rooms.cpython-313.pyc | Bin 14868 -> 15036 bytes routes/auth.py | 43 ++++++++++++++- routes/contacts.py | 15 +++--- routes/conversations.py | 12 +++++ routes/main.py | 10 +++- routes/rooms.py | 7 +++ templates/auth/change_password.html | 50 ++++++++++++++++++ templates/contacts/form.html | 37 ++----------- 12 files changed, 132 insertions(+), 42 deletions(-) create mode 100644 templates/auth/change_password.html diff --git a/routes/__pycache__/auth.cpython-313.pyc b/routes/__pycache__/auth.cpython-313.pyc index cc0be2cbea264b4e1dc9f8878e9fa7047a279d5a..3792ef580305a6f27c6b6e6256f3aab83f7c272b 100644 GIT binary patch delta 2561 zcmZ`*U2Gf07M@w}uHAV3lWbFmxUn~BlE#$SZ9@tq#tluOZSHM^vI#1Ll5XuyZ0fAb ztW88z3#Z)~5^-m<6-k05kL*=icHt+Ueq3Ut2~WQn5YjP}8d^Y?RaP zqH?NZlxwsUG{4LC&%13)-HLjbRJ+h=@oR zguqzUn@sD;3oSQ+;~^pd>?Y!<@)}t(tKtO~jn#P3gqu*5HR==(6+2RTGDoz$o?2Ke z7|DDlXH-Xs{z4%`^j6G;#?;YxHkZ`0W+Hm;AehTM$>8@jbjuy6xQE!^N6%J_l z`E_??cy?oWwkEZgI*xsLYEzo7$-#F|l=_Qf<-Ox&IbM?D|M&Ud>@WFxuMTebdP}a} zEfx$BFM|k2y20Mdz=TUVr;s44s)4^*C;@uF5tzLU*otaG+v|s3J@YHa3w>J-Bzo&$ z)!R_76e{sOB*ePiMOZjQi?Bb^cKkj+hh{Ln!pX5VAV!Q+`A4|I5c}4geWoH$W$y6nX`+huQQ+ zVPZcCfY+jk3#={x*l0u`gJACm7@|K3A;CIh`jEI!^fRY9NY9C1?XQc--*t7Y>>H^0 zJ4<_>_jn9*gHhU&@$yokTEsm|k#)MQdRX(>LAW5!lE!xe4Sp83u>~!~i@1 zpfltUz+w7>JK=AHfVQ>45qePS!a;gUdO(Dc=A&$Lv-G<3GY--Jc+#N*%o%YI$ouW- zK13E#NRUo?hwy2d_4W+|b5{MaMuH66xtV0%R)N!o8`(z+uB7&}8*#6IbeyV=TG>dUkhcxsiIJ=R9SGHSzCa#MavfT2lh9(;$ zwq-bDDj9<*BGHriC;?WIP6n&NX?;a0+V^WJshncu^2)N7Po|@*p(kw_ZxA7+n1y6g zH_gRDHv3X<)!A$kNQKq=faXogwAK<$=a;h)?_W|H9v#TsXPT)iLK_s9JOUsAi~+;} ztaNse$H9IA-~@xF=r@Ja_oug{+D|9M&f=fEDvbM)!5aEiM3VeQ;&S5ZQ=9I6weaAz zOK)GQgku}wSn1%ga(J>N?X3m-uEpPuSAqvNf(JgBE(gb7|L0%#yd{S#a`c8AEya#j z zrz%p;_3G!`D7UD2yH^2nG&9k<(%IQc4ea5GztGld6 zI+x3u1m?0HI%{U~7&JkR8cTD`j{g@Ozllzl(dnBg T_$>pz-Mn{lWo+@>T24O)h${%I8 zq24FS;V1PKfe(RoV!+>koiU5k>Sc+B%YV$K-Du@%Hg|X1Hmk7+^tJOO21nWsnFF7` z1RzI&>f7s{S#_Q2U8`erzTXy7oXj)(?y#2KbS91B@Wsr=6JqC{VfVUjjyd%P z?>dYUwgyHxeP=v$4FypY~!*TiBU|fz|WZr zWDCq__5miS?5V8X6X(J!Kou{5XR&rWY!&4NL{WgF^T|XJc%eqC(Y3~foLv(cbi~^N zed(Ke=5gg=<>2a}^X&Ga)vtV3izo7|dU@oN{8x@KI?hRc0}kWc#)%@U`LVS!4MQ?< olaAZ54bf`qSVW$-*=*N(drpaMiBG&ud>&pT;=z%!NhbCG0GjusK>z>% diff --git a/routes/__pycache__/contacts.cpython-313.pyc b/routes/__pycache__/contacts.cpython-313.pyc index eefd5f6d689b84fb391b6e262cd45adfe1a4a8a3..82385d22b818d7a3aec78aed2f3811665e982de9 100644 GIT binary patch delta 2857 zcmb7GOKcNY6rE?s&LobVkL}ow6FN=^)Q}HUb|4>UN*g3d%O@^Sz^$3s6MKT~32(*( zQYy2mDpjS8-lnQli7nlb)+gwZ+^q&!8pd9ky^M?G-2NxW!YfeXg%+lfSa*sR-!SS|`K7fhr#zwS2H|En@K* z4uTLjsl?q`Yr9zuy6qVrx;A;(@(d3R;Dv5ai{a^;k7nL`XVoq=xj!5$<(s}DB*^+*QOhSbwiNJ}uDFtfSW7=P_gjg`u97V- zNjN(WuJ|)`0I5zU*lyA76W2-iv;}+McC)3ZgAIH9jzjCa&rY(qXVi~@(FuTq^dK(r z`v#%I?53xW_}G2VRB;I9dl7~K%C@obLH_HsyiJ)>Nf=GAOg$}6BWG|Aj185u>T61LKVy_B@PG^0}8 zkg{4@%@44f-tM+-6uU~D2u%nP_OrLA7h@>brDQ{IHsU);~LN83`R0Hzc z+1}am0;}!MBd2t>TI!ugoXb_(HRwKZ=Hb)n>~5Qrh<(aW*)Y#lRgg z@bQkjVlRsZdh4fer*e12JUbWY1%AI9c;9ZvM$-`UNh1LtE?)&$Xqrf=hIEW-JjU19 ztkhFHf!dP@NP}?all4UDDTFr=&LZ#*pTQMUpVlMPA*2vCbA{F@W4Q@4UY}8_V4lP45k~wTm3Z#^nTT5vUG)4H+EntJQR+2-HVX8`UkKbX| zWP%k3M#%~G`y!PpnxblysO7(XXj=b%)?+J*Z}E}Aq% zU8QX0#$vYt1RMuWT-u7OBm!@399J5G0uXMbd=H<6V*<3zED0aB7A>1f z%&AGEz;9w;{w(g}T|SR16`$|R5p^<};RbuCjI?2LA z5~pw2SzUbtj~YhUVChE66}pw}DJ84Gm5#K#VSOSmKCk$10?eyPG?!^w8P+SH{6hd& zI)fF4$U-9{%(>?zM48$Xv=q%KLAlV(ufUv4&%-4r>kWDzi4$GU@hcN?LqhmKhM4%xiH|MS^+Ne0l5I3 zYXNz=ZdTXw6nG|-UGoY(zn~P-0|i6P>Tq8k9}O1Ifr^u_YzLwz=Tn@7w17LroD3Pm zz0LbmwsG(L2a(@(6vvfft0`8Khetbbg&~<`7sqm1s*qLo(+@xf_oASG1Gr)(g!~{J zU1q=Xl#>qq6$E)!l`9xO% delta 2484 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 diff --git a/routes/__pycache__/rooms.cpython-313.pyc b/routes/__pycache__/rooms.cpython-313.pyc index f893e97e77bd3ce9cc9eaa1d27b6a925c5203670..8a6e38e73b9bb37257ef90eaf681e9f00d4a68dc 100644 GIT binary patch delta 2732 zcmb7FO>7fa5caN}jUC&uga7}MwM~ExAt59Lhw>MdLLr3~wi2{5GE2NkEMl+w)+Qo{ z5|G-ey&&{ZD^BIm9(wA*r_xsKrK;2(DCJPJ5{HUQdnyQ|{z$Dl^VZ%ZCJpLJ`+4@w z&zt#X-t+a^7xnJPUT>ETp5(2abHbKu-BIqzwaq0_w#mX&@MwsHL|dNA*yPT9Sa!;; z2|J18BPU1bUD|Zj`vTuTCUjB8w;w`V?o}HW- znfYv3$0uR=1XlS3*YQbOJ|W1BvvLcsmB{_~(T$M0q89sCYz^sPV zVtB9>O(t}58niE?Sr43aEXwBbU)}xg?w{P0`il);_;<&~HEJWTfDbu=a1tRy2NH_g zoDBTV()SaYtvL{-$Z{(QD;qm!7Hf_pewr0CE}ZzyrZa&OtKE&#euM)EdlB{_Oad6r zx~`InQdXa0!lZ8ujT}{#l%FD_ODPsxQ*p)*b_%@uVv~!;Tge3uI{bHPz~1)^7U-e0 zwjB#5uLDRu|Fh~H=xLQ{2t{>Xg~`VHqz<#cY!q+^S(8Z~B)tQGHP`H|m#Ag!g4(L+ zENGYD)qTx^tmcY$+~Up1UAMG!klsiV`fKKGsI!{A)9O48j?XbDB0!+6Lem8(|t2Zzf-kcD@)@ zcvO%olc`v}T2yFG3U^Jz`VDyX3Vkz~Xz0=@Z29*CcX`1)%JidcqQE-4jefT+xxu_S z!9xl(k1*5{9a=uuI7j3;gnk6PGtBFEMV@ruP;@Yj8rD&asoMdp1YK&eR5Nem8Cd_6 zUK#oY@;X0!+sf;}jslmXH+P)nQkcP}HbkMXYFjb*mZ!X z$KX_bHA!xB3e7Au@cy>(!6@Z(tM569XMDp6Q)+XPXYF?5)_bw%ulZ2KyUy^i+q!wR zOJ>*Dm5zUiwK>L&;eac?JulaVlDbep1*t=zpW)SKZS+zyK|l06>7(((orAD;T*}h@ zyRLM*iB_+v`jAqGpd09yyZYn+sM)`qN&jj5JcDo+0Y`!$>jaBtdwgOe7}6Xb=bo}w ztk0|a$P%o<*@Eknr^C6V{l0COPUTYZdtCGp@8hPp$95YZL+~Sn9tw0ZmpaPSG44Q{ zdhDTqix0TnqdcPAG%ck^;b_|@tGQ2&`rCYX1e bJJ_}xY$VVv6HR^aDg6o5pPKm0frbAIzxW=a delta 2757 zcmbtWOKcNY6rJaB96SEy<6j&no;V4K69@?j1k*r61+;uxK2}AmrX9xdP%LbZ`^JHi zMNL`IRVCncQ5OAoQKT+fS*ldEmAdQ-)Y6|uqA8;LLP7l?QF`wi+cB1bMMs*GH}@Ui zch9}|y_YW+-za)+y4`I8JRhD~eKl=1ELQ+U9-9)}%clQvbaFz#4Wn z)Wx1(<%rDNlWk#PJ^l=y>R%eHl7^j0SJJ)KlJq1j!1XrahN|45_VvW{1I&&l%PGCH|p6-BhrNlStLcP^gaC-Gtd&We$h$k=xUR+gIfd zMe4lvHep6<%)UCg(I!mkMJe9TB=L*#pW@#ZTPI|Z2G}jzyUqX(dl5R>JFS}ode!Hrmh5 zdnczi!q9LnD0w-p9nWVqB~7Ps7MsgxLpxRTN=`NGIL>LuRJwuv>kW=!O!RSt8lOIa zpF0sY0K`4ih2vf}*X|EsFw_HJI1XpBMU~2_6QJ>E`>LlUoZ=cC8C}k)xs*yD>{`c! zf^hTU^0@;Jm@@qeo0u77Z5?0P#^7@)z@ouG`C7;K7XLO}Z9Bpa1Wdr~)l3-)vEO_H zL}GS-l&oVT{)rN=_KQnXhEtGXo zbT1I;K7{=U{p|G~#VPS2LX7>>6D!TYFdnSb49#3Rmdq5)lW3GM&%u-)$9Cbx zHTSNYs<^kR>SUN*LY|kaV|OAiu{{H)&0d~>UJjOjA9&l^&N~=Yn04L8-Wmy(V)*^Q zow?-Ow{nI^iv>7&)bu#z4ba_~4qkR%-G)A2=?vTjhBc*WS!x$bu=+|1JUp0{?3r1! zHfD_{3^xqs%S>0d8FM9F^(P`tVZ7(y)$^FUaQVmhLF|n2vC9^lx#L;uxMV}IbTwNu z9(jgGiv@~z)$Q~KwdPTVKiY-Rj<5+~5aAJo34~fN&^h+rcxX~WBdl5*=$N#IBJM`k;W_8$AAq7KXCZzPgK2Hfl%ePF+1IiJ`eP-%eSYP zrF8Gf8n^Ij8rFhRJQ8=^zqe*FwuY2@(S~Q7;X0h5dQpbUZ+c?75+lDyR2d!f{2Erc zSJY@NPBTo$v5b0L#u-{fPi$!qlIdVu!%cy zeY{A``r(O7@ywyPJ!uL7%SKT>_kKa3=-OP_KAY3hi&=FGeFbdzzn1/edit', methods=['GET', 'POST']) @login_required +@require_password_change def edit_contact(id): result = admin_required() if result: return result @@ -237,6 +238,7 @@ def edit_contact(id): @contacts_bp.route('//delete', methods=['POST']) @login_required +@require_password_change def delete_contact(id): result = admin_required() if result: return result @@ -251,6 +253,7 @@ def delete_contact(id): @contacts_bp.route('//toggle-active', methods=['POST']) @login_required +@require_password_change def toggle_active(id): result = admin_required() if result: return result diff --git a/routes/conversations.py b/routes/conversations.py index 1d482cb..c9c0427 100644 --- a/routes/conversations.py +++ b/routes/conversations.py @@ -3,6 +3,7 @@ from flask_login import login_required, current_user from flask_socketio import emit, join_room, leave_room from models import db, Conversation, User, Message, MessageAttachment from forms import ConversationForm +from routes.auth import require_password_change import os from werkzeug.utils import secure_filename from datetime import datetime @@ -44,6 +45,7 @@ def get_file_extension(filename): @conversations_bp.route('/') @login_required +@require_password_change def conversations(): search = request.args.get('search', '').strip() if current_user.is_admin: @@ -57,6 +59,7 @@ def conversations(): @conversations_bp.route('/create', methods=['GET', 'POST']) @login_required +@require_password_change def create_conversation(): if not current_user.is_admin: flash('Only administrators can create conversations.', 'error') @@ -89,6 +92,7 @@ def create_conversation(): @conversations_bp.route('/') @login_required +@require_password_change def conversation(conversation_id): conversation = Conversation.query.get_or_404(conversation_id) # Check if user is a member @@ -109,6 +113,7 @@ def conversation(conversation_id): @conversations_bp.route('//members') @login_required +@require_password_change def conversation_members(conversation_id): conversation = Conversation.query.get_or_404(conversation_id) if not current_user.is_admin and current_user not in conversation.members: @@ -126,6 +131,7 @@ def conversation_members(conversation_id): @conversations_bp.route('//members/add', methods=['POST']) @login_required +@require_password_change def add_member(conversation_id): conversation = Conversation.query.get_or_404(conversation_id) if not current_user.is_admin: @@ -149,6 +155,7 @@ def add_member(conversation_id): @conversations_bp.route('//members//remove', methods=['POST']) @login_required +@require_password_change def remove_member(conversation_id, user_id): conversation = Conversation.query.get_or_404(conversation_id) if not current_user.is_admin: @@ -170,6 +177,7 @@ def remove_member(conversation_id, user_id): @conversations_bp.route('//edit', methods=['GET', 'POST']) @login_required +@require_password_change def edit_conversation(conversation_id): if not current_user.is_admin: flash('Only administrators can edit conversations.', 'error') @@ -213,6 +221,7 @@ def edit_conversation(conversation_id): @conversations_bp.route('//delete', methods=['POST']) @login_required +@require_password_change def delete_conversation(conversation_id): if not current_user.is_admin: flash('Only administrators can delete conversations.', 'error') @@ -251,6 +260,7 @@ def on_leave(data): @conversations_bp.route('//send_message', methods=['POST']) @login_required +@require_password_change def send_message(conversation_id): conversation = Conversation.query.get_or_404(conversation_id) @@ -331,6 +341,7 @@ def send_message(conversation_id): @conversations_bp.route('/messages//attachment/') @login_required +@require_password_change def download_attachment(message_id, attachment_index): message = Message.query.get_or_404(message_id) conversation = message.conversation @@ -353,6 +364,7 @@ def download_attachment(message_id, attachment_index): @conversations_bp.route('//messages') @login_required +@require_password_change def get_messages(conversation_id): conversation = Conversation.query.get_or_404(conversation_id) diff --git a/routes/main.py b/routes/main.py index 5a78311..1644b7f 100644 --- a/routes/main.py +++ b/routes/main.py @@ -1,6 +1,7 @@ from flask import render_template, Blueprint, redirect, url_for, request, flash, Response from flask_login import current_user, login_required from models import User, db, Room, RoomFile, RoomMemberPermission, SiteSettings +from routes.auth import require_password_change import os from werkzeug.utils import secure_filename from sqlalchemy import func, case, literal_column, text @@ -26,13 +27,14 @@ def init_routes(main_bp): return dict(site_settings=site_settings) @main_bp.route('/') + @login_required + @require_password_change def home(): - if not current_user.is_authenticated: - return redirect(url_for('auth.login')) return redirect(url_for('main.dashboard')) @main_bp.route('/dashboard') @login_required + @require_password_change def dashboard(): logger.info("Loading dashboard...") # Get 3 most recent users @@ -265,6 +267,7 @@ def init_routes(main_bp): @main_bp.route('/profile', methods=['GET', 'POST']) @login_required + @require_password_change def profile(): if request.method == 'POST': # Handle profile picture removal @@ -321,16 +324,19 @@ def init_routes(main_bp): @main_bp.route('/starred') @login_required + @require_password_change def starred(): return render_template('starred/starred.html') @main_bp.route('/conversations') @login_required + @require_password_change def conversations(): return redirect(url_for('conversations.conversations')) @main_bp.route('/trash') @login_required + @require_password_change def trash(): return render_template('trash/trash.html') diff --git a/routes/rooms.py b/routes/rooms.py index a401200..ed8f6ed 100644 --- a/routes/rooms.py +++ b/routes/rooms.py @@ -3,11 +3,13 @@ from flask_login import login_required, current_user from models import db, Room, User, RoomMemberPermission, RoomFile from forms import RoomForm from routes.room_files import user_has_permission +from routes.auth import require_password_change rooms_bp = Blueprint('rooms', __name__, url_prefix='/rooms') @rooms_bp.route('/') @login_required +@require_password_change def rooms(): search = request.args.get('search', '').strip() if current_user.is_admin: @@ -27,6 +29,7 @@ def rooms(): @rooms_bp.route('/create', methods=['GET', 'POST']) @login_required +@require_password_change def create_room(): form = RoomForm() if form.validate_on_submit(): @@ -56,6 +59,7 @@ def create_room(): @rooms_bp.route('/') @login_required +@require_password_change def room(room_id): room = Room.query.get_or_404(room_id) # Admins always have access @@ -74,6 +78,7 @@ def room(room_id): @rooms_bp.route('//members') @login_required +@require_password_change def room_members(room_id): room = Room.query.get_or_404(room_id) # Admins always have access @@ -91,6 +96,7 @@ def room_members(room_id): @rooms_bp.route('//members/add', methods=['POST']) @login_required +@require_password_change def add_member(room_id): room = Room.query.get_or_404(room_id) # Membership check using RoomMemberPermission @@ -121,6 +127,7 @@ def add_member(room_id): @rooms_bp.route('//members//remove', methods=['POST']) @login_required +@require_password_change def remove_member(room_id, user_id): room = Room.query.get_or_404(room_id) # Membership check using RoomMemberPermission diff --git a/templates/auth/change_password.html b/templates/auth/change_password.html new file mode 100644 index 0000000..ee16885 --- /dev/null +++ b/templates/auth/change_password.html @@ -0,0 +1,50 @@ +{% extends "common/base.html" %} + +{% block title %}Change Password{% endblock %} + +{% block content %} +
+
+
+

Change Password

+
+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/contacts/form.html b/templates/contacts/form.html index bad06bd..69fbafd 100644 --- a/templates/contacts/form.html +++ b/templates/contacts/form.html @@ -6,7 +6,7 @@

- + {% if title %} {{ title }} {% else %} @@ -71,36 +71,6 @@ {% endif %}

- {% if current_user.is_admin %} -
- {{ form.new_password.label(class="block text-sm font-medium text-gray-700 mb-1") }} - {{ form.new_password(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 pr-10", autocomplete="new-password", id="new_password") }} - -
-
- {{ form.confirm_password.label(class="block text-sm font-medium text-gray-700 mb-1") }} - {{ form.confirm_password(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 pr-10", autocomplete="new-password", id="confirm_password") }} - - {% if form.confirm_password.errors %} - {% for error in form.confirm_password.errors %} -

{{ error }}

- {% endfor %} - {% endif %} -
- - {% endif %} -
{{ form.phone.label(class="block text-sm font-medium text-gray-700 mb-1") }} @@ -177,7 +147,10 @@
- {{ form.submit(class="text-white px-6 py-2 rounded-lg transition duration-200", style="background-color: #16767b; border: 1px solid #16767b;", onmouseover="this.style.backgroundColor='#1a8a90'", onmouseout="this.style.backgroundColor='#16767b'") }} + {{ form.submit(class="text-white px-6 py-2 rounded-lg transition duration-200", + style="background-color: var(--primary-color); border: 1px solid var(--primary-color);", + onmouseover="this.style.backgroundColor='var(--primary-light)'", + onmouseout="this.style.backgroundColor='var(--primary-color)'") }}