Skip to content

Commit

Permalink
Merge pull request #2 from Gozargah/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Alirezaja1384 authored Jul 12, 2024
2 parents 16ed7ec + 6dc0d38 commit e638d42
Show file tree
Hide file tree
Showing 36 changed files with 1,036 additions and 269 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ UVICORN_PORT = 8000
## If USE_CUSTOM_JSON_DEFAULT is set True, all following programs will use the JSON config
# USE_CUSTOM_JSON_FOR_V2RAYN=False
# USE_CUSTOM_JSON_FOR_V2RAYNG=True
# USE_CUSTOM_JSON_FOR_STREISAND=False

## Set headers for subscription
# SUB_PROFILE_TITLE = "Susbcription"
# SUB_SUPPORT_URL = "https://t.me/support"
# SUB_UPDATE_INTERVAL = "12"
# RANDOMIZE_SUBSCRIPTION_CONFIGS = True

# SQLALCHEMY_DATABASE_URL = "sqlite:///db.sqlite3"

Expand Down
1 change: 1 addition & 0 deletions app/dashboard/build/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"hostsDialog.host.wildcard": "Use <badge>*</badge> to generate a random string (works for wildcard domain names)",
"hostsDialog.sockopt": "Sockopt",
"hostsDialog.muxEnable": "Enable MUX",
"hostsDialog.randomUserAgent":"Use random user agent",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.fragment": "Fragment pattern",
"hostsDialog.fragment.info": "Correct pattern: length,interval,packets",
Expand Down
1 change: 1 addition & 0 deletions app/dashboard/build/locales/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"hostsDialog.host.wildcard": "از <badge>*</badge> برای ساخت عبارت تصادفی استفاده کنید (برای نام‌های wildcard کار می‌کند)",
"hostsDialog.sockopt": "Sockopt",
"hostsDialog.muxEnable": "فعالسازی MUX",
"hostsDialog.randomUserAgent":"استفاده از User Agent تصادفی",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.fragment": "الگو فرگمنت",
"hostsDialog.fragment.info": "length,interval,packet (e.g. 10-100,100-200,tlshello)",
Expand Down
1 change: 1 addition & 0 deletions app/dashboard/build/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
"hostsDialog.host.wildcard": "Используйте <badge>*</badge>, чтобы сгенерировать случайную строку (работает для wildcard доменов)",
"hostsDialog.sockopt": "Sockopt",
"hostsDialog.muxEnable": "Давать возможность MUX",
"hostsDialog.randomUserAgent":"Use random user agent",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.fragment": "Шаблон фрагмента",
"hostsDialog.fragment.info": "length,interval,packet (e.g. 10-100,100-200,tlshello)",
Expand Down
1 change: 1 addition & 0 deletions app/dashboard/build/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"hostsDialog.fingerprint": "指纹",
"hostsDialog.sockopt": "Sockopt",
"hostsDialog.muxEnable": "使能够 MUX",
"hostsDialog.randomUserAgent":"Use random user agent",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.fragment": "碎片图案",
"hostsDialog.fragment.info": "length,interval,packet (e.g. 10-100,100-200,tlshello)",
Expand Down
1 change: 1 addition & 0 deletions app/dashboard/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"hostsDialog.host.wildcard": "Use <badge>*</badge> to generate a random string (works for wildcard domain names)",
"hostsDialog.sockopt": "Sockopt",
"hostsDialog.muxEnable": "Enable MUX",
"hostsDialog.randomUserAgent":"Use random user agent",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.fragment": "Fragment pattern",
"hostsDialog.fragment.info": "Correct pattern: length,interval,packets",
Expand Down
1 change: 1 addition & 0 deletions app/dashboard/public/locales/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"hostsDialog.host.wildcard": "از <badge>*</badge> برای ساخت عبارت تصادفی استفاده کنید (برای نام‌های wildcard کار می‌کند)",
"hostsDialog.sockopt": "Sockopt",
"hostsDialog.muxEnable": "فعالسازی MUX",
"hostsDialog.randomUserAgent":"استفاده از User Agent تصادفی",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.fragment": "الگو فرگمنت",
"hostsDialog.fragment.info": "length,interval,packet (e.g. 10-100,100-200,tlshello)",
Expand Down
1 change: 1 addition & 0 deletions app/dashboard/public/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
"hostsDialog.host.wildcard": "Используйте <badge>*</badge>, чтобы сгенерировать случайную строку (работает для wildcard доменов)",
"hostsDialog.sockopt": "Sockopt",
"hostsDialog.muxEnable": "Давать возможность MUX",
"hostsDialog.randomUserAgent":"Use random user agent",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.fragment": "Шаблон фрагмента",
"hostsDialog.fragment.info": "length,interval,packet (e.g. 10-100,100-200,tlshello)",
Expand Down
1 change: 1 addition & 0 deletions app/dashboard/public/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"hostsDialog.fingerprint": "指纹",
"hostsDialog.sockopt": "Sockopt",
"hostsDialog.muxEnable": "使能够 MUX",
"hostsDialog.randomUserAgent":"Use random user agent",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.fragment": "碎片图案",
"hostsDialog.fragment.info": "length,interval,packet (e.g. 10-100,100-200,tlshello)",
Expand Down
24 changes: 24 additions & 0 deletions app/dashboard/src/components/HostsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const hostsSchema = z.record(
allowinsecure: z.boolean().nullable().default(false),
is_disabled: z.boolean().default(true),
fragment_setting: z.string().nullable(),
random_user_agent: z.boolean().default(false),
security: z.string(),
alpn: z.string(),
fingerprint: z.string(),
Expand Down Expand Up @@ -175,6 +176,7 @@ const AccordionInbound: FC<AccordionInboundType> = ({
allowinsecure: false,
is_disabled: false,
fragment_setting: "",
random_user_agent: false,
security: "inbound_default",
alpn: "",
fingerprint: "",
Expand Down Expand Up @@ -920,6 +922,28 @@ const AccordionInbound: FC<AccordionInboundType> = ({
</Error>
)}
</FormControl>
<FormControl
isInvalid={
!!(
accordionErrors &&
accordionErrors[index]?.random_user_agent
)
}
>
<Checkbox
{...form.register(
hostKey + "." + index + ".random_user_agent"
)}
>
<FormLabel>{t("hostsDialog.randomUserAgent")}</FormLabel>
</Checkbox>
{accordionErrors &&
accordionErrors[index]?.random_user_agent && (
<Error>
{accordionErrors[index]?.random_user_agent?.message}
</Error>
)}
</FormControl>
</VStack>
</AccordionPanel>
</AccordionItem>
Expand Down
1 change: 1 addition & 0 deletions app/db/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def update_hosts(db: Session, inbound_tag: str, modified_hosts: List[ProxyHostMo
is_disabled=host.is_disabled,
mux_enable=host.mux_enable,
fragment_setting=host.fragment_setting,
random_user_agent=host.random_user_agent,
) for host in modified_hosts
]
db.commit()
Expand Down
115 changes: 115 additions & 0 deletions app/db/migrations/versions/305943d779c4_add_h3_to_alpn_enum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
"""add h3 to alpn enum
Revision ID: 305943d779c4
Revises: 31f92220c0d0
Create Date: 2024-07-03 19:27:15.282711
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '305943d779c4'
down_revision = '31f92220c0d0'
branch_labels = None
depends_on = None


# Describing of enum
enum_name = "alpn"
temp_enum_name = f"temp_{enum_name}"
old_values = ("none", "h2", "http/1.1", "h2,http/1.1")
new_values = ("h3", "h3,h2", "h3,h2,http/1.1", *old_values)
# on downgrade
downgrade_from = ("h3", "h3,h2", "h3,h2,http/1.1", "")
downgrade_to = "none"
old_type = sa.Enum(*old_values, name=enum_name)
new_type = sa.Enum(*new_values, name=enum_name)
temp_type = sa.Enum(*new_values, name=temp_enum_name)


# Describing of table
table_name = "hosts"
column_name = "alpn"
temp_table = sa.sql.table(
table_name,
sa.Column(
column_name,
new_type,
nullable=False
)
)


def upgrade():
# temp type to use instead of old one
temp_type.create(op.get_bind(), checkfirst=False)

# changing of column type from old enum to new one.
# SQLite will create temp table for this
with op.batch_alter_table(table_name) as batch_op:
batch_op.alter_column(
column_name,
existing_type=old_type,
type_=temp_type,
existing_nullable=False,
postgresql_using=f"{column_name}::text::{temp_enum_name}"
)

# remove old enum, create new enum
old_type.drop(op.get_bind(), checkfirst=False)
new_type.create(op.get_bind(), checkfirst=False)

# changing of column type from temp enum to new one.
# SQLite will create temp table for this
with op.batch_alter_table(table_name) as batch_op:
batch_op.alter_column(
column_name,
existing_type=temp_type,
type_=new_type,
existing_nullable=False,
postgresql_using=f"{column_name}::text::{enum_name}"
)

# remove temp enum
temp_type.drop(op.get_bind(), checkfirst=False)


def downgrade():
# old enum don't have new value anymore.
# before downgrading from new enum to old one,
# we should replace new value from new enum with
# somewhat of old values from old enum
update_query = (
temp_table
.update()
.where(temp_table.c.alpn.in_(downgrade_from))
.values(alpn=downgrade_to)
)
op.execute(update_query)

temp_type.create(op.get_bind(), checkfirst=False)

with op.batch_alter_table(table_name) as batch_op:
batch_op.alter_column(
column_name,
existing_type=new_type,
type_=temp_type,
existing_nullable=False,
postgresql_using=f"{column_name}::text::{temp_enum_name}"
)

new_type.drop(op.get_bind(), checkfirst=False)
old_type.create(op.get_bind(), checkfirst=False)

with op.batch_alter_table(table_name) as batch_op:
batch_op.alter_column(
column_name,
existing_type=temp_type,
type_=old_type,
existing_nullable=False,
postgresql_using=f"{column_name}::text::{enum_name}"
)

temp_type.drop(op.get_bind(), checkfirst=False)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Add Support Random User-Agent
Revision ID: 31f92220c0d0
Revises: 4f045f53bef8
Create Date: 2024-06-01 21:28:33.310627
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '31f92220c0d0'
down_revision = '4f045f53bef8'
branch_labels = None
depends_on = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('hosts', sa.Column('random_user_agent', sa.Boolean(), server_default='0', nullable=False))
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('hosts', 'random_user_agent')
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@


def upgrade():
status_enum = sa.Enum('active', 'limited', 'expired', name='status')
status_enum.create(op.get_bind())

# temp type to use instead of old one
temp_type.create(op.get_bind(), checkfirst=False)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@


def upgrade() -> None:
proxyhostsecurity_enum = sa.Enum('inbound_default', 'none', 'tls', name='proxyhostsecurity')
proxyhostsecurity_enum.create(op.get_bind())

# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"hosts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@


def upgrade() -> None:
proxyhostalpn_enum = sa.Enum('none', 'h2', 'http/1.1', 'h2,http/1.1', name='proxyhostalpn')
proxyhostalpn_enum.create(op.get_bind(), checkfirst=True)

proxyhostfingerprint_enum = sa.Enum('none', 'chrome', 'firefox', 'safari', 'ios', 'android', 'edge', '360', 'qq', 'random', 'randomized', name='proxyhostfingerprint')
proxyhostfingerprint_enum.create(op.get_bind(), checkfirst=True)
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('hosts', sa.Column('alpn', sa.Enum('none', 'h2', 'http/1.1', 'h2,http/1.1', name='proxyhostalpn'), server_default='none', nullable=False))
op.add_column('hosts', sa.Column('fingerprint', sa.Enum('none', 'chrome', 'firefox', 'safari', 'ios', 'android', 'edge', '360', 'qq', 'random', 'randomized', name='proxyhostfingerprint'), server_default='none', nullable=False))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@


def upgrade() -> None:
userdatalimitresetstrategy = sa.Enum('no_reset', 'day', 'week', 'month', 'year', name='userdatalimitresetstrategy')
userdatalimitresetstrategy.create(op.get_bind())

# ### commands auto generated by Alembic - please adjust! ###
op.create_table('user_usage_logs',
sa.Column('id', sa.Integer(), nullable=False),
Expand Down
20 changes: 17 additions & 3 deletions app/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

from sqlalchemy import (JSON, BigInteger, Boolean, Column, DateTime, Enum,
Float, ForeignKey, Integer, String, Table,
UniqueConstraint)
UniqueConstraint, func)
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship
from sqlalchemy.sql.expression import text
from sqlalchemy.sql.expression import text, select

from app import xray
from app.db.base import Base
Expand Down Expand Up @@ -46,7 +47,7 @@ class User(Base):
nullable=False,
default=UserDataLimitResetStrategy.no_reset,
)
usage_logs = relationship("UserUsageResetLogs", back_populates="user")
usage_logs = relationship("UserUsageResetLogs", back_populates="user") # maybe rename it to reset_usage_logs?
expire = Column(Integer, nullable=True)
admin_id = Column(Integer, ForeignKey("admins.id"))
admin = relationship("Admin", back_populates="users")
Expand All @@ -60,6 +61,18 @@ class User(Base):
on_hold_timeout = Column(DateTime, nullable=True, default=None)
edit_at = Column(DateTime, nullable=True, default=None)

@hybrid_property
def reseted_usage(self):
return sum([log.used_traffic_at_reset for log in self.usage_logs])

@reseted_usage.expression
def reseted_usage(self):
return (
select([func.sum(UserUsageResetLogs.used_traffic_at_reset)]).
where(UserUsageResetLogs.user_id == self.id).
label('reseted_usage')
)

@property
def lifetime_used_traffic(self):
return (
Expand Down Expand Up @@ -194,6 +207,7 @@ class ProxyHost(Base):
is_disabled = Column(Boolean, nullable=True, default=False)
mux_enable = Column(Boolean, nullable=False, default=False, server_default='0')
fragment_setting = Column(String(100), nullable=True)
random_user_agent = Column(Boolean, nullable=False, default=False, server_default='0')


class System(Base):
Expand Down
13 changes: 5 additions & 8 deletions app/jobs/review_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,8 @@ def review():
xray.operations.remove_user(user)
update_user_status(db, user, status)

bg.add_task(
report.status_change, username=user.username, status=status,
user=UserResponse.from_orm(user), user_admin=user.admin
)
report.status_change(username=user.username, status=status,
user=UserResponse.from_orm(user), user_admin=user.admin)

logger.info(f"User \"{user.username}\" status changed to {status}")

Expand All @@ -82,10 +80,9 @@ def review():

update_user_status(db, user, status)
start_user_expire(db, user)
bg.add_task(
report.status_change, username=user.username, status=status,
user=UserResponse.from_orm(user), user_admin=user.admin
)

report.status_change(username=user.username, status=status,
user=UserResponse.from_orm(user), user_admin=user.admin)

logger.info(f"User \"{user.username}\" status changed to {status}")

Expand Down
Loading

0 comments on commit e638d42

Please sign in to comment.