Skip to content

Commit

Permalink
Merge pull request #477 from sparcs-kaist/develop
Browse files Browse the repository at this point in the history
Deploy v3.4.4
  • Loading branch information
DoyunShin authored Nov 29, 2024
2 parents ff3f33b + 6c4ff64 commit 5f75b4b
Show file tree
Hide file tree
Showing 30 changed files with 1,512 additions and 1,098 deletions.
2 changes: 1 addition & 1 deletion .docker/run-celery.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ done

sleep 5

while ! nc -vz $NEWARA_REDIS_ADDRESS 6379; do
while ! nc -vz $NEWARA_REDIS_ADDRESS $NEWARA_REDIS_PORT; do
>&2 echo "Redis is unavailable - sleeping"
sleep 1
done
Expand Down
2 changes: 1 addition & 1 deletion .docker/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ while ! nc -vz $NEWARA_DB_HOST $NEWARA_DB_PORT; do
sleep 1
done

while ! nc -vz $NEWARA_REDIS_ADDRESS 6379; do
while ! nc -vz $NEWARA_REDIS_ADDRESS $NEWARA_REDIS_PORT; do
>&2 echo "Redis is unavailable - sleeping"
sleep 1
done
Expand Down
38 changes: 30 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
DJANGO_ENV=development|production
SECRET_KEY=
# AWS S3
AWS_BUCKET_NAME=
AWS_BUCKET_NAME_STATIC=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

# SPARCS SSO
SSO_CLIENT_ID=
SSO_SECRET_KEY=
PORTAL_ID=
PORTAL_PASSWORD=
PORTAL_2FA_KEY=/[2-7A-Z]{16}/
DOCKERHUB_USERNAME=
DOCKERHUB_PASSWORD=
SENTRY_DSN=

# Django
DJANGO_ENV=development
SECRET_KEY=

# MySQL
NEWARA_DB_HOST=127.0.0.1
NEWARA_DB_PORT=3306
NEWARA_DB_USER=root
NEWARA_DB_PASSWORD=
NEWARA_DB_NAME=

# Redis
NEWARA_REDIS_ADDRESS=127.0.0.1
NEWARA_REDIS_PORT=6379

# Celery
C_FORCE_ROOT=true

# Elasticsearch
NEWARA_ELASTICSEARCH_HOST=127.0.0.1
NEWARA_ELASTICSEARCH_PORT=9200

# Logging
LOG_FILE_PATH=logs/http_access.log

# KAIST portal
PORTAL_JSESSIONID=
4 changes: 2 additions & 2 deletions .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ jobs:
- name: Run test
run: |
docker-compose -f docker-compose.test.yml run api test
docker-compose -f docker-compose.test.yml down
docker compose -f docker-compose.test.yml run api test
docker compose -f docker-compose.test.yml down
- if: env.PUSH == 'true'
name: Push docker image
run: |
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,9 @@ show_sql:

schema:
python3 manage.py spectacular --color --file schema.yml

local_env:
docker compose -f docker-compose.local.yml up -d

local_env_down:
docker compose -f docker-compose.local.yml down
3 changes: 2 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ django-celery-results = "*"
drf-spectacular = "*"
django-cacheops = "*"
django-elasticsearch-dsl = "~=7.3"
mysqlclient = "*"
mysqlclient = "~=2.2.4"
beautifulsoup4 = "*"
bleach = "*"
django-redis = "*"
Expand All @@ -38,6 +38,7 @@ uritemplate = "*"
tqdm = "*"
lxml = "*"
django-ses = "*"
pydantic = "*"

[dev-packages]
black = "*"
Expand Down
2,008 changes: 1,073 additions & 935 deletions Pipfile.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pre-commit install --hook-type commit-msg
## How to Run

```bash
docker compose -f docker-compose.local.yml up -d
pipenv shell
make run
```
Expand Down
11 changes: 8 additions & 3 deletions apps/core/views/viewsets/article.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import datetime
import time

from django.core.paginator import Paginator as DjangoPaginator
from django.db import models
from django.http import Http404
from django.utils import timezone
from django.utils.functional import cached_property
from django.utils.translation import gettext
from rest_framework import (
Expand Down Expand Up @@ -479,10 +481,13 @@ def recent(self, request, *args, **kwargs):

@decorators.action(detail=False, methods=["get"])
def top(self, request):
# The most recent article at the top
top_articles = Article.objects.exclude(topped_at__isnull=True).order_by(
"-topped_at", "-pk"
current_date = datetime.datetime.combine(
timezone.now().date(), datetime.time.min, datetime.timezone.utc
)
# get the articles that are created_at within a week and order by hit_count
top_articles = Article.objects.filter(
created_at__gte=current_date - datetime.timedelta(days=7)
).order_by("-hit_count", "-pk")

search_keyword = request.query_params.get("main_search__contains")
if search_keyword:
Expand Down
Empty file added ara/controller/__init__.py
Empty file.
Empty file added ara/controller/api.py
Empty file.
3 changes: 3 additions & 0 deletions ara/controller/authentication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class AuthLoggedInUser:
# TODO
pass
65 changes: 65 additions & 0 deletions ara/controller/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from enum import IntEnum, unique


@unique
class HttpStatusCode(IntEnum):
CONTINUE = 100
SWITCHING_PROTOCOLS = 101
OK = 200
CREATED = 201
ACCEPTED = 202
NON_AUTHORITATIVE_INFORMATION = 203
NO_CONTENT = 204
RESET_CONTENT = 205
PARTIAL_CONTENT = 206
MULTI_STATUS = 207
ALREADY_REPORTED = 208
IM_USED = 226
MULTIPLE_CHOICES = 300
MOVED_PERMANENTLY = 301
FOUND = 302
SEE_OTHER = 303
NOT_MODIFIED = 304
USE_PROXY = 305
RESERVED = 306
TEMPORARY_REDIRECT = 307
PERMANENT_REDIRECT = 308
BAD_REQUEST = 400
UNAUTHORIZED = 401
PAYMENT_REQUIRED = 402
FORBIDDEN = 403
NOT_FOUND = 404
METHOD_NOT_ALLOWED = 405
NOT_ACCEPTABLE = 406
PROXY_AUTHENTICATION_REQUIRED = 407
REQUEST_TIMEOUT = 408
CONFLICT = 409
GONE = 410
LENGTH_REQUIRED = 411
PRECONDITION_FAILED = 412
REQUEST_ENTITY_TOO_LARGE = 413
REQUEST_URI_TOO_LONG = 414
UNSUPPORTED_MEDIA_TYPE = 415
REQUESTED_RANGE_NOT_SATISFIABLE = 416
EXPECTATION_FAILED = 417
IM_A_TEAPOT = 418
UNPROCESSABLE_ENTITY = 422
LOCKED = 423
FAILED_DEPENDENCY = 424
UPGRADE_REQUIRED = 426
PRECONDITION_REQUIRED = 428
TOO_MANY_REQUESTS = 429
REQUEST_HEADER_FIELDS_TOO_LARGE = 431
UNAVAILABLE_FOR_LEGAL_REASONS = 451
INTERNAL_SERVER_ERROR = 500
NOT_IMPLEMENTED = 501
BAD_GATEWAY = 502
SERVICE_UNAVAILABLE = 503
GATEWAY_TIMEOUT = 504
HTTP_VERSION_NOT_SUPPORTED = 505
VARIANT_ALSO_NEGOTIATES = 506
INSUFFICIENT_STORAGE = 507
LOOP_DETECTED = 508
BANDWIDTH_LIMIT_EXCEEDED = 509
NOT_EXTENDED = 510
NETWORK_AUTHENTICATION_REQUIRED = 511
14 changes: 14 additions & 0 deletions ara/controller/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from typing import Any

from pydantic import BaseModel


class PaginatedData(BaseModel):
count: int
next: str | None
previous: str | None
results: list[Any]


class NesAraPagination:
pass
10 changes: 10 additions & 0 deletions ara/controller/request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import TypeVar

from django.contrib.auth import get_user_model
from django.http import HttpRequest

User = TypeVar("User", bound=get_user_model())


class LoggedInUserRequest(HttpRequest):
user: User
21 changes: 21 additions & 0 deletions ara/controller/response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from http import HTTPStatus
from typing import Any, NamedTuple

from pydantic import BaseModel


class AraResponse(NamedTuple):
status_code: HTTPStatus
data: Any


class AraErrorResponseBody(BaseModel):
# necessary
error_code: int | None
error_reason: str = ""

def __init__(self, exception: Exception):
message = str(exception)
# TODO: Create AraException and use error_code & error_reason
data = {"message": message}
super().__init__(**data)
Empty file added ara/controller/urls.py
Empty file.
Empty file added ara/domain/__init__.py
Empty file.
35 changes: 35 additions & 0 deletions ara/domain/ara_entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from typing import Any

from pydantic import BaseModel, PrivateAttr


class AraEntity(BaseModel):
_updated_fields: set[str] = PrivateAttr(set())

@property
def updated_fields(self):
return self._updated_fields

@property
def updated_values(self) -> dict[str, Any]:
return {key: getattr(self, key) for key in self._updated_fields}

def set_attribute(self, field_name: str, value: Any):
self.__dict__[field_name] = value
is_private_field = field_name.startswith("_") or field_name.startswith("__")
if is_private_field is False:
self._updated_fields.add(field_name)

def __setattr__(self, name: str, value: Any) -> None:
is_private_field = name.startswith("_") or name.startswith("__")
if is_private_field is False:
self._updated_fields.add(name)
return super().__setattr__(name, value)

class Config:
arbitrary_types_allowed = True


class AraEntityCreateInput(BaseModel):
class Config:
arbitrary_types_allowed = True
Empty file added ara/infra/__init__.py
Empty file.
Loading

0 comments on commit 5f75b4b

Please sign in to comment.