hiddifypanel 9.0.0.dev54__py3-none-any.whl → 9.0.0.dev61__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +2 -2
- hiddifypanel/base.py +5 -4
- hiddifypanel/hutils/__init__.py +8 -1
- hiddifypanel/hutils/auth.py +94 -0
- hiddifypanel/hutils/auto_ip_selector.py +1 -1
- hiddifypanel/hutils/convert.py +14 -0
- hiddifypanel/hutils/encode.py +11 -0
- hiddifypanel/hutils/flask.py +24 -0
- hiddifypanel/{panel/github_issue_generator.py → hutils/github_issue.py} +104 -14
- hiddifypanel/hutils/json.py +24 -0
- hiddifypanel/hutils/random.py +19 -0
- hiddifypanel/hutils/utils.py +0 -161
- hiddifypanel/models/__init__.py +1 -0
- hiddifypanel/models/admin.py +53 -8
- hiddifypanel/models/base_account.py +31 -169
- hiddifypanel/models/config_enum.py +23 -1
- hiddifypanel/models/domain.py +2 -2
- hiddifypanel/models/parent_domain.py +1 -0
- hiddifypanel/models/user.py +105 -33
- hiddifypanel/models/utils.py +3 -3
- hiddifypanel/panel/admin/Actions.py +5 -6
- hiddifypanel/panel/admin/AdminstratorAdmin.py +1 -1
- hiddifypanel/panel/admin/Backup.py +5 -5
- hiddifypanel/panel/admin/ChildAdmin.py +3 -3
- hiddifypanel/panel/admin/Dashboard.py +12 -10
- hiddifypanel/panel/admin/DomainAdmin.py +10 -9
- hiddifypanel/panel/admin/ProxyAdmin.py +4 -6
- hiddifypanel/panel/admin/QuickSetup.py +11 -13
- hiddifypanel/panel/admin/SettingAdmin.py +20 -10
- hiddifypanel/panel/admin/UserAdmin.py +14 -12
- hiddifypanel/panel/auth.py +43 -10
- hiddifypanel/panel/auth_back2.py +5 -5
- hiddifypanel/panel/cli.py +1 -0
- hiddifypanel/panel/commercial/ParentDomainAdmin.py +3 -3
- hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +1 -0
- hiddifypanel/panel/commercial/restapi/v1/tgbot.py +1 -2
- hiddifypanel/panel/commercial/restapi/v1/tgmsg.py +37 -29
- hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +5 -4
- hiddifypanel/panel/commercial/restapi/v2/user/configs_api.py +15 -7
- hiddifypanel/panel/commercial/restapi/v2/user/info_api.py +7 -11
- hiddifypanel/panel/commercial/telegrambot/Usage.py +2 -1
- hiddifypanel/panel/commercial/telegrambot/admin.py +1 -0
- hiddifypanel/panel/common.py +12 -89
- hiddifypanel/panel/common_bp/login.py +12 -12
- hiddifypanel/panel/database.py +22 -21
- hiddifypanel/panel/hiddify.py +27 -29
- hiddifypanel/panel/importer/xui.py +2 -2
- hiddifypanel/panel/init_db.py +32 -13
- hiddifypanel/panel/usage.py +2 -1
- hiddifypanel/panel/user/link_maker.py +118 -15
- hiddifypanel/panel/user/templates/new.html +4 -2
- hiddifypanel/panel/user/user.py +83 -38
- hiddifypanel/static/new/assets/{index-bd9ba5e9.js → index-2cd90979.js} +1 -1
- hiddifypanel/templates/fake.html +2 -2
- hiddifypanel/templates/master.html +1 -1
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +317 -189
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +346 -206
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +315 -195
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +315 -195
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +866 -2739
- {hiddifypanel-9.0.0.dev54.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/METADATA +2 -1
- {hiddifypanel-9.0.0.dev54.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/RECORD +72 -66
- {hiddifypanel-9.0.0.dev54.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/LICENSE.md +0 -0
- {hiddifypanel-9.0.0.dev54.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/WHEEL +0 -0
- {hiddifypanel-9.0.0.dev54.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/entry_points.txt +0 -0
- {hiddifypanel-9.0.0.dev54.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
|
|
2
2
|
from urllib.parse import urlparse
|
3
3
|
from flask_babelex import gettext as _
|
4
4
|
from flask_bootstrap import SwitchField
|
5
|
+
from hiddifypanel import hutils
|
5
6
|
# from flask_babelex import gettext as _
|
6
7
|
import wtforms as wtf
|
7
8
|
from flask_wtf import FlaskForm
|
@@ -10,7 +11,6 @@ import json
|
|
10
11
|
import json
|
11
12
|
from flask import render_template, request, jsonify, redirect, g
|
12
13
|
from hiddifypanel.panel.auth import login_required
|
13
|
-
from hiddifypanel.panel.hiddify import flash
|
14
14
|
from flask_wtf.file import FileField, FileRequired
|
15
15
|
from flask_classful import FlaskView
|
16
16
|
|
@@ -58,13 +58,13 @@ class Backup(FlaskView):
|
|
58
58
|
|
59
59
|
from flask_babel import refresh
|
60
60
|
refresh()
|
61
|
-
return redirect(url_for("admin.Actions:reinstall2"))
|
61
|
+
return redirect(hutils.flask.url_for("admin.Actions:reinstall2"))
|
62
62
|
# from . import Actions
|
63
63
|
# action = Actions()
|
64
64
|
# return action.reinstall(complete_install=True, domain_changed=True)
|
65
|
-
# #
|
65
|
+
# # hutils.flask.flash_config_success(full_install=True)
|
66
66
|
else:
|
67
|
-
flash(_('Config file is incorrect'), category='error')
|
67
|
+
hutils.flask.flash(_('Config file is incorrect'), category='error')
|
68
68
|
return render_template('backup.html', restore_form=restore_form)
|
69
69
|
|
70
70
|
|
@@ -74,7 +74,7 @@ def get_restore_form(empty=False):
|
|
74
74
|
enable_config_restore = SwitchField(_("Restore Settings"), description=_("Restore Settings description"), default=False)
|
75
75
|
enable_user_restore = SwitchField(_("Restore Users"), description=_("Restore Users description"), default=False)
|
76
76
|
enable_domain_restore = SwitchField(_("Restore Domain"), description=_("Restore Domain description"), default=False)
|
77
|
-
override_root_admin = SwitchField(_("Override Root Admin"), description=_("It will override the root admin to the current user"), default=
|
77
|
+
override_root_admin = SwitchField(_("Override Root Admin"), description=_("It will override the root admin to the current user"), default=False)
|
78
78
|
submit = wtf.fields.SubmitField(_('Submit'))
|
79
79
|
|
80
80
|
return RestoreForm(None) if empty else RestoreForm()
|
@@ -3,7 +3,7 @@ from hiddifypanel.models import *
|
|
3
3
|
from .adminlte import AdminLTEModelView
|
4
4
|
from flask_babelex import gettext as __
|
5
5
|
from flask_babelex import lazy_gettext as _
|
6
|
-
from flask import Markup
|
6
|
+
from flask import Markup, g
|
7
7
|
|
8
8
|
from hiddifypanel.panel.auth import login_required
|
9
9
|
from hiddifypanel.panel import hiddify
|
@@ -103,12 +103,12 @@ class ChildAdmin(AdminLTEModelView):
|
|
103
103
|
if len(model.show_domains) == Domain.query.count():
|
104
104
|
model.show_domains = []
|
105
105
|
|
106
|
-
|
106
|
+
hutils.flask.flash_config_success(restart_mode='apply', domain_changed=True)
|
107
107
|
|
108
108
|
def on_model_delete(self, model):
|
109
109
|
if len(ParentDomain.query.all()) <= 1:
|
110
110
|
raise ValidationError(f"at least one domain should exist")
|
111
|
-
|
111
|
+
hutils.flask.flash_config_success(restart_mode='apply', domain_changed=True)
|
112
112
|
|
113
113
|
def is_accessible(self):
|
114
114
|
if login_required(roles={Role.super_admin})(lambda: True)() != True:
|
@@ -11,7 +11,7 @@ import hiddifypanel
|
|
11
11
|
from hiddifypanel.models import *
|
12
12
|
from hiddifypanel.panel import hiddify
|
13
13
|
from hiddifypanel.panel.database import db
|
14
|
-
from hiddifypanel
|
14
|
+
from hiddifypanel import hutils
|
15
15
|
|
16
16
|
|
17
17
|
class Dashboard(FlaskView):
|
@@ -33,7 +33,7 @@ class Dashboard(FlaskView):
|
|
33
33
|
if hconfig(ConfigEnum.first_setup):
|
34
34
|
return redirect(url_for("admin.QuickSetup:index"))
|
35
35
|
if hiddifypanel.__release_date__ + datetime.timedelta(days=20) < datetime.datetime.now():
|
36
|
-
flash(_('This version of hiddify panel is outdated. Please update it from admin area.'), "danger")
|
36
|
+
hutils.flask.flash(_('This version of hiddify panel is outdated. Please update it from admin area.'), "danger") # type: ignore
|
37
37
|
bot = None
|
38
38
|
# if hconfig(ConfigEnum.license):
|
39
39
|
childs = None
|
@@ -65,21 +65,23 @@ class Dashboard(FlaskView):
|
|
65
65
|
|
66
66
|
if def_user and sslip_domains:
|
67
67
|
quick_setup = url_for("admin.QuickSetup:index")
|
68
|
-
flash((_('It seems that you have not setup the system completely. <a class="btn btn-success" href="%(quick_setup)s">Click here</a> to complete setup.',
|
68
|
+
hutils.flask.flash((_('It seems that you have not setup the system completely. <a class="btn btn-success" href="%(quick_setup)s">Click here</a> to complete setup.',
|
69
|
+
quick_setup=quick_setup)), 'warning') # type: ignore
|
69
70
|
if hconfig(ConfigEnum.is_parent):
|
70
|
-
flash(_("Please understand that parent panel is under test and the plan and the condition of use maybe change at anytime."), "danger")
|
71
|
+
hutils.flask.flash(_("Please understand that parent panel is under test and the plan and the condition of use maybe change at anytime."), "danger") # type: ignore
|
71
72
|
elif len(sslip_domains):
|
72
|
-
flash((_('It seems that you are using default domain (%(domain)s) which is not recommended.', domain=sslip_domains[0])), 'warning')
|
73
|
+
hutils.flask.flash((_('It seems that you are using default domain (%(domain)s) which is not recommended.', domain=sslip_domains[0])), 'warning') # type: ignore
|
73
74
|
if hconfig(ConfigEnum.is_parent):
|
74
|
-
flash(_("Please understand that parent panel is under test and the plan and the condition of use maybe change at anytime."), "danger")
|
75
|
+
hutils.flask.flash(_("Please understand that parent panel is under test and the plan and the condition of use maybe change at anytime."), "danger") # type: ignore
|
75
76
|
elif def_user:
|
76
77
|
d = domains[0]
|
77
|
-
flash((_('It seems that you have not created any users yet. Default user link: %(default_link)s',
|
78
|
+
hutils.flask.flash((_('It seems that you have not created any users yet. Default user link: %(default_link)s',
|
79
|
+
default_link=hiddify.get_html_user_link(def_user, d))), 'secondary') # type: ignore
|
78
80
|
if hiddify.is_ssh_password_authentication_enabled():
|
79
|
-
flash(_('ssh.password-login.warning.'), "warning")
|
81
|
+
hutils.flask.flash(_('ssh.password-login.warning.'), "warning") # type: ignore
|
80
82
|
|
81
83
|
# except:
|
82
|
-
# flash((_('Error!!!')),'info')
|
84
|
+
# hutils.flask.flash((_('Error!!!')),'info')
|
83
85
|
|
84
86
|
stats = {'system': hiddify.system_stats(), 'top5': hiddify.top_processes()}
|
85
87
|
return render_template('index.html', stats=stats, usage_history=DailyUsage.get_daily_usage_stats(admin_id, child_id), childs=childs)
|
@@ -91,5 +93,5 @@ class Dashboard(FlaskView):
|
|
91
93
|
child = Child.query.filter(Child.id == child_id).first()
|
92
94
|
db.session.delete(child)
|
93
95
|
db.session.commit()
|
94
|
-
flash(_("child has been removed!"), "success")
|
96
|
+
hutils.flask.flash(_("child has been removed!"), "success") # type: ignore
|
95
97
|
return self.index()
|
@@ -4,7 +4,6 @@ import hiddifypanel.panel.auth as auth
|
|
4
4
|
from hiddifypanel.models import *
|
5
5
|
import re
|
6
6
|
from flask import Markup, g
|
7
|
-
from flask import flash
|
8
7
|
from flask_babelex import gettext as __
|
9
8
|
from flask_babelex import lazy_gettext as _
|
10
9
|
from hiddifypanel.panel.run_commander import Command, commander
|
@@ -91,7 +90,7 @@ class DomainAdmin(AdminLTEModelView):
|
|
91
90
|
return Markup(f"<span class='badge'>{model.domain}</span>")
|
92
91
|
d = model.domain
|
93
92
|
if "*" in d:
|
94
|
-
d = d.replace("*",
|
93
|
+
d = d.replace("*", hutils.random.get_random_string(5, 15))
|
95
94
|
admin_link = hiddify.get_account_panel_link(g.account, d)
|
96
95
|
return Markup(
|
97
96
|
f'<div class="btn-group"><a href="{admin_link}" class="btn btn-xs btn-secondary">' + _("admin link") +
|
@@ -170,7 +169,7 @@ class DomainAdmin(AdminLTEModelView):
|
|
170
169
|
raise ValidationError(__("Can not connect to Cloudflare.")+f' {e}')
|
171
170
|
# elif model.mode==DomainType.auto_cdn_ip:
|
172
171
|
if model.alias and not model.alias.replace("_", "").isalnum():
|
173
|
-
flash(__("Using alias with special charachters may cause problem in some clients like FairVPN."), 'warning')
|
172
|
+
hutils.flask.flash(__("Using alias with special charachters may cause problem in some clients like FairVPN."), 'warning')
|
174
173
|
# raise ValidationError(_("You have to add your cloudflare api key to use this feature: "))
|
175
174
|
|
176
175
|
dip = hutils.ip.get_domain_ip(model.domain)
|
@@ -187,11 +186,13 @@ class DomainAdmin(AdminLTEModelView):
|
|
187
186
|
domain_ip_is_same_as_panel |= ipaddress.ip_address(dip) == ipaddress.ip_address(ipv6)
|
188
187
|
|
189
188
|
if model.mode == DomainType.direct and not domain_ip_is_same_as_panel:
|
190
|
-
flash(
|
189
|
+
hutils.flask.flash(
|
190
|
+
__(message=f"Domain IP={dip} is not matched with your ip={', '.join(list(map(str, ipv4_list)))} which is required in direct mode"),
|
191
|
+
category='warning')
|
191
192
|
# raise ValidationError(_("Domain IP=%(domain_ip)s is not matched with your ip=%(server_ip)s which is required in direct mode", server_ip=myip, domain_ip=dip))
|
192
193
|
|
193
194
|
if domain_ip_is_same_as_panel and model.mode in [DomainType.cdn, DomainType.relay, DomainType.fake, DomainType.auto_cdn_ip]:
|
194
|
-
flash(__(f"In CDN mode, Domain IP={dip} should be different to your ip={', '.join(list(map(str, ipv4_list)))}"), 'warning')
|
195
|
+
hutils.flask.flash(__(f"In CDN mode, Domain IP={dip} should be different to your ip={', '.join(list(map(str, ipv4_list)))}"), 'warning')
|
195
196
|
# raise ValidationError(_("In CDN mode, Domain IP=%(domain_ip)s should be different to your ip=%(server_ip)s", server_ip=myip, domain_ip=dip))
|
196
197
|
|
197
198
|
# if model.mode in [DomainType.ss_faketls, DomainType.telegram_faketls]:
|
@@ -220,7 +221,7 @@ class DomainAdmin(AdminLTEModelView):
|
|
220
221
|
if model.mode == DomainType.reality:
|
221
222
|
model.servernames = (model.domain).lower()
|
222
223
|
if not hiddify.is_domain_reality_friendly(model.domain):
|
223
|
-
# flash(_("Domain is not REALITY friendly!")+" "+d,'error')
|
224
|
+
# hutils.flask.flash(_("Domain is not REALITY friendly!")+" "+d,'error')
|
224
225
|
# return render_template('config.html', form=form)
|
225
226
|
raise ValidationError(_("Domain is not REALITY friendly!")+" "+model.domain)
|
226
227
|
|
@@ -235,7 +236,7 @@ class DomainAdmin(AdminLTEModelView):
|
|
235
236
|
continue
|
236
237
|
|
237
238
|
if not hiddify.is_domain_reality_friendly(d):
|
238
|
-
# flash(_("Domain is not REALITY friendly!")+" "+d,'error')
|
239
|
+
# hutils.flask.flash(_("Domain is not REALITY friendly!")+" "+d,'error')
|
239
240
|
# return render_template('config.html', form=form)
|
240
241
|
raise ValidationError(_("Domain is not REALITY friendly!")+" "+d)
|
241
242
|
|
@@ -255,7 +256,7 @@ class DomainAdmin(AdminLTEModelView):
|
|
255
256
|
old_db_domain = get_domain(model.domain)
|
256
257
|
if is_created or not old_db_domain or old_db_domain.mode != model.mode:
|
257
258
|
# return hiddify.reinstall_action(complete_install=False, domain_changed=True)
|
258
|
-
|
259
|
+
hutils.flask.flash_config_success(restart_mode='apply', domain_changed=True)
|
259
260
|
|
260
261
|
# def after_model_change(self,form, model, is_created):
|
261
262
|
# if model.show_domains.count==0:
|
@@ -267,7 +268,7 @@ class DomainAdmin(AdminLTEModelView):
|
|
267
268
|
# ShowDomain.query.filter_by(related_id == model.id).delete()
|
268
269
|
model.showed_by_domains = []
|
269
270
|
# db.session.commit()
|
270
|
-
|
271
|
+
hutils.flask.flash_config_success(restart_mode='apply', domain_changed=True)
|
271
272
|
|
272
273
|
def after_model_delete(self, model):
|
273
274
|
# if hconfig(ConfigEnum.parent_panel):
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from flask_babelex import gettext as _
|
2
|
+
from hiddifypanel import hutils
|
2
3
|
from hiddifypanel.models.role import Role
|
3
4
|
import wtforms as wtf
|
4
5
|
from flask_wtf import FlaskForm
|
@@ -7,13 +8,10 @@ from flask import render_template
|
|
7
8
|
|
8
9
|
|
9
10
|
from hiddifypanel.models import ConfigEnum, get_hconfigs, BoolConfig, ConfigEnum, hconfig, Proxy
|
10
|
-
from hiddifypanel.panel.hiddify import flash
|
11
11
|
from hiddifypanel.panel.database import db
|
12
12
|
from wtforms.fields import *
|
13
13
|
from hiddifypanel.panel import hiddify
|
14
14
|
from flask_classful import FlaskView
|
15
|
-
from hiddifypanel.panel.hiddify import flash
|
16
|
-
from hiddifypanel.panel import hiddify
|
17
15
|
from hiddifypanel.panel.auth import login_required
|
18
16
|
|
19
17
|
|
@@ -33,7 +31,7 @@ class ProxyAdmin(FlaskView):
|
|
33
31
|
if k in [c for c in ConfigEnum]:
|
34
32
|
BoolConfig.query.filter(BoolConfig.key == k).first().value = vs
|
35
33
|
if vs and k in [ConfigEnum.domain_fronting_http_enable, ConfigEnum.domain_fronting_tls_enable] and hconfig(ConfigEnum.domain_fronting_domain) == "":
|
36
|
-
flash((_('config.domain-fronting-notsetup-error')), 'danger')
|
34
|
+
hutils.flask.flash((_('config.domain-fronting-notsetup-error')), 'danger')
|
37
35
|
|
38
36
|
# print(cat,vs)
|
39
37
|
hiddify.get_available_proxies.invalidate_all()
|
@@ -58,12 +56,12 @@ class ProxyAdmin(FlaskView):
|
|
58
56
|
# print(cat,vs)
|
59
57
|
db.session.commit()
|
60
58
|
hiddify.get_available_proxies.invalidate_all()
|
61
|
-
|
59
|
+
hutils.flask.flash_config_success(restart_mode='apply', domain_changed=False)
|
62
60
|
# if hconfig(ConfigEnum.parent_panel):
|
63
61
|
# hiddify_api.sync_child_to_parent()
|
64
62
|
global_config_form = get_global_config_form(True)
|
65
63
|
else:
|
66
|
-
flash((_('config.validation-error')), 'danger')
|
64
|
+
hutils.flask.flash((_('config.validation-error')), 'danger')
|
67
65
|
|
68
66
|
return render_template('proxy.html', global_config_form=global_config_form, detailed_config_form=all_proxy_form)
|
69
67
|
|
@@ -1,26 +1,24 @@
|
|
1
|
-
|
2
|
-
from hiddifypanel import hutils
|
3
|
-
from hiddifypanel.models import *
|
1
|
+
import re
|
4
2
|
import flask_babel
|
5
3
|
import flask_babelex
|
6
4
|
|
7
5
|
# from flask_babelex import lazy_gettext as _
|
6
|
+
from flask import render_template, g
|
8
7
|
from flask_babelex import gettext as _
|
9
8
|
import wtforms as wtf
|
10
9
|
from flask_wtf import FlaskForm
|
11
10
|
from flask_bootstrap import SwitchField
|
12
11
|
from hiddifypanel.panel import hiddify
|
13
|
-
|
12
|
+
from wtforms.fields import *
|
13
|
+
from flask_classful import FlaskView
|
14
14
|
from wtforms.validators import ValidationError
|
15
|
+
# from gettext import gettext as _
|
15
16
|
|
16
|
-
import re
|
17
|
-
from flask import render_template, g
|
18
17
|
from hiddifypanel.models import Domain, DomainType, StrConfig, ConfigEnum, get_hconfigs
|
19
18
|
from hiddifypanel.panel.database import db
|
20
|
-
from
|
21
|
-
|
22
|
-
from hiddifypanel.
|
23
|
-
from flask_classful import FlaskView
|
19
|
+
from hiddifypanel.panel.auth import login_required
|
20
|
+
from hiddifypanel import hutils
|
21
|
+
from hiddifypanel.models import *
|
24
22
|
|
25
23
|
|
26
24
|
class QuickSetup(FlaskView):
|
@@ -51,9 +49,9 @@ class QuickSetup(FlaskView):
|
|
51
49
|
# with flask_babel.force_locale(lang_form.admin_lang.data):
|
52
50
|
# flask_babel.refresh()
|
53
51
|
# flask_babelex.refresh()
|
54
|
-
flash((_('quicksetup.setlang.success')), 'success')
|
52
|
+
hutils.flask.flash((_('quicksetup.setlang.success')), 'success')
|
55
53
|
else:
|
56
|
-
flash((_('quicksetup.setlang.error')), 'danger')
|
54
|
+
hutils.flask.flash((_('quicksetup.setlang.error')), 'danger')
|
57
55
|
|
58
56
|
return render_template(
|
59
57
|
'quick_setup.html', form=get_quick_setup_form(True),
|
@@ -80,7 +78,7 @@ class QuickSetup(FlaskView):
|
|
80
78
|
action = Actions.Actions()
|
81
79
|
return action.reinstall(domain_changed=True)
|
82
80
|
else:
|
83
|
-
flash(_('config.validation-error'), 'danger')
|
81
|
+
hutils.flask.flash(_('config.validation-error'), 'danger')
|
84
82
|
return render_template(
|
85
83
|
'quick_setup.html', form=quick_form, lang_form=get_lang_form(True),
|
86
84
|
ipv4=hutils.ip.get_ip(4),
|
@@ -1,9 +1,11 @@
|
|
1
|
+
import re
|
1
2
|
import flask_babel
|
2
3
|
import flask_babelex
|
3
4
|
from flask_babelex import lazy_gettext as _
|
4
5
|
# from flask_babelex import gettext as _
|
5
6
|
from flask import render_template, Markup, url_for, g
|
6
7
|
from flask import current_app as app
|
8
|
+
from hiddifypanel import hutils
|
7
9
|
from hiddifypanel.panel.auth import login_required
|
8
10
|
import wtforms as wtf
|
9
11
|
from flask_bootstrap import SwitchField
|
@@ -13,12 +15,10 @@ from flask_classful import FlaskView
|
|
13
15
|
from wtforms.fields import *
|
14
16
|
from flask_wtf import FlaskForm
|
15
17
|
|
16
|
-
import re
|
17
18
|
|
18
19
|
from hiddifypanel.models import BoolConfig, StrConfig, ConfigEnum, hconfig, ConfigCategory
|
19
20
|
from hiddifypanel.models import *
|
20
21
|
from hiddifypanel.panel.database import db
|
21
|
-
from hiddifypanel.panel.hiddify import flash
|
22
22
|
from hiddifypanel.panel.hiddify import get_random_domains
|
23
23
|
from hiddifypanel.panel import hiddify, custom_widgets
|
24
24
|
|
@@ -57,7 +57,7 @@ class SettingAdmin(FlaskView):
|
|
57
57
|
for p in v.split(","):
|
58
58
|
for k2, v2 in vs.items():
|
59
59
|
if "port" in k2 and k != k2 and p in v2:
|
60
|
-
flash(_("Port is already used! in")+f" {k2} {k}", 'error')
|
60
|
+
hutils.flask.flash(_("Port is already used! in")+f" {k2} {k}", 'error')
|
61
61
|
return render_template('config.html', form=form)
|
62
62
|
if k == ConfigEnum.parent_panel and v != '':
|
63
63
|
# v=(v+"/").replace("/admin",'')
|
@@ -65,10 +65,10 @@ class SettingAdmin(FlaskView):
|
|
65
65
|
|
66
66
|
# try:
|
67
67
|
# # if hiddify_api.sync_child_to_parent(v)['status'] != 200:
|
68
|
-
# # flash(_("Can not connect to parent panel!"), 'error')
|
68
|
+
# # hutils.flask.flash(_("Can not connect to parent panel!"), 'error')
|
69
69
|
# # return render_template('config.html', form=form)
|
70
70
|
# except:
|
71
|
-
# flash(_("Can not connect to parent panel!"), 'error')
|
71
|
+
# hutils.flask.flash(_("Can not connect to parent panel!"), 'error')
|
72
72
|
# return render_template('config.html', form=form)
|
73
73
|
StrConfig.query.filter(StrConfig.key == k, StrConfig.child_id == 0).first().value = v
|
74
74
|
if old_configs[k] != v:
|
@@ -78,20 +78,20 @@ class SettingAdmin(FlaskView):
|
|
78
78
|
|
79
79
|
merged_configs = {**old_configs, **changed_configs}
|
80
80
|
if len(set([merged_configs[ConfigEnum.proxy_path], merged_configs[ConfigEnum.proxy_path_client], merged_configs[ConfigEnum.proxy_path_admin]])) != 3:
|
81
|
-
flash(_("ProxyPath is already used! use different proxy path"), 'error')
|
81
|
+
hutils.flask.flash(_("ProxyPath is already used! use different proxy path"), 'error')#type: ignore
|
82
82
|
return render_template('config.html', form=form)
|
83
83
|
# for k in [ConfigEnum.reality_server_names,ConfigEnum.reality_fallback_domain]:
|
84
84
|
# v=merged_configs[k]
|
85
85
|
# for d in v.split(","):
|
86
86
|
# if not d:continue
|
87
87
|
# if not hiddify.is_domain_reality_friendly(d):
|
88
|
-
# flash(_("Domain is not REALITY friendly!")+" "+d,'error')
|
88
|
+
# hutils.flask.flash(_("Domain is not REALITY friendly!")+" "+d,'error')
|
89
89
|
# return render_template('config.html', form=form)
|
90
90
|
# hiddify.debug_flash_if_not_in_the_same_asn(d)
|
91
91
|
# fallback=merged_configs[ConfigEnum.reality_fallback_domain]
|
92
92
|
# for d in merged_configs[ConfigEnum.reality_server_names].split(","):
|
93
93
|
# if not hiddify.fallback_domain_compatible_with_servernames(fallback, d):
|
94
|
-
# flash(_("REALITY Fallback domain is not compaitble with server names!")+" "+d+" != "+fallback,'error')
|
94
|
+
# hutils.flask.flash(_("REALITY Fallback domain is not compaitble with server names!")+" "+d+" != "+fallback,'error')
|
95
95
|
# return render_template('config.html', form=form)
|
96
96
|
for k, v in changed_configs.items():
|
97
97
|
set_hconfig(k, v, 0, False)
|
@@ -110,7 +110,7 @@ class SettingAdmin(FlaskView):
|
|
110
110
|
if old_configs[ConfigEnum.admin_lang] != hconfig(ConfigEnum.admin_lang):
|
111
111
|
form = get_config_form()
|
112
112
|
else:
|
113
|
-
flash(_('config.validation-error'), 'danger')
|
113
|
+
hutils.flask.flash(_('config.validation-error'), 'danger')#type: ignore
|
114
114
|
|
115
115
|
return reset_action or render_template('config.html', form=form)
|
116
116
|
|
@@ -211,6 +211,10 @@ def get_config_form():
|
|
211
211
|
libs = [("python", _("lib.telegram.python")), ("tgo", _("lib.telegram.go")), ("orig", _("lib.telegram.orignal")), ("erlang", _("lib.telegram.erlang"))]
|
212
212
|
field = wtf.fields.SelectField(_("config.telegram_lib.label"), choices=libs, description=_(
|
213
213
|
"config.telegram_lib.description"), default=hconfig(ConfigEnum.telegram_lib))
|
214
|
+
elif c.key == ConfigEnum.mux_protocol:
|
215
|
+
choices = [("smux", 'smux'), ("yamux", "yamux"), ("h2mux", "h2mux")]
|
216
|
+
field = wtf.fields.SelectField(_(f"config.{c.key}.label"), choices=choices, description=_(f"config.{c.key}.description"), default=hconfig(c.key))
|
217
|
+
|
214
218
|
elif c.key == ConfigEnum.warp_sites:
|
215
219
|
validators = [wtf.validators.Length(max=2048)]
|
216
220
|
render_kw = {'class': "ltr", 'maxlength': 2048}
|
@@ -265,9 +269,15 @@ def get_config_form():
|
|
265
269
|
render_kw['required'] = ""
|
266
270
|
else:
|
267
271
|
validators.append(wtf.validators.Regexp("^(\d+)(,\d+)*$|^$", re.IGNORECASE, _("config.Invalid port")))
|
268
|
-
|
269
272
|
# validators.append(wtf.validators.Regexp("^(\d+)(,\d+)*$",re.IGNORECASE,_("config.port is required")))
|
270
273
|
|
274
|
+
# tls tricks validations
|
275
|
+
if c.key in [ConfigEnum.tls_fragment_size, ConfigEnum.tls_fragment_sleep, ConfigEnum.tls_padding_length]:
|
276
|
+
validators.append(wtf.validators.Regexp("^\d+-\d+$", re.IGNORECASE, _("config.Invalid! The pattern is number-number")+f' {c.key}'))
|
277
|
+
# mux and hysteria validations
|
278
|
+
if c.key in [ConfigEnum.hysteria_up_mbps, ConfigEnum.hysteria_down_mbps, ConfigEnum.mux_max_connections, ConfigEnum.mux_min_streams, ConfigEnum.mux_max_streams,
|
279
|
+
ConfigEnum.mux_brutal_down_mbps, ConfigEnum.mux_brutal_up_mbps]:
|
280
|
+
validators.append(wtf.validators.Regexp("^\d+$", re.IGNORECASE, _("config.Invalid! it should be a number only")+f' {c.key}'))
|
271
281
|
for val in validators:
|
272
282
|
if hasattr(val, "regex"):
|
273
283
|
render_kw['pattern'] = val.regex.pattern
|
@@ -1,9 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
from hiddifypanel.panel.hiddify import flash
|
5
|
-
from hiddifypanel.panel import hiddify, custom_widgets
|
1
|
+
import re
|
2
|
+
import datetime
|
3
|
+
import uuid
|
6
4
|
from apiflask import abort
|
5
|
+
from flask_bootstrap import SwitchField
|
7
6
|
from flask_babelex import gettext as __
|
8
7
|
from .adminlte import AdminLTEModelView
|
9
8
|
from wtforms.validators import NumberRange
|
@@ -11,10 +10,12 @@ from flask_babelex import lazy_gettext as _
|
|
11
10
|
from flask import Markup, g, request, url_for
|
12
11
|
from wtforms.validators import Regexp, ValidationError
|
13
12
|
from flask import current_app
|
14
|
-
|
15
|
-
import
|
16
|
-
import
|
13
|
+
|
14
|
+
from hiddifypanel.models import *
|
15
|
+
from hiddifypanel.drivers import user_driver
|
16
|
+
from hiddifypanel.panel import hiddify, custom_widgets
|
17
17
|
from hiddifypanel.panel.auth import login_required
|
18
|
+
from hiddifypanel import hutils
|
18
19
|
import hiddifypanel.panel.auth as auth
|
19
20
|
|
20
21
|
|
@@ -204,7 +205,7 @@ class UserAdmin(AdminLTEModelView):
|
|
204
205
|
if len(User.query.all()) <= 1:
|
205
206
|
raise ValidationError(f"at least one user should exist")
|
206
207
|
user_driver.remove_client(model)
|
207
|
-
#
|
208
|
+
# hutils.flask.flash_config_success()
|
208
209
|
|
209
210
|
def is_accessible(self):
|
210
211
|
if login_required(roles={Role.super_admin, Role.admin, Role.agent})(lambda: True)() != True:
|
@@ -246,12 +247,13 @@ class UserAdmin(AdminLTEModelView):
|
|
246
247
|
def on_model_change(self, form, model, is_created):
|
247
248
|
model.max_ips = max(3, model.max_ips or 10000)
|
248
249
|
if len(User.query.all()) % 4 == 0:
|
249
|
-
flash(('<div id="show-modal-donation"></div>'), ' d-none')
|
250
|
+
hutils.flask.flash(('<div id="show-modal-donation"></div>'), ' d-none')
|
250
251
|
if not re.match("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", model.uuid):
|
251
252
|
raise ValidationError('Invalid UUID e.g.,' + str(uuid.uuid4()))
|
252
|
-
|
253
253
|
if form.reset_usage.data:
|
254
254
|
model.current_usage_GB = 0
|
255
|
+
# if model.telegram_id and model.telegram_id != '0' and not re.match(r"^[1-9]\d*$", model.telegram_id):
|
256
|
+
# raise ValidationError('Invalid Telegram ID')
|
255
257
|
# if form.disable_user.data:
|
256
258
|
# model.mode=UserMode.disable
|
257
259
|
if form.reset_days.data:
|
@@ -275,7 +277,7 @@ class UserAdmin(AdminLTEModelView):
|
|
275
277
|
# xray_api.add_client(model.uuid)
|
276
278
|
# else:
|
277
279
|
# xray_api.remove_client(model.uuid)
|
278
|
-
#
|
280
|
+
# hutils.flask.flash_config_success()
|
279
281
|
|
280
282
|
def after_model_change(self, form, model, is_created):
|
281
283
|
if hconfig(ConfigEnum.first_setup):
|
hiddifypanel/panel/auth.py
CHANGED
@@ -10,13 +10,46 @@ import hiddifypanel.panel.hiddify as hiddify
|
|
10
10
|
from hiddifypanel import hutils
|
11
11
|
|
12
12
|
from werkzeug.local import LocalProxy
|
13
|
+
|
13
14
|
current_account = LocalProxy(lambda: _get_user())
|
14
15
|
|
15
16
|
|
17
|
+
class AnonymousAccount(BaseAccount):
|
18
|
+
__abstract__ = True
|
19
|
+
|
20
|
+
@property
|
21
|
+
def uuid(self):
|
22
|
+
return None
|
23
|
+
|
24
|
+
@property
|
25
|
+
def lang(self) -> Lang:
|
26
|
+
return None
|
27
|
+
|
28
|
+
@property
|
29
|
+
def role(self) -> Role | None:
|
30
|
+
return None
|
31
|
+
|
32
|
+
def get_id(self) -> str | None:
|
33
|
+
return "-1"
|
34
|
+
|
35
|
+
def __bool__(self):
|
36
|
+
return False
|
37
|
+
|
38
|
+
def __eq__(self, other):
|
39
|
+
if other == None:
|
40
|
+
return True
|
41
|
+
if isinstance(other, AnonymousAccount):
|
42
|
+
return True
|
43
|
+
return False
|
44
|
+
|
45
|
+
def __ne__(self, other):
|
46
|
+
return not self.__eq__(other)
|
47
|
+
|
48
|
+
|
16
49
|
def _get_user():
|
17
|
-
if not hasattr(g, "
|
18
|
-
g.
|
19
|
-
return g.
|
50
|
+
if not hasattr(g, "__account_store"):
|
51
|
+
g.__account_store = AnonymousAccount()
|
52
|
+
return g.__account_store
|
20
53
|
|
21
54
|
|
22
55
|
def admin_session_is_exist():
|
@@ -24,7 +57,7 @@ def admin_session_is_exist():
|
|
24
57
|
|
25
58
|
|
26
59
|
def logout_user():
|
27
|
-
g.
|
60
|
+
g.__account_store = None
|
28
61
|
if '_user_id' in session:
|
29
62
|
session.pop('_user_id')
|
30
63
|
if '_admin_id' in session:
|
@@ -33,7 +66,7 @@ def logout_user():
|
|
33
66
|
|
34
67
|
def login_user(user: AdminUser | User, remember=False, duration=None, force=False, fresh=True):
|
35
68
|
# abort(400, f'logining user: {user} {user.is_active}')
|
36
|
-
g.
|
69
|
+
g.__account_store = user
|
37
70
|
# if not user.is_active:
|
38
71
|
# return False
|
39
72
|
|
@@ -122,7 +155,7 @@ def init_app(app):
|
|
122
155
|
|
123
156
|
elif auth_header := request.headers.get("Hiddify_API_KEY"):
|
124
157
|
# print("auth_header", auth_header)
|
125
|
-
apikey = hutils.
|
158
|
+
apikey = hutils.auth.get_apikey_from_auth_header(auth_header)
|
126
159
|
account = get_account_by_api_key(apikey, is_admin_path)
|
127
160
|
if not account:
|
128
161
|
return logout_redirect()
|
@@ -139,23 +172,23 @@ def init_app(app):
|
|
139
172
|
return logout_redirect()
|
140
173
|
|
141
174
|
elif (session_user := session.get('_user_id')) and not is_admin_path:
|
142
|
-
print('session_user', session_user)
|
175
|
+
# print('session_user', session_user)
|
143
176
|
account = User.by_id(int(session_user.split("_")[1])) # type: ignore
|
144
177
|
if not account:
|
145
178
|
return logout_redirect()
|
146
179
|
elif (session_admin := session.get('_admin_id')) and is_admin_path:
|
147
|
-
print('session_admin', session_admin)
|
180
|
+
# print('session_admin', session_admin)
|
148
181
|
account = AdminUser.by_id(int(session_admin.split("_")[1])) # type: ignore
|
149
182
|
if not account:
|
150
183
|
return logout_redirect()
|
151
184
|
|
152
185
|
if account:
|
153
|
-
g.
|
186
|
+
g.__account_store = account
|
154
187
|
# g.account_uuid = account.uuid
|
155
188
|
g.is_admin = hiddify.is_admin_role(account.role) # type: ignore
|
156
189
|
login_user(account, force=True)
|
157
190
|
# print("loggining in")
|
158
|
-
if next_url is not None and g.user_agent['is_browser']:
|
191
|
+
if next_url is not None and g.user_agent['is_browser'] and ".webmanifest" not in request.path:
|
159
192
|
return redirect(next_url)
|
160
193
|
|
161
194
|
@app.url_value_preprocessor
|
hiddifypanel/panel/auth_back2.py
CHANGED
@@ -77,7 +77,7 @@ class CustumLoginManager(LoginManager):
|
|
77
77
|
is_api_call = False
|
78
78
|
|
79
79
|
if hiddify.is_api_call(request.path):
|
80
|
-
if apikey := hutils.
|
80
|
+
if apikey := hutils.auth.get_apikey_from_auth_header(auth_header):
|
81
81
|
account = User.by_uuid(apikey) or AdminUser.by_uuid(apikey)
|
82
82
|
is_api_call = True
|
83
83
|
else:
|
@@ -149,7 +149,7 @@ def get_account_by_api_key(api_key, is_admin):
|
|
149
149
|
|
150
150
|
|
151
151
|
def get_account_by_uuid(uuid, is_admin):
|
152
|
-
return AdminUser.by_uuid(
|
152
|
+
return AdminUser.by_uuid(uuid) if is_admin else User.by_uuid(uuid)
|
153
153
|
|
154
154
|
|
155
155
|
def init_app(app):
|
@@ -165,12 +165,12 @@ def init_app(app):
|
|
165
165
|
next_url = None
|
166
166
|
print("--------1")
|
167
167
|
if auth_header := request.headers.get("Authorization"):
|
168
|
-
apikey = hutils.
|
168
|
+
apikey = hutils.auth.get_apikey_from_auth_header(auth_header)
|
169
169
|
account = get_account_by_api_key(apikey, is_admin_path)
|
170
170
|
if not account:
|
171
171
|
logout_user()
|
172
172
|
|
173
|
-
if not account and (uuid := hutils.
|
173
|
+
if not account and (uuid := hutils.auth.get_uuid_from_url_path(request.path)):
|
174
174
|
account = get_account_by_uuid(uuid, is_admin_path)
|
175
175
|
if not account:
|
176
176
|
logout_user()
|
@@ -208,7 +208,7 @@ def init_app(app):
|
|
208
208
|
# return header_auth(request)
|
209
209
|
|
210
210
|
# parse id
|
211
|
-
acc_type, id = hutils.
|
211
|
+
acc_type, id = hutils.auth.parse_login_id(id) # type: ignore
|
212
212
|
if not acc_type or not id:
|
213
213
|
return
|
214
214
|
|
hiddifypanel/panel/cli.py
CHANGED
@@ -64,7 +64,7 @@ class ParentDomainAdmin(AdminLTEModelView):
|
|
64
64
|
form_columns = ['domain', "alias", 'show_domains']
|
65
65
|
|
66
66
|
def _domain_admin_link(view, context, model, name):
|
67
|
-
admin_link = hiddify.get_account_panel_link(g.account,model.domain)
|
67
|
+
admin_link = hiddify.get_account_panel_link(g.account, model.domain)
|
68
68
|
return Markup(f'<div class="btn-group"><a href="{admin_link}" class="btn btn-xs btn-secondary">' + _("admin link") +
|
69
69
|
f'</a><a href="{admin_link}" class="btn btn-xs btn-info ltr" target="_blank">{model.domain}</a></div>')
|
70
70
|
|
@@ -116,12 +116,12 @@ class ParentDomainAdmin(AdminLTEModelView):
|
|
116
116
|
if len(model.show_domains) == Domain.query.count():
|
117
117
|
model.show_domains = []
|
118
118
|
|
119
|
-
|
119
|
+
hutils.flask.flash_config_success(restart_mode='apply', domain_changed=True)
|
120
120
|
|
121
121
|
def on_model_delete(self, model):
|
122
122
|
if len(ParentDomain.query.all()) <= 1:
|
123
123
|
raise ValidationError(f"at least one domain should exist")
|
124
|
-
|
124
|
+
hutils.flask.flash_config_success(restart_mode='apply', domain_changed=True)
|
125
125
|
|
126
126
|
def is_accessible(self):
|
127
127
|
if login_required(roles={Role.super_admin, Role.admin})(lambda: True)() != True:
|