34
34
35
35
from werkzeug .utils import secure_filename
36
36
37
- from flask import request , url_for , flash , Response , make_response , redirect , abort , jsonify
37
+ from flask import request , url_for , flash , Response , make_response , redirect , abort , jsonify , session
38
38
from flask import current_app as app
39
39
from flask import g as flaskg
40
40
from flask_babel import format_datetime
95
95
from moin .constants .itemtypes import ITEMTYPE_DEFAULT , ITEMTYPE_TICKET
96
96
from moin .constants .contenttypes import * # noqa
97
97
from moin .constants .rights import SUPERUSER
98
+ from moin .constants .misc import FLASH_REPEAT
98
99
from moin .utils import crypto , rev_navigation , close_file , show_time , utcfromtimestamp
99
100
from moin .utils .crypto import make_uuid , hash_hexdigest
100
101
from moin .utils .interwiki import url_for_item , split_fqname , CompositeName
@@ -2366,12 +2367,36 @@ def usersettings():
2366
2367
# TODO: maybe "is_xhr = request.method == 'POST'" would work
2367
2368
is_xhr = request .accept_mimetypes .best in ("application/json" , "text/javascript" )
2368
2369
2370
+ class ValidUserSettingsPersonal (Validator ):
2371
+ """Validator for settings personal change, name, display-name"""
2372
+
2373
+ def validate (self , element , state ):
2374
+ invalid_id_in_use_msg = L_ ("This name is already in use: " )
2375
+ invalid_character_msg = L_ ("The Display-Name contains invalid characters: " )
2376
+ invalid_character_message = L_ ("The Username contains invalid characters: " )
2377
+ errors = []
2378
+ if set (form ["name" ].value ) != set (flaskg .user .name ):
2379
+ new_names = set (form ["name" ].value ) - set (flaskg .user .name )
2380
+ for name in new_names :
2381
+ if user .search_users (** {NAME_EXACT : name }):
2382
+ # duplicate name
2383
+ errors .append (invalid_id_in_use_msg + name )
2384
+ if not user .normalizeName (name ) == name :
2385
+ errors .append (invalid_character_message + name )
2386
+ display_name = form [DISPLAY_NAME ].value
2387
+ if display_name :
2388
+ if not user .normalizeName (display_name ) == display_name :
2389
+ errors .append (invalid_character_msg + display_name )
2390
+ if errors :
2391
+ return self .note_error (element , state , message = ", " .join (errors ))
2392
+ return True
2393
+
2369
2394
# these forms can't be global because we need app object, which is only available within a request:
2370
2395
class UserSettingsPersonalForm (Form ):
2371
2396
form_name = "usersettings_personal"
2372
2397
name = Names .using (label = L_ ("Usernames" )).with_properties (placeholder = L_ ("The login usernames you want to use" ))
2373
2398
display_name = OptionalText .using (label = L_ ("Display-Name" )).with_properties (
2374
- placeholder = L_ ("Your display name (informational )" )
2399
+ placeholder = L_ ("Your display name (optional, rarely used )" )
2375
2400
)
2376
2401
# _timezones_keys = sorted(Locale('en').time_zones.keys())
2377
2402
_timezones_keys = [str (tz ) for tz in pytz .common_timezones ]
@@ -2382,6 +2407,8 @@ class UserSettingsPersonalForm(Form):
2382
2407
)
2383
2408
submit_label = L_ ("Save" )
2384
2409
2410
+ validators = [ValidUserSettingsPersonal ()]
2411
+
2385
2412
class UserSettingsUIForm (Form ):
2386
2413
form_name = "usersettings_ui"
2387
2414
theme_name = RadioChoice .using (label = L_ ("Theme name" )).with_properties (
@@ -2437,24 +2464,6 @@ class UserSettingsUIForm(Form):
2437
2464
flaskg .user .save ()
2438
2465
response ["flash" ].append ((_ ("Your password has been changed." ), "info" ))
2439
2466
else :
2440
- if part == "personal" :
2441
- if set (form ["name" ].value ) != set (flaskg .user .name ):
2442
- new_names = set (form ["name" ].value ) - set (flaskg .user .name )
2443
- for name in new_names :
2444
- if user .search_users (** {NAME_EXACT : name }):
2445
- # duplicate name
2446
- response ["flash" ].append (
2447
- (_ ("The username '{name}' is already in use." ).format (name = name ), "error" )
2448
- )
2449
- success = False
2450
- if not user .normalizeName (name ) == name :
2451
- response ["flash" ].append (
2452
- (
2453
- _ ("The username '{name}' contains invalid characters" ).format (name = name ),
2454
- "error" ,
2455
- )
2456
- )
2457
- success = False
2458
2467
if part == "notification" :
2459
2468
if (
2460
2469
form ["email" ].value != flaskg .user .email
@@ -2513,9 +2522,12 @@ class UserSettingsUIForm(Form):
2513
2522
else :
2514
2523
# validation failed
2515
2524
response ["flash" ].append ((_ ("Nothing saved." ), "error" ))
2525
+
2516
2526
if not response ["flash" ]:
2517
2527
# if no flash message was added until here, we add a generic success message
2518
- response ["flash" ].append ((_ ("Your changes have been saved." ), "info" ))
2528
+ msg = _ ("Your changes have been saved." )
2529
+ response ["flash" ].append ((msg , "info" ))
2530
+ repeat_flash_msg (msg , "info" )
2519
2531
2520
2532
if response ["redirect" ] is not None or not is_xhr :
2521
2533
# if we redirect or it is no XHR request, we just flash() the messages normally
@@ -2544,6 +2556,15 @@ class UserSettingsUIForm(Form):
2544
2556
return render_template ("usersettings.html" , title_name = title_name , form_objs = forms )
2545
2557
2546
2558
2559
+ def repeat_flash_msg (msg , level ):
2560
+ """
2561
+ Add a flash message to flask session. The message will be re-flashed by the next transaction.
2562
+ """
2563
+ if FLASH_REPEAT not in session :
2564
+ session [FLASH_REPEAT ] = []
2565
+ session [FLASH_REPEAT ].append ((msg , level ))
2566
+
2567
+
2547
2568
@frontend .route ("/+bookmark" )
2548
2569
def bookmark ():
2549
2570
"""set bookmark (in time) for recent changes (or delete them)"""
0 commit comments