Add user activity

This commit is contained in:
2023-01-05 18:33:57 +01:00
parent 634dceaa14
commit 6fb2435a12
5 changed files with 81 additions and 5 deletions

View File

@@ -0,0 +1,40 @@
"""empty message
Revision ID: 64fe2045bf28
Revises: 750640043cd4
Create Date: 2023-01-05 18:28:05.296720
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "64fe2045bf28"
down_revision = "750640043cd4"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"user_activity",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("user", sa.Integer(), nullable=False),
sa.Column("updated", sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(
["user"],
["user_settings.id"],
name="fk_user_activity_user_settings_id_user",
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("user"),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("user_activity")
# ### end Alembic commands ###

View File

@@ -1,3 +1,5 @@
from datetime import datetime
import ormar import ormar
from core.db import metadata, database from core.db import metadata, database
@@ -30,3 +32,15 @@ class User(ormar.Model):
source: str = ormar.String(max_length=32) # type: ignore source: str = ormar.String(max_length=32) # type: ignore
allowed_langs = ormar.ManyToMany(Language) allowed_langs = ormar.ManyToMany(Language)
class UserActivity(ormar.Model):
class Meta(BaseMeta):
tablename = "user_activity"
id: int = ormar.Integer(primary_key=True) # type: ignore
user: User = ormar.ForeignKey(
User, nullable=False, unique=True, related_name="last_activity"
)
updated: datetime = ormar.DateTime(timezone=False) # type: ignore

View File

@@ -33,4 +33,5 @@ class UserUpdate(BaseModel):
class UserDetail(UserBase): class UserDetail(UserBase):
id: int
allowed_langs: list[LanguageDetail] allowed_langs: list[LanguageDetail]

View File

@@ -50,7 +50,7 @@ class UsersDataManager:
@classmethod @classmethod
async def get_user( async def get_user(
cls, user_id: int, redis: aioredis.Redis cls, user_id: int, redis: aioredis.Redis
) -> Optional[UserDetail]: ) -> Optional[UserDetail | User]:
if cached_user := await cls._get_user_from_cache(user_id, redis): if cached_user := await cls._get_user_from_cache(user_id, redis):
return cached_user return cached_user
@@ -60,7 +60,7 @@ class UsersDataManager:
return None return None
await cls._cache_user(user, redis) await cls._cache_user(user, redis)
return user # type: ignore return user
@classmethod @classmethod
def _is_has_data_to_update(cls, new_user: UserUpdate) -> bool: def _is_has_data_to_update(cls, new_user: UserUpdate) -> bool:
@@ -106,7 +106,7 @@ class UsersDataManager:
@classmethod @classmethod
async def create_or_update_user( async def create_or_update_user(
cls, data: UserCreateOrUpdate, redis: aioredis.Redis cls, data: UserCreateOrUpdate, redis: aioredis.Redis
): ) -> User | UserDetail:
user = await cls.get_user(data.user_id, redis) user = await cls.get_user(data.user_id, redis)
if user is None: if user is None:
@@ -121,7 +121,9 @@ class UsersDataManager:
@classmethod @classmethod
def _is_need_update( def _is_need_update(
cls, old_user: UserDetail, new_user: Union[UserUpdate, UserCreateOrUpdate] cls,
old_user: UserDetail | User,
new_user: Union[UserUpdate, UserCreateOrUpdate],
) -> bool: ) -> bool:
old_data = old_user.dict() old_data = old_user.dict()
new_data = new_user.dict() new_data = new_user.dict()

View File

@@ -1,3 +1,5 @@
from datetime import datetime
from fastapi import APIRouter, HTTPException, status, Depends, Request from fastapi import APIRouter, HTTPException, status, Depends, Request
from fastapi_pagination import Page, Params from fastapi_pagination import Page, Params
@@ -5,7 +7,7 @@ from fastapi_pagination.ext.ormar import paginate
from redis import asyncio as aioredis from redis import asyncio as aioredis
from app.depends import check_token from app.depends import check_token
from app.models import User, Language from app.models import User, Language, UserActivity
from app.serializers import ( from app.serializers import (
UserCreateOrUpdate, UserCreateOrUpdate,
UserUpdate, UserUpdate,
@@ -49,6 +51,23 @@ async def update_user(request: Request, user_id: int, data: UserUpdate):
return await UsersDataManager.update_user(user_id, data, redis) return await UsersDataManager.update_user(user_id, data, redis)
@users_router.post("/{user_id}/update_activity")
async def update_activity(
request: Request, user_id: int, data: UserCreateOrUpdate
) -> None:
redis: aioredis.Redis = request.app.state.redis
user = await UsersDataManager.create_or_update_user(data, redis)
activity = await UserActivity.objects.get_or_none(user__user_id=user_id)
if activity is None:
await UserActivity.objects.create(user=user.id, updated=datetime.now())
return
activity.updated = datetime.now()
await activity.update()
languages_router = APIRouter( languages_router = APIRouter(
prefix="/languages", tags=["languages"], dependencies=[Depends(check_token)] prefix="/languages", tags=["languages"], dependencies=[Depends(check_token)]
) )