Compare commits
1 Commits
fix/sv-aut
...
dev
Author | SHA1 | Date | |
---|---|---|---|
9f16ee022b |
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -162,4 +162,5 @@ views.json
|
|||
*.crt
|
||||
*cache.json
|
||||
.cursor
|
||||
.devcontainer/devcontainer.json
|
||||
|
||||
node_modules/
|
||||
|
|
|
@ -57,7 +57,7 @@ mkcert localhost
|
|||
Then, run the server:
|
||||
|
||||
```shell
|
||||
python -m granian main:app --interface asgi --host 0.0.0.0 --port 8000
|
||||
python server.py dev
|
||||
```
|
||||
|
||||
### Useful Commands
|
||||
|
|
20
main.py
20
main.py
|
@ -7,6 +7,7 @@ from os.path import exists
|
|||
from ariadne import load_schema_from_path, make_executable_schema
|
||||
from ariadne.asgi import GraphQL
|
||||
from starlette.applications import Starlette
|
||||
from starlette.middleware import Middleware
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse, Response
|
||||
|
@ -73,6 +74,24 @@ async def graphql_handler(request: Request):
|
|||
print(f"GraphQL error: {str(e)}")
|
||||
return JSONResponse({"error": str(e)}, status_code=500)
|
||||
|
||||
middleware = [
|
||||
# Начинаем с обработки ошибок
|
||||
Middleware(ExceptionHandlerMiddleware),
|
||||
# CORS должен быть перед другими middleware для корректной обработки preflight-запросов
|
||||
Middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=[
|
||||
"https://localhost:3000",
|
||||
"https://testing.discours.io",
|
||||
"https://testing3.discours.io",
|
||||
"https://discours.io",
|
||||
"https://new.discours.io"
|
||||
],
|
||||
allow_methods=["GET", "POST", "OPTIONS"], # Явно указываем OPTIONS
|
||||
allow_headers=["*"],
|
||||
allow_credentials=True,
|
||||
),
|
||||
]
|
||||
|
||||
# Обновляем маршрут в Starlette
|
||||
app = Starlette(
|
||||
|
@ -80,6 +99,7 @@ app = Starlette(
|
|||
Route("/", graphql_handler, methods=["GET", "POST"]),
|
||||
Route("/new-author", WebhookEndpoint),
|
||||
],
|
||||
middleware=middleware,
|
||||
lifespan=lifespan,
|
||||
debug=True,
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
log_format custom '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'origin=$http_origin allow_origin=$allow_origin status=$status '
|
||||
'origin=$http_origin status=$status '
|
||||
'"$http_referer" "$http_user_agent"';
|
||||
|
||||
{{ $proxy_settings := "proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_set_header Host $http_host; proxy_set_header X-Request-Start $msec;" }}
|
||||
|
@ -49,34 +49,6 @@ server {
|
|||
{{ $proxy_settings }}
|
||||
{{ $gzip_settings }}
|
||||
|
||||
# Handle CORS for OPTIONS method
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' $allow_origin always;
|
||||
add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS';
|
||||
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
add_header 'Access-Control-Max-Age' 1728000;
|
||||
add_header 'Content-Type' 'text/plain; charset=utf-8';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
|
||||
# Handle CORS for POST method
|
||||
if ($request_method = 'POST') {
|
||||
add_header 'Access-Control-Allow-Origin' $allow_origin always;
|
||||
add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
}
|
||||
|
||||
# Handle CORS for GET method
|
||||
if ($request_method = 'GET') {
|
||||
add_header 'Access-Control-Allow-Origin' $allow_origin always;
|
||||
add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
}
|
||||
|
||||
proxy_cache my_cache;
|
||||
proxy_cache_revalidate on;
|
||||
proxy_cache_min_uses 2;
|
||||
|
@ -95,14 +67,7 @@ server {
|
|||
}
|
||||
|
||||
location ~* \.(mp3|wav|ogg|flac|aac|aif|webm)$ {
|
||||
proxy_pass http://{{ $.APP }}-{{ $upstream_port }};
|
||||
if ($request_method = 'GET') {
|
||||
add_header 'Access-Control-Allow-Origin' $allow_origin always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
|
||||
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
}
|
||||
proxy_pass http://{{ $.APP }}-{{ $upstream_port }};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -77,45 +77,18 @@ async def get_authors_with_stats(limit=50, offset=0, by: Optional[str] = None):
|
|||
base_query = select(Author).where(Author.deleted_at.is_(None))
|
||||
|
||||
# Применяем сортировку
|
||||
|
||||
# vars for statistics sorting
|
||||
stats_sort_field = None
|
||||
stats_sort_direction = "desc"
|
||||
|
||||
if by:
|
||||
if isinstance(by, dict):
|
||||
logger.debug(f"Processing dict-based sorting: {by}")
|
||||
# Обработка словаря параметров сортировки
|
||||
from sqlalchemy import asc, desc, func
|
||||
from orm.shout import ShoutAuthor
|
||||
from orm.author import AuthorFollower
|
||||
from sqlalchemy import asc, desc
|
||||
|
||||
# Checking for order field in the dictionary
|
||||
if "order" in by:
|
||||
order_value = by["order"]
|
||||
logger.debug(f"Found order field with value: {order_value}")
|
||||
if order_value in ["shouts", "followers", "rating", "comments"]:
|
||||
stats_sort_field = order_value
|
||||
stats_sort_direction = "desc" # По умолчанию убывающая сортировка для статистики
|
||||
logger.debug(f"Applying statistics-based sorting by: {stats_sort_field}")
|
||||
elif order_value == "name":
|
||||
# Sorting by name in ascending order
|
||||
base_query = base_query.order_by(asc(Author.name))
|
||||
logger.debug("Applying alphabetical sorting by name")
|
||||
else:
|
||||
# If order is not a stats field, treat it as a regular field
|
||||
column = getattr(Author, order_value, None)
|
||||
if column:
|
||||
for field, direction in by.items():
|
||||
column = getattr(Author, field, None)
|
||||
if column:
|
||||
if direction.lower() == "desc":
|
||||
base_query = base_query.order_by(desc(column))
|
||||
else:
|
||||
# Regular sorting by fields
|
||||
for field, direction in by.items():
|
||||
column = getattr(Author, field, None)
|
||||
if column:
|
||||
if direction.lower() == "desc":
|
||||
base_query = base_query.order_by(desc(column))
|
||||
else:
|
||||
base_query = base_query.order_by(column)
|
||||
else:
|
||||
base_query = base_query.order_by(column)
|
||||
elif by == "new":
|
||||
base_query = base_query.order_by(desc(Author.created_at))
|
||||
elif by == "active":
|
||||
|
@ -126,55 +99,6 @@ async def get_authors_with_stats(limit=50, offset=0, by: Optional[str] = None):
|
|||
else:
|
||||
base_query = base_query.order_by(desc(Author.created_at))
|
||||
|
||||
# If sorting by statistics, modify the query
|
||||
if stats_sort_field == "shouts":
|
||||
# Sorting by the number of shouts
|
||||
from sqlalchemy import func, and_
|
||||
from orm.shout import Shout, ShoutAuthor
|
||||
|
||||
subquery = (
|
||||
select(
|
||||
ShoutAuthor.author,
|
||||
func.count(func.distinct(Shout.id)).label("shouts_count")
|
||||
)
|
||||
.select_from(ShoutAuthor)
|
||||
.join(Shout, ShoutAuthor.shout == Shout.id)
|
||||
.where(
|
||||
and_(
|
||||
Shout.deleted_at.is_(None),
|
||||
Shout.published_at.is_not(None)
|
||||
)
|
||||
)
|
||||
.group_by(ShoutAuthor.author)
|
||||
.subquery()
|
||||
)
|
||||
|
||||
base_query = (
|
||||
base_query
|
||||
.outerjoin(subquery, Author.id == subquery.c.author)
|
||||
.order_by(desc(func.coalesce(subquery.c.shouts_count, 0)))
|
||||
)
|
||||
elif stats_sort_field == "followers":
|
||||
# Sorting by the number of followers
|
||||
from sqlalchemy import func
|
||||
from orm.author import AuthorFollower
|
||||
|
||||
subquery = (
|
||||
select(
|
||||
AuthorFollower.author,
|
||||
func.count(func.distinct(AuthorFollower.follower)).label("followers_count")
|
||||
)
|
||||
.select_from(AuthorFollower)
|
||||
.group_by(AuthorFollower.author)
|
||||
.subquery()
|
||||
)
|
||||
|
||||
base_query = (
|
||||
base_query
|
||||
.outerjoin(subquery, Author.id == subquery.c.author)
|
||||
.order_by(desc(func.coalesce(subquery.c.followers_count, 0)))
|
||||
)
|
||||
|
||||
# Применяем лимит и смещение
|
||||
base_query = base_query.limit(limit).offset(offset)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user