hiddifypanel 10.70.8__py3-none-any.whl → 10.80.0__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.
Files changed (89) hide show
  1. hiddifypanel/VERSION +1 -1
  2. hiddifypanel/VERSION.py +5 -2
  3. hiddifypanel/__init__.py +5 -1
  4. hiddifypanel/apps/__init__.py +0 -0
  5. hiddifypanel/apps/asgi_app.py +7 -0
  6. hiddifypanel/apps/celery_app.py +3 -0
  7. hiddifypanel/apps/wsgi_app.py +5 -0
  8. hiddifypanel/auth.py +8 -3
  9. hiddifypanel/base.py +43 -126
  10. hiddifypanel/base_setup.py +82 -0
  11. hiddifypanel/cache.py +3 -2
  12. hiddifypanel/celery.py +45 -0
  13. hiddifypanel/database.py +7 -0
  14. hiddifypanel/drivers/ssh_liberty_bridge_api.py +2 -1
  15. hiddifypanel/drivers/wireguard_api.py +1 -1
  16. hiddifypanel/hutils/crypto.py +27 -0
  17. hiddifypanel/hutils/flask.py +5 -3
  18. hiddifypanel/hutils/network/cf_api.py +5 -5
  19. hiddifypanel/hutils/proxy/__init__.py +1 -0
  20. hiddifypanel/hutils/proxy/clash.py +3 -3
  21. hiddifypanel/hutils/proxy/shared.py +14 -18
  22. hiddifypanel/hutils/proxy/singbox.py +4 -2
  23. hiddifypanel/hutils/proxy/wireguard.py +34 -0
  24. hiddifypanel/hutils/proxy/xray.py +3 -3
  25. hiddifypanel/hutils/proxy/xrayjson.py +10 -7
  26. hiddifypanel/models/admin.py +1 -1
  27. hiddifypanel/models/base_account.py +3 -0
  28. hiddifypanel/models/config.py +5 -2
  29. hiddifypanel/models/config_enum.py +15 -2
  30. hiddifypanel/models/proxy.py +1 -1
  31. hiddifypanel/models/user.py +2 -2
  32. hiddifypanel/panel/__init__.py +8 -8
  33. hiddifypanel/panel/admin/AdminstratorAdmin.py +16 -10
  34. hiddifypanel/panel/admin/DomainAdmin.py +132 -98
  35. hiddifypanel/panel/admin/ProxyAdmin.py +4 -0
  36. hiddifypanel/panel/admin/QuickSetup.py +48 -17
  37. hiddifypanel/panel/admin/SettingAdmin.py +6 -0
  38. hiddifypanel/panel/admin/UserAdmin.py +63 -36
  39. hiddifypanel/panel/admin/adminlte.py +1 -1
  40. hiddifypanel/panel/admin/templates/index.html +6 -4
  41. hiddifypanel/panel/admin/templates/model/user_list.html +11 -3
  42. hiddifypanel/panel/cli.py +14 -3
  43. hiddifypanel/panel/commercial/restapi/v1/tgbot.py +19 -1
  44. hiddifypanel/panel/commercial/restapi/v2/admin/system_actions.py +5 -1
  45. hiddifypanel/panel/commercial/restapi/v2/admin/user_api.py +2 -1
  46. hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +76 -6
  47. hiddifypanel/panel/common.py +5 -2
  48. hiddifypanel/panel/common_bp/login.py +14 -8
  49. hiddifypanel/panel/hlogger.py +32 -0
  50. hiddifypanel/panel/init_db.py +157 -77
  51. hiddifypanel/panel/node/__init__.py +9 -0
  52. hiddifypanel/panel/node/a.py +14 -0
  53. hiddifypanel/panel/node/hello.py +14 -0
  54. hiddifypanel/panel/node/test.proto +13 -0
  55. hiddifypanel/panel/node/test_grpc.py +40 -0
  56. hiddifypanel/panel/node/test_pb2.py +40 -0
  57. hiddifypanel/panel/node/test_pb2.pyi +17 -0
  58. hiddifypanel/panel/node/test_pb2_grpc.py +97 -0
  59. hiddifypanel/panel/usage.py +13 -3
  60. hiddifypanel/panel/user/templates/base_singbox_config.json.j2 +16 -0
  61. hiddifypanel/panel/user/templates/home/home.html +1 -2
  62. hiddifypanel/panel/user/templates/home/multi.html +1 -2
  63. hiddifypanel/panel/user/user.py +13 -19
  64. hiddifypanel/static/apps-icon/singbox.ico +0 -0
  65. hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
  66. hiddifypanel/translations/en/LC_MESSAGES/messages.po +125 -30
  67. hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
  68. hiddifypanel/translations/fa/LC_MESSAGES/messages.po +123 -32
  69. hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
  70. hiddifypanel/translations/pt/LC_MESSAGES/messages.po +114 -22
  71. hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
  72. hiddifypanel/translations/ru/LC_MESSAGES/messages.po +129 -32
  73. hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
  74. hiddifypanel/translations/zh/LC_MESSAGES/messages.po +107 -18
  75. hiddifypanel/translations.i18n/en.json +73 -14
  76. hiddifypanel/translations.i18n/fa.json +72 -13
  77. hiddifypanel/translations.i18n/fr.json +28 -10
  78. hiddifypanel/translations.i18n/my.json +1266 -0
  79. hiddifypanel/translations.i18n/pt.json +68 -9
  80. hiddifypanel/translations.i18n/ru.json +75 -16
  81. hiddifypanel/translations.i18n/zh.json +67 -8
  82. hiddifypanel-10.80.0.dist-info/METADATA +137 -0
  83. {hiddifypanel-10.70.8.dist-info → hiddifypanel-10.80.0.dist-info}/RECORD +136 -119
  84. {hiddifypanel-10.70.8.dist-info → hiddifypanel-10.80.0.dist-info}/WHEEL +1 -2
  85. hiddifypanel-10.80.0.dist-info/entry_points.txt +3 -0
  86. hiddifypanel-10.70.8.dist-info/METADATA +0 -144
  87. hiddifypanel-10.70.8.dist-info/entry_points.txt +0 -2
  88. hiddifypanel-10.70.8.dist-info/top_level.txt +0 -1
  89. {hiddifypanel-10.70.8.dist-info → hiddifypanel-10.80.0.dist-info}/LICENSE.md +0 -0
@@ -11,17 +11,13 @@ from hiddifypanel.models import Proxy, ProxyProto, ProxyL3, ProxyTransport, Prox
11
11
  from hiddifypanel import hutils
12
12
 
13
13
 
14
- def get_ssh_hostkeys(dojson=False) -> list[str] | str:
15
- key_files = glob.glob(current_app.config['HIDDIFY_CONFIG_PATH'] + "/other/ssh/host_key/*_key.pub")
16
- host_keys = []
17
- for file_name in key_files:
18
- with open(file_name, "r") as f:
19
- host_key = f.read().strip()
20
- host_key = host_key.split()
21
- if len(host_key) > 2:
22
- host_key = host_key[:2] # strip the hostname part
23
- host_key = " ".join(host_key)
24
- host_keys.append(host_key)
14
+ def get_ssh_hostkeys(hconfigs,dojson=False) -> list[str] | str:
15
+ host_keys = [
16
+ # hconfigs[ConfigEnum.ssh_host_dsa_pub],
17
+ hconfigs[ConfigEnum.ssh_host_ed25519_pub],
18
+ hconfigs[ConfigEnum.ssh_host_ecdsa_pub],
19
+ hconfigs[ConfigEnum.ssh_host_rsa_pub],
20
+ ]
25
21
  if dojson:
26
22
  return json.dumps(host_keys)
27
23
  return host_keys
@@ -138,8 +134,8 @@ def get_proxies(child_id: int = 0, only_enabled=False) -> list['Proxy']:
138
134
  proxies = [c for c in proxies if 'trojan' not in c.proto]
139
135
  if not hconfig(ConfigEnum.httpupgrade_enable, child_id):
140
136
  proxies = [c for c in proxies if ProxyTransport.httpupgrade not in c.transport]
141
- if not hconfig(ConfigEnum.splithttp_enable, child_id):
142
- proxies = [c for c in proxies if ProxyTransport.splithttp not in c.transport]
137
+ if not hconfig(ConfigEnum.xhttp_enable, child_id):
138
+ proxies = [c for c in proxies if ProxyTransport.xhttp not in c.transport]
143
139
  if not hconfig(ConfigEnum.ws_enable, child_id):
144
140
  proxies = [c for c in proxies if ProxyTransport.WS not in c.transport]
145
141
  # if not hconfig(ConfigEnum.xtls_enable, child_id):
@@ -193,7 +189,7 @@ def get_valid_proxies(domains: list[Domain]) -> list[dict]:
193
189
  noDomainProxies = False
194
190
  if proxy.proto in [ProxyProto.ssh, ProxyProto.wireguard]:
195
191
  noDomainProxies = True
196
- if proxy.proto in [ProxyProto.ss] and proxy.transport not in [ProxyTransport.grpc, ProxyTransport.h2, ProxyTransport.WS, ProxyTransport.httpupgrade, ProxyTransport.splithttp]:
192
+ if proxy.proto in [ProxyProto.ss] and proxy.transport not in [ProxyTransport.grpc, ProxyTransport.h2, ProxyTransport.WS, ProxyTransport.httpupgrade, ProxyTransport.xhttp]:
197
193
  noDomainProxies = True
198
194
  options = []
199
195
  key = f'{proxy.proto}{proxy.transport}{proxy.cdn}{proxy.l3}'
@@ -417,9 +413,9 @@ def make_proxy(hconfigs: dict, proxy: Proxy, domain_db: Domain, phttp=80, ptls=4
417
413
  base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.path_httpupgrade]}'
418
414
  base["host"] = domain
419
415
  return base
420
- if proxy.transport in [ProxyTransport.splithttp]:
421
- base['transport'] = 'splithttp'
422
- base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.path_splithttp]}'
416
+ if proxy.transport in [ProxyTransport.xhttp]:
417
+ base['transport'] = 'xhttp'
418
+ base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.path_xhttp]}'
423
419
  # if 0 and 'h2' in base['alpn'] or 'h3' in base['alpn']:
424
420
  # base['path'] += "2"
425
421
  # else:
@@ -441,7 +437,7 @@ def make_proxy(hconfigs: dict, proxy: Proxy, domain_db: Domain, phttp=80, ptls=4
441
437
  return base
442
438
  if ProxyProto.ssh == proxy.proto:
443
439
  base['private_key'] = g.account.ed25519_private_key
444
- base['host_key'] = hutils.proxy.get_ssh_hostkeys(False)
440
+ base['host_keys'] = hutils.proxy.get_ssh_hostkeys(hconfigs,False)
445
441
  # base['ssh_port'] = hconfig(ConfigEnum.ssh_server_port)
446
442
  return base
447
443
  return {'name': name, 'msg': 'not valid', 'type': 'error', 'proto': proxy.proto}
@@ -45,7 +45,9 @@ def configs_as_json(domains: list[Domain], **kwargs) -> str:
45
45
 
46
46
 
47
47
  def is_xray_proxy(proxy: dict):
48
- if proxy['transport'] == ProxyTransport.splithttp:
48
+ if g.user_agent.get('is_hiddify_prefere_xray'):
49
+ return True
50
+ if proxy['transport'] == ProxyTransport.xhttp:
49
51
  return True
50
52
  return False
51
53
 
@@ -323,7 +325,7 @@ def add_ssh(all_base: list[dict], proxy: dict):
323
325
  base["user"] = proxy['uuid']
324
326
  base["private_key"] = proxy['private_key'] # .replace('\n', '\\n')
325
327
 
326
- base["host_key"] = proxy.get('host_key', [])
328
+ base["host_key"] = proxy.get('host_keys', [])
327
329
 
328
330
  socks_front = {
329
331
  "type": "socks",
@@ -0,0 +1,34 @@
1
+
2
+ def generate_wireguard_config(proxy: dict) -> str:
3
+ """
4
+ Generates a WireGuard configuration from a given proxy dictionary.
5
+
6
+ Args:
7
+ proxy (dict): Dictionary containing WireGuard and proxy details.
8
+
9
+ Returns:
10
+ str: A WireGuard configuration string.
11
+ """
12
+ name=f'{proxy["extra_info"]} {proxy["name"]}'
13
+ addrs = f"{proxy['wg_ipv4']}/32"
14
+ if proxy['wg_ipv6']:
15
+ addrs += f", {proxy['wg_ipv6']}/128"
16
+ config = f"""[Interface]
17
+ # Name = {name}
18
+ Address= {addrs}
19
+ PrivateKey = {proxy["wg_pk"]}
20
+ MTU = {proxy.get("mtu", 1380)}
21
+ DNS = {proxy.get("dns", "1.1.1.1")}
22
+
23
+ [Peer]
24
+ # Name = Public Peer for {name}
25
+ Endpoint = {proxy["server"]}:{proxy["port"]}
26
+ PublicKey = {proxy["wg_server_pub"]}
27
+ PresharedKey = {proxy['wg_psk']}
28
+ #PersistentKeepalive = {proxy.get("keep_alive", 25)}
29
+ """
30
+
31
+ #Address = {proxy.get("wg_ipv4", "0.0.0.0/32")}
32
+ #AllowedIPs = {proxy.get("allowed_ips", "0.0.0.0/0")}
33
+
34
+ return config
@@ -63,7 +63,7 @@ def to_link(proxy: dict) -> str | dict:
63
63
  streisand_ssh = hutils.encode.do_base_64(f'{proxy["uuid"]}:0:{proxy["private_key"]}::@{proxy["server"]}:{proxy["port"]}')
64
64
  baseurl += f'{streisand_ssh}#{name_link}'
65
65
  else:
66
- hk = ",".join(proxy["host_key"])
66
+ hk = ",".join(proxy["host_keys"])
67
67
  pk = proxy["private_key"].replace('\n', '')
68
68
  baseurl += f'{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}/?file=ssh&pk={pk}&hk={hk}#{name_link}'
69
69
 
@@ -126,10 +126,10 @@ def to_link(proxy: dict) -> str | dict:
126
126
  baseurl += "&encryption=none"
127
127
  if proxy.get('fingerprint', 'none') != 'none':
128
128
  baseurl += "&fp=" + proxy['fingerprint']
129
- if proxy.get('transport') in {ProxyTransport.splithttp}:
129
+ if proxy.get('transport') in {ProxyTransport.xhttp}:
130
130
  baseurl += "&core=xray"
131
131
  if proxy['l3'] != 'quic':
132
- if proxy.get('l3') != ProxyL3.reality and (proxy.get('transport') in {ProxyTransport.tcp, ProxyTransport.httpupgrade, ProxyTransport.splithttp}) and proxy['proto'] in [ProxyProto.vless, ProxyProto.trojan]:
132
+ if proxy.get('l3') != ProxyL3.reality and (proxy.get('transport') in {ProxyTransport.tcp, ProxyTransport.httpupgrade, ProxyTransport.xhttp}) and proxy['proto'] in [ProxyProto.vless, ProxyProto.trojan]:
133
133
  baseurl += '&headerType=http'
134
134
  else:
135
135
  baseurl += '&headerType=None'
@@ -50,10 +50,11 @@ def configs_as_json(domains: list[Domain], user: User, expire_days: int, remarks
50
50
  unsupported_transport = {}
51
51
  if g.user_agent.get('is_v2rayng'):
52
52
  # TODO: ensure which protocols are not supported in v2rayng
53
- unsupported_protos = {ProxyProto.wireguard, ProxyProto.hysteria, ProxyProto.hysteria2,
54
- ProxyProto.tuic, ProxyProto.ss, ProxyProto.ssr, ProxyProto.ssh}
53
+ unsupported_protos = { ProxyProto.hysteria, ProxyProto.hysteria2,
54
+ ProxyProto.tuic, ProxyProto.ssr, ProxyProto.ssh}
55
55
  if not hutils.flask.is_client_version(hutils.flask.ClientVersion.v2ryang, 1, 8, 18):
56
56
  unsupported_transport = {ProxyTransport.httpupgrade}
57
+ unsupported_protos.update({ProxyProto.wireguard})
57
58
 
58
59
  # multiple outbounds needs multiple whole base config not just one with multiple outbounds (at least for v2rayng)
59
60
  # https://github.com/2dust/v2rayNG/pull/2827#issue-2127534078
@@ -135,7 +136,9 @@ def add_wireguard_settings(base: dict, proxy: dict):
135
136
  base['settings']['mtu'] = 1380 # optional
136
137
  base['settings']['peers'] = [{
137
138
  'endpoint': f'{proxy["server"]}:{int(proxy["port"])}',
138
- 'publicKey': proxy["wg_server_pub"]
139
+ 'publicKey': proxy["wg_server_pub"],
140
+ "preSharedKey": proxy['wg_psk']
141
+
139
142
  # 'allowedIPs':'', 'preSharedKey':'', 'keepAlive':'' # optionals
140
143
  }]
141
144
 
@@ -262,9 +265,9 @@ def add_stream_settings(base: dict, proxy: dict):
262
265
  if proxy['transport'] == ProxyTransport.httpupgrade:
263
266
  ss['network'] = proxy['transport']
264
267
  add_httpupgrade_stream(ss, proxy)
265
- if proxy['transport'] == ProxyTransport.splithttp:
268
+ if proxy['transport'] == ProxyTransport.xhttp:
266
269
  ss['network'] = proxy['transport']
267
- add_splithttp_stream(ss, proxy)
270
+ add_xhttp_stream(ss, proxy)
268
271
  if proxy['transport'] == 'ws':
269
272
  ss['network'] = proxy['transport']
270
273
  add_ws_stream(ss, proxy)
@@ -338,8 +341,8 @@ def add_httpupgrade_stream(ss: dict, proxy: dict):
338
341
  }
339
342
 
340
343
 
341
- def add_splithttp_stream(ss: dict, proxy: dict):
342
- ss['splithttpSettings'] = {
344
+ def add_xhttp_stream(ss: dict, proxy: dict):
345
+ ss['xhttpSettings'] = {
343
346
  'path': proxy['path'],
344
347
  'host': proxy['host'],
345
348
  "headers": {
@@ -190,4 +190,4 @@ class AdminUser(BaseAccount, SerializerMixin):
190
190
  def before_insert(mapper, connection, target):
191
191
  from hiddifypanel import hutils
192
192
  hutils.model.gen_username(target)
193
- hutils.model.gen_password(target)
193
+ # hutils.model.gen_password(target)
@@ -41,6 +41,9 @@ class BaseAccount(db.Model, SerializerMixin, FlaskLoginUserMixin): # type: igno
41
41
  'telegram_id': self.telegram_id,
42
42
  'lang': self.lang
43
43
  }
44
+ def update_password(self,new_password):
45
+ self.password=new_password
46
+ db.session.commit()
44
47
 
45
48
  @classmethod
46
49
  def by_id(cls, id: int):
@@ -39,7 +39,7 @@ class StrConfig(db.Model, SerializerMixin):
39
39
  child_id = Column(Integer, ForeignKey('child.id'), primary_key=True, default=0)
40
40
  # category = db.Column(db.String(128), primary_key=True)
41
41
  key = Column(Enum(ConfigEnum), primary_key=True, default=ConfigEnum.admin_secret)
42
- value = Column(String(2048))
42
+ value = Column(String(3072))
43
43
 
44
44
  def to_dict(self: "StrConfig"):
45
45
  return {
@@ -153,7 +153,10 @@ def add_or_update_config(commit: bool = True, child_id: int | None = None, overr
153
153
  if child_id is None:
154
154
  child_id = Child.current().id
155
155
  c = config['key']
156
- ckey = ConfigEnum(c)
156
+ try:
157
+ ckey = ConfigEnum(c)
158
+ except:
159
+ return
157
160
  if c == ConfigEnum.unique_id and not override_unique_id:
158
161
  return
159
162
 
@@ -239,7 +239,7 @@ class ConfigEnum(metaclass=FastEnum):
239
239
  ws_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
240
240
  grpc_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
241
241
  httpupgrade_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
242
- splithttp_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
242
+ xhttp_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
243
243
 
244
244
  vless_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
245
245
  trojan_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
@@ -262,7 +262,7 @@ class ConfigEnum(metaclass=FastEnum):
262
262
  path_v2ray = _StrConfigDscr(ConfigCategory.hidden, ApplyMode.apply_config, hide_in_virtual_child=True) # deprecated
263
263
  path_ss = _StrConfigDscr(ConfigCategory.hidden, ApplyMode.apply_config, hide_in_virtual_child=True)
264
264
 
265
- path_splithttp = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
265
+ path_xhttp = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
266
266
  path_httpupgrade = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
267
267
  path_ws = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
268
268
  path_tcp = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
@@ -277,6 +277,19 @@ class ConfigEnum(metaclass=FastEnum):
277
277
  sub_full_clash_enable = _BoolConfigDscr(ConfigCategory.hidden)
278
278
  sub_full_clash_meta_enable = _BoolConfigDscr(ConfigCategory.hidden)
279
279
 
280
+
281
+ #ssh host keys
282
+ ssh_host_rsa_pk = _StrConfigDscr(ConfigCategory.hidden)
283
+ ssh_host_rsa_pub = _StrConfigDscr(ConfigCategory.hidden)
284
+ ssh_host_ed25519_pk = _StrConfigDscr(ConfigCategory.hidden)
285
+ ssh_host_ed25519_pub = _StrConfigDscr(ConfigCategory.hidden)
286
+ ssh_host_ecdsa_pk = _StrConfigDscr(ConfigCategory.hidden)
287
+ ssh_host_ecdsa_pub = _StrConfigDscr(ConfigCategory.hidden)
288
+ ssh_host_dsa_pk = _StrConfigDscr(ConfigCategory.hidden)
289
+ ssh_host_dsa_pub = _StrConfigDscr(ConfigCategory.hidden)
290
+
291
+
292
+
280
293
  hiddifycli_enable = _BoolConfigDscr(ConfigCategory.hidden, ApplyMode.reinstall)
281
294
 
282
295
  @classmethod
@@ -20,7 +20,7 @@ class ProxyTransport(StrEnum):
20
20
  tcp = auto()
21
21
  ssh = auto()
22
22
  httpupgrade = auto()
23
- splithttp = auto()
23
+ xhttp = auto()
24
24
  custom = auto()
25
25
  shadowsocks = auto()
26
26
 
@@ -76,7 +76,7 @@ class User(BaseAccount, SerializerMixin):
76
76
  current_usage = db.Column(db.BigInteger, default=0, nullable=False)
77
77
  last_reset_time = db.Column(db.Date, default=datetime.date.today())
78
78
  added_by = db.Column(db.Integer, db.ForeignKey('admin_user.id'), default=1)
79
- max_ips = db.Column(db.Integer, default=1000, nullable=False)
79
+ max_ips = db.Column(db.Integer, default=100, nullable=False)
80
80
  details = db.relationship('UserDetail', cascade="all,delete", backref='user', lazy='dynamic',)
81
81
  enable = db.Column(db.Boolean, default=True, nullable=False)
82
82
  ed25519_private_key = db.Column(db.String(500), default="")
@@ -347,6 +347,6 @@ class User(BaseAccount, SerializerMixin):
347
347
  def on_user_insert(mapper, connection, target):
348
348
  from hiddifypanel import hutils
349
349
  hutils.model.gen_username(target)
350
- hutils.model.gen_password(target)
350
+ # hutils.model.gen_password(target)
351
351
  hutils.model.gen_ed25519_keys(target)
352
352
  hutils.model.gen_wg_keys(target)
@@ -1,9 +1,9 @@
1
1
 
2
- from . import user
3
- # from . import admin
4
- from . import cli
5
- # from .. import database
6
- from . import common
7
- # from . import commercial
8
- # from .. import auth
9
- from . import common_bp
2
+ # from . import user
3
+ # # from . import admin
4
+ # from . import cli
5
+ # # from .. import database
6
+ # from . import common
7
+ # # from . import commercial
8
+ # # from .. import auth
9
+ # from . import common_bp
@@ -40,7 +40,7 @@ class SubAdminsField(SelectField):
40
40
  class AdminstratorAdmin(AdminLTEModelView):
41
41
  column_hide_backrefs = False
42
42
  column_list = ["name", 'UserLinks', 'mode', 'can_add_admin', 'max_active_users', 'max_users', 'online_users', 'comment',]
43
- form_columns = ["name", 'mode', 'can_add_admin', 'max_active_users', 'max_users', 'comment', "uuid"]
43
+ form_columns = ["name", 'mode', 'can_add_admin', 'max_active_users', 'max_users', 'comment', "uuid", "password"]
44
44
  list_template = 'model/admin_list.html'
45
45
  # column_editable_list = ['name']
46
46
  # edit_modal = True
@@ -59,6 +59,7 @@ class AdminstratorAdmin(AdminLTEModelView):
59
59
  "comment": _("Note"),
60
60
  'max_active_users': _("Max Active Users"),
61
61
  'max_users': _('Max Users'),
62
+ "password":_("user.password.title"),
62
63
  "online_users": _("Online Users"),
63
64
  'can_add_admin': _("Can add sub admin")
64
65
 
@@ -142,19 +143,18 @@ class AdminstratorAdmin(AdminLTEModelView):
142
143
  """)
143
144
 
144
145
  def _max_active_users_formatter(view, context, model, name):
145
-
146
- actives = [u for u in model.recursive_users_query().all() if u.is_active]
147
- u = len(actives)
146
+ """Optimized user count formatter using database queries"""
147
+ active_count = model.recursive_users_query().filter(User.is_active == True).count()
148
148
  if model.mode == AdminMode.super_admin:
149
- return f"{u} / ∞"
149
+ return f"{active_count} / ∞"
150
150
  t = model.max_active_users
151
- rate = round(u * 100 / (t + 0.000001))
152
- state = "danger" if u >= t else ('warning' if rate > 80 else 'success')
153
- color = "#ff7e7e" if u >= t else ('#ffc107' if rate > 80 else '#9ee150')
151
+ rate = round(active_count * 100 / (t + 0.000001))
152
+ color = "#ff7e7e" if active_count >= t else ('#ffc107' if rate > 80 else '#9ee150')
153
+
154
154
  return Markup(f"""
155
155
  <div class="progress progress-lg position-relative" style="min-width: 100px;">
156
156
  <div class="progress-bar progress-bar-striped" role="progressbar" style="width: {rate}%;background-color: {color};" aria-valuenow="{rate}" aria-valuemin="0" aria-valuemax="100"></div>
157
- <span class='badge position-absolute' style="left:auto;right:auto;width: 100%;font-size:1em">{u} {_('user.home.usage.from')} {t}</span>
157
+ <span class='badge position-absolute' style="left:auto;right:auto;width: 100%;font-size:1em">{active_count} {_('user.home.usage.from')} {t}</span>
158
158
 
159
159
  </div>
160
160
  """)
@@ -204,6 +204,7 @@ class AdminstratorAdmin(AdminLTEModelView):
204
204
  # else:
205
205
  # model.parent_admin_id=1
206
206
  # model.parent_admin=AdminUser.query.filter(AdminUser.id==1).first()
207
+
207
208
  if model.id != 1 and model.parent_admin is None:
208
209
  model.parent_admin_id = g.account.id
209
210
  model.parent_admin = g.account
@@ -212,12 +213,17 @@ class AdminstratorAdmin(AdminLTEModelView):
212
213
  raise ValidationError("Sub-Admin can not have more power!!!!")
213
214
  if g.account.mode == AdminMode.agent and model.mode != AdminMode.agent:
214
215
  raise ValidationError("Sub-Admin can not have more power!!!!")
216
+
217
+ if not model.password and not is_created:
218
+ model.password=AdminUser.by_id(model.id).password
219
+
215
220
 
216
221
  def on_model_delete(self, model):
217
222
  model.remove()
218
223
 
219
224
  def on_form_prefill(self, form, id=None):
220
-
225
+
226
+ form.password.data=""
221
227
  if g.account.mode != AdminMode.super_admin:
222
228
  del form.mode
223
229
  del form.can_add_admin