Skip to content
Snippets Groups Projects
Verified Commit 7f6c23d4 authored by Kevin Morris's avatar Kevin Morris
Browse files

housekeep: centralize datetime generation


Signed-off-by: Kevin Morris's avatarKevin Morris <kevr@0cost.org>
parent 7bcc8d7c
No related branches found
No related tags found
No related merge requests found
Showing
with 69 additions and 76 deletions
import functools
from datetime import datetime
from http import HTTPStatus
from typing import Callable
......@@ -13,7 +12,7 @@ from starlette.requests import HTTPConnection
import aurweb.config
from aurweb import db, filters, l10n, util
from aurweb import db, filters, l10n, time, util
from aurweb.models import Session, User
from aurweb.models.account_type import ACCOUNT_TYPE_ID
......@@ -110,7 +109,7 @@ class BasicAuthBackend(AuthenticationBackend):
"persistent_cookie_timeout")
# If no session with sid and a LastUpdateTS now or later exists.
now_ts = int(datetime.utcnow().timestamp())
now_ts = time.utcnow()
record = db.query(Session).filter(Session.SessionID == sid).first()
if not record:
return unauthenticated
......
from datetime import datetime
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import backref, relationship
from aurweb import schema
from aurweb import schema, time
from aurweb.models.declarative import Base
from aurweb.models.user import User as _User
......@@ -43,7 +41,7 @@ class PackageBase(Base):
# If no SubmittedTS/ModifiedTS is provided on creation, set them
# here to the current utc timestamp.
now = datetime.utcnow().timestamp()
now = time.utcnow()
if not self.SubmittedTS:
self.SubmittedTS = now
if not self.ModifiedTS:
......
import typing
from datetime import datetime
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import backref, relationship
from aurweb import schema
from aurweb import schema, time
from aurweb.models.declarative import Base
from aurweb.models.user import User as _User
......@@ -71,7 +69,7 @@ class TUVoteInfo(Base):
return attr
def is_running(self):
return self.End > int(datetime.utcnow().timestamp())
return self.End > time.utcnow()
def total_votes(self):
return self.Yes + self.No + self.Abstain
import hashlib
from datetime import datetime
from typing import List, Set
import bcrypt
......@@ -14,7 +13,7 @@ import aurweb.config
import aurweb.models.account_type
import aurweb.schema
from aurweb import db, logging, schema, util
from aurweb import db, logging, schema, time, util
from aurweb.models.account_type import AccountType as _AccountType
from aurweb.models.ban import is_banned
from aurweb.models.declarative import Base
......@@ -121,7 +120,7 @@ class User(Base):
exc = None
for i in range(tries):
exc = None
now_ts = datetime.utcnow().timestamp()
now_ts = time.utcnow()
try:
with db.begin():
self.LastLogin = now_ts
......
from datetime import datetime
from typing import List, Optional, Set
from fastapi import Request
from sqlalchemy import and_, orm
from aurweb import config, db, l10n, util
from aurweb import config, db, l10n, time, util
from aurweb.exceptions import InvariantError
from aurweb.models import PackageBase, PackageRequest, User
from aurweb.models.package_request import ACCEPTED_ID, PENDING_ID, REJECTED_ID
......@@ -106,7 +105,7 @@ def verify_orphan_request(user: User, pkgbase: PackageBase):
PackageRequest.ReqTypeID == ORPHAN_ID)
for pkgreq in requests:
idle_time = config.getint("options", "request_idle_time")
time_delta = int(datetime.utcnow().timestamp()) - pkgreq.RequestTS
time_delta = time.utcnow() - pkgreq.RequestTS
is_due = pkgreq.Status == PENDING_ID and time_delta > idle_time
if is_due:
# If the requester is the pkgbase maintainer or the
......@@ -128,7 +127,7 @@ def close_pkgreq(pkgreq: PackageRequest, closer: User,
:param target: Optional PackageBase instance to merge into
:param status: `pkgreq`.Status value to update to
"""
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
pkgreq.Status = status
pkgreq.Closer = closer
pkgreq.ClosureComment = (
......
from datetime import datetime
from fastapi import Request
from redis.client import Pipeline
from aurweb import config, db, logging
from aurweb import config, db, logging, time
from aurweb.models import ApiRateLimit
from aurweb.redis import redis_connection
......@@ -12,7 +10,7 @@ logger = logging.get_logger(__name__)
def _update_ratelimit_redis(request: Request, pipeline: Pipeline):
window_length = config.getint("ratelimit", "window_length")
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
time_to_delete = now - window_length
host = request.client.host
......@@ -37,7 +35,7 @@ def _update_ratelimit_redis(request: Request, pipeline: Pipeline):
def _update_ratelimit_db(request: Request):
window_length = config.getint("ratelimit", "window_length")
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
time_to_delete = now - window_length
records = db.query(ApiRateLimit).filter(
......
from datetime import datetime
from http import HTTPStatus
from fastapi import APIRouter, Form, HTTPException, Request
......@@ -6,7 +5,7 @@ from fastapi.responses import HTMLResponse, RedirectResponse
import aurweb.config
from aurweb import cookies, db
from aurweb import cookies, db, time
from aurweb.auth import requires_auth, requires_guest
from aurweb.l10n import get_translator_for_request
from aurweb.models import User
......@@ -57,8 +56,7 @@ async def login_post(request: Request,
login_timeout = aurweb.config.getint("options", "login_timeout")
expires_at = int(datetime.utcnow().timestamp()
+ max(cookie_timeout, login_timeout))
expires_at = int(time.utcnow() + max(cookie_timeout, login_timeout))
response = RedirectResponse(url=next,
status_code=HTTPStatus.SEE_OTHER)
......
......@@ -3,7 +3,6 @@ decorators in some way; more complex routes should be defined in their
own modules and imported here. """
import os
from datetime import datetime
from http import HTTPStatus
from fastapi import APIRouter, Form, HTTPException, Request, Response
......@@ -14,7 +13,7 @@ from sqlalchemy import and_, case, or_
import aurweb.config
import aurweb.models.package_request
from aurweb import cookies, db, models, util
from aurweb import cookies, db, models, time, util
from aurweb.cache import db_count_cache
from aurweb.models.account_type import TRUSTED_USER_AND_DEV_ID, TRUSTED_USER_ID
from aurweb.models.package_request import PENDING_ID
......@@ -97,7 +96,7 @@ async def index(request: Request):
redis, "trusted_user_count", query, expire=cache_expire)
# Current timestamp.
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
seven_days = 86400 * 7 # Seven days worth of seconds.
seven_days_ago = now - seven_days
......
from datetime import datetime
from http import HTTPStatus
from fastapi import APIRouter, Form, HTTPException, Query, Request, Response
from fastapi.responses import JSONResponse, RedirectResponse
from sqlalchemy import and_
from aurweb import config, db, l10n, logging, templates, util
from aurweb import config, db, l10n, logging, templates, time, util
from aurweb.auth import creds, requires_auth
from aurweb.exceptions import InvariantError, ValidationError
from aurweb.models import PackageBase
......@@ -146,7 +145,7 @@ async def pkgbase_flag_post(request: Request, name: str,
has_cred = request.user.has_credential(creds.PKGBASE_FLAG)
if has_cred and not pkgbase.Flagger:
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
with db.begin():
pkgbase.OutOfDateTS = now
pkgbase.Flagger = request.user
......@@ -170,7 +169,7 @@ async def pkgbase_comments_post(
# If the provided comment is different than the record's version,
# update the db record.
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
with db.begin():
comment = db.create(PackageComment, User=request.user,
PackageBase=pkgbase,
......@@ -268,7 +267,7 @@ async def pkgbase_comment_post(
# If the provided comment is different than the record's version,
# update the db record.
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
if db_comment.Comments != comment:
with db.begin():
db_comment.Comments = comment
......@@ -316,7 +315,7 @@ async def pkgbase_comment_pin(request: Request, name: str, id: int,
status_code=HTTPStatus.UNAUTHORIZED,
detail=_("You are not allowed to pin this comment."))
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
with db.begin():
comment.PinnedTS = now
......@@ -387,7 +386,7 @@ async def pkgbase_comment_delete(request: Request, name: str, id: int,
status_code=HTTPStatus.UNAUTHORIZED,
detail=_("You are not allowed to delete this comment."))
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
with db.begin():
comment.Deleter = request.user
comment.DelTS = now
......@@ -446,7 +445,7 @@ async def pkgbase_vote(request: Request, name: str):
).first()
has_cred = request.user.has_credential(creds.PKGBASE_VOTE)
if has_cred and not vote:
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
with db.begin():
db.create(PackageVote,
User=request.user,
......@@ -683,7 +682,7 @@ async def pkgbase_request_post(request: Request, name: str,
return render_template(request, "pkgbase/request.html", context)
# All good. Create a new PackageRequest based on the given type.
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
with db.begin():
pkgreq = db.create(PackageRequest,
ReqTypeID=types.get(type),
......
from datetime import datetime
from http import HTTPStatus
from fastapi import APIRouter, Form, Query, Request
from fastapi.responses import RedirectResponse
from sqlalchemy import case
from aurweb import db, defaults, util
from aurweb import db, defaults, time, util
from aurweb.auth import creds, requires_auth
from aurweb.models import PackageRequest, User
from aurweb.models.package_request import PENDING_ID, REJECTED_ID
......@@ -78,7 +77,7 @@ async def request_close_post(request: Request, id: int,
context = make_context(request, "Close Request")
context["pkgreq"] = pkgreq
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
with db.begin():
pkgreq.Closer = request.user
pkgreq.ClosureComment = comments
......
......@@ -2,14 +2,13 @@ import html
import re
import typing
from datetime import datetime
from http import HTTPStatus
from fastapi import APIRouter, Form, HTTPException, Request
from fastapi.responses import RedirectResponse, Response
from sqlalchemy import and_, or_
from aurweb import db, l10n, logging, models
from aurweb import db, l10n, logging, models, time
from aurweb.auth import creds, requires_auth
from aurweb.models import User
from aurweb.models.account_type import TRUSTED_USER_AND_DEV_ID, TRUSTED_USER_ID
......@@ -52,7 +51,7 @@ async def trusted_user(request: Request,
context["pp"] = pp = ITEMS_PER_PAGE
context["prev_len"] = MAX_AGENDA_LENGTH
ts = int(datetime.utcnow().timestamp())
ts = time.utcnow()
if current_by not in {"asc", "desc"}:
# If a malicious by was given, default to desc.
......@@ -290,7 +289,7 @@ async def trusted_user_addvote_post(request: Request,
# Gather some mapped constants and the current timestamp.
duration, quorum = ADDVOTE_SPECIFICS.get(type)
timestamp = int(datetime.utcnow().timestamp())
timestamp = time.utcnow()
# TODO: Review this. Is this even necessary?
# Remove <script> and <style> tags.
......
#!/usr/bin/env python3
from datetime import datetime
from sqlalchemy import and_
from aurweb import db
from aurweb import db, time
from aurweb.models import PackageBase
def _main():
# One day behind.
limit_to = int(datetime.utcnow().timestamp()) - 86400
limit_to = time.utcnow() - 86400
query = db.query(PackageBase).filter(
and_(PackageBase.SubmittedTS < limit_to,
......
#!/usr/bin/env python3
from datetime import datetime
from typing import List
from sqlalchemy import and_, func
from sqlalchemy.sql.functions import coalesce
from sqlalchemy.sql.functions import sum as _sum
from aurweb import db
from aurweb import db, time
from aurweb.models import PackageBase, PackageVote
......@@ -20,7 +19,7 @@ def run_variable(pkgbases: List[PackageBase] = []) -> None:
:param pkgbases: List of PackageBase instances
"""
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
# NumVotes subquery.
votes_subq = db.get_session().query(
......
#!/usr/bin/env python3
from datetime import datetime
from sqlalchemy import and_
import aurweb.config
from aurweb import db
from aurweb import db, time
from aurweb.models import TUVoteInfo
from aurweb.scripts import notify
......@@ -16,7 +14,7 @@ notify_cmd = aurweb.config.get('notifications', 'notify-cmd')
def main():
db.get_engine()
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
start = aurweb.config.getint("tuvotereminder", "range_start")
filter_from = now + start
......
#!/usr/bin/env python3
from datetime import datetime
from sqlalchemy import update
from aurweb import db
from aurweb import db, time
from aurweb.models import User
def _main():
limit_to = int(datetime.utcnow().timestamp()) - 86400 * 7
limit_to = time.utcnow() - 86400 * 7
update_ = update(User).where(
User.LastLogin < limit_to
......
import copy
import functools
import os
import zoneinfo
from datetime import datetime
from http import HTTPStatus
from typing import Callable
......@@ -80,8 +78,8 @@ def make_context(request: Request, title: str, next: str = None):
"timezone": timezone,
"timezones": time.SUPPORTED_TIMEZONES,
"title": title,
"now": datetime.now(tz=zoneinfo.ZoneInfo(timezone)),
"utcnow": int(datetime.utcnow().timestamp()),
"now": time.now(timezone),
"utcnow": time.utcnow(),
"config": aurweb.config,
"creds": aurweb.auth.creds,
"next": next if next else request.url.path,
......
......@@ -3,6 +3,7 @@ import zoneinfo
from collections import OrderedDict
from datetime import datetime
from urllib.parse import unquote
from zoneinfo import ZoneInfo
from fastapi import Request
......@@ -62,3 +63,22 @@ def get_request_timezone(request: Request):
if request.user.is_authenticated():
default_tz = request.user.Timezone
return unquote(request.cookies.get("AURTZ", default_tz))
def now(timezone: str) -> datetime:
"""
Get the current timezone-localized timestamp.
:param timezone: Valid timezone supported by ZoneInfo
:return: Current localized datetime
"""
return datetime.now(tz=ZoneInfo(timezone))
def utcnow() -> int:
"""
Get the current UTC timestamp.
:return: Current UTC timestamp
"""
return int(datetime.utcnow().timestamp())
from datetime import datetime
from typing import Any, Dict
from fastapi import Request
from aurweb import cookies, db, models
from aurweb import cookies, db, models, time
from aurweb.models.ssh_pub_key import get_fingerprint
from aurweb.util import strtobool
......@@ -14,7 +13,7 @@ def simple(U: str = str(), E: str = str(), H: bool = False,
CN: bool = False, UN: bool = False, ON: bool = False,
S: bool = False, user: models.User = None,
**kwargs) -> None:
now = int(datetime.utcnow().timestamp())
now = time.utcnow()
with db.begin():
user.Username = U or user.Username
user.Email = E or user.Email
......
......@@ -13,7 +13,7 @@ from fastapi.testclient import TestClient
import aurweb.models.account_type as at
from aurweb import captcha, db, logging
from aurweb import captcha, db, logging, time
from aurweb.asgi import app
from aurweb.db import create, query
from aurweb.models.accepted_term import AcceptedTerm
......@@ -155,7 +155,7 @@ def test_post_passreset_user(client: TestClient, user: User):
def test_post_passreset_resetkey(client: TestClient, user: User):
with db.begin():
user.session = Session(UsersID=user.ID, SessionID="blah",
LastUpdateTS=datetime.utcnow().timestamp())
LastUpdateTS=time.utcnow())
# Prepare a password reset.
with client as request:
......
from datetime import datetime
import fastapi
import pytest
from fastapi import HTTPException
from sqlalchemy.exc import IntegrityError
from aurweb import config, db
from aurweb import config, db, time
from aurweb.auth import AnonymousUser, BasicAuthBackend, _auth_required, account_type_required
from aurweb.models.account_type import USER, USER_ID
from aurweb.models.session import Session
......@@ -55,7 +53,7 @@ async def test_auth_backend_invalid_sid(backend: BasicAuthBackend):
@pytest.mark.asyncio
async def test_auth_backend_invalid_user_id():
# Create a new session with a fake user id.
now_ts = datetime.utcnow().timestamp()
now_ts = time.utcnow()
with pytest.raises(IntegrityError):
Session(UsersID=666, SessionID="realSession",
LastUpdateTS=now_ts + 5)
......@@ -65,7 +63,7 @@ async def test_auth_backend_invalid_user_id():
async def test_basic_auth_backend(user: User, backend: BasicAuthBackend):
# This time, everything matches up. We expect the user to
# equal the real_user.
now_ts = datetime.utcnow().timestamp()
now_ts = time.utcnow()
with db.begin():
db.create(Session, UsersID=user.ID, SessionID="realSession",
LastUpdateTS=now_ts + 5)
......@@ -87,7 +85,7 @@ async def test_expired_session(backend: BasicAuthBackend, user: User):
# Set Session.LastUpdateTS to 20 seconds expired.
timeout = config.getint("options", "login_timeout")
now_ts = int(datetime.utcnow().timestamp())
now_ts = time.utcnow()
with db.begin():
request.user.session.LastUpdateTS = now_ts - timeout - 20
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment