Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/core/hosts.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ async def _prepare_subscription_inbound_data(
# Get VLESS encryption from inbound
encryption = inbound_config.get("encryption", "none")

# Get flow from inbound (user can override later in share.py)
# Get flow from inbound for subscription generation.
inbound_flow = inbound_config.get("flow", "")
if inbound_flow == "none":
inbound_flow = ""
Expand Down
9 changes: 0 additions & 9 deletions app/db/crud/bulk.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,13 +436,6 @@ async def update_users_proxy_settings(
# Prepare the update statement
if dialect == "postgresql":
proxy_settings_expr = cast(User.proxy_settings, JSONB)
if bulk_model.flow is not None:
proxy_settings_expr = func.jsonb_set(
proxy_settings_expr,
text("'{vless,flow}'"),
cast(f"{bulk_model.flow.value}", JSONB),
True,
)
if bulk_model.method is not None:
proxy_settings_expr = func.jsonb_set(
proxy_settings_expr,
Expand All @@ -452,8 +445,6 @@ async def update_users_proxy_settings(
)
else:
proxy_settings_expr = User.proxy_settings
if bulk_model.flow is not None:
proxy_settings_expr = func.json_set(proxy_settings_expr, "$.vless.flow", f"{bulk_model.flow.value}")
if bulk_model.method is not None:
proxy_settings_expr = func.json_set(
proxy_settings_expr, "$.shadowsocks.method", f"{bulk_model.method.value}"
Expand Down
6 changes: 0 additions & 6 deletions app/db/crud/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,6 @@ async def bulk_reset_user_data_usage(

def _build_revoked_proxy_settings(db_user: User) -> dict:
proxy_settings = ProxyTable()
proxy_settings.vless.flow = db_user.proxy_settings.get("vless", {}).get("flow", "")
proxy_settings.shadowsocks.method = db_user.proxy_settings.get("shadowsocks", {}).get(
"method", "chacha20-ietf-poly1305"
)
Expand Down Expand Up @@ -1118,11 +1117,6 @@ async def reset_user_by_next(db: AsyncSession, db_user: User, *, clean_chart_dat

if db_user.next_plan.user_template.extra_settings:
proxy_settings = deepcopy(db_user.proxy_settings)
proxy_settings["vless"]["flow"] = (
db_user.next_plan.user_template.extra_settings["flow"]
if db_user.next_plan.user_template.extra_settings["flow"]
else ""
)
proxy_settings["shadowsocks"]["method"] = (
db_user.next_plan.user_template.extra_settings["method"]
if db_user.next_plan.user_template.extra_settings["method"]
Expand Down
7 changes: 0 additions & 7 deletions app/models/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,8 @@ class VMessSettings(BaseModel):
id: UUID = Field(default_factory=uuid4)


class XTLSFlows(StrEnum):
NONE = ""
VISION = "xtls-rprx-vision"
VISION_UDP = "xtls-rprx-vision-udp443"


class VlessSettings(BaseModel):
id: UUID = Field(default_factory=uuid4)
flow: XTLSFlows = XTLSFlows.NONE


class TrojanSettings(BaseModel):
Expand Down
3 changes: 1 addition & 2 deletions app/models/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator

from app.models.proxy import ShadowsocksMethods, XTLSFlows
from app.models.proxy import ShadowsocksMethods

from .notification_enable import NotificationEnable
from .validators import DiscordValidator, ProxyValidator, URLValidator
Expand Down Expand Up @@ -294,7 +294,6 @@ class HWIDSettings(BaseModel):


class General(BaseModel):
default_flow: XTLSFlows = Field(default=XTLSFlows.NONE)
default_method: ShadowsocksMethods = Field(default=ShadowsocksMethods.CHACHA20_POLY1305)


Expand Down
3 changes: 1 addition & 2 deletions app/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from app.db.models import DataLimitResetStrategy, UserStatus
from app.models.admin import AdminBase, AdminContactInfo
from app.models.proxy import ProxyTable, ShadowsocksMethods, XTLSFlows
from app.models.proxy import ProxyTable, ShadowsocksMethods
from app.models.stats import Period
from app.utils.helpers import fix_datetime_timezone

Expand Down Expand Up @@ -431,7 +431,6 @@ class BulkUser(BulkUserFilter):


class BulkUsersProxy(BulkUserFilter):
flow: XTLSFlows | None = Field(default=None)
method: ShadowsocksMethods | None = Field(default=None)


Expand Down
3 changes: 1 addition & 2 deletions app/models/user_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
from pydantic import BaseModel, ConfigDict, Field, field_validator

from app.db.models import DataLimitResetStrategy, UserStatusCreate
from app.models.proxy import ShadowsocksMethods, XTLSFlows
from app.models.proxy import ShadowsocksMethods

from .validators import ListValidator, UserValidator


class ExtraSettings(BaseModel):
flow: XTLSFlows | None = Field(XTLSFlows.NONE)
method: ShadowsocksMethods | None = Field(ShadowsocksMethods.CHACHA20_POLY1305)

def dict(self, *, no_obj=True, **kwargs):
Expand Down
6 changes: 1 addition & 5 deletions app/node/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ def _serialize_user_for_node(
if ProxyProtocol.vmess in allowed_protocols:
proxy_kwargs["vmess_id"] = user_settings.get("vmess", {}).get("id")
if ProxyProtocol.vless in allowed_protocols:
vless_settings = dict(user_settings.get("vless", {}))
if vless_settings.get("flow") == "xtls-rprx-vision-udp443":
vless_settings["flow"] = "xtls-rprx-vision"
proxy_kwargs["vless_id"] = vless_settings.get("id")
proxy_kwargs["vless_flow"] = vless_settings.get("flow")
proxy_kwargs["vless_id"] = user_settings.get("vless", {}).get("id")
if ProxyProtocol.trojan in allowed_protocols:
proxy_kwargs["trojan_password"] = user_settings.get("trojan", {}).get("password")
if ProxyProtocol.shadowsocks in allowed_protocols:
Expand Down
6 changes: 2 additions & 4 deletions app/operation/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,12 +974,8 @@ def load_base_user_args(template: UserTemplate) -> dict:
@staticmethod
def apply_settings(user_args: UserCreate | UserModify, template: UserTemplate) -> dict:
if template.extra_settings:
flow = template.extra_settings.get("flow", None)
method = template.extra_settings.get("method", None)

if flow is not None:
user_args.proxy_settings.vless.flow = flow

if method is not None:
user_args.proxy_settings.shadowsocks.method = method

Expand Down Expand Up @@ -1196,6 +1192,8 @@ async def bulk_modify_datalimit(self, db: AsyncSession, bulk_model: BulkUser):
return users_count

async def bulk_modify_proxy_settings(self, db: AsyncSession, bulk_model: BulkUsersProxy):
if bulk_model.method is None:
await self.raise_error(message="No supported proxy settings were provided", code=400, db=db)
if bulk_model.dry_run:
n = await count_bulk_proxy_targets(db, bulk_model)
return BulkOperationDryRunResponse(affected_users=n)
Expand Down
3 changes: 1 addition & 2 deletions app/subscription/clash.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,7 @@ def _build_vless(self, remark: str, address: str, inbound: SubscriptionInboundDa
if inbound.encryption != "none":
node["encryption"] = inbound.encryption

# Only add flow if inbound supports it
if inbound.flow_enabled and (flow := settings.get("flow", "")):
if inbound.flow_enabled and (flow := inbound.inbound_flow):
node["flow"] = flow

self._apply_tls(node, inbound.tls_config, "vless")
Expand Down
3 changes: 1 addition & 2 deletions app/subscription/links.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,7 @@ def _build_vless(self, remark: str, address: str, inbound: SubscriptionInboundDa
"headerType": getattr(inbound.transport_config, "header_type", "none"),
}

# Only add flow if inbound supports it
if inbound.flow_enabled and (flow := settings.get("flow", "")):
if inbound.flow_enabled and (flow := inbound.inbound_flow):
payload["flow"] = flow

self._apply_transport_settings(payload, "vless", inbound, path)
Expand Down
5 changes: 0 additions & 5 deletions app/subscription/share.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,6 @@ async def process_host(
if user_id is not None:
settings["_user_id"] = user_id

# Handle flow: user settings have priority, fall back to inbound flow
if "flow" in settings and settings["flow"] == "":
# User has empty flow, use inbound flow as default
settings["flow"] = inbound.inbound_flow

# Update format variables
format_variables.update({"PROTOCOL": inbound.protocol})
format_variables.update({"TRANSPORT": inbound.network})
Expand Down
3 changes: 1 addition & 2 deletions app/subscription/singbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,7 @@ def _build_vless(self, remark: str, address: str, inbound: SubscriptionInboundDa
id = self.vless_route(id, inbound.vless_route)
user_settings = {"uuid": id}

# Only add flow if inbound supports it
if inbound.flow_enabled and (flow := settings.get("flow", "")):
if inbound.flow_enabled and (flow := inbound.inbound_flow):
user_settings["flow"] = flow

return self._build_outbound(
Expand Down
3 changes: 1 addition & 2 deletions app/subscription/xray.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,7 @@ def _build_vless(self, address: str, inbound: SubscriptionInboundData, settings:

user_settings = {"id": id, "encryption": inbound.encryption}

# Only add flow if inbound supports it
if inbound.flow_enabled and (flow := settings.get("flow", "")):
if inbound.flow_enabled and (flow := inbound.inbound_flow):
user_settings["flow"] = flow

return self._build_outbound(
Expand Down
7 changes: 0 additions & 7 deletions dashboard/public/statics/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,6 @@
"saveSuccess": "General settings saved successfully",
"saveFailed": "Failed to save general settings",
"cancelSuccess": "Changes cancelled and original settings restored",
"defaultFlow": {
"title": "Default VLESS Flow",
"description": "Autofill the flow field for new VLESS users",
"none": "None"
},
"defaultMethod": {
"title": "Default Shadowsocks Method",
"description": "Autofill the encryption method for new Shadowsocks users"
Expand Down Expand Up @@ -1485,8 +1480,6 @@
"proxySettings.id": "ID",
"proxySettings.password": "Password",
"proxySettings.method": "Method",
"proxySettings.flow": "Flow",
"proxySettings.flowDeprecated": "Deprecated. This will be removed in future versions. Use inbound.settings.flow",
"proxySettings.hysteria": "Hysteria",
"proxySettings.hysteriaAuth": "Hysteria Auth",
"proxySettings.wireguardPrivateKey": "WireGuard Private key",
Expand Down
7 changes: 0 additions & 7 deletions dashboard/public/statics/locales/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -456,11 +456,6 @@
"saveSuccess": "تنظیمات عمومی با موفقیت ذخیره شد",
"saveFailed": "ذخیره تنظیمات عمومی ناموفق بود",
"cancelSuccess": "تغییرات لغو شد و تنظیمات اصلی بازیابی شد",
"defaultFlow": {
"title": "جریان VLESS پیش‌فرض",
"description": "پر کردن خودکار فیلد جریان برای کاربران جدید VLESS",
"none": "بدون"
},
"defaultMethod": {
"title": "روش پیش‌فرض Shadowsocks",
"description": "پر کردن خودکار روش رمزنگاری برای کاربران جدید Shadowsocks"
Expand Down Expand Up @@ -1322,8 +1317,6 @@
"userDialog.proxySettings.id": "شناسه (ID)",
"userDialog.proxySettings.password": "رمز عبور",
"userDialog.proxySettings.method": "روش رمزنگاری",
"userDialog.proxySettings.flow": "جریان (Flow)",
"userDialog.proxySettings.flowDeprecated": "این مورد منسوخ شده است و در نسخه‌های بعدی حذف می‌شود. به‌جای آن از inbound.settings.flow استفاده کنید",
"userDialog.proxySettings.hysteria": "Hysteria",
"userDialog.proxySettings.hysteriaAuth": "احراز هویت Hysteria",
"userDialog.proxySettings.wireguardPrivateKey": "کلید خصوصی وایرگارد",
Expand Down
7 changes: 0 additions & 7 deletions dashboard/public/statics/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,6 @@
"saveSuccess": "Общие настройки успешно сохранены",
"saveFailed": "Не удалось сохранить общие настройки",
"cancelSuccess": "Изменения отменены и исходные настройки восстановлены",
"defaultFlow": {
"title": "Поток VLESS по умолчанию",
"description": "Автоматически заполнять поле потока для новых пользователей VLESS",
"none": "Нет"
},
"defaultMethod": {
"title": "Метод Shadowsocks по умолчанию",
"description": "Автоматически заполнять метод шифрования для новых пользователей Shadowsocks"
Expand Down Expand Up @@ -2597,8 +2592,6 @@
"proxySettings.id": "ID",
"proxySettings.password": "Пароль",
"proxySettings.method": "Метод",
"proxySettings.flow": "Поток (Flow)",
"proxySettings.flowDeprecated": "Устарело. Будет удалено в следующих версиях. Используйте вместо этого inbound.settings.flow",
"proxySettings.hysteria": "Hysteria",
"proxySettings.hysteriaAuth": "Аутентификация Hysteria",
"proxySettings.wireguardPrivateKey": "Приватный ключ WireGuard",
Expand Down
7 changes: 0 additions & 7 deletions dashboard/public/statics/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -600,11 +600,6 @@
"saveSuccess": "常规设置保存成功",
"saveFailed": "常规设置保存失败",
"cancelSuccess": "更改已取消,原始设置已恢复",
"defaultFlow": {
"title": "默认 VLESS 流",
"description": "为新 VLESS 用户自动填写流字段",
"none": "无"
},
"defaultMethod": {
"title": "默认 Shadowsocks 加密方式",
"description": "为新 Shadowsocks 用户自动填写加密方式"
Expand Down Expand Up @@ -1456,8 +1451,6 @@
"userDialog.proxySettings.id": "ID",
"userDialog.proxySettings.password": "密码",
"userDialog.proxySettings.method": "加密方式",
"userDialog.proxySettings.flow": "流 (Flow)",
"userDialog.proxySettings.flowDeprecated": "此项已弃用,将在后续版本中移除。请改用 inbound.settings.flow",
"userDialog.proxySettings.hysteria": "Hysteria",
"userDialog.proxySettings.hysteriaAuth": "Hysteria 认证",
"userDialog.proxySettings.wireguardPrivateKey": "WireGuard 私钥",
Expand Down
37 changes: 0 additions & 37 deletions dashboard/src/features/users/dialogs/user-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,6 @@ function UserModal({ isDialogOpen, onOpenChange, form, editingUser, editingUserI
},
vless: {
id: uuidv4(),
flow: '' as '' | 'xtls-rprx-vision' | 'xtls-rprx-vision-udp443' | undefined,
},
trojan: {
password: generatePassword(),
Expand Down Expand Up @@ -1216,9 +1215,6 @@ function UserModal({ isDialogOpen, onOpenChange, form, editingUser, editingUserI
{} as Record<string, unknown>,
)

if (protocol === 'vless' && !cleanedProtocolSettings.flow) {
delete cleanedProtocolSettings.flow
}
if (protocol === 'shadowsocks' && !cleanedProtocolSettings.method) {
delete cleanedProtocolSettings.method
}
Expand Down Expand Up @@ -1359,7 +1355,6 @@ function UserModal({ isDialogOpen, onOpenChange, form, editingUser, editingUserI
form.setValue('proxy_settings', undefined)
form.setValue('data_limit', 0)
if (generalSettings) {
form.setValue('proxy_settings.vless.flow', generalSettings.default_flow || '')
const validMethods = ['aes-128-gcm', 'aes-256-gcm', 'chacha20-ietf-poly1305', 'xchacha20-poly1305'] as const
const method = validMethods.find(m => m === generalSettings.default_method)
if (method) {
Expand Down Expand Up @@ -1826,38 +1821,6 @@ function UserModal({ isDialogOpen, onOpenChange, form, editingUser, editingUserI
)
}}
/>
<FormField
control={form.control}
name="proxy_settings.vless.flow"
render={({ field }) => (
<FormItem className="mb-2">
<FormLabel>
{t('userDialog.proxySettings.vless')} {t('userDialog.proxySettings.flow')}
</FormLabel>
<FormControl>
<Select
value={field.value ?? 'none'}
onValueChange={val => {
const flowValue = val === 'none' ? '' : val
field.onChange(flowValue)
handleFieldChange('proxy_settings.vless.flow', flowValue)
}}
>
<SelectTrigger>
<SelectValue placeholder={t('userDialog.proxySettings.flow')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="none">{t('userDialog.proxySettings.flow.none', { defaultValue: 'None' })}</SelectItem>
<SelectItem value="xtls-rprx-vision">xtls-rprx-vision</SelectItem>
<SelectItem value="xtls-rprx-vision-udp443">xtls-rprx-vision-udp443</SelectItem>
</SelectContent>
</Select>
</FormControl>
<p className="text-xs text-amber-600 dark:text-amber-400">{t('userDialog.proxySettings.flowDeprecated')}</p>
<FormMessage />
</FormItem>
)}
/>
{/* Trojan */}
<FormField
control={form.control}
Expand Down
3 changes: 0 additions & 3 deletions dashboard/src/features/users/forms/user-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ import { z } from 'zod'

export const userStatusEnum = z.enum(['active', 'disabled', 'limited', 'expired', 'on_hold'])
export const userDataLimitResetStrategyEnum = z.enum(['no_reset', 'day', 'week', 'month', 'year'])
export const xtlsFlowsEnum = z.enum(['', 'xtls-rprx-vision', 'xtls-rprx-vision-udp443'])
export const shadowsocksMethodsEnum = z.enum(['aes-128-gcm', 'aes-256-gcm', 'chacha20-ietf-poly1305', 'xchacha20-poly1305'])

export const vMessSettingsSchema = z.object({
id: z.string().uuid().optional(),
})
export const vlessSettingsSchema = z.object({
id: z.string().uuid().optional(),
flow: xtlsFlowsEnum.optional(),
})
export const trojanSettingsSchema = z.object({
password: z.string().min(2).max(32).optional(),
Expand Down Expand Up @@ -110,7 +108,6 @@ export const getDefaultUserForm = async () => {
},
vless: {
id: undefined,
flow: '',
},
trojan: {
password: undefined,
Expand Down
Loading
Loading