Handle visits

This commit is contained in:
Sven Heidemann 2024-12-14 19:19:27 +01:00
parent e7a6a4b16b
commit dd5769823f
9 changed files with 112 additions and 1 deletions

View File

@ -1,9 +1,13 @@
from flask import redirect, jsonify import json
from flask import redirect, jsonify, request
from api.route import Route from api.route import Route
from core.logger import Logger from core.logger import Logger
from data.schemas.public.short_url import ShortUrl from data.schemas.public.short_url import ShortUrl
from data.schemas.public.short_url_dao import shortUrlDao from data.schemas.public.short_url_dao import shortUrlDao
from data.schemas.public.short_url_visit import ShortUrlVisit
from data.schemas.public.short_url_visit_dao import shortUrlVisitDao
logger = Logger(__name__) logger = Logger(__name__)
@ -26,4 +30,15 @@ async def handle_short_url(path: str):
if from_db is None: if from_db is None:
return {"error": "Short URL not found"}, 404 return {"error": "Short URL not found"}, 404
try:
await shortUrlVisitDao.create(
ShortUrlVisit(
0,
from_db.id,
request.headers.get("User-Agent")
)
)
except Exception as e:
logger.error(f"Failed to update short url {from_db.short_url} with error", e)
return redirect(from_db.target_url) return redirect(from_db.target_url)

View File

@ -9,6 +9,7 @@ type ShortUrl implements DbModel {
shortUrl: String shortUrl: String
targetUrl: String targetUrl: String
description: String description: String
visits: Int
group: Group group: Group
deleted: Boolean deleted: Boolean

View File

@ -9,3 +9,4 @@ class ShortUrlQuery(DbModelQueryABC):
self.set_field("targetUrl", lambda x, *_: x.target_url) self.set_field("targetUrl", lambda x, *_: x.target_url)
self.set_field("description", lambda x, *_: x.description) self.set_field("description", lambda x, *_: x.description)
self.set_field("group", lambda x, *_: x.group) self.set_field("group", lambda x, *_: x.group)
self.set_field("visits", lambda x, *_: x.visit_count)

View File

@ -68,6 +68,12 @@ class ShortUrl(DbModelABC):
return await groupDao.get_by_id(self._group_id) return await groupDao.get_by_id(self._group_id)
@async_property
async def visit_count(self) -> int:
from data.schemas.public.short_url_visit_dao import shortUrlVisitDao
return await shortUrlVisitDao.count_by_id(self.id)
def to_dto(self) -> dict: def to_dto(self) -> dict:
return { return {
"id": self.id, "id": self.id,

View File

@ -0,0 +1,37 @@
from datetime import datetime
from typing import Optional
from async_property import async_property
from core.database.abc.db_model_abc import DbModelABC
from core.typing import SerialId
from data.schemas.public.short_url import ShortUrl
from data.schemas.public.short_url_dao import shortUrlDao
class ShortUrlVisit(DbModelABC):
def __init__(
self,
id: SerialId,
short_url_id: SerialId,
client: Optional[str],
deleted: bool = False,
editor_id: Optional[SerialId] = None,
created: Optional[datetime] = None,
updated: Optional[datetime] = None,
):
DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
self._short_url_id = short_url_id
self._client = client
@property
def short_url_id(self) -> SerialId:
return self._short_url_id
@async_property
async def short_url(self) -> ShortUrl:
return await shortUrlDao.get_by_id(self._short_url_id)
@property
def client(self) -> Optional[str]:
return self._client

View File

@ -0,0 +1,25 @@
from core.logger import DBLogger
from data.schemas.public.short_url import ShortUrl
from data.schemas.public.short_url_visit import ShortUrlVisit
logger = DBLogger(__name__)
from core.database.abc.db_model_dao_abc import DbModelDaoABC
class ShortUrlVisitDao(DbModelDaoABC[ShortUrlVisit]):
def __init__(self):
DbModelDaoABC.__init__(self, __name__, ShortUrl, "public.short_url_visits")
self.attribute(ShortUrlVisit.short_url_id, int)
self.attribute(ShortUrlVisit.client, str)
async def count_by_id(self, fid: int) -> int:
result = await self._db.select_map(
f"SELECT COUNT(*) FROM {self._table_name} WHERE shortUrlId = {fid}"
)
if result is None or len(result) == 0:
return 0
return result[0]["count"]
shortUrlVisitDao = ShortUrlVisitDao()

View File

@ -0,0 +1,23 @@
CREATE TABLE IF NOT EXISTS public.short_url_visits
(
Id SERIAL PRIMARY KEY,
ShortUrlId INT NOT NULL REFERENCES public.short_urls (Id),
Client TEXT NOT NULL,
-- for history
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
EditorId INT NULL REFERENCES administration.users (Id),
CreatedUtc timestamptz NOT NULL DEFAULT NOW(),
UpdatedUtc timestamptz NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS public.short_url_visits_history
(
LIKE public.short_url_visits
);
CREATE TRIGGER short_url_visits_history_trigger
BEFORE INSERT OR UPDATE OR DELETE
ON public.short_url_visits
FOR EACH ROW
EXECUTE FUNCTION public.history_trigger_function();

View File

@ -6,6 +6,7 @@ export interface ShortUrl extends DbModel {
shortUrl: string; shortUrl: string;
targetUrl: string; targetUrl: string;
description: string; description: string;
visits: number;
group?: Group; group?: Group;
} }

View File

@ -60,6 +60,7 @@ export class ShortUrlsDataService
shortUrl shortUrl
targetUrl targetUrl
description description
visits
group { group {
id id
name name
@ -98,6 +99,7 @@ export class ShortUrlsDataService
shortUrl shortUrl
targetUrl targetUrl
description description
visits
group { group {
id id
name name