-
Notifications
You must be signed in to change notification settings - Fork 73
feat: Add SS-2022 relay support #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughAdds Shadowsocks 2022 relay inbound tag support: database migration and model field, host validation and relay-password resolution, propagation of ordered relay_passwords into subscription payloads and handlers, plus frontend UI, types, and localization updates. Changes
Sequence DiagramsequenceDiagram
participant UI as Frontend HostModal
participant API as Backend API
participant Validate as HostOperation Validator
participant Core as CoreHosts PrepareData
participant Sub as Subscription Handler
UI->>API: create_host(payload with ss2022_relay_inbound_tags)
API->>Validate: _validate_ss2022_relay_chain(host)
Note over Validate: Check tags exist, not self-referential,\nand each maps to a 2022 inbound with password
Validate-->>API: validation result
API->>Core: _prepare_subscription_inbound_data(host)
Note over Core: Resolve relay_passwords by\ncollecting passwords from referenced inbounds
Core-->>API: SubscriptionInboundData(relay_passwords=[...])
API->>Sub: detect_shadowsocks_2022(..., relay_passwords)
Note over Sub: Prepend relay_passwords into\nSS-2022 password chain when applicable
Sub-->>API: (method, password)
API-->>UI: host created / updated
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (2)
dashboard/src/components/dialogs/HostModal.tsx (1)
3008-3014: Consider adding an info popover for relay settings.For consistency with other sections (network, security, transport, etc.), consider adding an info icon with a popover explaining what SS-2022 relay inbounds are and how they work. This would help users understand this feature, especially since it's a new addition.
Example placement:
<AccordionTrigger> <div className="flex items-center gap-2"> <CircleArrowRight className="h-4 w-4" /> <span>{t('hostsDialog.relaySettings')}</span> </div> </AccordionTrigger> <AccordionContent className="px-2"> <FormField control={form.control} name="ss2022_relay_inbound_tags" render={({ field }) => ( <FormItem> - <FormLabel>{t('hostsDialog.ss2022RelayInbounds')}</FormLabel> + <div className="flex items-center gap-2"> + <FormLabel>{t('hostsDialog.ss2022RelayInbounds')}</FormLabel> + <Popover> + <PopoverTrigger asChild> + <Button type="button" variant="ghost" size="icon" className="h-4 w-4 p-0 hover:bg-transparent"> + <Info className="h-4 w-4 text-muted-foreground" /> + </Button> + </PopoverTrigger> + <PopoverContent className="w-[320px] p-3" side="right" align="start" sideOffset={5}> + <p className="text-[11px] text-muted-foreground">{t('hostsDialog.relaySettings.info')}</p> + </PopoverContent> + </Popover> + </div> <div className="flex flex-col gap-2">Don't forget to add the corresponding translation keys to your locale files.
dashboard/src/components/hosts/Hosts.tsx (1)
607-607: Inconsistent nullish handling operators.Line 607 uses the nullish coalescing operator (
??), while lines 643 and 750 use the logical OR operator (||). For consistency and correctness, prefer??throughout, as it only checks fornullorundefinedwithout treating other falsy values (like0or'') as nullish.Apply this diff to standardize the operator:
- ss2022_relay_inbound_tags: host.ss2022_relay_inbound_tags || [], + ss2022_relay_inbound_tags: host.ss2022_relay_inbound_tags ?? [],Also applies to: 643-643, 750-750
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
app/core/hosts.py(2 hunks)app/db/migrations/versions/4bbb43d025bc_add_ss2022_relay_tags_to_hosts.py(1 hunks)app/db/models.py(1 hunks)app/models/host.py(1 hunks)app/models/subscription.py(1 hunks)app/operation/host.py(5 hunks)app/subscription/base.py(1 hunks)app/subscription/clash.py(1 hunks)app/subscription/links.py(1 hunks)app/subscription/outline.py(1 hunks)app/subscription/singbox.py(1 hunks)app/subscription/xray.py(1 hunks)dashboard/public/statics/locales/en.json(1 hunks)dashboard/public/statics/locales/fa.json(1 hunks)dashboard/public/statics/locales/ru.json(1 hunks)dashboard/public/statics/locales/zh.json(1 hunks)dashboard/src/components/dialogs/HostModal.tsx(2 hunks)dashboard/src/components/hosts/Hosts.tsx(5 hunks)dashboard/src/components/hosts/SortableHost.tsx(1 hunks)dashboard/src/pages/_dashboard._index.tsx(1 hunks)dashboard/src/pages/_dashboard.hosts.tsx(1 hunks)dashboard/src/service/api/index.ts(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
app/operation/host.py (3)
dashboard/src/service/api/index.ts (1)
CreateHost(1546-1571)app/operation/__init__.py (2)
check_inbound_tags(155-158)raise_error(40-49)app/core/manager.py (1)
get_inbound_by_tag(80-85)
app/db/models.py (1)
app/db/compiles_types.py (1)
StringArray(51-71)
dashboard/src/components/dialogs/HostModal.tsx (4)
dashboard/src/components/ui/accordion.tsx (3)
AccordionItem(44-44)AccordionTrigger(44-44)AccordionContent(44-44)dashboard/src/components/ui/form.tsx (5)
FormField(104-104)FormItem(104-104)FormLabel(104-104)FormControl(104-104)FormMessage(104-104)dashboard/src/components/ui/select.tsx (5)
Select(105-105)SelectTrigger(105-105)SelectValue(105-105)SelectContent(105-105)SelectItem(105-105)app/db/models.py (1)
inbounds(196-206)
app/core/hosts.py (1)
app/core/manager.py (1)
get_inbound_by_tag(80-85)
🔇 Additional comments (23)
app/subscription/outline.py (1)
28-28: LGTM! Relay password support added.The addition of
relay_passwordsparameter usinggetattrwith aNonefallback safely handles inbounds without relay configuration.dashboard/public/statics/locales/ru.json (1)
961-964: LGTM! Translation keys added for relay settings.The four new Russian translation keys for SS-2022 relay inbound UI elements are correctly placed and align with the feature implementation.
dashboard/src/pages/_dashboard._index.tsx (1)
222-222: LGTM! Default value added for relay inbound tags.The empty array default for
ss2022_relay_inbound_tagsis consistent with other array fields in the form and aligns with the new host configuration schema.dashboard/src/components/hosts/SortableHost.tsx (1)
98-98: LGTM! Relay tags preserved during status toggle.The addition of
ss2022_relay_inbound_tagswith a fallback to empty array ensures relay configuration is preserved when toggling the host's disabled state.app/subscription/clash.py (1)
352-352: LGTM! SS-2022 relay support added to Clash Meta.The relay password parameter is safely retrieved and passed to the SS-2022 detection logic, consistent with the implementation in other subscription handlers.
dashboard/public/statics/locales/en.json (1)
765-768: LGTM! English translations added for relay settings.The four new translation keys for SS-2022 relay inbound UI elements are clear, consistent with existing terminology, and properly positioned in the locale file.
app/subscription/links.py (1)
280-280: LGTM! Relay password support added to link generation.The relay password parameter is properly integrated into the Shadowsocks link builder using the same safe attribute access pattern as other handlers.
app/subscription/singbox.py (1)
260-260: LGTM! SS-2022 relay support added to Sing-box.The relay password parameter is consistently integrated into the Sing-box Shadowsocks outbound builder, completing support across all subscription formats.
app/subscription/xray.py (1)
417-417: LGTM: Clean integration of relay passwords into SS-2022 detection.The use of
getattrwith aNonedefault is appropriate defensive programming for the optionalrelay_passwordsattribute.app/models/host.py (1)
202-203: LGTM: Well-documented field addition for SS-2022 relay support.The field definition is clean with appropriate typing, default value, and a clear comment explaining its purpose as an ordered relay chain.
app/models/subscription.py (1)
217-218: LGTM: Proper field definition with correct default factory.Using
Field(default_factory=list)avoids the mutable default argument antipattern, and the documentation clearly explains the ordered relay password chain concept.dashboard/src/pages/_dashboard.hosts.tsx (1)
152-155: LGTM: Appropriate conditional inclusion of relay tags.The logic correctly includes
ss2022_relay_inbound_tagsonly when populated, avoiding unnecessary empty arrays in the payload. This is consistent with the optional nature of the field.dashboard/public/statics/locales/fa.json (1)
645-648: LGTM: Localization keys added for relay settings UI.The four new translation keys are appropriately placed within the
hostsDialogsection and align with the relay inbound management feature. The keys are consistent with similar additions in other locale files (en, zh, ru).app/db/models.py (1)
451-454: LGTM: Database field definition aligns with the data model.The column definition is consistent with similar fields in the model, using
StringArray(256)which properly handles list-to-string serialization. The optional typing and clear comment make the purpose explicit.app/core/hosts.py (2)
99-108: LGTM: Relay password resolution with graceful error handling.The logic correctly iterates through relay inbound tags, fetches their configurations, validates they are SS-2022 inbounds with passwords, and builds the ordered relay password chain. The broad
except Exception: continueis acceptable here for graceful degradation—invalid or missing relay inbounds are simply skipped rather than failing the entire operation.
228-228: LGTM: Relay passwords properly threaded into subscription data.The
relay_passwordslist is correctly included in theSubscriptionInboundDatapayload, enabling downstream subscription handlers to construct SS-2022 relay chains.dashboard/public/statics/locales/zh.json (1)
1004-1007: LGTM: Chinese localization for relay settings UI.The translation keys mirror those added in other locale files (fa, en, ru), ensuring consistent UI labeling across all supported languages for the SS-2022 relay feature.
dashboard/src/components/dialogs/HostModal.tsx (1)
18-18: LGTM!The
CircleArrowRighticon import is correctly added and used in the relay settings accordion trigger on line 3011.dashboard/src/service/api/index.ts (1)
1544-1571: Relay tag plumbing matches the backend schema.
The new type aliases and optional payload fields line up with the SS2022 relay additions elsewhere, so the generated client remains consistent.app/subscription/base.py (1)
125-158: Password assembly handles relay chains cleanly.
Gracefully prepending relay PSKs while retaining the original two-part format keeps compatibility and matches the expected SS-2022 layout.app/operation/host.py (1)
116-130: Relay chain validation looks solid.
Checking existence, avoiding self-reference, and asserting 2022/password requirements should prevent misconfigured relay chains from slipping through.dashboard/src/components/hosts/Hosts.tsx (1)
150-150: LGTM! Proper typing and validation.The addition of
ss2022_relay_inbound_tagsto both the interface and schema is correct. The optional array of strings is appropriately typed and validated.Also applies to: 404-404
app/db/migrations/versions/4bbb43d025bc_add_ss2022_relay_tags_to_hosts.py (1)
28-30: LGTM! Proper downgrade implementation.Using
batch_alter_tableensures SQLite compatibility when dropping the column.
app/db/migrations/versions/4bbb43d025bc_add_ss2022_relay_tags_to_hosts.py
Show resolved
Hide resolved
app/db/migrations/versions/4bbb43d025bc_add_ss2022_relay_tags_to_hosts.py
Outdated
Show resolved
Hide resolved
| <Select | ||
| value={''} | ||
| onValueChange={(value: string) => { | ||
| if (!value || value.trim() === '') return | ||
| const current = Array.isArray(field.value) ? field.value : [] | ||
| field.onChange([...current, value]) | ||
| }} | ||
| > | ||
| <FormControl> | ||
| <SelectTrigger dir={dir} className="w-full py-5"> | ||
| <SelectValue placeholder={t('hostsDialog.selectRelayInbounds')} /> | ||
| </SelectTrigger> | ||
| </FormControl> | ||
| <SelectContent dir={dir} className="bg-background"> | ||
| {inbounds.map(tag => ( | ||
| <SelectItem key={tag} value={tag} className="cursor-pointer"> | ||
| {tag} | ||
| </SelectItem> | ||
| ))} | ||
| </SelectContent> | ||
| </Select> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add duplicate prevention for relay inbound tags.
The relay tag selection allows adding the same inbound tag multiple times. The status field (lines 637-708) demonstrates the pattern used elsewhere in this file to prevent duplicates by disabling already-selected options.
Apply this diff to prevent duplicate relay tags:
<Select
value={''}
onValueChange={(value: string) => {
if (!value || value.trim() === '') return
const current = Array.isArray(field.value) ? field.value : []
+ // Prevent duplicates
+ if (current.includes(value)) return
field.onChange([...current, value])
}}
>
<FormControl>
<SelectTrigger dir={dir} className="w-full py-5">
<SelectValue placeholder={t('hostsDialog.selectRelayInbounds')} />
</SelectTrigger>
</FormControl>
<SelectContent dir={dir} className="bg-background">
{inbounds.map(tag => (
- <SelectItem key={tag} value={tag} className="cursor-pointer">
+ <SelectItem
+ key={tag}
+ value={tag}
+ className="cursor-pointer"
+ disabled={field.value?.includes(tag)}
+ >
{tag}
</SelectItem>
))}
</SelectContent>
</Select>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Select | |
| value={''} | |
| onValueChange={(value: string) => { | |
| if (!value || value.trim() === '') return | |
| const current = Array.isArray(field.value) ? field.value : [] | |
| field.onChange([...current, value]) | |
| }} | |
| > | |
| <FormControl> | |
| <SelectTrigger dir={dir} className="w-full py-5"> | |
| <SelectValue placeholder={t('hostsDialog.selectRelayInbounds')} /> | |
| </SelectTrigger> | |
| </FormControl> | |
| <SelectContent dir={dir} className="bg-background"> | |
| {inbounds.map(tag => ( | |
| <SelectItem key={tag} value={tag} className="cursor-pointer"> | |
| {tag} | |
| </SelectItem> | |
| ))} | |
| </SelectContent> | |
| </Select> | |
| <Select | |
| value={''} | |
| onValueChange={(value: string) => { | |
| if (!value || value.trim() === '') return | |
| const current = Array.isArray(field.value) ? field.value : [] | |
| // Prevent duplicates | |
| if (current.includes(value)) return | |
| field.onChange([...current, value]) | |
| }} | |
| > | |
| <FormControl> | |
| <SelectTrigger dir={dir} className="w-full py-5"> | |
| <SelectValue placeholder={t('hostsDialog.selectRelayInbounds')} /> | |
| </SelectTrigger> | |
| </FormControl> | |
| <SelectContent dir={dir} className="bg-background"> | |
| {inbounds.map(tag => ( | |
| <SelectItem | |
| key={tag} | |
| value={tag} | |
| className="cursor-pointer" | |
| disabled={field.value?.includes(tag)} | |
| > | |
| {tag} | |
| </SelectItem> | |
| ))} | |
| </SelectContent> | |
| </Select> |
🤖 Prompt for AI Agents
In dashboard/src/components/dialogs/HostModal.tsx around lines 3044 to 3064, the
relay inbound Select allows adding the same tag multiple times; update the
SelectItem rendering to detect the current selected tags
(Array.isArray(field.value) ? field.value : []) and disable (or skip) any
SelectItem whose tag is already included so the option cannot be re-selected;
keep the Select value and onValueChange behavior but use the current selection
to set a disabled prop (or filter the inbounds list) so duplicate tags cannot be
added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
dashboard/src/components/dialogs/HostModal.tsx (1)
3045-3062: Block duplicate relay selection entries.
onValueChangestill pushes the chosen tag without checking whether it’s already present, so users can add the same relay inbound repeatedly. This is the same duplicate-selection bug that was highlighted previously and it breaks the assumption that the relay chain is an ordered set of distinct hops. Please add an early return when the tag is already selected and disable the corresponding dropdown option so it can’t be re-picked.if (!value || value.trim() === '') return const current = Array.isArray(field.value) ? field.value : [] - field.onChange([...current, value]) + if (current.includes(value)) return + field.onChange([...current, value]) ... - {inbounds.map(tag => ( - <SelectItem key={tag} value={tag} className="cursor-pointer"> + {inbounds.map(tag => ( + <SelectItem + key={tag} + value={tag} + className="cursor-pointer" + disabled={Array.isArray(field.value) && field.value.includes(tag)} + >
🧹 Nitpick comments (2)
dashboard/public/statics/locales/fa.json (1)
645-648: Minor typography: add space before (SS-2022).Prefer "ورودیهای رله (SS-2022)" for readability and consistency with other locales.
dashboard/public/statics/locales/ru.json (1)
961-964: Minor wording for natural Russian.Consider:
- ss2022RelayInbounds: "Релейные входы (SS-2022)"
- relaySettings: "Настройки ретрансляции"
- selectRelayInbounds: "Выберите релейные входы"
- clearAllRelayInbounds: "Очистить все релейные входы"
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
app/core/hosts.py(2 hunks)app/db/migrations/versions/4bbb43d025bc_add_ss2022_relay_tags_to_hosts.py(1 hunks)app/db/models.py(1 hunks)app/models/host.py(1 hunks)app/models/subscription.py(1 hunks)app/operation/host.py(5 hunks)app/subscription/base.py(1 hunks)app/subscription/clash.py(1 hunks)app/subscription/links.py(1 hunks)app/subscription/outline.py(1 hunks)app/subscription/singbox.py(1 hunks)app/subscription/xray.py(1 hunks)dashboard/public/statics/locales/en.json(1 hunks)dashboard/public/statics/locales/fa.json(1 hunks)dashboard/public/statics/locales/ru.json(1 hunks)dashboard/public/statics/locales/zh.json(1 hunks)dashboard/src/components/dialogs/HostModal.tsx(2 hunks)dashboard/src/components/hosts/Hosts.tsx(5 hunks)dashboard/src/components/hosts/SortableHost.tsx(1 hunks)dashboard/src/pages/_dashboard._index.tsx(1 hunks)dashboard/src/pages/_dashboard.hosts.tsx(1 hunks)dashboard/src/service/api/index.ts(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (11)
- dashboard/src/components/hosts/SortableHost.tsx
- dashboard/public/statics/locales/en.json
- app/core/hosts.py
- app/subscription/base.py
- dashboard/src/service/api/index.ts
- app/subscription/outline.py
- app/subscription/links.py
- app/subscription/clash.py
- app/models/subscription.py
- dashboard/src/pages/_dashboard._index.tsx
- app/operation/host.py
🧰 Additional context used
🧬 Code graph analysis (2)
app/db/models.py (1)
app/db/compiles_types.py (1)
StringArray(51-71)
dashboard/src/components/dialogs/HostModal.tsx (4)
dashboard/src/components/ui/accordion.tsx (3)
AccordionItem(44-44)AccordionTrigger(44-44)AccordionContent(44-44)dashboard/src/components/ui/form.tsx (5)
FormField(104-104)FormItem(104-104)FormLabel(104-104)FormControl(104-104)FormMessage(104-104)dashboard/src/components/ui/select.tsx (5)
Select(105-105)SelectTrigger(105-105)SelectValue(105-105)SelectContent(105-105)SelectItem(105-105)app/db/models.py (1)
inbounds(196-206)
🔇 Additional comments (4)
dashboard/public/statics/locales/zh.json (1)
1004-1007: LGTM — keys and phrasing are consistent.app/subscription/singbox.py (1)
252-261: No issues found — relay_passwords properly propagated across all call sites.Verification confirms:
- The
detect_shadowsocks_2022signature includesrelay_passwords: list[str] | None = Noneparameter (base.py:151)- All 5 call sites (xray.py, outline.py, singbox.py, links.py, clash.py) consistently pass
getattr(inbound, "relay_passwords", None)- The relay_passwords is correctly used in the password_to_2022() invocation (base.py:156)
- The singbox.py changes are correct and consistent with existing implementations
app/subscription/xray.py (1)
409-418: LGTM — relay_passwords integration verified end-to-end.All subscription modules (xray, singbox, clash, outline, links) call
detect_shadowsocks_2022with relay_passwords as the final parameter in identical order. Function signature matches all call sites. SubscriptionInboundData model includes relay_passwords field. Implementation inpassword_to_2022correctly chains relay passwords before user password. Ordering preserved: DB → model → core/hosts → subscription.app/db/migrations/versions/4bbb43d025bc_add_ss2022_relay_tags_to_hosts.py (1)
19-25: Schema mismatch and loss of ordering — use JSON (list) to match ORM and feature semantics.String(2048) can’t safely round‑trip an ordered string list and diverges from the Python type. Store as JSON (list) to preserve order.
-from alembic import op -import sqlalchemy as sa +from alembic import op +import sqlalchemy as sa def upgrade() -> None: - op.add_column('hosts', sa.Column('ss2022_relay_inbound_tags', sa.String(length=2048), nullable=True)) + bind = op.get_bind() + # Prefer JSON to preserve order; fallback to text on dialects without native JSON + if bind.dialect.name in ("postgresql", "mysql", "sqlite"): + op.add_column( + "hosts", + sa.Column("ss2022_relay_inbound_tags", sa.JSON(none_as_null=True), nullable=True), + ) + else: + op.add_column("hosts", sa.Column("ss2022_relay_inbound_tags", sa.Text(), nullable=True)) def downgrade() -> None: - with op.batch_alter_table('hosts') as batch_op: - batch_op.drop_column('ss2022_relay_inbound_tags') + with op.batch_alter_table("hosts") as batch_op: + batch_op.drop_column("ss2022_relay_inbound_tags")Likely an incorrect or invalid review comment.
| # Ordered relay chain for Shadowsocks 2022: list of inbound tags to be used as relays | ||
| ss2022_relay_inbound_tags: list[str] | None = Field(default=None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preserve order + validate relay tags.
Add a validator to trim, drop empties, enforce max length (≤256), and de‑dup while preserving order. Also consider verifying tags exist among known inbounds.
class CreateHost(BaseHost):
+ @field_validator("ss2022_relay_inbound_tags", mode="after")
+ def validate_ss2022_relay_inbound_tags(cls, v):
+ if v is None:
+ return None
+ seen = set()
+ cleaned: list[str] = []
+ for tag in v:
+ tag = (tag or "").strip()
+ if not tag:
+ continue
+ if len(tag) > 256:
+ raise ValueError("Relay inbound tag length must be ≤ 256")
+ if tag not in seen:
+ seen.add(tag)
+ cleaned.append(tag)
+ return cleanedCommittable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
app/models/host.py around lines 202 to 203, the ss2022_relay_inbound_tags field
needs a Pydantic validator that trims whitespace from each tag, drops empty
strings, enforces a max length of 256 characters per tag (raise ValueError on
violation), and de-duplicates tags while preserving their original order;
implement a @validator("ss2022_relay_inbound_tags", pre=True, always=False) that
returns None if input is None, otherwise processes the list accordingly and
raises clear errors for invalid items, and — if feasible in this model — verify
each tag exists among known inbounds (e.g., compare against self.inbounds or a
passed-in list of inbound tags) and raise a validation error for unknown tags.
|
Do you test this? |
app/db/models.py
Outdated
| ech_config_list: Mapped[Optional[str]] = mapped_column(String(512), default=None) | ||
| # Ordered relay inbound tags for Shadowsocks 2022 | ||
| ss2022_relay_inbound_tags: Mapped[Optional[list[str]]] = mapped_column( | ||
| StringArray(256), default=None, nullable=True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you set 256 length here but in migration is 2048, choose one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
256 is the length of array item, which is the same as "inbound_tag". While 2048 is the total length, including all items and separators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, StringArray type don't work this way
| status: set[UserStatus] | None = Field(default_factory=set) | ||
| ech_config_list: str | None = Field(default=None) | ||
| # Ordered relay chain for Shadowsocks 2022: list of inbound tags to be used as relays | ||
| ss2022_relay_inbound_tags: list[str] | None = Field(default=None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
total length should be checked here
| return await get_hosts(db=db) | ||
|
|
||
| async def _validate_ss2022_relay_chain(self, host: CreateHost) -> None: | ||
| tags = getattr(host, "ss2022_relay_inbound_tags", None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you have a pydantic model in here and you can just use the values directly, no need for getattr
| if not cfg or not cfg.get("is_2022"): | ||
| await self.raise_error(f"{tag} is not a Shadowsocks 2022 inbound", 400) | ||
| if not cfg.get("password"): | ||
| await self.raise_error(f"{tag} has no inbound password configured", 400) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we need an extra check in here. both inbound should be in same core config if im not wrong
Yes I have deployed it on my server. |
|
also why target branch is main ? change it to next |
|
we wait few days for changes, after that if there is no response i close this pr |
Will push changes this week. I was busy working on other projects. |
| return set[str](v for v in value.split(",") if v) | ||
| return set[str](value) | ||
|
|
||
| class StringList(TypeDecorator): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are you adding an extra model for no reason?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StringArray is not order-preserving because it decodes to set instead of list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are already a few uses of StringArray and they uses set[str]. So it's better to keep it there and create a new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why order-preserving is important here when inbounds are excluded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relay servers are chained to provide a path to final server. The order reflects how the packets go through, therefore order is inherently important.
Inbounds that act as relay need to be excluded because the "client" field in them is filled with the information of next hop instead of the panel managed clients. User will need to fill them manually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like my description on the PR is not clear enough to illustrate how relay works.
I will put a working example later.
This is a prove of concept implementation.
SS-2022 has a feature called Extensible Identity Headers. It allows relays without giving them the user PSKs. xray-core supports this feature and have examples on configuration file.
This PR adds support for relay only for SS-2022.
To use this feature, one have to add inbounds specifically for relay:
In the host settings, there is a field to select relay inbounds.
The final password for user subscription will be
{{ relay psk 0 }}:{{ relay psk 1 }}:..:{{ server spk }}:{{ user psk }}.Summary by CodeRabbit
New Features
Bug Fixes
Documentation