Compare commits

..

No commits in common. "master" and "v6.2.7" have entirely different histories.

207 changed files with 4485 additions and 8155 deletions

View file

@ -1,5 +1,5 @@
# EditorConfig configuration for aurweb # EditorConfig configuration for aurweb
# https://editorconfig.org # https://EditorConfig.org
# Top-most EditorConfig file # Top-most EditorConfig file
root = true root = true

4
.gitignore vendored
View file

@ -57,7 +57,3 @@ test-emails/
env/ env/
venv/ venv/
.venv/ .venv/
# Ignore some terraform files
/ci/tf/.terraform
/ci/tf/terraform.tfstate*

View file

@ -13,22 +13,24 @@ variables:
TEST_RECURSION_LIMIT: 10000 TEST_RECURSION_LIMIT: 10000
CURRENT_DIR: "$(pwd)" CURRENT_DIR: "$(pwd)"
LOG_CONFIG: logging.test.conf LOG_CONFIG: logging.test.conf
DEV_FQDN: aurweb-$CI_COMMIT_REF_SLUG.sandbox.archlinux.page
INFRASTRUCTURE_REPO: https://gitlab.archlinux.org/archlinux/infrastructure.git
lint: lint:
stage: .pre stage: .pre
before_script: before_script:
- pacman -Sy --noconfirm --noprogressbar - pacman -Sy --noconfirm --noprogressbar --cachedir .pkg-cache
archlinux-keyring archlinux-keyring
- pacman -Syu --noconfirm --noprogressbar - pacman -Syu --noconfirm --noprogressbar --cachedir .pkg-cache
git python python-pre-commit git python python-pre-commit
script: script:
# https://github.com/pre-commit/pre-commit/issues/2178#issuecomment-1002163763
- export SETUPTOOLS_USE_DISTUTILS=stdlib
- export XDG_CACHE_HOME=.pre-commit - export XDG_CACHE_HOME=.pre-commit
- pre-commit run -a - pre-commit run -a
test: test:
stage: test stage: test
tags:
- fast-single-thread
before_script: before_script:
- export PATH="$HOME/.poetry/bin:${PATH}" - export PATH="$HOME/.poetry/bin:${PATH}"
- ./docker/scripts/install-deps.sh - ./docker/scripts/install-deps.sh
@ -59,103 +61,34 @@ test:
coverage_format: cobertura coverage_format: cobertura
path: coverage.xml path: coverage.xml
.init_tf: &init_tf deploy:
- pacman -Syu --needed --noconfirm terraform
- export TF_VAR_name="aurweb-${CI_COMMIT_REF_SLUG}"
- TF_ADDRESS="${CI_API_V4_URL}/projects/${TF_STATE_PROJECT}/terraform/state/${CI_COMMIT_REF_SLUG}"
- cd ci/tf
- >
terraform init \
-backend-config="address=${TF_ADDRESS}" \
-backend-config="lock_address=${TF_ADDRESS}/lock" \
-backend-config="unlock_address=${TF_ADDRESS}/lock" \
-backend-config="username=x-access-token" \
-backend-config="password=${TF_STATE_GITLAB_ACCESS_TOKEN}" \
-backend-config="lock_method=POST" \
-backend-config="unlock_method=DELETE" \
-backend-config="retry_wait_min=5"
deploy_review:
stage: deploy stage: deploy
script: tags:
- *init_tf - secure
- terraform apply -auto-approve
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://$DEV_FQDN
on_stop: stop_review
auto_stop_in: 1 week
rules: rules:
- if: $CI_COMMIT_REF_NAME =~ /^renovate\// - if: $CI_COMMIT_BRANCH == "pu"
when: never
- if: $CI_MERGE_REQUEST_ID && $CI_PROJECT_PATH == "archlinux/aurweb"
when: manual when: manual
variables:
provision_review: FASTAPI_BACKEND: gunicorn
stage: deploy FASTAPI_WORKERS: 5
needs: AURWEB_FASTAPI_PREFIX: https://aur-dev.archlinux.org
- deploy_review AURWEB_SSHD_PREFIX: ssh://aur@aur-dev.archlinux.org:2222
COMMIT_HASH: $CI_COMMIT_SHA
GIT_DATA_DIR: git_data
script: script:
- *init_tf - pacman -Syu --noconfirm docker docker-compose socat openssh
- pacman -Syu --noconfirm --needed ansible git openssh jq - chmod 600 ${SSH_KEY}
# Get ssh key from terraform state file - socat "UNIX-LISTEN:/tmp/docker.sock,reuseaddr,fork" EXEC:"ssh -o UserKnownHostsFile=${SSH_KNOWN_HOSTS} -Ti ${SSH_KEY} ${SSH_USER}@${SSH_HOST}" &
- mkdir -p ~/.ssh - export DOCKER_HOST="unix:///tmp/docker.sock"
- chmod 700 ~/.ssh # Set secure login config for aurweb.
- terraform show -json | - sed -ri "s/^(disable_http_login).*$/\1 = 1/" conf/config.dev
jq -r '.values.root_module.resources[] | - docker-compose build
select(.address == "tls_private_key.this") | - docker-compose -f docker-compose.yml -f docker-compose.aur-dev.yml down --remove-orphans
.values.private_key_openssh' > ~/.ssh/id_ed25519 - docker-compose -f docker-compose.yml -f docker-compose.aur-dev.yml up -d
- chmod 400 ~/.ssh/id_ed25519 - docker image prune -f
# Clone infra repo - docker container prune -f
- git clone $INFRASTRUCTURE_REPO - docker volume prune -f
- cd infrastructure
# Remove vault files
- rm $(git grep -l 'ANSIBLE_VAULT;1.1;AES256$')
# Remove vault config
- sed -i '/^vault/d' ansible.cfg
# Add host config
- mkdir -p host_vars/$DEV_FQDN
- 'echo "filesystem: btrfs" > host_vars/$DEV_FQDN/misc'
# Add host
- echo "$DEV_FQDN" > hosts
# Add our pubkey and hostkeys
- ssh-keyscan $DEV_FQDN >> ~/.ssh/known_hosts
- ssh-keygen -f ~/.ssh/id_ed25519 -y > pubkeys/aurweb-dev.pub
# Run our ansible playbook
- >
ansible-playbook playbooks/aur-dev.archlinux.org.yml \
-e "aurdev_fqdn=$DEV_FQDN" \
-e "aurweb_repository=$CI_REPOSITORY_URL" \
-e "aurweb_version=$CI_COMMIT_SHA" \
-e "{\"vault_mariadb_users\":{\"root\":\"aur\"}}" \
-e "vault_aurweb_db_password=aur" \
-e "vault_aurweb_gitlab_instance=https://does.not.exist" \
-e "vault_aurweb_error_project=set-me" \
-e "vault_aurweb_error_token=set-me" \
-e "vault_aurweb_secret=aur" \
-e "vault_goaurrpc_metrics_token=aur" \
-e '{"root_additional_keys": ["moson.pub", "aurweb-dev.pub"]}'
environment:
name: review/$CI_COMMIT_REF_NAME
action: access
rules:
- if: $CI_COMMIT_REF_NAME =~ /^renovate\//
when: never
- if: $CI_MERGE_REQUEST_ID && $CI_PROJECT_PATH == "archlinux/aurweb"
stop_review:
stage: deploy
needs:
- deploy_review
script:
- *init_tf
- terraform destroy -auto-approve
- 'curl --silent --show-error --fail --header "Private-Token: ${TF_STATE_GITLAB_ACCESS_TOKEN}" --request DELETE "${CI_API_V4_URL}/projects/${TF_STATE_PROJECT}/terraform/state/${CI_COMMIT_REF_SLUG}"'
environment: environment:
name: review/$CI_COMMIT_REF_NAME name: development
action: stop url: https://aur-dev.archlinux.org
rules:
- if: $CI_COMMIT_REF_NAME =~ /^renovate\//
when: never
- if: $CI_MERGE_REQUEST_ID && $CI_PROJECT_PATH == "archlinux/aurweb"
when: manual

View file

@ -1,6 +1,6 @@
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0 rev: v4.4.0
hooks: hooks:
- id: check-added-large-files - id: check-added-large-files
- id: check-case-conflict - id: check-case-conflict
@ -12,7 +12,7 @@ repos:
- id: debug-statements - id: debug-statements
- repo: https://github.com/myint/autoflake - repo: https://github.com/myint/autoflake
rev: v2.3.1 rev: v2.0.1
hooks: hooks:
- id: autoflake - id: autoflake
args: args:
@ -21,16 +21,16 @@ repos:
- --ignore-init-module-imports - --ignore-init-module-imports
- repo: https://github.com/pycqa/isort - repo: https://github.com/pycqa/isort
rev: 5.13.2 rev: 5.12.0
hooks: hooks:
- id: isort - id: isort
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 24.4.1 rev: 23.1.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/PyCQA/flake8 - repo: https://github.com/PyCQA/flake8
rev: 7.0.0 rev: 6.0.0
hooks: hooks:
- id: flake8 - id: flake8

View file

@ -1,5 +1,5 @@
[main] [main]
host = https://app.transifex.com host = https://www.transifex.com
[o:lfleischer:p:aurweb:r:aurwebpot] [o:lfleischer:p:aurweb:r:aurwebpot]
file_filter = po/<lang>.po file_filter = po/<lang>.po

View file

@ -30,6 +30,11 @@ read the instructions below.
ssl_certificate /etc/ssl/certs/aur.cert.pem; ssl_certificate /etc/ssl/certs/aur.cert.pem;
ssl_certificate_key /etc/ssl/private/aur.key.pem; ssl_certificate_key /etc/ssl/private/aur.key.pem;
# TU Bylaws redirect.
location = /trusted-user/TUbylaws.html {
return 301 https://tu-bylaws.aur.archlinux.org;
}
# smartgit location. # smartgit location.
location ~ "^/([a-z0-9][a-z0-9.+_-]*?)(\.git)?/(git-(receive|upload)-pack|HEAD|info/refs|objects/(info/(http-)?alternates|packs)|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))$" { location ~ "^/([a-z0-9][a-z0-9.+_-]*?)(\.git)?/(git-(receive|upload)-pack|HEAD|info/refs|objects/(info/(http-)?alternates|packs)|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))$" {
include uwsgi_params; include uwsgi_params;
@ -120,7 +125,7 @@ interval:
*/2 * * * * bash -c 'poetry run aurweb-pkgmaint' */2 * * * * bash -c 'poetry run aurweb-pkgmaint'
*/2 * * * * bash -c 'poetry run aurweb-usermaint' */2 * * * * bash -c 'poetry run aurweb-usermaint'
*/2 * * * * bash -c 'poetry run aurweb-popupdate' */2 * * * * bash -c 'poetry run aurweb-popupdate'
*/12 * * * * bash -c 'poetry run aurweb-votereminder' */12 * * * * bash -c 'poetry run aurweb-tuvotereminder'
7) Create a new database and a user and import the aurweb SQL schema: 7) Create a new database and a user and import the aurweb SQL schema:

View file

@ -11,8 +11,8 @@ The aurweb project includes
* A web interface to search for packaging scripts and display package details. * A web interface to search for packaging scripts and display package details.
* An SSH/Git interface to submit and update packages and package meta data. * An SSH/Git interface to submit and update packages and package meta data.
* Community features such as comments, votes, package flagging and requests. * Community features such as comments, votes, package flagging and requests.
* Editing/deletion of packages and accounts by Package Maintainers and Developers. * Editing/deletion of packages and accounts by Trusted Users and Developers.
* Area for Package Maintainers to post AUR-related proposals and vote on them. * Area for Trusted Users to post AUR-related proposals and vote on them.
Directory Layout Directory Layout
---------------- ----------------
@ -56,7 +56,7 @@ Translations
------------ ------------
Translations are welcome via our Transifex project at Translations are welcome via our Transifex project at
https://www.transifex.com/lfleischer/aurweb; see [doc/i18n.md](./doc/i18n.md) for details. https://www.transifex.com/lfleischer/aurweb; see `doc/i18n.txt` for details.
![Transifex](https://www.transifex.com/projects/p/aurweb/chart/image_png) ![Transifex](https://www.transifex.com/projects/p/aurweb/chart/image_png)

View file

@ -6,7 +6,6 @@ import re
import sys import sys
import traceback import traceback
import typing import typing
from contextlib import asynccontextmanager
from urllib.parse import quote_plus from urllib.parse import quote_plus
import requests import requests
@ -14,12 +13,7 @@ from fastapi import FastAPI, HTTPException, Request, Response
from fastapi.responses import RedirectResponse from fastapi.responses import RedirectResponse
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from jinja2 import TemplateNotFound from jinja2 import TemplateNotFound
from opentelemetry import trace from prometheus_client import multiprocess
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from sqlalchemy import and_ from sqlalchemy import and_
from starlette.exceptions import HTTPException as StarletteHTTPException from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.middleware.authentication import AuthenticationMiddleware from starlette.middleware.authentication import AuthenticationMiddleware
@ -28,6 +22,7 @@ from starlette.middleware.sessions import SessionMiddleware
import aurweb.captcha # noqa: F401 import aurweb.captcha # noqa: F401
import aurweb.config import aurweb.config
import aurweb.filters # noqa: F401 import aurweb.filters # noqa: F401
import aurweb.pkgbase.util as pkgbaseutil
from aurweb import aur_logging, prometheus, util from aurweb import aur_logging, prometheus, util
from aurweb.aur_redis import redis_connection from aurweb.aur_redis import redis_connection
from aurweb.auth import BasicAuthBackend from aurweb.auth import BasicAuthBackend
@ -39,18 +34,11 @@ from aurweb.routers import APP_ROUTES
from aurweb.templates import make_context, render_template from aurweb.templates import make_context, render_template
logger = aur_logging.get_logger(__name__) logger = aur_logging.get_logger(__name__)
session_secret = aurweb.config.get("fastapi", "session_secret")
@asynccontextmanager
async def lifespan(app: FastAPI):
await app_startup()
yield
# Setup the FastAPI app. # Setup the FastAPI app.
app = FastAPI(lifespan=lifespan) app = FastAPI()
session_secret = aurweb.config.get("fastapi", "session_secret")
# Instrument routes with the prometheus-fastapi-instrumentator # Instrument routes with the prometheus-fastapi-instrumentator
# library with custom collectors and expose /metrics. # library with custom collectors and expose /metrics.
@ -59,17 +47,7 @@ instrumentator().add(prometheus.http_requests_total())
instrumentator().instrument(app) instrumentator().instrument(app)
# Instrument FastAPI for tracing @app.on_event("startup")
FastAPIInstrumentor.instrument_app(app)
resource = Resource(attributes={"service.name": "aurweb"})
otlp_endpoint = aurweb.config.get("tracing", "otlp_endpoint")
otlp_exporter = OTLPSpanExporter(endpoint=otlp_endpoint)
span_processor = BatchSpanProcessor(otlp_exporter)
trace.set_tracer_provider(TracerProvider(resource=resource))
trace.get_tracer_provider().add_span_processor(span_processor)
async def app_startup(): async def app_startup():
# https://stackoverflow.com/questions/67054759/about-the-maximum-recursion-error-in-fastapi # https://stackoverflow.com/questions/67054759/about-the-maximum-recursion-error-in-fastapi
# Test failures have been observed by internal starlette code when # Test failures have been observed by internal starlette code when
@ -113,6 +91,12 @@ async def app_startup():
get_engine() get_engine()
def child_exit(server, worker): # pragma: no cover
"""This function is required for gunicorn customization
of prometheus multiprocessing."""
multiprocess.mark_process_dead(worker.pid)
async def internal_server_error(request: Request, exc: Exception) -> Response: async def internal_server_error(request: Request, exc: Exception) -> Response:
""" """
Catch all uncaught Exceptions thrown in a route. Catch all uncaught Exceptions thrown in a route.
@ -228,16 +212,10 @@ async def http_exception_handler(request: Request, exc: HTTPException) -> Respon
if exc.status_code == http.HTTPStatus.NOT_FOUND: if exc.status_code == http.HTTPStatus.NOT_FOUND:
tokens = request.url.path.split("/") tokens = request.url.path.split("/")
matches = re.match("^([a-z0-9][a-z0-9.+_-]*?)(\\.git)?$", tokens[1]) matches = re.match("^([a-z0-9][a-z0-9.+_-]*?)(\\.git)?$", tokens[1])
if matches and len(tokens) == 2: if matches:
try: try:
pkgbase = get_pkg_or_base(matches.group(1)) pkgbase = get_pkg_or_base(matches.group(1))
context["pkgbase"] = pkgbase context = pkgbaseutil.make_context(request, pkgbase)
context["git_clone_uri_anon"] = aurweb.config.get(
"options", "git_clone_uri_anon"
)
context["git_clone_uri_priv"] = aurweb.config.get(
"options", "git_clone_uri_priv"
)
except HTTPException: except HTTPException:
pass pass

View file

@ -1,5 +1,4 @@
import fakeredis import fakeredis
from opentelemetry.instrumentation.redis import RedisInstrumentor
from redis import ConnectionPool, Redis from redis import ConnectionPool, Redis
import aurweb.config import aurweb.config
@ -8,8 +7,6 @@ from aurweb import aur_logging
logger = aur_logging.get_logger(__name__) logger = aur_logging.get_logger(__name__)
pool = None pool = None
RedisInstrumentor().instrument()
class FakeConnectionPool: class FakeConnectionPool:
"""A fake ConnectionPool class which holds an internal reference """A fake ConnectionPool class which holds an internal reference

View file

@ -71,7 +71,7 @@ class AnonymousUser:
return False return False
@staticmethod @staticmethod
def is_package_maintainer(): def is_trusted_user():
return False return False
@staticmethod @staticmethod
@ -205,7 +205,7 @@ def account_type_required(one_of: set):
@router.get('/some_route') @router.get('/some_route')
@auth_required(True) @auth_required(True)
@account_type_required({"Package Maintainer", "Package Maintainer & Developer"}) @account_type_required({"Trusted User", "Trusted User & Developer"})
async def some_route(request: fastapi.Request): async def some_route(request: fastapi.Request):
return Response() return Response()

View file

@ -1,7 +1,7 @@
from aurweb.models.account_type import ( from aurweb.models.account_type import (
DEVELOPER_ID, DEVELOPER_ID,
PACKAGE_MAINTAINER_AND_DEV_ID, TRUSTED_USER_AND_DEV_ID,
PACKAGE_MAINTAINER_ID, TRUSTED_USER_ID,
USER_ID, USER_ID,
) )
from aurweb.models.user import User from aurweb.models.user import User
@ -30,49 +30,47 @@ PKGBASE_VOTE = 16
PKGREQ_FILE = 23 PKGREQ_FILE = 23
PKGREQ_CLOSE = 17 PKGREQ_CLOSE = 17
PKGREQ_LIST = 18 PKGREQ_LIST = 18
PM_ADD_VOTE = 19 TU_ADD_VOTE = 19
PM_LIST_VOTES = 20 TU_LIST_VOTES = 20
PM_VOTE = 21 TU_VOTE = 21
PKGBASE_MERGE = 29 PKGBASE_MERGE = 29
user_developer_or_package_maintainer = set( user_developer_or_trusted_user = set(
[USER_ID, PACKAGE_MAINTAINER_ID, DEVELOPER_ID, PACKAGE_MAINTAINER_AND_DEV_ID] [USER_ID, TRUSTED_USER_ID, DEVELOPER_ID, TRUSTED_USER_AND_DEV_ID]
) )
package_maintainer_or_dev = set( trusted_user_or_dev = set([TRUSTED_USER_ID, DEVELOPER_ID, TRUSTED_USER_AND_DEV_ID])
[PACKAGE_MAINTAINER_ID, DEVELOPER_ID, PACKAGE_MAINTAINER_AND_DEV_ID] developer = set([DEVELOPER_ID, TRUSTED_USER_AND_DEV_ID])
) trusted_user = set([TRUSTED_USER_ID, TRUSTED_USER_AND_DEV_ID])
developer = set([DEVELOPER_ID, PACKAGE_MAINTAINER_AND_DEV_ID])
package_maintainer = set([PACKAGE_MAINTAINER_ID, PACKAGE_MAINTAINER_AND_DEV_ID])
cred_filters = { cred_filters = {
PKGBASE_FLAG: user_developer_or_package_maintainer, PKGBASE_FLAG: user_developer_or_trusted_user,
PKGBASE_NOTIFY: user_developer_or_package_maintainer, PKGBASE_NOTIFY: user_developer_or_trusted_user,
PKGBASE_VOTE: user_developer_or_package_maintainer, PKGBASE_VOTE: user_developer_or_trusted_user,
PKGREQ_FILE: user_developer_or_package_maintainer, PKGREQ_FILE: user_developer_or_trusted_user,
ACCOUNT_CHANGE_TYPE: package_maintainer_or_dev, ACCOUNT_CHANGE_TYPE: trusted_user_or_dev,
ACCOUNT_EDIT: package_maintainer_or_dev, ACCOUNT_EDIT: trusted_user_or_dev,
ACCOUNT_LAST_LOGIN: package_maintainer_or_dev, ACCOUNT_LAST_LOGIN: trusted_user_or_dev,
ACCOUNT_LIST_COMMENTS: package_maintainer_or_dev, ACCOUNT_LIST_COMMENTS: trusted_user_or_dev,
ACCOUNT_SEARCH: package_maintainer_or_dev, ACCOUNT_SEARCH: trusted_user_or_dev,
COMMENT_DELETE: package_maintainer_or_dev, COMMENT_DELETE: trusted_user_or_dev,
COMMENT_UNDELETE: package_maintainer_or_dev, COMMENT_UNDELETE: trusted_user_or_dev,
COMMENT_VIEW_DELETED: package_maintainer_or_dev, COMMENT_VIEW_DELETED: trusted_user_or_dev,
COMMENT_EDIT: package_maintainer_or_dev, COMMENT_EDIT: trusted_user_or_dev,
COMMENT_PIN: package_maintainer_or_dev, COMMENT_PIN: trusted_user_or_dev,
PKGBASE_ADOPT: package_maintainer_or_dev, PKGBASE_ADOPT: trusted_user_or_dev,
PKGBASE_SET_KEYWORDS: package_maintainer_or_dev, PKGBASE_SET_KEYWORDS: trusted_user_or_dev,
PKGBASE_DELETE: package_maintainer_or_dev, PKGBASE_DELETE: trusted_user_or_dev,
PKGBASE_EDIT_COMAINTAINERS: package_maintainer_or_dev, PKGBASE_EDIT_COMAINTAINERS: trusted_user_or_dev,
PKGBASE_DISOWN: package_maintainer_or_dev, PKGBASE_DISOWN: trusted_user_or_dev,
PKGBASE_LIST_VOTERS: package_maintainer_or_dev, PKGBASE_LIST_VOTERS: trusted_user_or_dev,
PKGBASE_UNFLAG: package_maintainer_or_dev, PKGBASE_UNFLAG: trusted_user_or_dev,
PKGREQ_CLOSE: package_maintainer_or_dev, PKGREQ_CLOSE: trusted_user_or_dev,
PKGREQ_LIST: package_maintainer_or_dev, PKGREQ_LIST: trusted_user_or_dev,
PM_ADD_VOTE: package_maintainer, TU_ADD_VOTE: trusted_user,
PM_LIST_VOTES: package_maintainer_or_dev, TU_LIST_VOTES: trusted_user_or_dev,
PM_VOTE: package_maintainer, TU_VOTE: trusted_user,
ACCOUNT_EDIT_DEV: developer, ACCOUNT_EDIT_DEV: developer,
PKGBASE_MERGE: package_maintainer_or_dev, PKGBASE_MERGE: trusted_user_or_dev,
} }

View file

@ -1,4 +1,4 @@
from datetime import UTC, datetime from datetime import datetime
class Benchmark: class Benchmark:
@ -7,7 +7,7 @@ class Benchmark:
def _timestamp(self) -> float: def _timestamp(self) -> float:
"""Generate a timestamp.""" """Generate a timestamp."""
return float(datetime.now(UTC).timestamp()) return float(datetime.utcnow().timestamp())
def start(self) -> int: def start(self) -> int:
"""Start a benchmark.""" """Start a benchmark."""

View file

@ -1,5 +1,4 @@
import pickle import pickle
from typing import Any, Callable
from sqlalchemy import orm from sqlalchemy import orm
@ -10,22 +9,6 @@ from aurweb.prometheus import SEARCH_REQUESTS
_redis = redis_connection() _redis = redis_connection()
def lambda_cache(key: str, value: Callable[[], Any], expire: int = None) -> list:
"""Store and retrieve lambda results via redis cache.
:param key: Redis key
:param value: Lambda callable returning the value
:param expire: Optional expiration in seconds
:return: result of callable or cache
"""
result = _redis.get(key)
if result is not None:
return pickle.loads(result)
_redis.set(key, (pickle.dumps(result := value())), ex=expire)
return result
def db_count_cache(key: str, query: orm.Query, expire: int = None) -> int: def db_count_cache(key: str, query: orm.Query, expire: int = None) -> int:
"""Store and retrieve a query.count() via redis cache. """Store and retrieve a query.count() via redis cache.

View file

@ -1,9 +1,7 @@
""" This module consists of aurweb's CAPTCHA utility functions and filters. """ """ This module consists of aurweb's CAPTCHA utility functions and filters. """
import hashlib import hashlib
from jinja2 import pass_context from jinja2 import pass_context
from sqlalchemy import func
from aurweb.db import query from aurweb.db import query
from aurweb.models import User from aurweb.models import User
@ -12,8 +10,7 @@ from aurweb.templates import register_filter
def get_captcha_salts(): def get_captcha_salts():
"""Produce salts based on the current user count.""" """Produce salts based on the current user count."""
count = query(func.count(User.ID)).scalar() count = query(User).count()
salts = [] salts = []
for i in range(0, 6): for i in range(0, 6):
salts.append(f"aurweb-{count - i}") salts.append(f"aurweb-{count - i}")

View file

@ -298,12 +298,9 @@ def get_engine(dbname: str = None, echo: bool = False):
connect_args["check_same_thread"] = False connect_args["check_same_thread"] = False
kwargs = {"echo": echo, "connect_args": connect_args} kwargs = {"echo": echo, "connect_args": connect_args}
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from sqlalchemy import create_engine from sqlalchemy import create_engine
engine = create_engine(get_sqlalchemy_url(), **kwargs) _engines[dbname] = create_engine(get_sqlalchemy_url(), **kwargs)
SQLAlchemyInstrumentor().instrument(engine=engine)
_engines[dbname] = engine
if is_sqlite: # pragma: no cover if is_sqlite: # pragma: no cover
setup_sqlite(_engines.get(dbname)) setup_sqlite(_engines.get(dbname))

View file

@ -1,6 +1,6 @@
import copy import copy
import math import math
from datetime import UTC, datetime from datetime import datetime
from typing import Any, Union from typing import Any, Union
from urllib.parse import quote_plus, urlencode from urllib.parse import quote_plus, urlencode
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
@ -94,7 +94,7 @@ def tn(context: dict[str, Any], count: int, singular: str, plural: str) -> str:
@register_filter("dt") @register_filter("dt")
def timestamp_to_datetime(timestamp: int): def timestamp_to_datetime(timestamp: int):
return datetime.fromtimestamp(timestamp, UTC) return datetime.utcfromtimestamp(int(timestamp))
@register_filter("as_timezone") @register_filter("as_timezone")
@ -118,9 +118,9 @@ def to_qs(query: dict[str, Any]) -> str:
@register_filter("get_vote") @register_filter("get_vote")
def get_vote(voteinfo, request: fastapi.Request): def get_vote(voteinfo, request: fastapi.Request):
from aurweb.models import Vote from aurweb.models import TUVote
return voteinfo.votes.filter(Vote.User == request.user).first() return voteinfo.tu_votes.filter(TUVote.User == request.user).first()
@register_filter("number_format") @register_filter("number_format")

View file

@ -265,7 +265,7 @@ def pkgbase_disown(pkgbase, user, privileged):
conn = aurweb.db.Connection() conn = aurweb.db.Connection()
# Make the first co-maintainer the new maintainer, unless the action was # Make the first co-maintainer the new maintainer, unless the action was
# enforced by a Package Maintainer. # enforced by a Trusted User.
if initialized_by_owner: if initialized_by_owner:
comaintainers = pkgbase_get_comaintainers(pkgbase) comaintainers = pkgbase_get_comaintainers(pkgbase)
if len(comaintainers) > 0: if len(comaintainers) > 0:

View file

@ -440,8 +440,6 @@ def main(): # noqa: C901
cur = conn.execute("SELECT Name FROM PackageBlacklist") cur = conn.execute("SELECT Name FROM PackageBlacklist")
blacklist = [row[0] for row in cur.fetchall()] blacklist = [row[0] for row in cur.fetchall()]
if pkgbase in blacklist:
warn_or_die("pkgbase is blacklisted: {:s}".format(pkgbase))
cur = conn.execute("SELECT Name, Repo FROM OfficialProviders") cur = conn.execute("SELECT Name, Repo FROM OfficialProviders")
providers = dict(cur.fetchall()) providers = dict(cur.fetchall())

View file

@ -13,9 +13,9 @@ def feed_initial_data(conn):
aurweb.schema.AccountTypes.insert(), aurweb.schema.AccountTypes.insert(),
[ [
{"ID": 1, "AccountType": "User"}, {"ID": 1, "AccountType": "User"},
{"ID": 2, "AccountType": "Package Maintainer"}, {"ID": 2, "AccountType": "Trusted User"},
{"ID": 3, "AccountType": "Developer"}, {"ID": 3, "AccountType": "Developer"},
{"ID": 4, "AccountType": "Package Maintainer & Developer"}, {"ID": 4, "AccountType": "Trusted User & Developer"},
], ],
) )
conn.execute( conn.execute(

View file

@ -64,24 +64,11 @@ class Translator:
translator = Translator() translator = Translator()
def get_request_language(request: Request) -> str: def get_request_language(request: Request):
"""Get a request's language from either query param, user setting or if request.user.is_authenticated():
cookie. We use the configuration's [options] default_lang otherwise.
@param request FastAPI request
"""
request_lang = request.query_params.get("language")
cookie_lang = request.cookies.get("AURLANG")
if request_lang and request_lang in SUPPORTED_LANGUAGES:
return request_lang
elif (
request.user.is_authenticated()
and request.user.LangPreference in SUPPORTED_LANGUAGES
):
return request.user.LangPreference return request.user.LangPreference
elif cookie_lang and cookie_lang in SUPPORTED_LANGUAGES: default_lang = aurweb.config.get("options", "default_lang")
return cookie_lang return request.cookies.get("AURLANG", default_lang)
return aurweb.config.get_with_fallback("options", "default_lang", "en")
def get_raw_translator_for_request(request: Request): def get_raw_translator_for_request(request: Request):

View file

@ -1,5 +1,4 @@
""" Collection of all aurweb SQLAlchemy declarative models. """ """ Collection of all aurweb SQLAlchemy declarative models. """
from .accepted_term import AcceptedTerm # noqa: F401 from .accepted_term import AcceptedTerm # noqa: F401
from .account_type import AccountType # noqa: F401 from .account_type import AccountType # noqa: F401
from .api_rate_limit import ApiRateLimit # noqa: F401 from .api_rate_limit import ApiRateLimit # noqa: F401
@ -27,6 +26,6 @@ from .request_type import RequestType # noqa: F401
from .session import Session # noqa: F401 from .session import Session # noqa: F401
from .ssh_pub_key import SSHPubKey # noqa: F401 from .ssh_pub_key import SSHPubKey # noqa: F401
from .term import Term # noqa: F401 from .term import Term # noqa: F401
from .tu_vote import TUVote # noqa: F401
from .tu_voteinfo import TUVoteInfo # noqa: F401
from .user import User # noqa: F401 from .user import User # noqa: F401
from .vote import Vote # noqa: F401
from .voteinfo import VoteInfo # noqa: F401

View file

@ -2,21 +2,21 @@ from aurweb import schema
from aurweb.models.declarative import Base from aurweb.models.declarative import Base
USER = "User" USER = "User"
PACKAGE_MAINTAINER = "Package Maintainer" TRUSTED_USER = "Trusted User"
DEVELOPER = "Developer" DEVELOPER = "Developer"
PACKAGE_MAINTAINER_AND_DEV = "Package Maintainer & Developer" TRUSTED_USER_AND_DEV = "Trusted User & Developer"
USER_ID = 1 USER_ID = 1
PACKAGE_MAINTAINER_ID = 2 TRUSTED_USER_ID = 2
DEVELOPER_ID = 3 DEVELOPER_ID = 3
PACKAGE_MAINTAINER_AND_DEV_ID = 4 TRUSTED_USER_AND_DEV_ID = 4
# Map string constants to integer constants. # Map string constants to integer constants.
ACCOUNT_TYPE_ID = { ACCOUNT_TYPE_ID = {
USER: USER_ID, USER: USER_ID,
PACKAGE_MAINTAINER: PACKAGE_MAINTAINER_ID, TRUSTED_USER: TRUSTED_USER_ID,
DEVELOPER: DEVELOPER_ID, DEVELOPER: DEVELOPER_ID,
PACKAGE_MAINTAINER_AND_DEV: PACKAGE_MAINTAINER_AND_DEV_ID, TRUSTED_USER_AND_DEV: TRUSTED_USER_AND_DEV_ID,
} }
# Reversed ACCOUNT_TYPE_ID mapping. # Reversed ACCOUNT_TYPE_ID mapping.

View file

@ -2,7 +2,6 @@ from fastapi import Request
from aurweb import db, schema from aurweb import db, schema
from aurweb.models.declarative import Base from aurweb.models.declarative import Base
from aurweb.util import get_client_ip
class Ban(Base): class Ban(Base):
@ -15,6 +14,6 @@ class Ban(Base):
def is_banned(request: Request): def is_banned(request: Request):
ip = get_client_ip(request) ip = request.client.host
exists = db.query(Ban).filter(Ban.IPAddress == ip).exists() exists = db.query(Ban).filter(Ban.IPAddress == ip).exists()
return db.query(exists).scalar() return db.query(exists).scalar()

View file

@ -57,17 +57,14 @@ class PackageDependency(Base):
params=("NULL"), params=("NULL"),
) )
def is_aur_package(self) -> bool:
pkg = db.query(_Package).filter(_Package.Name == self.DepName).exists()
return db.query(pkg).scalar()
def is_package(self) -> bool: def is_package(self) -> bool:
pkg = db.query(_Package).filter(_Package.Name == self.DepName).exists()
official = ( official = (
db.query(_OfficialProvider) db.query(_OfficialProvider)
.filter(_OfficialProvider.Name == self.DepName) .filter(_OfficialProvider.Name == self.DepName)
.exists() .exists()
) )
return self.is_aur_package() or db.query(official).scalar() return db.query(pkg).scalar() or db.query(official).scalar()
def provides(self) -> list[PackageRelation]: def provides(self) -> list[PackageRelation]:
from aurweb.models.relation_type import PROVIDES_ID from aurweb.models.relation_type import PROVIDES_ID

View file

@ -3,24 +3,24 @@ from sqlalchemy.orm import backref, relationship
from aurweb import schema from aurweb import schema
from aurweb.models.declarative import Base from aurweb.models.declarative import Base
from aurweb.models.tu_voteinfo import TUVoteInfo as _TUVoteInfo
from aurweb.models.user import User as _User from aurweb.models.user import User as _User
from aurweb.models.voteinfo import VoteInfo as _VoteInfo
class Vote(Base): class TUVote(Base):
__table__ = schema.Votes __table__ = schema.TU_Votes
__tablename__ = __table__.name __tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.VoteID, __table__.c.UserID]} __mapper_args__ = {"primary_key": [__table__.c.VoteID, __table__.c.UserID]}
VoteInfo = relationship( VoteInfo = relationship(
_VoteInfo, _TUVoteInfo,
backref=backref("votes", lazy="dynamic"), backref=backref("tu_votes", lazy="dynamic"),
foreign_keys=[__table__.c.VoteID], foreign_keys=[__table__.c.VoteID],
) )
User = relationship( User = relationship(
_User, _User,
backref=backref("votes", lazy="dynamic"), backref=backref("tu_votes", lazy="dynamic"),
foreign_keys=[__table__.c.UserID], foreign_keys=[__table__.c.UserID],
) )
@ -30,13 +30,13 @@ class Vote(Base):
if not self.VoteInfo and not self.VoteID: if not self.VoteInfo and not self.VoteID:
raise IntegrityError( raise IntegrityError(
statement="Foreign key VoteID cannot be null.", statement="Foreign key VoteID cannot be null.",
orig="Votes.VoteID", orig="TU_Votes.VoteID",
params=("NULL"), params=("NULL"),
) )
if not self.User and not self.UserID: if not self.User and not self.UserID:
raise IntegrityError( raise IntegrityError(
statement="Foreign key UserID cannot be null.", statement="Foreign key UserID cannot be null.",
orig="Votes.UserID", orig="TU_Votes.UserID",
params=("NULL"), params=("NULL"),
) )

View file

@ -8,14 +8,14 @@ from aurweb.models.declarative import Base
from aurweb.models.user import User as _User from aurweb.models.user import User as _User
class VoteInfo(Base): class TUVoteInfo(Base):
__table__ = schema.VoteInfo __table__ = schema.TU_VoteInfo
__tablename__ = __table__.name __tablename__ = __table__.name
__mapper_args__ = {"primary_key": [__table__.c.ID]} __mapper_args__ = {"primary_key": [__table__.c.ID]}
Submitter = relationship( Submitter = relationship(
_User, _User,
backref=backref("voteinfo_set", lazy="dynamic"), backref=backref("tu_voteinfo_set", lazy="dynamic"),
foreign_keys=[__table__.c.SubmitterID], foreign_keys=[__table__.c.SubmitterID],
) )
@ -30,35 +30,35 @@ class VoteInfo(Base):
if self.Agenda is None: if self.Agenda is None:
raise IntegrityError( raise IntegrityError(
statement="Column Agenda cannot be null.", statement="Column Agenda cannot be null.",
orig="VoteInfo.Agenda", orig="TU_VoteInfo.Agenda",
params=("NULL"), params=("NULL"),
) )
if self.User is None: if self.User is None:
raise IntegrityError( raise IntegrityError(
statement="Column User cannot be null.", statement="Column User cannot be null.",
orig="VoteInfo.User", orig="TU_VoteInfo.User",
params=("NULL"), params=("NULL"),
) )
if self.Submitted is None: if self.Submitted is None:
raise IntegrityError( raise IntegrityError(
statement="Column Submitted cannot be null.", statement="Column Submitted cannot be null.",
orig="VoteInfo.Submitted", orig="TU_VoteInfo.Submitted",
params=("NULL"), params=("NULL"),
) )
if self.End is None: if self.End is None:
raise IntegrityError( raise IntegrityError(
statement="Column End cannot be null.", statement="Column End cannot be null.",
orig="VoteInfo.End", orig="TU_VoteInfo.End",
params=("NULL"), params=("NULL"),
) )
if not self.Submitter: if not self.Submitter:
raise IntegrityError( raise IntegrityError(
statement="Foreign key SubmitterID cannot be null.", statement="Foreign key SubmitterID cannot be null.",
orig="VoteInfo.SubmitterID", orig="TU_VoteInfo.SubmitterID",
params=("NULL"), params=("NULL"),
) )

View file

@ -122,7 +122,7 @@ class User(Base):
try: try:
with db.begin(): with db.begin():
self.LastLogin = now_ts self.LastLogin = now_ts
self.LastLoginIPAddress = util.get_client_ip(request) self.LastLoginIPAddress = request.client.host
if not self.session: if not self.session:
sid = generate_unique_sid() sid = generate_unique_sid()
self.session = db.create( self.session = db.create(
@ -157,25 +157,25 @@ class User(Base):
with db.begin(): with db.begin():
db.delete(self.session) db.delete(self.session)
def is_package_maintainer(self): def is_trusted_user(self):
return self.AccountType.ID in { return self.AccountType.ID in {
aurweb.models.account_type.PACKAGE_MAINTAINER_ID, aurweb.models.account_type.TRUSTED_USER_ID,
aurweb.models.account_type.PACKAGE_MAINTAINER_AND_DEV_ID, aurweb.models.account_type.TRUSTED_USER_AND_DEV_ID,
} }
def is_developer(self): def is_developer(self):
return self.AccountType.ID in { return self.AccountType.ID in {
aurweb.models.account_type.DEVELOPER_ID, aurweb.models.account_type.DEVELOPER_ID,
aurweb.models.account_type.PACKAGE_MAINTAINER_AND_DEV_ID, aurweb.models.account_type.TRUSTED_USER_AND_DEV_ID,
} }
def is_elevated(self): def is_elevated(self):
"""A User is 'elevated' when they have either a """A User is 'elevated' when they have either a
Package Maintainer or Developer AccountType.""" Trusted User or Developer AccountType."""
return self.AccountType.ID in { return self.AccountType.ID in {
aurweb.models.account_type.PACKAGE_MAINTAINER_ID, aurweb.models.account_type.TRUSTED_USER_ID,
aurweb.models.account_type.DEVELOPER_ID, aurweb.models.account_type.DEVELOPER_ID,
aurweb.models.account_type.PACKAGE_MAINTAINER_AND_DEV_ID, aurweb.models.account_type.TRUSTED_USER_AND_DEV_ID,
} }
def can_edit_user(self, target: "User") -> bool: def can_edit_user(self, target: "User") -> bool:
@ -188,7 +188,7 @@ class User(Base):
In short, a user must at least have credentials and be at least In short, a user must at least have credentials and be at least
the same account type as the target. the same account type as the target.
User < Package Maintainer < Developer < Package Maintainer & Developer User < Trusted User < Developer < Trusted User & Developer
:param target: Target User to be edited :param target: Target User to be edited
:return: Boolean indicating whether `self` can edit `target` :return: Boolean indicating whether `self` can edit `target`

View file

@ -83,11 +83,9 @@ def package_link(package: Union[Package, OfficialProvider]) -> str:
@register_filter("provides_markup") @register_filter("provides_markup")
def provides_markup(provides: Providers) -> str: def provides_markup(provides: Providers) -> str:
links = [] return ", ".join(
for pkg in provides: [f'<a href="{package_link(pkg)}">{pkg.Name}</a>' for pkg in provides]
aur = "<sup><small>AUR</small></sup>" if not pkg.is_official else "" )
links.append(f'<a href="{package_link(pkg)}">{pkg.Name}</a>{aur}')
return ", ".join(links)
def get_pkg_or_base( def get_pkg_or_base(

View file

@ -94,7 +94,7 @@ def _retry_disown(request: Request, pkgbase: PackageBase):
notifs.append(notif) notifs.append(notif)
elif request.user.has_credential(creds.PKGBASE_DISOWN): elif request.user.has_credential(creds.PKGBASE_DISOWN):
# Otherwise, the request user performing this disownage is a # Otherwise, the request user performing this disownage is a
# Package Maintainer and we treat it like a standard orphan request. # Trusted User and we treat it like a standard orphan request.
notifs += handle_request(request, ORPHAN_ID, pkgbase) notifs += handle_request(request, ORPHAN_ID, pkgbase)
with db.begin(): with db.begin():
pkgbase.Maintainer = None pkgbase.Maintainer = None
@ -187,7 +187,7 @@ def pkgbase_merge_instance(
# Log this out for accountability purposes. # Log this out for accountability purposes.
logger.info( logger.info(
f"Package Maintainer '{request.user.Username}' merged " f"Trusted User '{request.user.Username}' merged "
f"'{pkgbasename}' into '{target.Name}'." f"'{pkgbasename}' into '{target.Name}'."
) )

View file

@ -2,7 +2,6 @@ from typing import Any
from fastapi import Request from fastapi import Request
from sqlalchemy import and_ from sqlalchemy import and_
from sqlalchemy.orm import joinedload
from aurweb import config, db, defaults, l10n, time, util from aurweb import config, db, defaults, l10n, time, util
from aurweb.models import PackageBase, User from aurweb.models import PackageBase, User
@ -12,7 +11,17 @@ from aurweb.models.package_comment import PackageComment
from aurweb.models.package_request import PENDING_ID, PackageRequest from aurweb.models.package_request import PENDING_ID, PackageRequest
from aurweb.models.package_vote import PackageVote from aurweb.models.package_vote import PackageVote
from aurweb.scripts import notify from aurweb.scripts import notify
from aurweb.templates import make_context as _make_context from aurweb.templates import (
make_context as _make_context,
make_variable_context as _make_variable_context,
)
async def make_variable_context(
request: Request, pkgbase: PackageBase
) -> dict[str, Any]:
ctx = await _make_variable_context(request, pkgbase.Name)
return make_context(request, pkgbase, ctx)
def make_context( def make_context(
@ -27,8 +36,6 @@ def make_context(
if not context: if not context:
context = _make_context(request, pkgbase.Name) context = _make_context(request, pkgbase.Name)
is_authenticated = request.user.is_authenticated()
# Per page and offset. # Per page and offset.
offset, per_page = util.sanitize_params( offset, per_page = util.sanitize_params(
request.query_params.get("O", defaults.O), request.query_params.get("O", defaults.O),
@ -41,15 +48,12 @@ def make_context(
context["pkgbase"] = pkgbase context["pkgbase"] = pkgbase
context["comaintainers"] = [ context["comaintainers"] = [
c.User c.User
for c in pkgbase.comaintainers.options(joinedload(PackageComaintainer.User)) for c in pkgbase.comaintainers.order_by(
.order_by(PackageComaintainer.Priority.asc()) PackageComaintainer.Priority.asc()
.all() ).all()
] ]
if is_authenticated: context["unflaggers"] = context["comaintainers"].copy()
context["unflaggers"] = context["comaintainers"].copy() context["unflaggers"].extend([pkgbase.Maintainer, pkgbase.Flagger])
context["unflaggers"].extend([pkgbase.Maintainer, pkgbase.Flagger])
else:
context["unflaggers"] = []
context["packages_count"] = pkgbase.packages.count() context["packages_count"] = pkgbase.packages.count()
context["keywords"] = pkgbase.keywords context["keywords"] = pkgbase.keywords
@ -66,28 +70,17 @@ def make_context(
).order_by(PackageComment.CommentTS.desc()) ).order_by(PackageComment.CommentTS.desc())
context["is_maintainer"] = bool(request.user == pkgbase.Maintainer) context["is_maintainer"] = bool(request.user == pkgbase.Maintainer)
if is_authenticated: context["notified"] = request.user.notified(pkgbase)
context["notified"] = request.user.notified(pkgbase)
else:
context["notified"] = False
context["out_of_date"] = bool(pkgbase.OutOfDateTS) context["out_of_date"] = bool(pkgbase.OutOfDateTS)
if is_authenticated: context["voted"] = request.user.package_votes.filter(
context["voted"] = db.query( PackageVote.PackageBaseID == pkgbase.ID
request.user.package_votes.filter( ).scalar()
PackageVote.PackageBaseID == pkgbase.ID
).exists()
).scalar()
else:
context["voted"] = False
if is_authenticated: context["requests"] = pkgbase.requests.filter(
context["requests"] = pkgbase.requests.filter( and_(PackageRequest.Status == PENDING_ID, PackageRequest.ClosedTS.is_(None))
and_(PackageRequest.Status == PENDING_ID, PackageRequest.ClosedTS.is_(None)) ).count()
).count()
else:
context["requests"] = []
context["popularity"] = popularity(pkgbase, time.utcnow()) context["popularity"] = popularity(pkgbase, time.utcnow())

View file

@ -1,9 +1,6 @@
from http import HTTPStatus
from typing import Any from typing import Any
from fastapi import HTTPException from aurweb import db
from aurweb import config, db
from aurweb.exceptions import ValidationError from aurweb.exceptions import ValidationError
from aurweb.models import PackageBase from aurweb.models import PackageBase
@ -15,8 +12,8 @@ def request(
merge_into: str, merge_into: str,
context: dict[str, Any], context: dict[str, Any],
) -> None: ) -> None:
# validate comment if not comments:
comment(comments) raise ValidationError(["The comment field must not be empty."])
if type == "merge": if type == "merge":
# Perform merge-related checks. # Perform merge-related checks.
@ -35,21 +32,3 @@ def request(
if target.ID == pkgbase.ID: if target.ID == pkgbase.ID:
# TODO: This error needs to be translated. # TODO: This error needs to be translated.
raise ValidationError(["You cannot merge a package base into itself."]) raise ValidationError(["You cannot merge a package base into itself."])
def comment(comment: str):
if not comment:
raise ValidationError(["The comment field must not be empty."])
if len(comment) > config.getint("options", "max_chars_comment", 5000):
raise ValidationError(["Maximum number of characters for comment exceeded."])
def comment_raise_http_ex(comments: str):
try:
comment(comments)
except ValidationError as err:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=err.data[0],
)

View file

@ -4,7 +4,6 @@ from redis.client import Pipeline
from aurweb import aur_logging, config, db, time from aurweb import aur_logging, config, db, time
from aurweb.aur_redis import redis_connection from aurweb.aur_redis import redis_connection
from aurweb.models import ApiRateLimit from aurweb.models import ApiRateLimit
from aurweb.util import get_client_ip
logger = aur_logging.get_logger(__name__) logger = aur_logging.get_logger(__name__)
@ -14,7 +13,7 @@ def _update_ratelimit_redis(request: Request, pipeline: Pipeline):
now = time.utcnow() now = time.utcnow()
time_to_delete = now - window_length time_to_delete = now - window_length
host = get_client_ip(request) host = request.client.host
window_key = f"ratelimit-ws:{host}" window_key = f"ratelimit-ws:{host}"
requests_key = f"ratelimit:{host}" requests_key = f"ratelimit:{host}"
@ -56,7 +55,7 @@ def _update_ratelimit_db(request: Request):
record.Requests += 1 record.Requests += 1
return record return record
host = get_client_ip(request) host = request.client.host
record = db.query(ApiRateLimit, ApiRateLimit.IP == host).first() record = db.query(ApiRateLimit, ApiRateLimit.IP == host).first()
record = retry_create(record, now, host) record = retry_create(record, now, host)
@ -93,7 +92,7 @@ def check_ratelimit(request: Request):
record = update_ratelimit(request, pipeline) record = update_ratelimit(request, pipeline)
# Get cache value, else None. # Get cache value, else None.
host = get_client_ip(request) host = request.client.host
pipeline.get(f"ratelimit:{host}") pipeline.get(f"ratelimit:{host}")
requests = pipeline.execute()[0] requests = pipeline.execute()[0]

View file

@ -3,18 +3,17 @@ API routers for FastAPI.
See https://fastapi.tiangolo.com/tutorial/bigger-applications/ See https://fastapi.tiangolo.com/tutorial/bigger-applications/
""" """
from . import ( from . import (
accounts, accounts,
auth, auth,
html, html,
package_maintainer,
packages, packages,
pkgbase, pkgbase,
requests, requests,
rpc, rpc,
rss, rss,
sso, sso,
trusted_user,
) )
""" """
@ -29,7 +28,7 @@ APP_ROUTES = [
packages, packages,
pkgbase, pkgbase,
requests, requests,
package_maintainer, trusted_user,
rss, rss,
rpc, rpc,
sso, sso,

View file

@ -184,9 +184,9 @@ def make_account_form_context(
lambda e: request.user.AccountTypeID >= e[0], lambda e: request.user.AccountTypeID >= e[0],
[ [
(at.USER_ID, f"Normal {at.USER}"), (at.USER_ID, f"Normal {at.USER}"),
(at.PACKAGE_MAINTAINER_ID, at.PACKAGE_MAINTAINER), (at.TRUSTED_USER_ID, at.TRUSTED_USER),
(at.DEVELOPER_ID, at.DEVELOPER), (at.DEVELOPER_ID, at.DEVELOPER),
(at.PACKAGE_MAINTAINER_AND_DEV_ID, at.PACKAGE_MAINTAINER_AND_DEV), (at.TRUSTED_USER_AND_DEV_ID, at.TRUSTED_USER_AND_DEV),
], ],
) )
) )
@ -520,9 +520,7 @@ async def account_comments(request: Request, username: str):
@router.get("/accounts") @router.get("/accounts")
@requires_auth @requires_auth
@account_type_required( @account_type_required({at.TRUSTED_USER, at.DEVELOPER, at.TRUSTED_USER_AND_DEV})
{at.PACKAGE_MAINTAINER, at.DEVELOPER, at.PACKAGE_MAINTAINER_AND_DEV}
)
async def accounts(request: Request): async def accounts(request: Request):
context = make_context(request, "Accounts") context = make_context(request, "Accounts")
return render_template(request, "account/search.html", context) return render_template(request, "account/search.html", context)
@ -531,9 +529,7 @@ async def accounts(request: Request):
@router.post("/accounts") @router.post("/accounts")
@handle_form_exceptions @handle_form_exceptions
@requires_auth @requires_auth
@account_type_required( @account_type_required({at.TRUSTED_USER, at.DEVELOPER, at.TRUSTED_USER_AND_DEV})
{at.PACKAGE_MAINTAINER, at.DEVELOPER, at.PACKAGE_MAINTAINER_AND_DEV}
)
async def accounts_post( async def accounts_post(
request: Request, request: Request,
O: int = Form(default=0), # Offset O: int = Form(default=0), # Offset
@ -568,9 +564,9 @@ async def accounts_post(
# Convert parameter T to an AccountType ID. # Convert parameter T to an AccountType ID.
account_types = { account_types = {
"u": at.USER_ID, "u": at.USER_ID,
"t": at.PACKAGE_MAINTAINER_ID, "t": at.TRUSTED_USER_ID,
"d": at.DEVELOPER_ID, "d": at.DEVELOPER_ID,
"td": at.PACKAGE_MAINTAINER_AND_DEV_ID, "td": at.TRUSTED_USER_AND_DEV_ID,
} }
account_type_id = account_types.get(T, None) account_type_id = account_types.get(T, None)

View file

@ -1,7 +1,6 @@
""" AURWeb's primary routing module. Define all routes via @app.app.{get,post} """ AURWeb's primary routing module. Define all routes via @app.app.{get,post}
decorators in some way; more complex routes should be defined in their decorators in some way; more complex routes should be defined in their
own modules and imported here. """ own modules and imported here. """
import os import os
from http import HTTPStatus from http import HTTPStatus

View file

@ -167,8 +167,7 @@ async def package(
rels_data["r"].append(rel) rels_data["r"].append(rel)
# Add our base information. # Add our base information.
context = pkgbaseutil.make_context(request, pkgbase) context = await pkgbaseutil.make_variable_context(request, pkgbase)
context["q"] = dict(request.query_params)
context.update({"all_deps": all_deps, "all_reqs": all_reqs}) context.update({"all_deps": all_deps, "all_reqs": all_reqs})
@ -190,17 +189,6 @@ async def package(
if not all_deps: if not all_deps:
deps = deps.limit(max_listing) deps = deps.limit(max_listing)
context["dependencies"] = deps.all() context["dependencies"] = deps.all()
# Existing dependencies to avoid multiple lookups
context["dependencies_names_from_aur"] = [
item.Name
for item in db.query(models.Package)
.filter(
models.Package.Name.in_(
pkg.package_dependencies.with_entities(models.PackageDependency.DepName)
)
)
.all()
]
# Package requirements (other packages depend on this one). # Package requirements (other packages depend on this one).
reqs = pkgutil.pkg_required(pkg.Name, [p.RelName for p in rels_data.get("p", [])]) reqs = pkgutil.pkg_required(pkg.Name, [p.RelName for p in rels_data.get("p", [])])
@ -211,8 +199,6 @@ async def package(
context["licenses"] = pkg.package_licenses context["licenses"] = pkg.package_licenses
context["groups"] = pkg.package_groups
conflicts = pkg.package_relations.filter( conflicts = pkg.package_relations.filter(
models.PackageRelation.RelTypeID == CONFLICTS_ID models.PackageRelation.RelTypeID == CONFLICTS_ID
).order_by(models.PackageRelation.RelName.asc()) ).order_by(models.PackageRelation.RelName.asc())

View file

@ -159,8 +159,6 @@ async def pkgbase_flag_post(
request, "pkgbase/flag.html", context, status_code=HTTPStatus.BAD_REQUEST request, "pkgbase/flag.html", context, status_code=HTTPStatus.BAD_REQUEST
) )
validate.comment_raise_http_ex(comments)
has_cred = request.user.has_credential(creds.PKGBASE_FLAG) has_cred = request.user.has_credential(creds.PKGBASE_FLAG)
if has_cred and not pkgbase.OutOfDateTS: if has_cred and not pkgbase.OutOfDateTS:
now = time.utcnow() now = time.utcnow()
@ -187,7 +185,8 @@ async def pkgbase_comments_post(
"""Add a new comment via POST request.""" """Add a new comment via POST request."""
pkgbase = get_pkg_or_base(name, PackageBase) pkgbase = get_pkg_or_base(name, PackageBase)
validate.comment_raise_http_ex(comment) if not comment:
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST)
# If the provided comment is different than the record's version, # If the provided comment is different than the record's version,
# update the db record. # update the db record.
@ -305,9 +304,9 @@ async def pkgbase_comment_post(
pkgbase = get_pkg_or_base(name, PackageBase) pkgbase = get_pkg_or_base(name, PackageBase)
db_comment = get_pkgbase_comment(pkgbase, id) db_comment = get_pkgbase_comment(pkgbase, id)
validate.comment_raise_http_ex(comment) if not comment:
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST)
if request.user.ID != db_comment.UsersID: elif request.user.ID != db_comment.UsersID:
raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED) raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED)
# If the provided comment is different than the record's version, # If the provided comment is different than the record's version,
@ -603,9 +602,6 @@ async def pkgbase_disown_post(
): ):
pkgbase = get_pkg_or_base(name, PackageBase) pkgbase = get_pkg_or_base(name, PackageBase)
if comments:
validate.comment_raise_http_ex(comments)
comaints = {c.User for c in pkgbase.comaintainers} comaints = {c.User for c in pkgbase.comaintainers}
approved = [pkgbase.Maintainer] + list(comaints) approved = [pkgbase.Maintainer] + list(comaints)
has_cred = request.user.has_credential(creds.PKGBASE_DISOWN, approved=approved) has_cred = request.user.has_credential(creds.PKGBASE_DISOWN, approved=approved)
@ -877,7 +873,6 @@ async def pkgbase_delete_post(
) )
if comments: if comments:
validate.comment_raise_http_ex(comments)
# Update any existing deletion requests' ClosureComment. # Update any existing deletion requests' ClosureComment.
with db.begin(): with db.begin():
requests = pkgbase.requests.filter( requests = pkgbase.requests.filter(
@ -913,9 +908,7 @@ async def pkgbase_merge_get(
# Perhaps additionally: bad_credential_status_code(creds.PKGBASE_MERGE). # Perhaps additionally: bad_credential_status_code(creds.PKGBASE_MERGE).
# Don't take these examples verbatim. We should find good naming. # Don't take these examples verbatim. We should find good naming.
if not request.user.has_credential(creds.PKGBASE_MERGE): if not request.user.has_credential(creds.PKGBASE_MERGE):
context["errors"] = [ context["errors"] = ["Only Trusted Users and Developers can merge packages."]
"Only Package Maintainers and Developers can merge packages."
]
status_code = HTTPStatus.UNAUTHORIZED status_code = HTTPStatus.UNAUTHORIZED
return render_template( return render_template(
@ -941,9 +934,7 @@ async def pkgbase_merge_post(
# TODO: Lookup errors from credential instead of hardcoding them. # TODO: Lookup errors from credential instead of hardcoding them.
if not request.user.has_credential(creds.PKGBASE_MERGE): if not request.user.has_credential(creds.PKGBASE_MERGE):
context["errors"] = [ context["errors"] = ["Only Trusted Users and Developers can merge packages."]
"Only Package Maintainers and Developers can merge packages."
]
return render_template( return render_template(
request, "pkgbase/merge.html", context, status_code=HTTPStatus.UNAUTHORIZED request, "pkgbase/merge.html", context, status_code=HTTPStatus.UNAUTHORIZED
) )
@ -971,9 +962,6 @@ async def pkgbase_merge_post(
request, "pkgbase/merge.html", context, status_code=HTTPStatus.BAD_REQUEST request, "pkgbase/merge.html", context, status_code=HTTPStatus.BAD_REQUEST
) )
if comments:
validate.comment_raise_http_ex(comments)
with db.begin(): with db.begin():
update_closure_comment(pkgbase, MERGE_ID, comments, target=target) update_closure_comment(pkgbase, MERGE_ID, comments, target=target)

View file

@ -23,7 +23,6 @@ OpenAPI Routes:
OpenAPI example (version 5): /rpc/v5/info/my-package OpenAPI example (version 5): /rpc/v5/info/my-package
""" """
import hashlib import hashlib
import re import re
from http import HTTPStatus from http import HTTPStatus
@ -181,7 +180,7 @@ async def rpc_post(
type: Optional[str] = Form(default=None), type: Optional[str] = Form(default=None),
by: Optional[str] = Form(default=defaults.RPC_SEARCH_BY), by: Optional[str] = Form(default=defaults.RPC_SEARCH_BY),
arg: Optional[str] = Form(default=None), arg: Optional[str] = Form(default=None),
args: list[str] = Form(default=[], alias="arg[]"), args: Optional[list[str]] = Form(default=[], alias="arg[]"),
callback: Optional[str] = Form(default=None), callback: Optional[str] = Form(default=None),
): ):
return await rpc_request(request, v, type, by, arg, args, callback) return await rpc_request(request, v, type, by, arg, args, callback)

View file

@ -2,8 +2,7 @@ from fastapi import APIRouter, Request
from fastapi.responses import Response from fastapi.responses import Response
from feedgen.feed import FeedGenerator from feedgen.feed import FeedGenerator
from aurweb import config, db, filters from aurweb import db, filters
from aurweb.cache import lambda_cache
from aurweb.models import Package, PackageBase from aurweb.models import Package, PackageBase
router = APIRouter() router = APIRouter()
@ -57,11 +56,9 @@ async def rss(request: Request):
) )
) )
# we use redis for caching the results of the feedgen feed = make_rss_feed(request, packages)
cache_expire = config.getint("cache", "expiry_time_rss", 300)
feed = lambda_cache("rss", lambda: make_rss_feed(request, packages), cache_expire)
response = Response(feed, media_type="application/rss+xml") response = Response(feed, media_type="application/rss+xml")
return response return response
@ -79,11 +76,7 @@ async def rss_modified(request: Request):
) )
) )
# we use redis for caching the results of the feedgen feed = make_rss_feed(request, packages)
cache_expire = config.getint("cache", "expiry_time_rss", 300)
feed = lambda_cache(
"rss_modified", lambda: make_rss_feed(request, packages), cache_expire
)
response = Response(feed, media_type="application/rss+xml") response = Response(feed, media_type="application/rss+xml")
return response return response

View file

@ -80,9 +80,7 @@ def open_session(request, conn, user_id):
conn.execute( conn.execute(
Users.update() Users.update()
.where(Users.c.ID == user_id) .where(Users.c.ID == user_id)
.values( .values(LastLogin=int(time.time()), LastLoginIPAddress=request.client.host)
LastLogin=int(time.time()), LastLoginIPAddress=util.get_client_ip(request)
)
) )
return sid return sid
@ -112,7 +110,7 @@ async def authenticate(
Receive an OpenID Connect ID token, validate it, then process it to create Receive an OpenID Connect ID token, validate it, then process it to create
an new AUR session. an new AUR session.
""" """
if is_ip_banned(conn, util.get_client_ip(request)): if is_ip_banned(conn, request.client.host):
_ = get_translator_for_request(request) _ = get_translator_for_request(request)
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, status_code=HTTPStatus.FORBIDDEN,

View file

@ -11,16 +11,13 @@ from aurweb import aur_logging, db, l10n, models, time
from aurweb.auth import creds, requires_auth from aurweb.auth import creds, requires_auth
from aurweb.exceptions import handle_form_exceptions from aurweb.exceptions import handle_form_exceptions
from aurweb.models import User from aurweb.models import User
from aurweb.models.account_type import ( from aurweb.models.account_type import TRUSTED_USER_AND_DEV_ID, TRUSTED_USER_ID
PACKAGE_MAINTAINER_AND_DEV_ID,
PACKAGE_MAINTAINER_ID,
)
from aurweb.templates import make_context, make_variable_context, render_template from aurweb.templates import make_context, make_variable_context, render_template
router = APIRouter() router = APIRouter()
logger = aur_logging.get_logger(__name__) logger = aur_logging.get_logger(__name__)
# Some PM route specific constants. # Some TU route specific constants.
ITEMS_PER_PAGE = 10 # Paged table size. ITEMS_PER_PAGE = 10 # Paged table size.
MAX_AGENDA_LENGTH = 75 # Agenda table column length. MAX_AGENDA_LENGTH = 75 # Agenda table column length.
@ -29,32 +26,32 @@ ADDVOTE_SPECIFICS = {
# When a proposal is added, duration is added to the current # When a proposal is added, duration is added to the current
# timestamp. # timestamp.
# "addvote_type": (duration, quorum) # "addvote_type": (duration, quorum)
"add_pm": (7 * 24 * 60 * 60, 0.66), "add_tu": (7 * 24 * 60 * 60, 0.66),
"remove_pm": (7 * 24 * 60 * 60, 0.75), "remove_tu": (7 * 24 * 60 * 60, 0.75),
"remove_inactive_pm": (5 * 24 * 60 * 60, 0.66), "remove_inactive_tu": (5 * 24 * 60 * 60, 0.66),
"bylaws": (7 * 24 * 60 * 60, 0.75), "bylaws": (7 * 24 * 60 * 60, 0.75),
} }
def populate_package_maintainer_counts(context: dict[str, Any]) -> None: def populate_trusted_user_counts(context: dict[str, Any]) -> None:
pm_query = db.query(User).filter( tu_query = db.query(User).filter(
or_( or_(
User.AccountTypeID == PACKAGE_MAINTAINER_ID, User.AccountTypeID == TRUSTED_USER_ID,
User.AccountTypeID == PACKAGE_MAINTAINER_AND_DEV_ID, User.AccountTypeID == TRUSTED_USER_AND_DEV_ID,
) )
) )
context["package_maintainer_count"] = pm_query.count() context["trusted_user_count"] = tu_query.count()
# In case any records have a None InactivityTS. # In case any records have a None InactivityTS.
active_pm_query = pm_query.filter( active_tu_query = tu_query.filter(
or_(User.InactivityTS.is_(None), User.InactivityTS == 0) or_(User.InactivityTS.is_(None), User.InactivityTS == 0)
) )
context["active_package_maintainer_count"] = active_pm_query.count() context["active_trusted_user_count"] = active_tu_query.count()
@router.get("/package-maintainer") @router.get("/tu")
@requires_auth @requires_auth
async def package_maintainer( async def trusted_user(
request: Request, request: Request,
coff: int = 0, # current offset coff: int = 0, # current offset
cby: str = "desc", # current by cby: str = "desc", # current by
@ -63,10 +60,10 @@ async def package_maintainer(
): # past by ): # past by
"""Proposal listings.""" """Proposal listings."""
if not request.user.has_credential(creds.PM_LIST_VOTES): if not request.user.has_credential(creds.TU_LIST_VOTES):
return RedirectResponse("/", status_code=HTTPStatus.SEE_OTHER) return RedirectResponse("/", status_code=HTTPStatus.SEE_OTHER)
context = make_context(request, "Package Maintainer") context = make_context(request, "Trusted User")
current_by, past_by = cby, pby current_by, past_by = cby, pby
current_off, past_off = coff, poff current_off, past_off = coff, poff
@ -87,9 +84,9 @@ async def package_maintainer(
context["past_by"] = past_by context["past_by"] = past_by
current_votes = ( current_votes = (
db.query(models.VoteInfo) db.query(models.TUVoteInfo)
.filter(models.VoteInfo.End > ts) .filter(models.TUVoteInfo.End > ts)
.order_by(models.VoteInfo.Submitted.desc()) .order_by(models.TUVoteInfo.Submitted.desc())
) )
context["current_votes_count"] = current_votes.count() context["current_votes_count"] = current_votes.count()
current_votes = current_votes.limit(pp).offset(current_off) current_votes = current_votes.limit(pp).offset(current_off)
@ -99,9 +96,9 @@ async def package_maintainer(
context["current_off"] = current_off context["current_off"] = current_off
past_votes = ( past_votes = (
db.query(models.VoteInfo) db.query(models.TUVoteInfo)
.filter(models.VoteInfo.End <= ts) .filter(models.TUVoteInfo.End <= ts)
.order_by(models.VoteInfo.Submitted.desc()) .order_by(models.TUVoteInfo.Submitted.desc())
) )
context["past_votes_count"] = past_votes.count() context["past_votes_count"] = past_votes.count()
past_votes = past_votes.limit(pp).offset(past_off) past_votes = past_votes.limit(pp).offset(past_off)
@ -110,29 +107,29 @@ async def package_maintainer(
) )
context["past_off"] = past_off context["past_off"] = past_off
last_vote = func.max(models.Vote.VoteID).label("LastVote") last_vote = func.max(models.TUVote.VoteID).label("LastVote")
last_votes_by_pm = ( last_votes_by_tu = (
db.query(models.Vote) db.query(models.TUVote)
.join(models.User) .join(models.User)
.join(models.VoteInfo, models.VoteInfo.ID == models.Vote.VoteID) .join(models.TUVoteInfo, models.TUVoteInfo.ID == models.TUVote.VoteID)
.filter( .filter(
and_( and_(
models.Vote.VoteID == models.VoteInfo.ID, models.TUVote.VoteID == models.TUVoteInfo.ID,
models.User.ID == models.Vote.UserID, models.User.ID == models.TUVote.UserID,
models.VoteInfo.End < ts, models.TUVoteInfo.End < ts,
or_(models.User.AccountTypeID == 2, models.User.AccountTypeID == 4), or_(models.User.AccountTypeID == 2, models.User.AccountTypeID == 4),
) )
) )
.with_entities(models.Vote.UserID, last_vote, models.User.Username) .with_entities(models.TUVote.UserID, last_vote, models.User.Username)
.group_by(models.Vote.UserID) .group_by(models.TUVote.UserID)
.order_by(last_vote.desc(), models.User.Username.asc()) .order_by(last_vote.desc(), models.User.Username.asc())
) )
context["last_votes_by_pm"] = last_votes_by_pm.all() context["last_votes_by_tu"] = last_votes_by_tu.all()
context["current_by_next"] = "asc" if current_by == "desc" else "desc" context["current_by_next"] = "asc" if current_by == "desc" else "desc"
context["past_by_next"] = "asc" if past_by == "desc" else "desc" context["past_by_next"] = "asc" if past_by == "desc" else "desc"
populate_package_maintainer_counts(context) populate_trusted_user_counts(context)
context["q"] = { context["q"] = {
"coff": current_off, "coff": current_off,
@ -141,33 +138,33 @@ async def package_maintainer(
"pby": past_by, "pby": past_by,
} }
return render_template(request, "package-maintainer/index.html", context) return render_template(request, "tu/index.html", context)
def render_proposal( def render_proposal(
request: Request, request: Request,
context: dict, context: dict,
proposal: int, proposal: int,
voteinfo: models.VoteInfo, voteinfo: models.TUVoteInfo,
voters: typing.Iterable[models.User], voters: typing.Iterable[models.User],
vote: models.Vote, vote: models.TUVote,
status_code: HTTPStatus = HTTPStatus.OK, status_code: HTTPStatus = HTTPStatus.OK,
): ):
"""Render a single PM proposal.""" """Render a single TU proposal."""
context["proposal"] = proposal context["proposal"] = proposal
context["voteinfo"] = voteinfo context["voteinfo"] = voteinfo
context["voters"] = voters.all() context["voters"] = voters.all()
total = voteinfo.total_votes() total = voteinfo.total_votes()
participation = (total / voteinfo.ActiveUsers) if voteinfo.ActiveUsers else 0 participation = (total / voteinfo.ActiveTUs) if voteinfo.ActiveTUs else 0
context["participation"] = participation context["participation"] = participation
accepted = (voteinfo.Yes > voteinfo.ActiveUsers / 2) or ( accepted = (voteinfo.Yes > voteinfo.ActiveTUs / 2) or (
participation > voteinfo.Quorum and voteinfo.Yes > voteinfo.No participation > voteinfo.Quorum and voteinfo.Yes > voteinfo.No
) )
context["accepted"] = accepted context["accepted"] = accepted
can_vote = voters.filter(models.Vote.User == request.user).first() is None can_vote = voters.filter(models.TUVote.User == request.user).first() is None
context["can_vote"] = can_vote context["can_vote"] = can_vote
if not voteinfo.is_running(): if not voteinfo.is_running():
@ -176,41 +173,41 @@ def render_proposal(
context["vote"] = vote context["vote"] = vote
context["has_voted"] = vote is not None context["has_voted"] = vote is not None
return render_template( return render_template(request, "tu/show.html", context, status_code=status_code)
request, "package-maintainer/show.html", context, status_code=status_code
)
@router.get("/package-maintainer/{proposal}") @router.get("/tu/{proposal}")
@requires_auth @requires_auth
async def package_maintainer_proposal(request: Request, proposal: int): async def trusted_user_proposal(request: Request, proposal: int):
if not request.user.has_credential(creds.PM_LIST_VOTES): if not request.user.has_credential(creds.TU_LIST_VOTES):
return RedirectResponse("/package-maintainer", status_code=HTTPStatus.SEE_OTHER) return RedirectResponse("/tu", status_code=HTTPStatus.SEE_OTHER)
context = await make_variable_context(request, "Package Maintainer") context = await make_variable_context(request, "Trusted User")
proposal = int(proposal) proposal = int(proposal)
voteinfo = db.query(models.VoteInfo).filter(models.VoteInfo.ID == proposal).first() voteinfo = (
db.query(models.TUVoteInfo).filter(models.TUVoteInfo.ID == proposal).first()
)
if not voteinfo: if not voteinfo:
raise HTTPException(status_code=HTTPStatus.NOT_FOUND) raise HTTPException(status_code=HTTPStatus.NOT_FOUND)
voters = ( voters = (
db.query(models.User) db.query(models.User)
.join(models.Vote) .join(models.TUVote)
.filter(models.Vote.VoteID == voteinfo.ID) .filter(models.TUVote.VoteID == voteinfo.ID)
) )
vote = ( vote = (
db.query(models.Vote) db.query(models.TUVote)
.filter( .filter(
and_( and_(
models.Vote.UserID == request.user.ID, models.TUVote.UserID == request.user.ID,
models.Vote.VoteID == voteinfo.ID, models.TUVote.VoteID == voteinfo.ID,
) )
) )
.first() .first()
) )
if not request.user.has_credential(creds.PM_VOTE): if not request.user.has_credential(creds.TU_VOTE):
context["error"] = "Only Package Maintainers are allowed to vote." context["error"] = "Only Trusted Users are allowed to vote."
if voteinfo.User == request.user.Username: if voteinfo.User == request.user.Username:
context["error"] = "You cannot vote in an proposal about you." context["error"] = "You cannot vote in an proposal about you."
elif vote is not None: elif vote is not None:
@ -221,41 +218,43 @@ async def package_maintainer_proposal(request: Request, proposal: int):
@db.async_retry_deadlock @db.async_retry_deadlock
@router.post("/package-maintainer/{proposal}") @router.post("/tu/{proposal}")
@handle_form_exceptions @handle_form_exceptions
@requires_auth @requires_auth
async def package_maintainer_proposal_post( async def trusted_user_proposal_post(
request: Request, proposal: int, decision: str = Form(...) request: Request, proposal: int, decision: str = Form(...)
): ):
if not request.user.has_credential(creds.PM_LIST_VOTES): if not request.user.has_credential(creds.TU_LIST_VOTES):
return RedirectResponse("/package-maintainer", status_code=HTTPStatus.SEE_OTHER) return RedirectResponse("/tu", status_code=HTTPStatus.SEE_OTHER)
context = await make_variable_context(request, "Package Maintainer") context = await make_variable_context(request, "Trusted User")
proposal = int(proposal) # Make sure it's an int. proposal = int(proposal) # Make sure it's an int.
voteinfo = db.query(models.VoteInfo).filter(models.VoteInfo.ID == proposal).first() voteinfo = (
db.query(models.TUVoteInfo).filter(models.TUVoteInfo.ID == proposal).first()
)
if not voteinfo: if not voteinfo:
raise HTTPException(status_code=HTTPStatus.NOT_FOUND) raise HTTPException(status_code=HTTPStatus.NOT_FOUND)
voters = ( voters = (
db.query(models.User) db.query(models.User)
.join(models.Vote) .join(models.TUVote)
.filter(models.Vote.VoteID == voteinfo.ID) .filter(models.TUVote.VoteID == voteinfo.ID)
) )
vote = ( vote = (
db.query(models.Vote) db.query(models.TUVote)
.filter( .filter(
and_( and_(
models.Vote.UserID == request.user.ID, models.TUVote.UserID == request.user.ID,
models.Vote.VoteID == voteinfo.ID, models.TUVote.VoteID == voteinfo.ID,
) )
) )
.first() .first()
) )
status_code = HTTPStatus.OK status_code = HTTPStatus.OK
if not request.user.has_credential(creds.PM_VOTE): if not request.user.has_credential(creds.TU_VOTE):
context["error"] = "Only Package Maintainers are allowed to vote." context["error"] = "Only Trusted Users are allowed to vote."
status_code = HTTPStatus.UNAUTHORIZED status_code = HTTPStatus.UNAUTHORIZED
elif voteinfo.User == request.user.Username: elif voteinfo.User == request.user.Username:
context["error"] = "You cannot vote in an proposal about you." context["error"] = "You cannot vote in an proposal about you."
@ -278,7 +277,7 @@ async def package_maintainer_proposal_post(
"Invalid 'decision' value.", status_code=HTTPStatus.BAD_REQUEST "Invalid 'decision' value.", status_code=HTTPStatus.BAD_REQUEST
) )
vote = db.create(models.Vote, User=request.user, VoteInfo=voteinfo) vote = db.create(models.TUVote, User=request.user, VoteInfo=voteinfo)
context["error"] = "You've already voted for this proposal." context["error"] = "You've already voted for this proposal."
return render_proposal(request, context, proposal, voteinfo, voters, vote) return render_proposal(request, context, proposal, voteinfo, voters, vote)
@ -286,17 +285,17 @@ async def package_maintainer_proposal_post(
@router.get("/addvote") @router.get("/addvote")
@requires_auth @requires_auth
async def package_maintainer_addvote( async def trusted_user_addvote(
request: Request, user: str = str(), type: str = "add_pm", agenda: str = str() request: Request, user: str = str(), type: str = "add_tu", agenda: str = str()
): ):
if not request.user.has_credential(creds.PM_ADD_VOTE): if not request.user.has_credential(creds.TU_ADD_VOTE):
return RedirectResponse("/package-maintainer", status_code=HTTPStatus.SEE_OTHER) return RedirectResponse("/tu", status_code=HTTPStatus.SEE_OTHER)
context = await make_variable_context(request, "Add Proposal") context = await make_variable_context(request, "Add Proposal")
if type not in ADDVOTE_SPECIFICS: if type not in ADDVOTE_SPECIFICS:
context["error"] = "Invalid type." context["error"] = "Invalid type."
type = "add_pm" # Default it. type = "add_tu" # Default it.
context["user"] = user context["user"] = user
context["type"] = type context["type"] = type
@ -309,14 +308,14 @@ async def package_maintainer_addvote(
@router.post("/addvote") @router.post("/addvote")
@handle_form_exceptions @handle_form_exceptions
@requires_auth @requires_auth
async def package_maintainer_addvote_post( async def trusted_user_addvote_post(
request: Request, request: Request,
user: str = Form(default=str()), user: str = Form(default=str()),
type: str = Form(default=str()), type: str = Form(default=str()),
agenda: str = Form(default=str()), agenda: str = Form(default=str()),
): ):
if not request.user.has_credential(creds.PM_ADD_VOTE): if not request.user.has_credential(creds.TU_ADD_VOTE):
return RedirectResponse("/package-maintainer", status_code=HTTPStatus.SEE_OTHER) return RedirectResponse("/tu", status_code=HTTPStatus.SEE_OTHER)
# Build a context. # Build a context.
context = await make_variable_context(request, "Add Proposal") context = await make_variable_context(request, "Add Proposal")
@ -338,8 +337,10 @@ async def package_maintainer_addvote_post(
utcnow = time.utcnow() utcnow = time.utcnow()
voteinfo = ( voteinfo = (
db.query(models.VoteInfo) db.query(models.TUVoteInfo)
.filter(and_(models.VoteInfo.User == user, models.VoteInfo.End > utcnow)) .filter(
and_(models.TUVoteInfo.User == user, models.TUVoteInfo.End > utcnow)
)
.count() .count()
) )
if voteinfo: if voteinfo:
@ -351,7 +352,7 @@ async def package_maintainer_addvote_post(
if type not in ADDVOTE_SPECIFICS: if type not in ADDVOTE_SPECIFICS:
context["error"] = "Invalid type." context["error"] = "Invalid type."
context["type"] = type = "add_pm" # Default for rendering. context["type"] = type = "add_tu" # Default for rendering.
return render_addvote(context, HTTPStatus.BAD_REQUEST) return render_addvote(context, HTTPStatus.BAD_REQUEST)
if not agenda: if not agenda:
@ -362,12 +363,12 @@ async def package_maintainer_addvote_post(
duration, quorum = ADDVOTE_SPECIFICS.get(type) duration, quorum = ADDVOTE_SPECIFICS.get(type)
timestamp = time.utcnow() timestamp = time.utcnow()
# Active PM types we filter for. # Active TU types we filter for.
types = {PACKAGE_MAINTAINER_ID, PACKAGE_MAINTAINER_AND_DEV_ID} types = {TRUSTED_USER_ID, TRUSTED_USER_AND_DEV_ID}
# Create a new VoteInfo (proposal)! # Create a new TUVoteInfo (proposal)!
with db.begin(): with db.begin():
active_pms = ( active_tus = (
db.query(User) db.query(User)
.filter( .filter(
and_( and_(
@ -379,16 +380,16 @@ async def package_maintainer_addvote_post(
.count() .count()
) )
voteinfo = db.create( voteinfo = db.create(
models.VoteInfo, models.TUVoteInfo,
User=user, User=user,
Agenda=html.escape(agenda), Agenda=html.escape(agenda),
Submitted=timestamp, Submitted=timestamp,
End=(timestamp + duration), End=(timestamp + duration),
Quorum=quorum, Quorum=quorum,
ActiveUsers=active_pms, ActiveTUs=active_tus,
Submitter=request.user, Submitter=request.user,
) )
# Redirect to the new proposal. # Redirect to the new proposal.
endpoint = f"/package-maintainer/{voteinfo.ID}" endpoint = f"/tu/{voteinfo.ID}"
return RedirectResponse(endpoint, status_code=HTTPStatus.SEE_OTHER) return RedirectResponse(endpoint, status_code=HTTPStatus.SEE_OTHER)

View file

@ -5,6 +5,7 @@ Changes here should always be accompanied by an Alembic migration, which can be
usually be automatically generated. See `migrations/README` for details. usually be automatically generated. See `migrations/README` for details.
""" """
from sqlalchemy import ( from sqlalchemy import (
CHAR, CHAR,
TIMESTAMP, TIMESTAMP,
@ -183,8 +184,6 @@ PackageBases = Table(
Index("BasesNumVotes", "NumVotes"), Index("BasesNumVotes", "NumVotes"),
Index("BasesPackagerUID", "PackagerUID"), Index("BasesPackagerUID", "PackagerUID"),
Index("BasesSubmitterUID", "SubmitterUID"), Index("BasesSubmitterUID", "SubmitterUID"),
Index("BasesSubmittedTS", "SubmittedTS"),
Index("BasesModifiedTS", "ModifiedTS"),
mysql_engine="InnoDB", mysql_engine="InnoDB",
mysql_charset="utf8mb4", mysql_charset="utf8mb4",
mysql_collate="utf8mb4_general_ci", mysql_collate="utf8mb4_general_ci",
@ -527,8 +526,8 @@ PackageRequests = Table(
# Vote information # Vote information
VoteInfo = Table( TU_VoteInfo = Table(
"VoteInfo", "TU_VoteInfo",
metadata, metadata,
Column("ID", INTEGER(unsigned=True), primary_key=True), Column("ID", INTEGER(unsigned=True), primary_key=True),
Column("Agenda", Text, nullable=False), Column("Agenda", Text, nullable=False),
@ -547,10 +546,7 @@ VoteInfo = Table(
"Abstain", INTEGER(unsigned=True), nullable=False, server_default=text("'0'") "Abstain", INTEGER(unsigned=True), nullable=False, server_default=text("'0'")
), ),
Column( Column(
"ActiveUsers", "ActiveTUs", INTEGER(unsigned=True), nullable=False, server_default=text("'0'")
INTEGER(unsigned=True),
nullable=False,
server_default=text("'0'"),
), ),
mysql_engine="InnoDB", mysql_engine="InnoDB",
mysql_charset="utf8mb4", mysql_charset="utf8mb4",
@ -559,10 +555,10 @@ VoteInfo = Table(
# Individual vote records # Individual vote records
Votes = Table( TU_Votes = Table(
"Votes", "TU_Votes",
metadata, metadata,
Column("VoteID", ForeignKey("VoteInfo.ID", ondelete="CASCADE"), nullable=False), Column("VoteID", ForeignKey("TU_VoteInfo.ID", ondelete="CASCADE"), nullable=False),
Column("UserID", ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False), Column("UserID", ForeignKey("Users.ID", ondelete="CASCADE"), nullable=False),
mysql_engine="InnoDB", mysql_engine="InnoDB",
) )

View file

@ -6,7 +6,6 @@ See `aurweb-adduser --help` for documentation.
Copyright (C) 2022 aurweb Development Team Copyright (C) 2022 aurweb Development Team
All Rights Reserved All Rights Reserved
""" """
import argparse import argparse
import sys import sys
import traceback import traceback

View file

@ -3,7 +3,6 @@ Perform an action on the aurweb config.
When AUR_CONFIG_IMMUTABLE is set, the `set` action is noop. When AUR_CONFIG_IMMUTABLE is set, the `set` action is noop.
""" """
import argparse import argparse
import configparser import configparser
import os import os

View file

@ -3,7 +3,7 @@ import importlib
import os import os
import sys import sys
import traceback import traceback
from datetime import UTC, datetime from datetime import datetime
import orjson import orjson
import pygit2 import pygit2
@ -60,7 +60,7 @@ def update_repository(repo: pygit2.Repository):
except pygit2.GitError: except pygit2.GitError:
base = [] base = []
utcnow = datetime.now(UTC) utcnow = datetime.utcnow()
author = pygit2.Signature( author = pygit2.Signature(
config.get("git-archive", "author"), config.get("git-archive", "author"),
config.get("git-archive", "author-email"), config.get("git-archive", "author-email"),

View file

@ -20,7 +20,7 @@ from aurweb.models.package_comment import PackageComment
from aurweb.models.package_notification import PackageNotification from aurweb.models.package_notification import PackageNotification
from aurweb.models.package_request import PackageRequest from aurweb.models.package_request import PackageRequest
from aurweb.models.request_type import RequestType from aurweb.models.request_type import RequestType
from aurweb.models.vote import Vote from aurweb.models.tu_vote import TUVote
logger = aur_logging.get_logger(__name__) logger = aur_logging.get_logger(__name__)
@ -744,11 +744,11 @@ class RequestCloseNotification(Notification):
return headers return headers
class VoteReminderNotification(Notification): class TUVoteReminderNotification(Notification):
def __init__(self, vote_id): def __init__(self, vote_id):
self._vote_id = int(vote_id) self._vote_id = int(vote_id)
subquery = db.query(Vote.UserID).filter(Vote.VoteID == vote_id) subquery = db.query(TUVote.UserID).filter(TUVote.VoteID == vote_id)
query = ( query = (
db.query(User) db.query(User)
.filter( .filter(
@ -769,7 +769,7 @@ class VoteReminderNotification(Notification):
def get_subject(self, lang): def get_subject(self, lang):
return aurweb.l10n.translator.translate( return aurweb.l10n.translator.translate(
"Package Maintainer Vote Reminder: Proposal {id}", lang "TU Vote Reminder: Proposal {id}", lang
).format(id=self._vote_id) ).format(id=self._vote_id)
def get_body(self, lang): def get_body(self, lang):
@ -780,7 +780,7 @@ class VoteReminderNotification(Notification):
).format(id=self._vote_id) ).format(id=self._vote_id)
def get_refs(self): def get_refs(self):
return (aur_location + "/package-maintainer/?id=" + str(self._vote_id),) return (aur_location + "/tu/?id=" + str(self._vote_id),)
def main(): def main():
@ -799,7 +799,7 @@ def main():
"delete": DeleteNotification, "delete": DeleteNotification,
"request-open": RequestOpenNotification, "request-open": RequestOpenNotification,
"request-close": RequestCloseNotification, "request-close": RequestCloseNotification,
"vote-reminder": VoteReminderNotification, "tu-vote-reminder": TUVoteReminderNotification,
} }
with db.begin(): with db.begin():

View file

@ -121,20 +121,6 @@ class HeadingExtension(markdown.extensions.Extension):
md.treeprocessors.register(HeadingTreeprocessor(md), "heading", 30) md.treeprocessors.register(HeadingTreeprocessor(md), "heading", 30)
class StrikethroughInlineProcessor(markdown.inlinepatterns.InlineProcessor):
def handleMatch(self, m, data):
el = Element("del")
el.text = m.group(1)
return el, m.start(0), m.end(0)
class StrikethroughExtension(markdown.extensions.Extension):
def extendMarkdown(self, md):
pattern = r"~~(.*?)~~"
processor = StrikethroughInlineProcessor(pattern, md)
md.inlinePatterns.register(processor, "del", 40)
def save_rendered_comment(comment: PackageComment, html: str): def save_rendered_comment(comment: PackageComment, html: str):
with db.begin(): with db.begin():
comment.RenderedComment = html comment.RenderedComment = html
@ -151,13 +137,11 @@ def update_comment_render(comment: PackageComment) -> None:
html = markdown.markdown( html = markdown.markdown(
text, text,
extensions=[ extensions=[
"md_in_html",
"fenced_code", "fenced_code",
LinkifyExtension(), LinkifyExtension(),
FlysprayLinksExtension(), FlysprayLinksExtension(),
GitCommitsExtension(pkgbasename), GitCommitsExtension(pkgbasename),
HeadingExtension(), HeadingExtension(),
StrikethroughExtension(),
], ],
) )
@ -169,9 +153,6 @@ def update_comment_render(comment: PackageComment) -> None:
"h6", "h6",
"br", "br",
"hr", "hr",
"del",
"details",
"summary",
] ]
html = bleach.clean(html, tags=allowed_tags) html = bleach.clean(html, tags=allowed_tags)
save_rendered_comment(comment, html) save_rendered_comment(comment, html)

View file

@ -4,7 +4,7 @@ from sqlalchemy import and_
import aurweb.config import aurweb.config
from aurweb import db, time from aurweb import db, time
from aurweb.models import VoteInfo from aurweb.models import TUVoteInfo
from aurweb.scripts import notify from aurweb.scripts import notify
notify_cmd = aurweb.config.get("notifications", "notify-cmd") notify_cmd = aurweb.config.get("notifications", "notify-cmd")
@ -15,17 +15,17 @@ def main():
now = time.utcnow() now = time.utcnow()
start = aurweb.config.getint("votereminder", "range_start") start = aurweb.config.getint("tuvotereminder", "range_start")
filter_from = now + start filter_from = now + start
end = aurweb.config.getint("votereminder", "range_end") end = aurweb.config.getint("tuvotereminder", "range_end")
filter_to = now + end filter_to = now + end
query = db.query(VoteInfo.ID).filter( query = db.query(TUVoteInfo.ID).filter(
and_(VoteInfo.End >= filter_from, VoteInfo.End <= filter_to) and_(TUVoteInfo.End >= filter_from, TUVoteInfo.End <= filter_to)
) )
for voteinfo in query: for voteinfo in query:
notif = notify.VoteReminderNotification(voteinfo.ID) notif = notify.TUVoteReminderNotification(voteinfo.ID)
notif.send() notif.send()

View file

@ -7,6 +7,7 @@ This module uses a global state, since you cant open two servers with the sam
configuration anyway. configuration anyway.
""" """
import argparse import argparse
import atexit import atexit
import os import os
@ -51,46 +52,46 @@ def generate_nginx_config():
fastapi_bind = aurweb.config.get("fastapi", "bind_address") fastapi_bind = aurweb.config.get("fastapi", "bind_address")
fastapi_host = fastapi_bind.split(":")[0] fastapi_host = fastapi_bind.split(":")[0]
config_path = os.path.join(temporary_dir, "nginx.conf") config_path = os.path.join(temporary_dir, "nginx.conf")
with open(config_path, "w") as config: config = open(config_path, "w")
# We double nginx's braces because they conflict with Python's f-strings. # We double nginx's braces because they conflict with Python's f-strings.
config.write( config.write(
f""" f"""
events {{}} events {{}}
daemon off; daemon off;
error_log /dev/stderr info; error_log /dev/stderr info;
pid {os.path.join(temporary_dir, "nginx.pid")}; pid {os.path.join(temporary_dir, "nginx.pid")};
http {{ http {{
access_log /dev/stdout; access_log /dev/stdout;
client_body_temp_path {os.path.join(temporary_dir, "client_body")}; client_body_temp_path {os.path.join(temporary_dir, "client_body")};
proxy_temp_path {os.path.join(temporary_dir, "proxy")}; proxy_temp_path {os.path.join(temporary_dir, "proxy")};
fastcgi_temp_path {os.path.join(temporary_dir, "fastcgi")}1 2; fastcgi_temp_path {os.path.join(temporary_dir, "fastcgi")}1 2;
uwsgi_temp_path {os.path.join(temporary_dir, "uwsgi")}; uwsgi_temp_path {os.path.join(temporary_dir, "uwsgi")};
scgi_temp_path {os.path.join(temporary_dir, "scgi")}; scgi_temp_path {os.path.join(temporary_dir, "scgi")};
server {{ server {{
listen {fastapi_host}:{FASTAPI_NGINX_PORT}; listen {fastapi_host}:{FASTAPI_NGINX_PORT};
location / {{ location / {{
try_files $uri @proxy_to_app; try_files $uri @proxy_to_app;
}} }}
location @proxy_to_app {{ location @proxy_to_app {{
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off; proxy_redirect off;
proxy_buffering off; proxy_buffering off;
proxy_pass http://{fastapi_bind}; proxy_pass http://{fastapi_bind};
}}
}} }}
}} }}
""" }}
) """
)
return config_path return config_path
def spawn_child(_args): def spawn_child(args):
"""Open a subprocess and add it to the global state.""" """Open a subprocess and add it to the global state."""
if verbosity >= 1: if verbosity >= 1:
print(f":: Spawning {_args}", file=sys.stderr) print(f":: Spawning {args}", file=sys.stderr)
children.append(subprocess.Popen(_args)) children.append(subprocess.Popen(args))
def start(): def start():
@ -171,17 +172,17 @@ def start():
) )
def _kill_children(_children: Iterable, exceptions=None) -> list[Exception]: def _kill_children(
children: Iterable, exceptions: list[Exception] = []
) -> list[Exception]:
""" """
Kill each process found in `children`. Kill each process found in `children`.
:param _children: Iterable of child processes :param children: Iterable of child processes
:param exceptions: Exception memo :param exceptions: Exception memo
:return: `exceptions` :return: `exceptions`
""" """
if exceptions is None: for p in children:
exceptions = []
for p in _children:
try: try:
p.terminate() p.terminate()
if verbosity >= 1: if verbosity >= 1:
@ -191,17 +192,17 @@ def _kill_children(_children: Iterable, exceptions=None) -> list[Exception]:
return exceptions return exceptions
def _wait_for_children(_children: Iterable, exceptions=None) -> list[Exception]: def _wait_for_children(
children: Iterable, exceptions: list[Exception] = []
) -> list[Exception]:
""" """
Wait for each process to end found in `children`. Wait for each process to end found in `children`.
:param _children: Iterable of child processes :param children: Iterable of child processes
:param exceptions: Exception memo :param exceptions: Exception memo
:return: `exceptions` :return: `exceptions`
""" """
if exceptions is None: for p in children:
exceptions = []
for p in _children:
try: try:
rc = p.wait() rc = p.wait()
if rc != 0 and rc != -15: if rc != 0 and rc != -15:

View file

@ -3,11 +3,7 @@ from sqlalchemy import func
from aurweb import config, db, time from aurweb import config, db, time
from aurweb.cache import db_count_cache, db_query_cache from aurweb.cache import db_count_cache, db_query_cache
from aurweb.models import PackageBase, PackageRequest, RequestType, User from aurweb.models import PackageBase, PackageRequest, RequestType, User
from aurweb.models.account_type import ( from aurweb.models.account_type import TRUSTED_USER_AND_DEV_ID, TRUSTED_USER_ID, USER_ID
PACKAGE_MAINTAINER_AND_DEV_ID,
PACKAGE_MAINTAINER_ID,
USER_ID,
)
from aurweb.models.package_request import ( from aurweb.models.package_request import (
ACCEPTED_ID, ACCEPTED_ID,
CLOSED_ID, CLOSED_ID,
@ -26,7 +22,7 @@ HOMEPAGE_COUNTERS = [
"year_old_updated", "year_old_updated",
"never_updated", "never_updated",
"user_count", "user_count",
"package_maintainer_count", "trusted_user_count",
] ]
REQUEST_COUNTERS = [ REQUEST_COUNTERS = [
"total_requests", "total_requests",
@ -36,7 +32,7 @@ REQUEST_COUNTERS = [
"rejected_requests", "rejected_requests",
] ]
PROMETHEUS_USER_COUNTERS = [ PROMETHEUS_USER_COUNTERS = [
("package_maintainer_count", "package_maintainer"), ("trusted_user_count", "tu"),
("regular_user_count", "user"), ("regular_user_count", "user"),
] ]
PROMETHEUS_PACKAGE_COUNTERS = [ PROMETHEUS_PACKAGE_COUNTERS = [
@ -96,12 +92,12 @@ class Statistics:
# Users # Users
case "user_count": case "user_count":
query = self.user_query query = self.user_query
case "package_maintainer_count": case "trusted_user_count":
query = self.user_query.filter( query = self.user_query.filter(
User.AccountTypeID.in_( User.AccountTypeID.in_(
( (
PACKAGE_MAINTAINER_ID, TRUSTED_USER_ID,
PACKAGE_MAINTAINER_AND_DEV_ID, TRUSTED_USER_AND_DEV_ID,
) )
) )
) )

View file

@ -3,6 +3,7 @@ import functools
import os import os
from http import HTTPStatus from http import HTTPStatus
from typing import Callable from typing import Callable
from zoneinfo import ZoneInfoNotFoundError
import jinja2 import jinja2
from fastapi import Request from fastapi import Request
@ -70,12 +71,14 @@ def make_context(request: Request, title: str, next: str = None):
commit_url = aurweb.config.get_with_fallback("devel", "commit_url", None) commit_url = aurweb.config.get_with_fallback("devel", "commit_url", None)
commit_hash = aurweb.config.get_with_fallback("devel", "commit_hash", None) commit_hash = aurweb.config.get_with_fallback("devel", "commit_hash", None)
max_chars_comment = aurweb.config.getint("options", "max_chars_comment", 5000)
if commit_hash: if commit_hash:
# Shorten commit_hash to a short Git hash. # Shorten commit_hash to a short Git hash.
commit_hash = commit_hash[:7] commit_hash = commit_hash[:7]
timezone = time.get_request_timezone(request) try:
timezone = time.get_request_timezone(request)
except ZoneInfoNotFoundError:
timezone = DEFAULT_TIMEZONE
language = l10n.get_request_language(request) language = l10n.get_request_language(request)
return { return {
"request": request, "request": request,
@ -93,7 +96,6 @@ def make_context(request: Request, title: str, next: str = None):
"creds": aurweb.auth.creds, "creds": aurweb.auth.creds,
"next": next if next else request.url.path, "next": next if next else request.url.path,
"version": os.environ.get("COMMIT_HASH", aurweb.config.AURWEB_VERSION), "version": os.environ.get("COMMIT_HASH", aurweb.config.AURWEB_VERSION),
"max_chars_comment": max_chars_comment,
} }
@ -108,7 +110,9 @@ async def make_variable_context(request: Request, title: str, next: str = None):
) )
for k, v in to_copy.items(): for k, v in to_copy.items():
if k not in context: if k == "timezone":
context[k] = v if v in time.SUPPORTED_TIMEZONES else DEFAULT_TIMEZONE
else:
context[k] = v context[k] = v
context["q"] = dict(request.query_params) context["q"] = dict(request.query_params)

View file

@ -51,8 +51,8 @@ def setup_test_db(*args):
models.Session.__tablename__, models.Session.__tablename__,
models.SSHPubKey.__tablename__, models.SSHPubKey.__tablename__,
models.Term.__tablename__, models.Term.__tablename__,
models.Vote.__tablename__, models.TUVote.__tablename__,
models.VoteInfo.__tablename__, models.TUVoteInfo.__tablename__,
models.User.__tablename__, models.User.__tablename__,
] ]

View file

@ -1,8 +0,0 @@
from aurweb import prometheus
def clear_metrics():
prometheus.PACKAGES.clear()
prometheus.REQUESTS.clear()
prometheus.SEARCH_REQUESTS.clear()
prometheus.USERS.clear()

View file

@ -1,6 +1,7 @@
import zoneinfo import zoneinfo
from collections import OrderedDict from collections import OrderedDict
from datetime import UTC, datetime from datetime import datetime
from urllib.parse import unquote
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
from fastapi import Request from fastapi import Request
@ -57,20 +58,16 @@ SUPPORTED_TIMEZONES = OrderedDict(
) )
def get_request_timezone(request: Request) -> str: def get_request_timezone(request: Request):
"""Get a request's timezone from either query param or user settings. """Get a request's timezone by its AURTZ cookie. We use the
We use the configuration's [options] default_timezone otherwise. configuration's [options] default_timezone otherwise.
@param request FastAPI request @param request FastAPI request
""" """
request_tz = request.query_params.get("timezone") default_tz = aurweb.config.get("options", "default_timezone")
if request_tz and request_tz in SUPPORTED_TIMEZONES: if request.user.is_authenticated():
return request_tz default_tz = request.user.Timezone
elif ( return unquote(request.cookies.get("AURTZ", default_tz))
request.user.is_authenticated() and request.user.Timezone in SUPPORTED_TIMEZONES
):
return request.user.Timezone
return aurweb.config.get_with_fallback("options", "default_timezone", "UTC")
def now(timezone: str) -> datetime: def now(timezone: str) -> datetime:
@ -89,4 +86,4 @@ def utcnow() -> int:
:return: Current UTC timestamp :return: Current UTC timestamp
""" """
return int(datetime.now(UTC).timestamp()) return int(datetime.utcnow().timestamp())

View file

@ -6,7 +6,6 @@ out of form data from /account/register or /account/{username}/edit.
All functions in this module raise aurweb.exceptions.ValidationError All functions in this module raise aurweb.exceptions.ValidationError
when encountering invalid criteria and return silently otherwise. when encountering invalid criteria and return silently otherwise.
""" """
from fastapi import Request from fastapi import Request
from sqlalchemy import and_ from sqlalchemy import and_
@ -57,9 +56,12 @@ def invalid_password(
) -> None: ) -> None:
if P: if P:
if not util.valid_password(P): if not util.valid_password(P):
passwd_min_len = config.getint("options", "passwd_min_len") username_min_len = config.getint("options", "username_min_len")
raise ValidationError( raise ValidationError(
[_("Your password must be at least %s characters.") % (passwd_min_len)] [
_("Your password must be at least %s characters.")
% (username_min_len)
]
) )
elif not C: elif not C:
raise ValidationError(["Please confirm your new password."]) raise ValidationError(["Please confirm your new password."])
@ -68,7 +70,7 @@ def invalid_password(
def is_banned(request: Request = None, **kwargs) -> None: def is_banned(request: Request = None, **kwargs) -> None:
host = util.get_client_ip(request) host = request.client.host
exists = db.query(models.Ban, models.Ban.IPAddress == host).exists() exists = db.query(models.Ban, models.Ban.IPAddress == host).exists()
if db.query(exists).scalar(): if db.query(exists).scalar():
raise ValidationError( raise ValidationError(
@ -218,7 +220,7 @@ def invalid_account_type(
raise ValidationError([error]) raise ValidationError([error])
logger.debug( logger.debug(
f"Package Maintainer '{request.user.Username}' has " f"Trusted User '{request.user.Username}' has "
f"modified '{user.Username}' account's type to" f"modified '{user.Username}' account's type to"
f" {name}." f" {name}."
) )

View file

@ -208,11 +208,3 @@ def hash_query(query: Query):
return sha1( return sha1(
str(query.statement.compile(compile_kwargs={"literal_binds": True})).encode() str(query.statement.compile(compile_kwargs={"literal_binds": True})).encode()
).hexdigest() ).hexdigest()
def get_client_ip(request: fastapi.Request) -> str:
"""
Returns the client's IP address for a Request.
Falls back to 'testclient' if request.client is None
"""
return request.client.host if request.client else "testclient"

View file

@ -1,61 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/dns" {
version = "3.3.2"
hashes = [
"h1:HjskPLRqmCw8Q/kiSuzti3iJBSpcAvcBFdlwFFQuoDE=",
"zh:05d2d50e301318362a4a82e6b7a9734ace07bc01abaaa649c566baf98814755f",
"zh:1e9fd1c3bfdda777e83e42831dd45b7b9e794250a0f351e5fd39762e8a0fe15b",
"zh:40e715fc7a2ede21f919567249b613844692c2f8a64f93ee64e5b68bae7ac2a2",
"zh:454d7aa83000a6e2ba7a7bfde4bcf5d7ed36298b22d760995ca5738ab02ee468",
"zh:46124ded51b4153ad90f12b0305fdbe0c23261b9669aa58a94a31c9cca2f4b19",
"zh:55a4f13d20f73534515a6b05701abdbfc54f4e375ba25b2dffa12afdad20e49d",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:7903b1ceb8211e2b8c79290e2e70906a4b88f4fba71c900eb3a425ce12f1716a",
"zh:b79fc4f444ef7a2fd7111a80428c070ad824f43a681699e99ab7f83074dfedbd",
"zh:ca9f45e0c4cb94e7d62536c226024afef3018b1de84f1ea4608b51bcd497a2a0",
"zh:ddc8bd894559d7d176e0ceb0bb1ae266519b01b315362ebfee8327bb7e7e5fa8",
"zh:e77334c0794ef8f9354b10e606040f6b0b67b373f5ff1db65bddcdd4569b428b",
]
}
provider "registry.terraform.io/hashicorp/tls" {
version = "4.0.4"
hashes = [
"h1:pe9vq86dZZKCm+8k1RhzARwENslF3SXb9ErHbQfgjXU=",
"zh:23671ed83e1fcf79745534841e10291bbf34046b27d6e68a5d0aab77206f4a55",
"zh:45292421211ffd9e8e3eb3655677700e3c5047f71d8f7650d2ce30242335f848",
"zh:59fedb519f4433c0fdb1d58b27c210b27415fddd0cd73c5312530b4309c088be",
"zh:5a8eec2409a9ff7cd0758a9d818c74bcba92a240e6c5e54b99df68fff312bbd5",
"zh:5e6a4b39f3171f53292ab88058a59e64825f2b842760a4869e64dc1dc093d1fe",
"zh:810547d0bf9311d21c81cc306126d3547e7bd3f194fc295836acf164b9f8424e",
"zh:824a5f3617624243bed0259d7dd37d76017097dc3193dac669be342b90b2ab48",
"zh:9361ccc7048be5dcbc2fafe2d8216939765b3160bd52734f7a9fd917a39ecbd8",
"zh:aa02ea625aaf672e649296bce7580f62d724268189fe9ad7c1b36bb0fa12fa60",
"zh:c71b4cd40d6ec7815dfeefd57d88bc592c0c42f5e5858dcc88245d371b4b8b1e",
"zh:dabcd52f36b43d250a3d71ad7abfa07b5622c69068d989e60b79b2bb4f220316",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}
provider "registry.terraform.io/hetznercloud/hcloud" {
version = "1.42.0"
hashes = [
"h1:cr9lh26H3YbWSHb7OUnCoYw169cYO3Cjpt3yPnRhXS0=",
"zh:153b5f39d780e9a18bc1ea377d872647d328d943813cbd25d3d20863f8a37782",
"zh:35b9e95760c58cca756e34ad5f4138ac6126aa3e8c41b4a0f1d5dc9ee5666c73",
"zh:47a3cdbce982f2b4e17f73d4934bdb3e905a849b36fb59b80f87d852496ed049",
"zh:6a718c244c2ba300fbd43791661a061ad1ab16225ef3e8aeaa3db8c9eff12c85",
"zh:a2cbfc95c5e2c9422ed0a7b6292192c38241220d5b7813c678f937ab3ef962ae",
"zh:b837e118e08fd36aa8be48af7e9d0d3d112d2680c79cfc71cfe2501fb40dbefa",
"zh:bf66db8c680e18b77e16dc1f20ed1cdcc7876bfb7848c320ccb86f0fb80661ed",
"zh:c1ad80bbe48dc8a272a02dcdb4b12f019606f445606651c01e561b9d72d816b1",
"zh:d4e616701128ad14a6b5a427b0e9145ece4cad02aa3b5f9945c6d0b9ada8ab70",
"zh:d9d01f727037d028720100a5bc9fd213cb01e63e4b439a16f2f482c147976530",
"zh:dea047ee4d679370d4376fb746c4b959bf51dd06047c1c2656b32789c2433643",
"zh:e5ad7a3c556894bd40b28a874e7d2f6924876fa75fa443136a7d6ab9a00abbaa",
"zh:edf6e7e129157bd45e3da4a330d1ace17a336d417c3b77c620f302d440c368e8",
"zh:f610bc729866d58da9cffa4deae34dbfdba96655e855a87c6bb2cb7b35a8961c",
]
}

View file

@ -1,67 +0,0 @@
terraform {
backend "http" {
}
}
provider "hcloud" {
token = var.hcloud_token
}
provider "dns" {
update {
server = var.dns_server
key_name = var.dns_tsig_key
key_algorithm = var.dns_tsig_algorithm
key_secret = var.dns_tsig_secret
}
}
resource "tls_private_key" "this" {
algorithm = "ED25519"
}
resource "hcloud_ssh_key" "this" {
name = var.name
public_key = tls_private_key.this.public_key_openssh
}
data "hcloud_image" "this" {
with_selector = "custom_image=archlinux"
most_recent = true
with_status = ["available"]
}
resource "hcloud_server" "this" {
name = var.name
image = data.hcloud_image.this.id
server_type = var.server_type
datacenter = var.datacenter
ssh_keys = [hcloud_ssh_key.this.name]
public_net {
ipv4_enabled = true
ipv6_enabled = true
}
}
resource "hcloud_rdns" "this" {
for_each = { ipv4 : hcloud_server.this.ipv4_address, ipv6 : hcloud_server.this.ipv6_address }
server_id = hcloud_server.this.id
ip_address = each.value
dns_ptr = "${var.name}.${var.dns_zone}"
}
resource "dns_a_record_set" "this" {
zone = "${var.dns_zone}."
name = var.name
addresses = [hcloud_server.this.ipv4_address]
ttl = 300
}
resource "dns_aaaa_record_set" "this" {
zone = "${var.dns_zone}."
name = var.name
addresses = [hcloud_server.this.ipv6_address]
ttl = 300
}

View file

@ -1,4 +0,0 @@
server_type = "cpx11"
datacenter = "fsn1-dc14"
dns_server = "redirect.archlinux.org"
dns_zone = "sandbox.archlinux.page"

View file

@ -1,36 +0,0 @@
variable "hcloud_token" {
type = string
sensitive = true
}
variable "dns_server" {
type = string
}
variable "dns_tsig_key" {
type = string
}
variable "dns_tsig_algorithm" {
type = string
}
variable "dns_tsig_secret" {
type = string
}
variable "dns_zone" {
type = string
}
variable "name" {
type = string
}
variable "server_type" {
type = string
}
variable "datacenter" {
type = string
}

View file

@ -1,13 +0,0 @@
terraform {
required_providers {
tls = {
source = "hashicorp/tls"
}
hcloud = {
source = "hetznercloud/hcloud"
}
dns = {
source = "hashicorp/dns"
}
}
}

View file

@ -47,6 +47,6 @@ commit_parsers = [
# filter out the commits that are not matched by commit parsers # filter out the commits that are not matched by commit parsers
filter_commits = false filter_commits = false
# glob pattern for matching git tags # glob pattern for matching git tags
tag_pattern = "v[0-9]." tag_pattern = "*[0-9]*"
# regex for skipping tags # regex for skipping tags
skip_tags = "v0.1.0-beta.1" skip_tags = "v0.1.0-beta.1"

View file

@ -49,8 +49,6 @@ salt_rounds = 12
redis_address = redis://localhost redis_address = redis://localhost
; Toggles traceback display in templates/errors/500.html. ; Toggles traceback display in templates/errors/500.html.
traceback = 0 traceback = 0
; Maximum number of characters for a comment
max_chars_comment = 5000
[ratelimit] [ratelimit]
request_limit = 4000 request_limit = 4000
@ -160,10 +158,10 @@ commit_url = https://gitlab.archlinux.org/archlinux/aurweb/-/commits/%s
; sed -r "s/^;?(commit_hash) =.*$/\1 = $(git rev-parse HEAD)/" config ; sed -r "s/^;?(commit_hash) =.*$/\1 = $(git rev-parse HEAD)/" config
;commit_hash = 1234567 ;commit_hash = 1234567
[votereminder] [tuvotereminder]
; Offsets used to determine when Package Maintainers should be reminded about ; Offsets used to determine when TUs should be reminded about
; votes that they should make. ; votes that they should make.
; Reminders will be sent out for all votes that a Package Maintainer has not yet ; Reminders will be sent out for all votes that a TU has not yet
; voted on based on `now + range_start <= End <= now + range_end`. ; voted on based on `now + range_start <= End <= now + range_end`.
range_start = 500 range_start = 500
range_end = 172800 range_end = 172800
@ -175,8 +173,3 @@ max_search_entries = 50000
expiry_time_search = 600 expiry_time_search = 600
; number of seconds after a cache entry for statistics queries expires, default is 5 minutes ; number of seconds after a cache entry for statistics queries expires, default is 5 minutes
expiry_time_statistics = 300 expiry_time_statistics = 300
; number of seconds after a cache entry for rss queries expires, default is 5 minutes
expiry_time_rss = 300
[tracing]
otlp_endpoint = http://localhost:4318/v1/traces

View file

@ -73,6 +73,3 @@ pkgnames-repo = pkgnames.git
[aurblup] [aurblup]
db-path = YOUR_AUR_ROOT/aurblup/ db-path = YOUR_AUR_ROOT/aurblup/
[tracing]
otlp_endpoint = http://tempo:4318/v1/traces

View file

@ -35,7 +35,7 @@ usually points to the git-serve program.
If SSH has been configured to pass on the AUR_OVERWRITE environment variable If SSH has been configured to pass on the AUR_OVERWRITE environment variable
(via SendEnv, see ssh_config(5) for details) and the user's account is a (via SendEnv, see ssh_config(5) for details) and the user's account is a
registered Package Maintainer or Developer, this will be passed on to the git-update registered Trusted User or Developer, this will be passed on to the git-update
program in order to enable a non-fast-forward push. program in order to enable a non-fast-forward push.
The INSTALL file in the top-level directory contains detailed instructions on The INSTALL file in the top-level directory contains detailed instructions on
@ -70,8 +70,8 @@ The Update Hook: git-update
The Git update hook, called git-update, performs several subtasks: The Git update hook, called git-update, performs several subtasks:
* Prevent from creating branches or tags other than master. * Prevent from creating branches or tags other than master.
* Deny non-fast-forwards, except for Package Maintainers and Developers. * Deny non-fast-forwards, except for Trusted Users and Developers.
* Deny blacklisted packages, except for Package Maintainers and Developers. * Deny blacklisted packages, except for Trusted Users and Developers.
* Verify each new commit (validate meta data, impose file size limits, ...) * Verify each new commit (validate meta data, impose file size limits, ...)
* Update package base information and package information in the database. * Update package base information and package information in the database.
* Update the named branch and the namespaced HEAD ref of the package. * Update the named branch and the namespaced HEAD ref of the package.
@ -109,7 +109,7 @@ is also recommended to disable automatic garbage collection by setting
receive.autogc to false. Remember to periodically run `git gc` manually or receive.autogc to false. Remember to periodically run `git gc` manually or
setup a maintenance script which initiates the garbage collection if you follow setup a maintenance script which initiates the garbage collection if you follow
this advice. For gc.pruneExpire, we recommend "3.months.ago", such that commits this advice. For gc.pruneExpire, we recommend "3.months.ago", such that commits
that became unreachable by Package Maintainer intervention are kept for a while. that became unreachable by TU intervention are kept for a while.
Script Wrappers (poetry) Script Wrappers (poetry)
------------------------ ------------------------

View file

@ -3,9 +3,9 @@ aurweb Translation
This document describes how to create and maintain aurweb translations. This document describes how to create and maintain aurweb translations.
Creating an aurweb translation requires a Transifex (https://app.transifex.com/) Creating an aurweb translation requires a Transifex (http://www.transifex.com/)
account. You will need to register with a translation team on the aurweb account. You will need to register with a translation team on the aurweb
project page (https://app.transifex.com/lfleischer/aurweb/). project page (http://www.transifex.com/projects/p/aurweb/).
Creating a New Translation Creating a New Translation
@ -21,23 +21,23 @@ strings for the translation to be usable, and it may have to be disabled.
1. Check out the aurweb source using git: 1. Check out the aurweb source using git:
$ git clone https://gitlab.archlinux.org/archlinux/aurweb.git aurweb-git $ git clone https://gitlab.archlinux.org/archlinux/aurweb.git aurweb-git
2. Go into the "po/" directory in the aurweb source and run [msginit(1)][msginit] to 2. Go into the "po/" directory in the aurweb source and run msginit(1) to
create a initial translation file from our translation catalog: create a initial translation file from our translation catalog:
$ cd aurweb-git $ cd aurweb-git
$ git checkout master $ git checkout master
$ git pull $ git pull
$ cd po $ cd po
$ msginit -l <locale> -o <locale>.po -i aurweb.pot $ msginit -l <locale> -o <locale>.po -i aurweb.pot
3. Use some editor or a translation helper like poedit to add translations: 3. Use some editor or a translation helper like poedit to add translations:
$ poedit <locale>.po $ poedit <locale>.po
5. If you have a working aurweb setup, add a line for the new translation in 5. If you have a working aurweb setup, add a line for the new translation in
"po/Makefile" and test if everything looks right. "web/lib/config.inc.php.proto" and test if everything looks right.
6. Upload the newly created ".po" file to Transifex. If you don't like the web 6. Upload the newly created ".po" file to Transifex. If you don't like the web
interface, you can also use transifex-client to do that (see below). interface, you can also use transifex-client to do that (see below).
@ -49,15 +49,13 @@ Updating an Existing Translation
1. Download current translation files from Transifex. You can also do this 1. Download current translation files from Transifex. You can also do this
using transifex-client which is available through the AUR: using transifex-client which is available through the AUR:
$ tx pull -a $ tx pull -a
2. Update the existing translation file using an editor or a tool like poedit: 2. Update the existing translation file using an editor or a tool like poedit:
$ poedit po/<locale>.po $ poedit po/<locale>.po
3. Push the updated translation file back to Transifex. Using transifex-client, 3. Push the updated translation file back to Transifex. Using transifex-client,
this works as follows: this works as follows:
$ tx push -r aurweb.aurwebpot -t -l <locale> $ tx push -r aurweb.aurwebpot -t -l <locale>
[msginit]: https://man.archlinux.org/man/msginit.1

View file

@ -12,8 +12,8 @@ package maintenance from the command-line. More details can be found in
The web interface can be used to browse packages, view package details, manage The web interface can be used to browse packages, view package details, manage
aurweb accounts, add comments, vote for packages, flag packages, and submit aurweb accounts, add comments, vote for packages, flag packages, and submit
requests. Package Maintainers can update package maintainers and delete/merge requests. Trusted Users can update package maintainers and delete/merge
packages. The web interface also includes an area for Package Maintainers to post packages. The web interface also includes an area for Trusted Users to post
AUR-related proposals and vote on them. AUR-related proposals and vote on them.
The RPC interface can be used to query package information via HTTP. The RPC interface can be used to query package information via HTTP.
@ -62,8 +62,8 @@ computations and clean up the database:
the official repositories. It is also used to prevent users from uploading the official repositories. It is also used to prevent users from uploading
packages that are in the official repositories already. packages that are in the official repositories already.
* aurweb-votereminder sends out reminders if the voting period for a * aurweb-tuvotereminder sends out reminders to TUs if the voting period for a
Package Maintainer proposal ends soon. TU proposal ends soon.
* aurweb-popupdate is used to recompute the popularity score of packages. * aurweb-popupdate is used to recompute the popularity score of packages.
@ -107,13 +107,13 @@ usually scheduled using Cron. The current setup is:
2 */2 * * * poetry run aurweb-aurblup 2 */2 * * * poetry run aurweb-aurblup
3 */2 * * * poetry run aurweb-pkgmaint 3 */2 * * * poetry run aurweb-pkgmaint
4 */2 * * * poetry run aurweb-usermaint 4 */2 * * * poetry run aurweb-usermaint
5 */12 * * * poetry run aurweb-votereminder 5 */12 * * * poetry run aurweb-tuvotereminder
---- ----
Advanced Administrative Features Advanced Administrative Features
-------------------------------- --------------------------------
Package Maintainers can set the AUR_OVERWRITE environment variable to enable Trusted Users can set the AUR_OVERWRITE environment variable to enable
non-fast-forward pushes to the Git repositories. This feature is documented in non-fast-forward pushes to the Git repositories. This feature is documented in
`doc/git-interface.txt`. `doc/git-interface.txt`.

View file

@ -1,4 +1,5 @@
--- version: "3.8"
services: services:
ca: ca:
volumes: volumes:

View file

@ -1,10 +1,16 @@
--- version: "3.8"
services: services:
ca: ca:
volumes: volumes:
- ./data:/data - ./data:/data
- step:/root/.step - step:/root/.step
mariadb_init:
depends_on:
mariadb:
condition: service_healthy
git: git:
volumes: volumes:
- git_data:/aurweb/aur.git - git_data:/aurweb/aur.git
@ -15,6 +21,9 @@ services:
- git_data:/aurweb/aur.git - git_data:/aurweb/aur.git
- ./data:/data - ./data:/data
- smartgit_run:/var/run/smartgit - smartgit_run:/var/run/smartgit
depends_on:
mariadb:
condition: service_healthy
fastapi: fastapi:
volumes: volumes:

View file

@ -1,4 +1,3 @@
---
# #
# Docker service definitions for the aurweb project. # Docker service definitions for the aurweb project.
# #
@ -17,6 +16,8 @@
# #
# Copyright (C) 2021 aurweb Development # Copyright (C) 2021 aurweb Development
# All Rights Reserved. # All Rights Reserved.
version: "3.8"
services: services:
aurweb-image: aurweb-image:
build: . build: .
@ -48,7 +49,7 @@ services:
image: aurweb:latest image: aurweb:latest
init: true init: true
entrypoint: /docker/mariadb-entrypoint.sh entrypoint: /docker/mariadb-entrypoint.sh
command: /usr/bin/mariadbd-safe --datadir=/var/lib/mysql command: /usr/bin/mysqld_safe --datadir=/var/lib/mysql
ports: ports:
# This will expose mariadbd on 127.0.0.1:13306 in the host. # This will expose mariadbd on 127.0.0.1:13306 in the host.
# Ex: `mysql -uaur -paur -h 127.0.0.1 -P 13306 aurweb` # Ex: `mysql -uaur -paur -h 127.0.0.1 -P 13306 aurweb`
@ -80,7 +81,7 @@ services:
environment: environment:
- MARIADB_PRIVILEGED=1 - MARIADB_PRIVILEGED=1
entrypoint: /docker/mariadb-entrypoint.sh entrypoint: /docker/mariadb-entrypoint.sh
command: /usr/bin/mariadbd-safe --datadir=/var/lib/mysql command: /usr/bin/mysqld_safe --datadir=/var/lib/mysql
ports: ports:
# This will expose mariadbd on 127.0.0.1:13307 in the host. # This will expose mariadbd on 127.0.0.1:13307 in the host.
# Ex: `mysql -uaur -paur -h 127.0.0.1 -P 13306 aurweb` # Ex: `mysql -uaur -paur -h 127.0.0.1 -P 13306 aurweb`
@ -106,10 +107,8 @@ services:
test: "bash /docker/health/sshd.sh" test: "bash /docker/health/sshd.sh"
interval: 3s interval: 3s
depends_on: depends_on:
mariadb:
condition: service_healthy
mariadb_init: mariadb_init:
condition: service_completed_successfully condition: service_started
volumes: volumes:
- mariadb_run:/var/run/mysqld - mariadb_run:/var/run/mysqld
@ -123,9 +122,6 @@ services:
healthcheck: healthcheck:
test: "bash /docker/health/smartgit.sh" test: "bash /docker/health/smartgit.sh"
interval: 3s interval: 3s
depends_on:
mariadb:
condition: service_healthy
cgit-fastapi: cgit-fastapi:
image: aurweb:latest image: aurweb:latest
@ -156,10 +152,8 @@ services:
entrypoint: /docker/cron-entrypoint.sh entrypoint: /docker/cron-entrypoint.sh
command: /docker/scripts/run-cron.sh command: /docker/scripts/run-cron.sh
depends_on: depends_on:
mariadb:
condition: service_healthy
mariadb_init: mariadb_init:
condition: service_completed_successfully condition: service_started
volumes: volumes:
- ./aurweb:/aurweb/aurweb - ./aurweb:/aurweb/aurweb
- mariadb_run:/var/run/mysqld - mariadb_run:/var/run/mysqld
@ -188,12 +182,6 @@ services:
condition: service_healthy condition: service_healthy
cron: cron:
condition: service_started condition: service_started
mariadb:
condition: service_healthy
mariadb_init:
condition: service_completed_successfully
tempo:
condition: service_healthy
volumes: volumes:
- archives:/var/lib/aurweb/archives - archives:/var/lib/aurweb/archives
- mariadb_run:/var/run/mysqld - mariadb_run:/var/run/mysqld
@ -293,56 +281,6 @@ services:
- ./test:/aurweb/test - ./test:/aurweb/test
- ./templates:/aurweb/templates - ./templates:/aurweb/templates
grafana:
# TODO: check if we need init: true
image: grafana/grafana:11.1.3
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
- GF_AUTH_DISABLE_LOGIN_FORM=true
- GF_LOG_LEVEL=warn
# check if depends ar ecorrect, does stopping or restarting a child exit grafana?
depends_on:
prometheus:
condition: service_healthy
tempo:
condition: service_healthy
ports:
- "127.0.0.1:3000:3000"
volumes:
- ./docker/config/grafana/datasources:/etc/grafana/provisioning/datasources
prometheus:
image: prom/prometheus:latest
command:
- --config.file=/etc/prometheus/prometheus.yml
- --web.enable-remote-write-receiver
- --web.listen-address=prometheus:9090
healthcheck:
# TODO: check if there is a status route
test: "sh /docker/health/prometheus.sh"
interval: 3s
ports:
- "127.0.0.1:9090:9090"
volumes:
- ./docker/config/prometheus.yml:/etc/prometheus/prometheus.yml
- ./docker/health/prometheus.sh:/docker/health/prometheus.sh
tempo:
image: grafana/tempo:2.5.0
command:
- -config.file=/etc/tempo/config.yml
healthcheck:
# TODO: check if there is a status route
test: "sh /docker/health/tempo.sh"
interval: 3s
ports:
- "127.0.0.1:3200:3200"
- "127.0.0.1:4318:4318"
volumes:
- ./docker/config/tempo.yml:/etc/tempo/config.yml
- ./docker/health/tempo.sh:/docker/health/tempo.sh
volumes: volumes:
mariadb_test_run: {} mariadb_test_run: {}
mariadb_run: {} # Share /var/run/mysqld/mysqld.sock mariadb_run: {} # Share /var/run/mysqld/mysqld.sock

View file

@ -47,7 +47,7 @@ Luckily such data can be generated.
docker compose exec fastapi /bin/bash docker compose exec fastapi /bin/bash
pacman -S words fortune-mod pacman -S words fortune-mod
./schema/gendummydata.py dummy.sql ./schema/gendummydata.py dummy.sql
mariadb aurweb < dummy.sql mysql aurweb < dummy.sql
``` ```
The generation script may prompt you to install other Arch packages before it The generation script may prompt you to install other Arch packages before it

View file

@ -4,4 +4,4 @@ AUR_CONFIG='/aurweb/conf/config'
*/2 * * * * bash -c 'aurweb-pkgmaint' */2 * * * * bash -c 'aurweb-pkgmaint'
*/2 * * * * bash -c 'aurweb-usermaint' */2 * * * * bash -c 'aurweb-usermaint'
*/2 * * * * bash -c 'aurweb-popupdate' */2 * * * * bash -c 'aurweb-popupdate'
*/12 * * * * bash -c 'aurweb-votereminder' */12 * * * * bash -c 'aurweb-tuvotereminder'

View file

@ -1,42 +0,0 @@
---
apiVersion: 1
deleteDatasources:
- name: Prometheus
- name: Tempo
datasources:
- name: Prometheus
type: prometheus
uid: prometheus
access: proxy
url: http://prometheus:9090
orgId: 1
editable: false
jsonData:
timeInterval: 1m
- name: Tempo
type: tempo
uid: tempo
access: proxy
url: http://tempo:3200
orgId: 1
editable: false
jsonData:
tracesToMetrics:
datasourceUid: 'prometheus'
spanStartTimeShift: '1h'
spanEndTimeShift: '-1h'
serviceMap:
datasourceUid: 'prometheus'
nodeGraph:
enabled: true
search:
hide: false
traceQuery:
timeShiftEnabled: true
spanStartTimeShift: '1h'
spanEndTimeShift: '-1h'
spanBar:
type: 'Tag'
tag: 'http.path'

View file

@ -1,15 +0,0 @@
---
global:
scrape_interval: 60s
scrape_configs:
- job_name: tempo
static_configs:
- targets: ['tempo:3200']
labels:
instance: tempo
- job_name: aurweb
static_configs:
- targets: ['fastapi:8000']
labels:
instance: aurweb

View file

@ -1,54 +0,0 @@
---
stream_over_http_enabled: true
server:
http_listen_address: tempo
http_listen_port: 3200
log_level: info
query_frontend:
search:
duration_slo: 5s
throughput_bytes_slo: 1.073741824e+09
trace_by_id:
duration_slo: 5s
distributor:
receivers:
otlp:
protocols:
http:
endpoint: tempo:4318
log_received_spans:
enabled: false
metric_received_spans:
enabled: false
ingester:
max_block_duration: 5m
compactor:
compaction:
block_retention: 1h
metrics_generator:
registry:
external_labels:
source: tempo
storage:
path: /tmp/tempo/generator/wal
remote_write:
- url: http://prometheus:9090/api/v1/write
send_exemplars: true
traces_storage:
path: /tmp/tempo/generator/traces
storage:
trace:
backend: local
wal:
path: /tmp/tempo/wal
local:
path: /tmp/tempo/blocks
overrides:
metrics_generator_processors: [service-graphs, span-metrics, local-blocks]

View file

@ -1,2 +1,2 @@
#!/bin/bash #!/bin/bash
exec mariadb-admin ping --silent exec mysqladmin ping --silent

View file

@ -1,2 +0,0 @@
#!/bin/sh
exec wget -q http://prometheus:9090/status -O /dev/null

View file

@ -1,2 +0,0 @@
#!/bin/sh
exec wget -q http://tempo:3200/status -O /dev/null

View file

@ -6,8 +6,8 @@ MYSQL_DATA=/var/lib/mysql
mariadb-install-db --user=mysql --basedir=/usr --datadir=$MYSQL_DATA mariadb-install-db --user=mysql --basedir=/usr --datadir=$MYSQL_DATA
# Start it up. # Start it up.
mariadbd-safe --datadir=$MYSQL_DATA --skip-networking & mysqld_safe --datadir=$MYSQL_DATA --skip-networking &
while ! mariadb-admin ping 2>/dev/null; do while ! mysqladmin ping 2>/dev/null; do
sleep 1s sleep 1s
done done
@ -15,17 +15,17 @@ done
DATABASE="aurweb" # Persistent database for fastapi. DATABASE="aurweb" # Persistent database for fastapi.
echo "Taking care of primary database '${DATABASE}'..." echo "Taking care of primary database '${DATABASE}'..."
mariadb -u root -e "CREATE USER IF NOT EXISTS 'aur'@'localhost' IDENTIFIED BY 'aur';" mysql -u root -e "CREATE USER IF NOT EXISTS 'aur'@'localhost' IDENTIFIED BY 'aur';"
mariadb -u root -e "CREATE USER IF NOT EXISTS 'aur'@'%' IDENTIFIED BY 'aur';" mysql -u root -e "CREATE USER IF NOT EXISTS 'aur'@'%' IDENTIFIED BY 'aur';"
mariadb -u root -e "CREATE DATABASE IF NOT EXISTS $DATABASE;" mysql -u root -e "CREATE DATABASE IF NOT EXISTS $DATABASE;"
mariadb -u root -e "CREATE USER IF NOT EXISTS 'aur'@'%' IDENTIFIED BY 'aur';" mysql -u root -e "CREATE USER IF NOT EXISTS 'aur'@'%' IDENTIFIED BY 'aur';"
mariadb -u root -e "GRANT ALL ON aurweb.* TO 'aur'@'localhost';" mysql -u root -e "GRANT ALL ON aurweb.* TO 'aur'@'localhost';"
mariadb -u root -e "GRANT ALL ON aurweb.* TO 'aur'@'%';" mysql -u root -e "GRANT ALL ON aurweb.* TO 'aur'@'%';"
mariadb -u root -e "CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY 'aur';" mysql -u root -e "CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY 'aur';"
mariadb -u root -e "GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION;" mysql -u root -e "GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION;"
mariadb-admin -uroot shutdown mysqladmin -uroot shutdown
exec "$@" exec "$@"

View file

@ -13,7 +13,7 @@ pacman -Sy --noconfirm --noprogressbar archlinux-keyring
# Install other OS dependencies. # Install other OS dependencies.
pacman -Syu --noconfirm --noprogressbar \ pacman -Syu --noconfirm --noprogressbar \
git gpgme nginx redis openssh \ --cachedir .pkg-cache git gpgme nginx redis openssh \
mariadb mariadb-libs cgit-aurweb uwsgi uwsgi-plugin-cgi \ mariadb mariadb-libs cgit-aurweb uwsgi uwsgi-plugin-cgi \
python-pip pyalpm python-srcinfo curl libeatmydata cronie \ python-pip pyalpm python-srcinfo curl libeatmydata cronie \
python-poetry python-poetry-core step-cli step-ca asciidoc \ python-poetry python-poetry-core step-cli step-ca asciidoc \

View file

@ -1,7 +0,0 @@
from prometheus_client import multiprocess
def child_exit(server, worker): # pragma: no cover
"""This function is required for gunicorn customization
of prometheus multiprocessing."""
multiprocess.mark_process_dead(worker.pid)

View file

@ -1,29 +0,0 @@
"""add indices on PackageBases for RSS order by
Revision ID: 38e5b9982eea
Revises: 7d65d35fae45
Create Date: 2024-08-03 01:35:39.104283
"""
from alembic import op
# revision identifiers, used by Alembic.
revision = "38e5b9982eea"
down_revision = "7d65d35fae45"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_index("BasesModifiedTS", "PackageBases", ["ModifiedTS"], unique=False)
op.create_index("BasesSubmittedTS", "PackageBases", ["SubmittedTS"], unique=False)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index("BasesSubmittedTS", table_name="PackageBases")
op.drop_index("BasesModifiedTS", table_name="PackageBases")
# ### end Alembic commands ###

View file

@ -5,7 +5,6 @@ Revises: ef39fcd6e1cd
Create Date: 2021-05-17 14:23:00.008479 Create Date: 2021-05-17 14:23:00.008479
""" """
from alembic import op from alembic import op
import aurweb.config import aurweb.config

View file

@ -5,7 +5,6 @@ Revises: d64e5571bc8d
Create Date: 2022-09-22 18:08:03.280664 Create Date: 2022-09-22 18:08:03.280664
""" """
from alembic import op from alembic import op
from sqlalchemy.exc import OperationalError from sqlalchemy.exc import OperationalError

View file

@ -1,38 +0,0 @@
"""Rename TU to Package Maintainer
Revision ID: 6a64dd126029
Revises: c5a6a9b661a0
Create Date: 2023-09-01 13:48:15.315244
"""
from aurweb import db
from aurweb.models import AccountType
# revision identifiers, used by Alembic.
revision = "6a64dd126029"
down_revision = "c5a6a9b661a0"
branch_labels = None
depends_on = None
# AccountTypes
# ID 2 -> Trusted User / Package Maintainer
# ID 4 -> Trusted User & Developer / Package Maintainer & Developer
def upgrade():
with db.begin():
tu = db.query(AccountType).filter(AccountType.ID == 2).first()
tudev = db.query(AccountType).filter(AccountType.ID == 4).first()
tu.AccountType = "Package Maintainer"
tudev.AccountType = "Package Maintainer & Developer"
def downgrade():
with db.begin():
pm = db.query(AccountType).filter(AccountType.ID == 2).first()
pmdev = db.query(AccountType).filter(AccountType.ID == 4).first()
pm.AccountType = "Trusted User"
pmdev.AccountType = "Trusted User & Developer"

View file

@ -1,48 +0,0 @@
"""Rename TU tables/columns
Revision ID: 7d65d35fae45
Revises: 6a64dd126029
Create Date: 2023-09-10 10:21:33.092342
"""
from alembic import op
from sqlalchemy.dialects.mysql import INTEGER
# revision identifiers, used by Alembic.
revision = "7d65d35fae45"
down_revision = "6a64dd126029"
branch_labels = None
depends_on = None
# TU_VoteInfo -> VoteInfo
# TU_VoteInfo.ActiveTUs -> VoteInfo.ActiveUsers
# TU_Votes -> Votes
def upgrade():
# Tables
op.rename_table("TU_VoteInfo", "VoteInfo")
op.rename_table("TU_Votes", "Votes")
# Columns
op.alter_column(
"VoteInfo",
"ActiveTUs",
existing_type=INTEGER(unsigned=True),
new_column_name="ActiveUsers",
)
def downgrade():
# Tables
op.rename_table("VoteInfo", "TU_VoteInfo")
op.rename_table("Votes", "TU_Votes")
# Columns
op.alter_column(
"TU_VoteInfo",
"ActiveUsers",
existing_type=INTEGER(unsigned=True),
new_column_name="ActiveTUs",
)

View file

@ -5,7 +5,6 @@ Revises: 6441d3b65270
Create Date: 2022-10-17 11:11:46.203322 Create Date: 2022-10-17 11:11:46.203322
""" """
from alembic import op from alembic import op
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.

View file

@ -15,7 +15,6 @@ Revision ID: be7adae47ac3
Revises: 56e2ce8e2ffa Revises: 56e2ce8e2ffa
Create Date: 2022-01-06 14:37:07.899778 Create Date: 2022-01-06 14:37:07.899778
""" """
from alembic import op from alembic import op
from sqlalchemy.dialects.mysql import INTEGER, TINYINT from sqlalchemy.dialects.mysql import INTEGER, TINYINT

View file

@ -5,7 +5,6 @@ Revises: e4e49ffce091
Create Date: 2023-07-02 13:46:52.522146 Create Date: 2023-07-02 13:46:52.522146
""" """
from alembic import op from alembic import op
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.

View file

@ -5,7 +5,6 @@ Revises: be7adae47ac3
Create Date: 2022-02-18 12:47:05.322766 Create Date: 2022-02-18 12:47:05.322766
""" """
from datetime import datetime from datetime import datetime
import sqlalchemy as sa import sqlalchemy as sa

View file

@ -5,7 +5,6 @@ Revises: 9e3158957fd7
Create Date: 2023-04-19 23:24:25.854874 Create Date: 2023-04-19 23:24:25.854874
""" """
from alembic import op from alembic import op
from sqlalchemy.exc import OperationalError from sqlalchemy.exc import OperationalError

View file

@ -5,7 +5,6 @@ Revises: f47cad5d6d03
Create Date: 2020-06-08 10:04:13.898617 Create Date: 2020-06-08 10:04:13.898617
""" """
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op from alembic import op
from sqlalchemy.engine.reflection import Inspector from sqlalchemy.engine.reflection import Inspector

View file

@ -4,7 +4,6 @@ Revision ID: f47cad5d6d03
Create Date: 2020-02-23 13:23:32.331396 Create Date: 2020-02-23 13:23:32.331396
""" """
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = "f47cad5d6d03" revision = "f47cad5d6d03"
down_revision = None down_revision = None

131
po/ar.po
View file

@ -12,7 +12,7 @@ msgstr ""
"POT-Creation-Date: 2020-01-31 09:29+0100\n" "POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2011-04-10 13:21+0000\n" "PO-Revision-Date: 2011-04-10 13:21+0000\n"
"Last-Translator: صفا الفليج <safaalfulaij@hotmail.com>, 2015-2016\n" "Last-Translator: صفا الفليج <safaalfulaij@hotmail.com>, 2015-2016\n"
"Language-Team: Arabic (http://app.transifex.com/lfleischer/aurweb/language/ar/)\n" "Language-Team: Arabic (http://www.transifex.com/lfleischer/aurweb/language/ar/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -133,15 +133,15 @@ msgid "Type"
msgstr "النّوع" msgstr "النّوع"
#: html/addvote.php #: html/addvote.php
msgid "Addition of a Package Maintainer" msgid "Addition of a TU"
msgstr "" msgstr "إضافة م‌م"
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer" msgid "Removal of a TU"
msgstr "" msgstr "إزالة م‌م"
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer (undeclared inactivity)" msgid "Removal of a TU (undeclared inactivity)"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
@ -199,10 +199,9 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"Welcome to the AUR! Please read the %sAUR User Guidelines%s for more " "Welcome to the AUR! Please read the %sAUR User Guidelines%s and %sAUR TU "
"information and the %sAUR Submission Guidelines%s if you want to contribute " "Guidelines%s for more information."
"a PKGBUILD." msgstr "مرحبًا بك في م‌م‌آ! فضلًا اقرأ %sإرشادات مستخدمي م‌م‌آ%s و%sإرشادات مستخدمي م‌م‌آ الموثوقين (م‌م)%s لمعلومات أكثر."
msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
@ -216,8 +215,8 @@ msgid "Remember to vote for your favourite packages!"
msgstr "تذكّر أن تصوّت لحزمك المفضّلة!" msgstr "تذكّر أن تصوّت لحزمك المفضّلة!"
#: html/home.php #: html/home.php
msgid "Some packages may be provided as binaries in [extra]." msgid "Some packages may be provided as binaries in [community]."
msgstr "قد تكون بعض الحزم متوفّرة كثنائيّات في مستودع المجتمع [extra]." msgstr "قد تكون بعض الحزم متوفّرة كثنائيّات في مستودع المجتمع [community]."
#: html/home.php #: html/home.php
msgid "DISCLAIMER" msgid "DISCLAIMER"
@ -266,8 +265,8 @@ msgstr "طلب الحذف"
msgid "" msgid ""
"Request a package to be removed from the Arch User Repository. Please do not" "Request a package to be removed from the Arch User Repository. Please do not"
" use this if a package is broken and can be fixed easily. Instead, contact " " use this if a package is broken and can be fixed easily. Instead, contact "
"the maintainer and file orphan request if necessary." "the package maintainer and file orphan request if necessary."
msgstr "" msgstr "اطلب أن تُزال الحزمة من مستودع مستخدمي آرتش. فضلًا لا تستخدم هذه إن كانت الحزمة معطوبة ويمكن إصلاحها بسهولة. بدل ذلك تواصل مع مصين الحزمة وأبلغ عن طلب \"يتيمة\" إن تطلّب الأمر."
#: html/home.php #: html/home.php
msgid "Merge Request" msgid "Merge Request"
@ -309,11 +308,10 @@ msgstr "النّقاش"
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"General discussion regarding the Arch User Repository (AUR) and Package " "General discussion regarding the Arch User Repository (AUR) and Trusted User"
"Maintainer structure takes place on %saur-general%s. For discussion relating" " structure takes place on %saur-general%s. For discussion relating to the "
" to the development of the AUR web interface, use the %saur-dev%s mailing " "development of the AUR web interface, use the %saur-dev%s mailing list."
"list." msgstr "النّقاشات العاّمة حول مستودع مستخدمي آرتش (م‌م‌آ) وبنية المستخدمين الموثوقين تكون في %saur-general%s. للنّقاشات المتعلّقة بتطوير واجهة وِبّ م‌م‌آ، استخدم قائمة %saur-dev%s البريديّة."
msgstr ""
#: html/home.php #: html/home.php
msgid "Bug Reporting" msgid "Bug Reporting"
@ -324,9 +322,9 @@ msgstr "الإبلاغ عن العلل"
msgid "" msgid ""
"If you find a bug in the AUR web interface, please fill out a bug report on " "If you find a bug in the AUR web interface, please fill out a bug report on "
"our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface" "our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface"
" %sonly%s. To report packaging bugs contact the maintainer or leave a " " %sonly%s. To report packaging bugs contact the package maintainer or leave "
"comment on the appropriate package page." "a comment on the appropriate package page."
msgstr "" msgstr "إن وجدت علّة في واجهة وِبّ م‌م‌آ، فضلًا املأ تقريرًا بها في %sمتعقّب العلل%s. استخدم المتعقّب للإبلاغ عن العلل في واجهة وِبّ م‌م‌آ %sفقط%s. للإبلاغ عن علل الحزم راسل مديرها أو اترك تعليقًا في صفحة الحزمة المناسبة."
#: html/home.php #: html/home.php
msgid "Package Search" msgid "Package Search"
@ -526,8 +524,8 @@ msgid "Delete"
msgstr "احذف" msgstr "احذف"
#: html/pkgdel.php #: html/pkgdel.php
msgid "Only Package Maintainers and Developers can delete packages." msgid "Only Trusted Users and Developers can delete packages."
msgstr "" msgstr "يمكن فقط للمستخدمين الموثوقين والمطوّرين حذف الحزم."
#: html/pkgdisown.php template/pkgbase_actions.php #: html/pkgdisown.php template/pkgbase_actions.php
msgid "Disown Package" msgid "Disown Package"
@ -567,8 +565,8 @@ msgid "Disown"
msgstr "تنازل" msgstr "تنازل"
#: html/pkgdisown.php #: html/pkgdisown.php
msgid "Only Package Maintainers and Developers can disown packages." msgid "Only Trusted Users and Developers can disown packages."
msgstr "" msgstr "يمكن فقط للمستخدمين الموثوقين والمطوّرين التّنازل عن الحزم."
#: html/pkgflagcomment.php #: html/pkgflagcomment.php
msgid "Flag Comment" msgid "Flag Comment"
@ -657,8 +655,8 @@ msgid "Merge"
msgstr "دمج" msgstr "دمج"
#: html/pkgmerge.php #: html/pkgmerge.php
msgid "Only Package Maintainers and Developers can merge packages." msgid "Only Trusted Users and Developers can merge packages."
msgstr "" msgstr "يمكن فقط للمستخدمين الموثوقين والمطوّرين دمج الحزم."
#: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php #: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php
msgid "Submit Request" msgid "Submit Request"
@ -715,8 +713,8 @@ msgid "I accept the terms and conditions above."
msgstr "" msgstr ""
#: html/tu.php template/account_details.php template/header.php #: html/tu.php template/account_details.php template/header.php
msgid "Package Maintainer" msgid "Trusted User"
msgstr "" msgstr "مستخدم موثوق"
#: html/tu.php #: html/tu.php
msgid "Could not retrieve proposal details." msgid "Could not retrieve proposal details."
@ -727,8 +725,8 @@ msgid "Voting is closed for this proposal."
msgstr "أُغلق التّصويت على هذا الرّأي." msgstr "أُغلق التّصويت على هذا الرّأي."
#: html/tu.php #: html/tu.php
msgid "Only Package Maintainers are allowed to vote." msgid "Only Trusted Users are allowed to vote."
msgstr "" msgstr "فقط المستخدمين الموثوقين مسموح لهم بالتّصويت."
#: html/tu.php #: html/tu.php
msgid "You cannot vote in an proposal about you." msgid "You cannot vote in an proposal about you."
@ -1223,8 +1221,8 @@ msgstr "مطوّر"
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
#: template/search_accounts_form.php #: template/search_accounts_form.php
msgid "Package Maintainer & Developer" msgid "Trusted User & Developer"
msgstr "" msgstr "مستخدم موثوق ومطوّر"
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
#: template/search_accounts_form.php #: template/search_accounts_form.php
@ -1326,6 +1324,10 @@ msgstr ""
msgid "Normal user" msgid "Normal user"
msgstr "مستخدم عاديّ" msgstr "مستخدم عاديّ"
#: template/account_edit_form.php template/search_accounts_form.php
msgid "Trusted user"
msgstr "مستخدم موثوق"
#: template/account_edit_form.php template/search_accounts_form.php #: template/account_edit_form.php template/search_accounts_form.php
msgid "Account Suspended" msgid "Account Suspended"
msgstr "حساب معلّق" msgstr "حساب معلّق"
@ -1398,15 +1400,6 @@ msgid ""
" the Arch User Repository." " the Arch User Repository."
msgstr "المعلومات الآتية مطلوبة فقط إن أردت تقديم حزم إلى مستودع مستخدمي آرتش." msgstr "المعلومات الآتية مطلوبة فقط إن أردت تقديم حزم إلى مستودع مستخدمي آرتش."
#: templates/partials/account_form.html
msgid ""
"Specify multiple SSH Keys separated by new line, empty lines are ignored."
msgstr ""
#: templates/partials/account_form.html
msgid "Hide deleted comments"
msgstr ""
#: template/account_edit_form.php #: template/account_edit_form.php
msgid "SSH Public Key" msgid "SSH Public Key"
msgstr "مفتاح SSH العموميّ" msgstr "مفتاح SSH العموميّ"
@ -1834,22 +1827,22 @@ msgstr "ادمج مع"
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a deletion request, you ask a Package Maintainer to delete the" "By submitting a deletion request, you ask a Trusted User to delete the "
" package base. This type of request should be used for duplicates, software " "package base. This type of request should be used for duplicates, software "
"abandoned by upstream, as well as illegal and irreparably broken packages." "abandoned by upstream, as well as illegal and irreparably broken packages."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a merge request, you ask a Package Maintainer to delete the " "By submitting a merge request, you ask a Trusted User to delete the package "
"package base and transfer its votes and comments to another package base. " "base and transfer its votes and comments to another package base. Merging a "
"Merging a package does not affect the corresponding Git repositories. Make " "package does not affect the corresponding Git repositories. Make sure you "
"sure you update the Git history of the target package yourself." "update the Git history of the target package yourself."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting an orphan request, you ask a Package Maintainer to disown the " "By submitting an orphan request, you ask a Trusted User to disown the "
"package base. Please only do this if the package needs maintainer action, " "package base. Please only do this if the package needs maintainer action, "
"the maintainer is MIA and you already tried to contact the maintainer " "the maintainer is MIA and you already tried to contact the maintainer "
"previously." "previously."
@ -2122,8 +2115,8 @@ msgid "Registered Users"
msgstr "المستخدمون المسجّلون" msgstr "المستخدمون المسجّلون"
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Package Maintainers" msgid "Trusted Users"
msgstr "" msgstr "المستخدمون الموثوقون"
#: template/stats/updates_table.php #: template/stats/updates_table.php
msgid "Recent Updates" msgid "Recent Updates"
@ -2308,7 +2301,7 @@ msgstr ""
#: scripts/notify.py #: scripts/notify.py
#, python-brace-format #, python-brace-format
msgid "Package Maintainer Vote Reminder: Proposal {id}" msgid "TU Vote Reminder: Proposal {id}"
msgstr "" msgstr ""
#: scripts/notify.py #: scripts/notify.py
@ -2362,35 +2355,3 @@ msgid ""
"This action will close any pending package requests related to it. If " "This action will close any pending package requests related to it. If "
"%sComments%s are omitted, a closure comment will be autogenerated." "%sComments%s are omitted, a closure comment will be autogenerated."
msgstr "" msgstr ""
#: templates/partials/tu/proposal/details.html
msgid "assigned"
msgstr ""
#: templaets/partials/packages/package_metadata.html
msgid "Show %d more"
msgstr ""
#: templates/partials/packages/package_metadata.html
msgid "dependencies"
msgstr ""
#: aurweb/routers/accounts.py
msgid "The account has not been deleted, check the confirmation checkbox."
msgstr ""
#: templates/partials/packages/comment_form.html
msgid "Cancel"
msgstr ""
#: templates/requests.html
msgid "Package name"
msgstr ""
#: templates/partials/account_form.html
msgid ""
"Note that if you hide your email address, it'll end up on the BCC list for "
"any request notifications. In case someone replies to these notifications, "
"you won't receive an email. However, replies are typically sent to the "
"mailing-list and would then be visible in the archive."
msgstr ""

258
po/ast.po
View file

@ -1,21 +1,19 @@
# SOME DESCRIPTIVE TITLE. # SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the AURWEB package. # This file is distributed under the same license as the AURWEB package.
# #
# Translators: # Translators:
# enolp <enolp@softastur.org>, 2014-2015,2017,2020,2022 # enolp <enolp@softastur.org>, 2014-2015,2017
# enolp <enolp@softastur.org>, 2020 # Ḷḷumex03 <tornes@opmbx.org>, 2014
# Ḷḷumex03, 2014 # prflr88 <prflr88@gmail.com>, 2014-2015
# Ḷḷumex03, 2014
# Pablo Lezaeta Reyes <prflr88@gmail.com>, 2014-2015
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: aurweb\n" "Project-Id-Version: aurweb\n"
"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n" "Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n" "POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2011-04-10 13:21+0000\n" "PO-Revision-Date: 2020-03-07 17:55+0000\n"
"Last-Translator: enolp <enolp@softastur.org>, 2014-2015,2017,2020,2022\n" "Last-Translator: enolp <enolp@softastur.org>\n"
"Language-Team: Asturian (http://app.transifex.com/lfleischer/aurweb/language/ast/)\n" "Language-Team: Asturian (http://www.transifex.com/lfleischer/aurweb/language/ast/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -24,7 +22,7 @@ msgstr ""
#: html/404.php #: html/404.php
msgid "Page Not Found" msgid "Page Not Found"
msgstr "Nun s'atopó la páxina" msgstr ""
#: html/404.php #: html/404.php
msgid "Sorry, the page you've requested does not exist." msgid "Sorry, the page you've requested does not exist."
@ -50,7 +48,7 @@ msgstr ""
#: html/503.php #: html/503.php
msgid "Service Unavailable" msgid "Service Unavailable"
msgstr "El serviciu nun ta disponible" msgstr ""
#: html/503.php #: html/503.php
msgid "" msgid ""
@ -71,11 +69,11 @@ msgstr ""
#: html/account.php #: html/account.php
msgid "Could not retrieve information for the specified user." msgid "Could not retrieve information for the specified user."
msgstr "Nun se pudo recuperar la información del usuariu especificáu." msgstr ""
#: html/account.php #: html/account.php
msgid "You do not have permission to edit this account." msgid "You do not have permission to edit this account."
msgstr "Nun tienes permisu pa editar esta cuenta." msgstr ""
#: html/account.php lib/acctfuncs.inc.php #: html/account.php lib/acctfuncs.inc.php
msgid "Invalid password." msgid "Invalid password."
@ -136,15 +134,15 @@ msgid "Type"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Addition of a Package Maintainer" msgid "Addition of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer" msgid "Removal of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer (undeclared inactivity)" msgid "Removal of a TU (undeclared inactivity)"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
@ -202,9 +200,8 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"Welcome to the AUR! Please read the %sAUR User Guidelines%s for more " "Welcome to the AUR! Please read the %sAUR User Guidelines%s and %sAUR TU "
"information and the %sAUR Submission Guidelines%s if you want to contribute " "Guidelines%s for more information."
"a PKGBUILD."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -219,7 +216,7 @@ msgid "Remember to vote for your favourite packages!"
msgstr "" msgstr ""
#: html/home.php #: html/home.php
msgid "Some packages may be provided as binaries in [extra]." msgid "Some packages may be provided as binaries in [community]."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -263,18 +260,18 @@ msgstr ""
#: html/home.php #: html/home.php
msgid "Deletion Request" msgid "Deletion Request"
msgstr "Solicitú de desaniciu" msgstr ""
#: html/home.php #: html/home.php
msgid "" msgid ""
"Request a package to be removed from the Arch User Repository. Please do not" "Request a package to be removed from the Arch User Repository. Please do not"
" use this if a package is broken and can be fixed easily. Instead, contact " " use this if a package is broken and can be fixed easily. Instead, contact "
"the maintainer and file orphan request if necessary." "the package maintainer and file orphan request if necessary."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
msgid "Merge Request" msgid "Merge Request"
msgstr "Solicitú de mecíu" msgstr ""
#: html/home.php #: html/home.php
msgid "" msgid ""
@ -307,15 +304,14 @@ msgstr ""
#: html/home.php #: html/home.php
msgid "Discussion" msgid "Discussion"
msgstr "Discutiniu" msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"General discussion regarding the Arch User Repository (AUR) and Package " "General discussion regarding the Arch User Repository (AUR) and Trusted User"
"Maintainer structure takes place on %saur-general%s. For discussion relating" " structure takes place on %saur-general%s. For discussion relating to the "
" to the development of the AUR web interface, use the %saur-dev%s mailing " "development of the AUR web interface, use the %saur-dev%s mailing list."
"list."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -327,8 +323,8 @@ msgstr ""
msgid "" msgid ""
"If you find a bug in the AUR web interface, please fill out a bug report on " "If you find a bug in the AUR web interface, please fill out a bug report on "
"our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface" "our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface"
" %sonly%s. To report packaging bugs contact the maintainer or leave a " " %sonly%s. To report packaging bugs contact the package maintainer or leave "
"comment on the appropriate package page." "a comment on the appropriate package page."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -477,12 +473,6 @@ msgid ""
"checkbox." "checkbox."
msgstr "" msgstr ""
#: aurweb/routers/packages.py
msgid ""
"The selected packages have not been adopted, check the confirmation "
"checkbox."
msgstr ""
#: html/pkgbase.php lib/pkgreqfuncs.inc.php #: html/pkgbase.php lib/pkgreqfuncs.inc.php
msgid "Cannot find package to merge votes and comments into." msgid "Cannot find package to merge votes and comments into."
msgstr "" msgstr ""
@ -529,7 +519,7 @@ msgid "Delete"
msgstr "" msgstr ""
#: html/pkgdel.php #: html/pkgdel.php
msgid "Only Package Maintainers and Developers can delete packages." msgid "Only Trusted Users and Developers can delete packages."
msgstr "" msgstr ""
#: html/pkgdisown.php template/pkgbase_actions.php #: html/pkgdisown.php template/pkgbase_actions.php
@ -570,7 +560,7 @@ msgid "Disown"
msgstr "" msgstr ""
#: html/pkgdisown.php #: html/pkgdisown.php
msgid "Only Package Maintainers and Developers can disown packages." msgid "Only Trusted Users and Developers can disown packages."
msgstr "" msgstr ""
#: html/pkgflagcomment.php #: html/pkgflagcomment.php
@ -581,14 +571,6 @@ msgstr ""
msgid "Flag Package Out-Of-Date" msgid "Flag Package Out-Of-Date"
msgstr "" msgstr ""
#: templates/packages/flag.html
msgid ""
"This seems to be a VCS package. Please do %snot%s flag it out-of-date if the"
" package version in the AUR does not match the most recent commit. Flagging "
"this package should only be done if the sources moved or changes in the "
"PKGBUILD are required because of recent upstream changes."
msgstr ""
#: html/pkgflag.php #: html/pkgflag.php
#, php-format #, php-format
msgid "" msgid ""
@ -660,7 +642,7 @@ msgid "Merge"
msgstr "" msgstr ""
#: html/pkgmerge.php #: html/pkgmerge.php
msgid "Only Package Maintainers and Developers can merge packages." msgid "Only Trusted Users and Developers can merge packages."
msgstr "" msgstr ""
#: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php #: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php
@ -715,22 +697,22 @@ msgstr ""
#: html/tos.php #: html/tos.php
msgid "I accept the terms and conditions above." msgid "I accept the terms and conditions above."
msgstr "Acepto los términos y les condiciones d'arriba." msgstr ""
#: html/tu.php template/account_details.php template/header.php #: html/tu.php template/account_details.php template/header.php
msgid "Package Maintainer" msgid "Trusted User"
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
msgid "Could not retrieve proposal details." msgid "Could not retrieve proposal details."
msgstr "Nun se pudieron recuperar los detalles de la propuesta." msgstr ""
#: html/tu.php #: html/tu.php
msgid "Voting is closed for this proposal." msgid "Voting is closed for this proposal."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
msgid "Only Package Maintainers are allowed to vote." msgid "Only Trusted Users are allowed to vote."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -885,10 +867,6 @@ msgstr ""
msgid "Account suspended" msgid "Account suspended"
msgstr "" msgstr ""
#: aurweb/routers/accounts.py
msgid "You do not have permission to suspend accounts."
msgstr ""
#: lib/acctfuncs.inc.php #: lib/acctfuncs.inc.php
#, php-format #, php-format
msgid "" msgid ""
@ -932,7 +910,7 @@ msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "Comment cannot be empty." msgid "Comment cannot be empty."
msgstr "El comentariu nun pue tar baleru." msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "Comment has been added." msgid "Comment has been added."
@ -940,7 +918,7 @@ msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "You must be logged in before you can edit package information." msgid "You must be logged in before you can edit package information."
msgstr "Tienes d'aniciar la sesión enantes d'editar la información del paquete." msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "Missing comment ID." msgid "Missing comment ID."
@ -948,15 +926,15 @@ msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "No more than 5 comments can be pinned." msgid "No more than 5 comments can be pinned."
msgstr "Nun se puen fixar más de 5 comentarios." msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "You are not allowed to pin this comment." msgid "You are not allowed to pin this comment."
msgstr "Nun tienes permisu pa fixar esti comentariu." msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "You are not allowed to unpin this comment." msgid "You are not allowed to unpin this comment."
msgstr "Nun tienes permisu pa lliberar esti comentariu." msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "Comment has been pinned." msgid "Comment has been pinned."
@ -972,30 +950,6 @@ msgstr ""
#: lib/pkgbasefuncs.inc.php lib/pkgfuncs.inc.php #: lib/pkgbasefuncs.inc.php lib/pkgfuncs.inc.php
msgid "Package details could not be found." msgid "Package details could not be found."
msgstr "Nun se pudieron atopar los detalles del paquete."
#: aurweb/routers/auth.py
msgid "Bad Referer header."
msgstr ""
#: aurweb/routers/packages.py
msgid "You did not select any packages to be notified about."
msgstr ""
#: aurweb/routers/packages.py
msgid "The selected packages' notifications have been enabled."
msgstr ""
#: aurweb/routers/packages.py
msgid "You did not select any packages for notification removal."
msgstr ""
#: aurweb/routers/packages.py
msgid "A package you selected does not have notifications enabled."
msgstr ""
#: aurweb/routers/packages.py
msgid "The selected packages' notifications have been removed."
msgstr "" msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
@ -1034,10 +988,6 @@ msgstr ""
msgid "You did not select any packages to delete." msgid "You did not select any packages to delete."
msgstr "" msgstr ""
#: aurweb/routers/packages.py
msgid "One of the packages you selected does not exist."
msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "The selected packages have been deleted." msgid "The selected packages have been deleted."
msgstr "" msgstr ""
@ -1046,18 +996,10 @@ msgstr ""
msgid "You must be logged in before you can adopt packages." msgid "You must be logged in before you can adopt packages."
msgstr "" msgstr ""
#: aurweb/routers/package.py
msgid "You are not allowed to adopt one of the packages you selected."
msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "You must be logged in before you can disown packages." msgid "You must be logged in before you can disown packages."
msgstr "" msgstr ""
#: aurweb/routers/packages.py
msgid "You are not allowed to disown one of the packages you selected."
msgstr ""
#: lib/pkgbasefuncs.inc.php #: lib/pkgbasefuncs.inc.php
msgid "You did not select any packages to adopt." msgid "You did not select any packages to adopt."
msgstr "" msgstr ""
@ -1226,7 +1168,7 @@ msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
#: template/search_accounts_form.php #: template/search_accounts_form.php
msgid "Package Maintainer & Developer" msgid "Trusted User & Developer"
msgstr "" msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
@ -1329,6 +1271,10 @@ msgstr ""
msgid "Normal user" msgid "Normal user"
msgstr "" msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php
msgid "Trusted user"
msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php #: template/account_edit_form.php template/search_accounts_form.php
msgid "Account Suspended" msgid "Account Suspended"
msgstr "" msgstr ""
@ -1401,15 +1347,6 @@ msgid ""
" the Arch User Repository." " the Arch User Repository."
msgstr "" msgstr ""
#: templates/partials/account_form.html
msgid ""
"Specify multiple SSH Keys separated by new line, empty lines are ignored."
msgstr ""
#: templates/partials/account_form.html
msgid "Hide deleted comments"
msgstr ""
#: template/account_edit_form.php #: template/account_edit_form.php
msgid "SSH Public Key" msgid "SSH Public Key"
msgstr "" msgstr ""
@ -1614,7 +1551,7 @@ msgstr ""
#: template/pkgbase_details.php template/pkg_details.php #: template/pkgbase_details.php template/pkg_details.php
#: template/pkg_search_form.php #: template/pkg_search_form.php
msgid "Keywords" msgid "Keywords"
msgstr "Pallabres clave" msgstr ""
#: template/pkgbase_details.php template/pkg_details.php #: template/pkgbase_details.php template/pkg_details.php
#: template/pkg_search_form.php #: template/pkg_search_form.php
@ -1833,22 +1770,22 @@ msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a deletion request, you ask a Package Maintainer to delete the" "By submitting a deletion request, you ask a Trusted User to delete the "
" package base. This type of request should be used for duplicates, software " "package base. This type of request should be used for duplicates, software "
"abandoned by upstream, as well as illegal and irreparably broken packages." "abandoned by upstream, as well as illegal and irreparably broken packages."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a merge request, you ask a Package Maintainer to delete the " "By submitting a merge request, you ask a Trusted User to delete the package "
"package base and transfer its votes and comments to another package base. " "base and transfer its votes and comments to another package base. Merging a "
"Merging a package does not affect the corresponding Git repositories. Make " "package does not affect the corresponding Git repositories. Make sure you "
"sure you update the Git history of the target package yourself." "update the Git history of the target package yourself."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting an orphan request, you ask a Package Maintainer to disown the " "By submitting an orphan request, you ask a Trusted User to disown the "
"package base. Please only do this if the package needs maintainer action, " "package base. Please only do this if the package needs maintainer action, "
"the maintainer is MIA and you already tried to contact the maintainer " "the maintainer is MIA and you already tried to contact the maintainer "
"previously." "previously."
@ -1868,7 +1805,7 @@ msgstr[1] ""
#: template/pkgreq_results.php template/pkg_search_results.php #: template/pkgreq_results.php template/pkg_search_results.php
#, php-format #, php-format
msgid "Page %d of %d." msgid "Page %d of %d."
msgstr "Páxina %d de %d." msgstr ""
#: template/pkgreq_results.php #: template/pkgreq_results.php
msgid "Package" msgid "Package"
@ -2082,7 +2019,7 @@ msgstr ""
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Orphan Packages" msgid "Orphan Packages"
msgstr "Paquetes güérfanos" msgstr ""
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Packages added in the past 7 days" msgid "Packages added in the past 7 days"
@ -2102,15 +2039,15 @@ msgstr ""
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Registered Users" msgid "Registered Users"
msgstr "Usuarios rexistraos" msgstr ""
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Package Maintainers" msgid "Trusted Users"
msgstr "" msgstr ""
#: template/stats/updates_table.php #: template/stats/updates_table.php
msgid "Recent Updates" msgid "Recent Updates"
msgstr "Anovamientos de recién" msgstr ""
#: template/stats/updates_table.php #: template/stats/updates_table.php
msgid "more" msgid "more"
@ -2155,7 +2092,7 @@ msgstr ""
#: template/tu_details.php #: template/tu_details.php
msgid "Participation" msgid "Participation"
msgstr "Participación" msgstr ""
#: template/tu_last_votes_list.php #: template/tu_last_votes_list.php
msgid "Last Votes by TU" msgid "Last Votes by TU"
@ -2291,7 +2228,7 @@ msgstr ""
#: scripts/notify.py #: scripts/notify.py
#, python-brace-format #, python-brace-format
msgid "Package Maintainer Vote Reminder: Proposal {id}" msgid "TU Vote Reminder: Proposal {id}"
msgstr "" msgstr ""
#: scripts/notify.py #: scripts/notify.py
@ -2300,80 +2237,3 @@ msgid ""
"Please remember to cast your vote on proposal {id} [1]. The voting period " "Please remember to cast your vote on proposal {id} [1]. The voting period "
"ends in less than 48 hours." "ends in less than 48 hours."
msgstr "" msgstr ""
#: aurweb/routers/accounts.py
msgid "Invalid account type provided."
msgstr ""
#: aurweb/routers/accounts.py
msgid "You do not have permission to change account types."
msgstr ""
#: aurweb/routers/accounts.py
msgid "You do not have permission to change this user's account type to %s."
msgstr ""
#: aurweb/packages/requests.py
msgid "No due existing orphan requests to accept for %s."
msgstr ""
#: aurweb/asgi.py
msgid "Internal Server Error"
msgstr "Fallu internu del sirvidor"
#: templates/errors/500.html
msgid "A fatal error has occurred."
msgstr "Asocedió un fallu fatal."
#: templates/errors/500.html
msgid ""
"Details have been logged and will be reviewed by the postmaster posthaste. "
"We apologize for any inconvenience this may have caused."
msgstr ""
#: aurweb/scripts/notify.py
msgid "AUR Server Error"
msgstr ""
#: templates/pkgbase/merge.html templates/packages/delete.html
#: templates/packages/disown.html
msgid "Related package request closure comments..."
msgstr ""
#: templates/pkgbase/merge.html templates/packages/delete.html
msgid ""
"This action will close any pending package requests related to it. If "
"%sComments%s are omitted, a closure comment will be autogenerated."
msgstr ""
#: templates/partials/tu/proposal/details.html
msgid "assigned"
msgstr ""
#: templaets/partials/packages/package_metadata.html
msgid "Show %d more"
msgstr ""
#: templates/partials/packages/package_metadata.html
msgid "dependencies"
msgstr ""
#: aurweb/routers/accounts.py
msgid "The account has not been deleted, check the confirmation checkbox."
msgstr ""
#: templates/partials/packages/comment_form.html
msgid "Cancel"
msgstr ""
#: templates/requests.html
msgid "Package name"
msgstr ""
#: templates/partials/account_form.html
msgid ""
"Note that if you hide your email address, it'll end up on the BCC list for "
"any request notifications. In case someone replies to these notifications, "
"you won't receive an email. However, replies are typically sent to the "
"mailing-list and would then be visible in the archive."
msgstr ""

View file

@ -132,15 +132,15 @@ msgid "Type"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Addition of a Package Maintainer" msgid "Addition of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer" msgid "Removal of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer (undeclared inactivity)" msgid "Removal of a TU (undeclared inactivity)"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
@ -198,9 +198,8 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"Welcome to the AUR! Please read the %sAUR User Guidelines%s for more " "Welcome to the AUR! Please read the %sAUR User Guidelines%s and %sAUR TU "
"information and the %sAUR Submission Guidelines%s if you want to contribute " "Guidelines%s for more information."
"a PKGBUILD."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -215,7 +214,7 @@ msgid "Remember to vote for your favourite packages!"
msgstr "" msgstr ""
#: html/home.php #: html/home.php
msgid "Some packages may be provided as binaries in [extra]." msgid "Some packages may be provided as binaries in [community]."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -265,7 +264,7 @@ msgstr ""
msgid "" msgid ""
"Request a package to be removed from the Arch User Repository. Please do not " "Request a package to be removed from the Arch User Repository. Please do not "
"use this if a package is broken and can be fixed easily. Instead, contact " "use this if a package is broken and can be fixed easily. Instead, contact "
"the maintainer and file orphan request if necessary." "the package maintainer and file orphan request if necessary."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -308,7 +307,7 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"General discussion regarding the Arch User Repository (AUR) and Package Maintainer " "General discussion regarding the Arch User Repository (AUR) and Trusted User "
"structure takes place on %saur-general%s. For discussion relating to the " "structure takes place on %saur-general%s. For discussion relating to the "
"development of the AUR web interface, use the %saur-dev%s mailing list." "development of the AUR web interface, use the %saur-dev%s mailing list."
msgstr "" msgstr ""
@ -322,7 +321,7 @@ msgstr ""
msgid "" msgid ""
"If you find a bug in the AUR web interface, please fill out a bug report on " "If you find a bug in the AUR web interface, please fill out a bug report on "
"our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface " "our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface "
"%sonly%s. To report packaging bugs contact the maintainer or leave a " "%sonly%s. To report packaging bugs contact the package maintainer or leave a "
"comment on the appropriate package page." "comment on the appropriate package page."
msgstr "" msgstr ""
@ -523,7 +522,7 @@ msgid "Delete"
msgstr "" msgstr ""
#: html/pkgdel.php #: html/pkgdel.php
msgid "Only Package Maintainers and Developers can delete packages." msgid "Only Trusted Users and Developers can delete packages."
msgstr "" msgstr ""
#: html/pkgdisown.php template/pkgbase_actions.php #: html/pkgdisown.php template/pkgbase_actions.php
@ -564,7 +563,7 @@ msgid "Disown"
msgstr "" msgstr ""
#: html/pkgdisown.php #: html/pkgdisown.php
msgid "Only Package Maintainers and Developers can disown packages." msgid "Only Trusted Users and Developers can disown packages."
msgstr "" msgstr ""
#: html/pkgflagcomment.php #: html/pkgflagcomment.php
@ -655,7 +654,7 @@ msgid "Merge"
msgstr "" msgstr ""
#: html/pkgmerge.php #: html/pkgmerge.php
msgid "Only Package Maintainers and Developers can merge packages." msgid "Only Trusted Users and Developers can merge packages."
msgstr "" msgstr ""
#: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php #: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php
@ -713,7 +712,7 @@ msgid "I accept the terms and conditions above."
msgstr "" msgstr ""
#: html/tu.php template/account_details.php template/header.php #: html/tu.php template/account_details.php template/header.php
msgid "Package Maintainer" msgid "Trusted User"
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -725,7 +724,7 @@ msgid "Voting is closed for this proposal."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
msgid "Only Package Maintainers are allowed to vote." msgid "Only Trusted Users are allowed to vote."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -1221,7 +1220,7 @@ msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
#: template/search_accounts_form.php #: template/search_accounts_form.php
msgid "Package Maintainer & Developer" msgid "Trusted User & Developer"
msgstr "" msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
@ -1323,6 +1322,10 @@ msgstr ""
msgid "Normal user" msgid "Normal user"
msgstr "" msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php
msgid "Trusted user"
msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php #: template/account_edit_form.php template/search_accounts_form.php
msgid "Account Suspended" msgid "Account Suspended"
msgstr "" msgstr ""
@ -1826,14 +1829,14 @@ msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a deletion request, you ask a Package Maintainer to delete the " "By submitting a deletion request, you ask a Trusted User to delete the "
"package base. This type of request should be used for duplicates, software " "package base. This type of request should be used for duplicates, software "
"abandoned by upstream, as well as illegal and irreparably broken packages." "abandoned by upstream, as well as illegal and irreparably broken packages."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a merge request, you ask a Package Maintainer to delete the package " "By submitting a merge request, you ask a Trusted User to delete the package "
"base and transfer its votes and comments to another package base. Merging a " "base and transfer its votes and comments to another package base. Merging a "
"package does not affect the corresponding Git repositories. Make sure you " "package does not affect the corresponding Git repositories. Make sure you "
"update the Git history of the target package yourself." "update the Git history of the target package yourself."
@ -1841,7 +1844,7 @@ msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting an orphan request, you ask a Package Maintainer to disown the " "By submitting an orphan request, you ask a Trusted User to disown the "
"package base. Please only do this if the package needs maintainer action, " "package base. Please only do this if the package needs maintainer action, "
"the maintainer is MIA and you already tried to contact the maintainer " "the maintainer is MIA and you already tried to contact the maintainer "
"previously." "previously."
@ -2097,7 +2100,7 @@ msgid "Registered Users"
msgstr "" msgstr ""
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Package Maintainers" msgid "Trusted Users"
msgstr "" msgstr ""
#: template/stats/updates_table.php #: template/stats/updates_table.php
@ -2284,7 +2287,7 @@ msgstr ""
#: scripts/notify.py #: scripts/notify.py
#, python-brace-format #, python-brace-format
msgid "Package Maintainer Vote Reminder: Proposal {id}" msgid "TU Vote Reminder: Proposal {id}"
msgstr "" msgstr ""
#: scripts/notify.py #: scripts/notify.py
@ -2371,7 +2374,3 @@ msgid "Note that if you hide your email address, it'll "
"receive an email. However, replies are typically sent to the " "receive an email. However, replies are typically sent to the "
"mailing-list and would then be visible in the archive." "mailing-list and would then be visible in the archive."
msgstr "" msgstr ""
#: templates/partials/packages/comment_form.html
msgid "Maximum number of characters"
msgstr ""

103
po/az.po
View file

@ -10,7 +10,7 @@ msgstr ""
"POT-Creation-Date: 2020-01-31 09:29+0100\n" "POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2011-04-10 13:21+0000\n" "PO-Revision-Date: 2011-04-10 13:21+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Azerbaijani (http://app.transifex.com/lfleischer/aurweb/language/az/)\n" "Language-Team: Azerbaijani (http://www.transifex.com/lfleischer/aurweb/language/az/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -131,15 +131,15 @@ msgid "Type"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Addition of a Package Maintainer" msgid "Addition of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer" msgid "Removal of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer (undeclared inactivity)" msgid "Removal of a TU (undeclared inactivity)"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
@ -197,9 +197,8 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"Welcome to the AUR! Please read the %sAUR User Guidelines%s for more " "Welcome to the AUR! Please read the %sAUR User Guidelines%s and %sAUR TU "
"information and the %sAUR Submission Guidelines%s if you want to contribute " "Guidelines%s for more information."
"a PKGBUILD."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -214,7 +213,7 @@ msgid "Remember to vote for your favourite packages!"
msgstr "" msgstr ""
#: html/home.php #: html/home.php
msgid "Some packages may be provided as binaries in [extra]." msgid "Some packages may be provided as binaries in [community]."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -264,7 +263,7 @@ msgstr ""
msgid "" msgid ""
"Request a package to be removed from the Arch User Repository. Please do not" "Request a package to be removed from the Arch User Repository. Please do not"
" use this if a package is broken and can be fixed easily. Instead, contact " " use this if a package is broken and can be fixed easily. Instead, contact "
"the maintainer and file orphan request if necessary." "the package maintainer and file orphan request if necessary."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -307,10 +306,9 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"General discussion regarding the Arch User Repository (AUR) and Package " "General discussion regarding the Arch User Repository (AUR) and Trusted User"
"Maintainer structure takes place on %saur-general%s. For discussion relating" " structure takes place on %saur-general%s. For discussion relating to the "
" to the development of the AUR web interface, use the %saur-dev%s mailing " "development of the AUR web interface, use the %saur-dev%s mailing list."
"list."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -322,8 +320,8 @@ msgstr ""
msgid "" msgid ""
"If you find a bug in the AUR web interface, please fill out a bug report on " "If you find a bug in the AUR web interface, please fill out a bug report on "
"our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface" "our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface"
" %sonly%s. To report packaging bugs contact the maintainer or leave a " " %sonly%s. To report packaging bugs contact the package maintainer or leave "
"comment on the appropriate package page." "a comment on the appropriate package page."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -524,7 +522,7 @@ msgid "Delete"
msgstr "" msgstr ""
#: html/pkgdel.php #: html/pkgdel.php
msgid "Only Package Maintainers and Developers can delete packages." msgid "Only Trusted Users and Developers can delete packages."
msgstr "" msgstr ""
#: html/pkgdisown.php template/pkgbase_actions.php #: html/pkgdisown.php template/pkgbase_actions.php
@ -565,7 +563,7 @@ msgid "Disown"
msgstr "" msgstr ""
#: html/pkgdisown.php #: html/pkgdisown.php
msgid "Only Package Maintainers and Developers can disown packages." msgid "Only Trusted Users and Developers can disown packages."
msgstr "" msgstr ""
#: html/pkgflagcomment.php #: html/pkgflagcomment.php
@ -655,7 +653,7 @@ msgid "Merge"
msgstr "" msgstr ""
#: html/pkgmerge.php #: html/pkgmerge.php
msgid "Only Package Maintainers and Developers can merge packages." msgid "Only Trusted Users and Developers can merge packages."
msgstr "" msgstr ""
#: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php #: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php
@ -713,7 +711,7 @@ msgid "I accept the terms and conditions above."
msgstr "" msgstr ""
#: html/tu.php template/account_details.php template/header.php #: html/tu.php template/account_details.php template/header.php
msgid "Package Maintainer" msgid "Trusted User"
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -725,7 +723,7 @@ msgid "Voting is closed for this proposal."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
msgid "Only Package Maintainers are allowed to vote." msgid "Only Trusted Users are allowed to vote."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -1221,7 +1219,7 @@ msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
#: template/search_accounts_form.php #: template/search_accounts_form.php
msgid "Package Maintainer & Developer" msgid "Trusted User & Developer"
msgstr "" msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
@ -1324,6 +1322,10 @@ msgstr ""
msgid "Normal user" msgid "Normal user"
msgstr "" msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php
msgid "Trusted user"
msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php #: template/account_edit_form.php template/search_accounts_form.php
msgid "Account Suspended" msgid "Account Suspended"
msgstr "" msgstr ""
@ -1396,15 +1398,6 @@ msgid ""
" the Arch User Repository." " the Arch User Repository."
msgstr "" msgstr ""
#: templates/partials/account_form.html
msgid ""
"Specify multiple SSH Keys separated by new line, empty lines are ignored."
msgstr ""
#: templates/partials/account_form.html
msgid "Hide deleted comments"
msgstr ""
#: template/account_edit_form.php #: template/account_edit_form.php
msgid "SSH Public Key" msgid "SSH Public Key"
msgstr "" msgstr ""
@ -1828,22 +1821,22 @@ msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a deletion request, you ask a Package Maintainer to delete the" "By submitting a deletion request, you ask a Trusted User to delete the "
" package base. This type of request should be used for duplicates, software " "package base. This type of request should be used for duplicates, software "
"abandoned by upstream, as well as illegal and irreparably broken packages." "abandoned by upstream, as well as illegal and irreparably broken packages."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a merge request, you ask a Package Maintainer to delete the " "By submitting a merge request, you ask a Trusted User to delete the package "
"package base and transfer its votes and comments to another package base. " "base and transfer its votes and comments to another package base. Merging a "
"Merging a package does not affect the corresponding Git repositories. Make " "package does not affect the corresponding Git repositories. Make sure you "
"sure you update the Git history of the target package yourself." "update the Git history of the target package yourself."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting an orphan request, you ask a Package Maintainer to disown the " "By submitting an orphan request, you ask a Trusted User to disown the "
"package base. Please only do this if the package needs maintainer action, " "package base. Please only do this if the package needs maintainer action, "
"the maintainer is MIA and you already tried to contact the maintainer " "the maintainer is MIA and you already tried to contact the maintainer "
"previously." "previously."
@ -2100,7 +2093,7 @@ msgid "Registered Users"
msgstr "" msgstr ""
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Package Maintainers" msgid "Trusted Users"
msgstr "" msgstr ""
#: template/stats/updates_table.php #: template/stats/updates_table.php
@ -2286,7 +2279,7 @@ msgstr ""
#: scripts/notify.py #: scripts/notify.py
#, python-brace-format #, python-brace-format
msgid "Package Maintainer Vote Reminder: Proposal {id}" msgid "TU Vote Reminder: Proposal {id}"
msgstr "" msgstr ""
#: scripts/notify.py #: scripts/notify.py
@ -2340,35 +2333,3 @@ msgid ""
"This action will close any pending package requests related to it. If " "This action will close any pending package requests related to it. If "
"%sComments%s are omitted, a closure comment will be autogenerated." "%sComments%s are omitted, a closure comment will be autogenerated."
msgstr "" msgstr ""
#: templates/partials/tu/proposal/details.html
msgid "assigned"
msgstr ""
#: templaets/partials/packages/package_metadata.html
msgid "Show %d more"
msgstr ""
#: templates/partials/packages/package_metadata.html
msgid "dependencies"
msgstr ""
#: aurweb/routers/accounts.py
msgid "The account has not been deleted, check the confirmation checkbox."
msgstr ""
#: templates/partials/packages/comment_form.html
msgid "Cancel"
msgstr ""
#: templates/requests.html
msgid "Package name"
msgstr ""
#: templates/partials/account_form.html
msgid ""
"Note that if you hide your email address, it'll end up on the BCC list for "
"any request notifications. In case someone replies to these notifications, "
"you won't receive an email. However, replies are typically sent to the "
"mailing-list and would then be visible in the archive."
msgstr ""

View file

@ -10,7 +10,7 @@ msgstr ""
"POT-Creation-Date: 2020-01-31 09:29+0100\n" "POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2011-04-10 13:21+0000\n" "PO-Revision-Date: 2011-04-10 13:21+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Azerbaijani (Azerbaijan) (http://app.transifex.com/lfleischer/aurweb/language/az_AZ/)\n" "Language-Team: Azerbaijani (Azerbaijan) (http://www.transifex.com/lfleischer/aurweb/language/az_AZ/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -131,15 +131,15 @@ msgid "Type"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Addition of a Package Maintainer" msgid "Addition of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer" msgid "Removal of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer (undeclared inactivity)" msgid "Removal of a TU (undeclared inactivity)"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
@ -197,9 +197,8 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"Welcome to the AUR! Please read the %sAUR User Guidelines%s for more " "Welcome to the AUR! Please read the %sAUR User Guidelines%s and %sAUR TU "
"information and the %sAUR Submission Guidelines%s if you want to contribute " "Guidelines%s for more information."
"a PKGBUILD."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -214,7 +213,7 @@ msgid "Remember to vote for your favourite packages!"
msgstr "" msgstr ""
#: html/home.php #: html/home.php
msgid "Some packages may be provided as binaries in [extra]." msgid "Some packages may be provided as binaries in [community]."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -264,7 +263,7 @@ msgstr ""
msgid "" msgid ""
"Request a package to be removed from the Arch User Repository. Please do not" "Request a package to be removed from the Arch User Repository. Please do not"
" use this if a package is broken and can be fixed easily. Instead, contact " " use this if a package is broken and can be fixed easily. Instead, contact "
"the maintainer and file orphan request if necessary." "the package maintainer and file orphan request if necessary."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -307,10 +306,9 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"General discussion regarding the Arch User Repository (AUR) and Package " "General discussion regarding the Arch User Repository (AUR) and Trusted User"
"Maintainer structure takes place on %saur-general%s. For discussion relating" " structure takes place on %saur-general%s. For discussion relating to the "
" to the development of the AUR web interface, use the %saur-dev%s mailing " "development of the AUR web interface, use the %saur-dev%s mailing list."
"list."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -322,8 +320,8 @@ msgstr ""
msgid "" msgid ""
"If you find a bug in the AUR web interface, please fill out a bug report on " "If you find a bug in the AUR web interface, please fill out a bug report on "
"our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface" "our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface"
" %sonly%s. To report packaging bugs contact the maintainer or leave a " " %sonly%s. To report packaging bugs contact the package maintainer or leave "
"comment on the appropriate package page." "a comment on the appropriate package page."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -524,7 +522,7 @@ msgid "Delete"
msgstr "" msgstr ""
#: html/pkgdel.php #: html/pkgdel.php
msgid "Only Package Maintainers and Developers can delete packages." msgid "Only Trusted Users and Developers can delete packages."
msgstr "" msgstr ""
#: html/pkgdisown.php template/pkgbase_actions.php #: html/pkgdisown.php template/pkgbase_actions.php
@ -565,7 +563,7 @@ msgid "Disown"
msgstr "" msgstr ""
#: html/pkgdisown.php #: html/pkgdisown.php
msgid "Only Package Maintainers and Developers can disown packages." msgid "Only Trusted Users and Developers can disown packages."
msgstr "" msgstr ""
#: html/pkgflagcomment.php #: html/pkgflagcomment.php
@ -655,7 +653,7 @@ msgid "Merge"
msgstr "" msgstr ""
#: html/pkgmerge.php #: html/pkgmerge.php
msgid "Only Package Maintainers and Developers can merge packages." msgid "Only Trusted Users and Developers can merge packages."
msgstr "" msgstr ""
#: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php #: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php
@ -713,7 +711,7 @@ msgid "I accept the terms and conditions above."
msgstr "" msgstr ""
#: html/tu.php template/account_details.php template/header.php #: html/tu.php template/account_details.php template/header.php
msgid "Package Maintainer" msgid "Trusted User"
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -725,7 +723,7 @@ msgid "Voting is closed for this proposal."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
msgid "Only Package Maintainers are allowed to vote." msgid "Only Trusted Users are allowed to vote."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -1221,7 +1219,7 @@ msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
#: template/search_accounts_form.php #: template/search_accounts_form.php
msgid "Package Maintainer & Developer" msgid "Trusted User & Developer"
msgstr "" msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
@ -1324,6 +1322,10 @@ msgstr ""
msgid "Normal user" msgid "Normal user"
msgstr "" msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php
msgid "Trusted user"
msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php #: template/account_edit_form.php template/search_accounts_form.php
msgid "Account Suspended" msgid "Account Suspended"
msgstr "" msgstr ""
@ -1396,15 +1398,6 @@ msgid ""
" the Arch User Repository." " the Arch User Repository."
msgstr "" msgstr ""
#: templates/partials/account_form.html
msgid ""
"Specify multiple SSH Keys separated by new line, empty lines are ignored."
msgstr ""
#: templates/partials/account_form.html
msgid "Hide deleted comments"
msgstr ""
#: template/account_edit_form.php #: template/account_edit_form.php
msgid "SSH Public Key" msgid "SSH Public Key"
msgstr "" msgstr ""
@ -1828,22 +1821,22 @@ msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a deletion request, you ask a Package Maintainer to delete the" "By submitting a deletion request, you ask a Trusted User to delete the "
" package base. This type of request should be used for duplicates, software " "package base. This type of request should be used for duplicates, software "
"abandoned by upstream, as well as illegal and irreparably broken packages." "abandoned by upstream, as well as illegal and irreparably broken packages."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a merge request, you ask a Package Maintainer to delete the " "By submitting a merge request, you ask a Trusted User to delete the package "
"package base and transfer its votes and comments to another package base. " "base and transfer its votes and comments to another package base. Merging a "
"Merging a package does not affect the corresponding Git repositories. Make " "package does not affect the corresponding Git repositories. Make sure you "
"sure you update the Git history of the target package yourself." "update the Git history of the target package yourself."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting an orphan request, you ask a Package Maintainer to disown the " "By submitting an orphan request, you ask a Trusted User to disown the "
"package base. Please only do this if the package needs maintainer action, " "package base. Please only do this if the package needs maintainer action, "
"the maintainer is MIA and you already tried to contact the maintainer " "the maintainer is MIA and you already tried to contact the maintainer "
"previously." "previously."
@ -2100,7 +2093,7 @@ msgid "Registered Users"
msgstr "" msgstr ""
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Package Maintainers" msgid "Trusted Users"
msgstr "" msgstr ""
#: template/stats/updates_table.php #: template/stats/updates_table.php
@ -2286,7 +2279,7 @@ msgstr ""
#: scripts/notify.py #: scripts/notify.py
#, python-brace-format #, python-brace-format
msgid "Package Maintainer Vote Reminder: Proposal {id}" msgid "TU Vote Reminder: Proposal {id}"
msgstr "" msgstr ""
#: scripts/notify.py #: scripts/notify.py
@ -2340,35 +2333,3 @@ msgid ""
"This action will close any pending package requests related to it. If " "This action will close any pending package requests related to it. If "
"%sComments%s are omitted, a closure comment will be autogenerated." "%sComments%s are omitted, a closure comment will be autogenerated."
msgstr "" msgstr ""
#: templates/partials/tu/proposal/details.html
msgid "assigned"
msgstr ""
#: templaets/partials/packages/package_metadata.html
msgid "Show %d more"
msgstr ""
#: templates/partials/packages/package_metadata.html
msgid "dependencies"
msgstr ""
#: aurweb/routers/accounts.py
msgid "The account has not been deleted, check the confirmation checkbox."
msgstr ""
#: templates/partials/packages/comment_form.html
msgid "Cancel"
msgstr ""
#: templates/requests.html
msgid "Package name"
msgstr ""
#: templates/partials/account_form.html
msgid ""
"Note that if you hide your email address, it'll end up on the BCC list for "
"any request notifications. In case someone replies to these notifications, "
"you won't receive an email. However, replies are typically sent to the "
"mailing-list and would then be visible in the archive."
msgstr ""

103
po/bg.po
View file

@ -10,7 +10,7 @@ msgstr ""
"POT-Creation-Date: 2020-01-31 09:29+0100\n" "POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2011-04-10 13:21+0000\n" "PO-Revision-Date: 2011-04-10 13:21+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Bulgarian (http://app.transifex.com/lfleischer/aurweb/language/bg/)\n" "Language-Team: Bulgarian (http://www.transifex.com/lfleischer/aurweb/language/bg/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -131,15 +131,15 @@ msgid "Type"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Addition of a Package Maintainer" msgid "Addition of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer" msgid "Removal of a TU"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer (undeclared inactivity)" msgid "Removal of a TU (undeclared inactivity)"
msgstr "" msgstr ""
#: html/addvote.php #: html/addvote.php
@ -197,9 +197,8 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"Welcome to the AUR! Please read the %sAUR User Guidelines%s for more " "Welcome to the AUR! Please read the %sAUR User Guidelines%s and %sAUR TU "
"information and the %sAUR Submission Guidelines%s if you want to contribute " "Guidelines%s for more information."
"a PKGBUILD."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -214,7 +213,7 @@ msgid "Remember to vote for your favourite packages!"
msgstr "" msgstr ""
#: html/home.php #: html/home.php
msgid "Some packages may be provided as binaries in [extra]." msgid "Some packages may be provided as binaries in [community]."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -264,7 +263,7 @@ msgstr ""
msgid "" msgid ""
"Request a package to be removed from the Arch User Repository. Please do not" "Request a package to be removed from the Arch User Repository. Please do not"
" use this if a package is broken and can be fixed easily. Instead, contact " " use this if a package is broken and can be fixed easily. Instead, contact "
"the maintainer and file orphan request if necessary." "the package maintainer and file orphan request if necessary."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -307,10 +306,9 @@ msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"General discussion regarding the Arch User Repository (AUR) and Package " "General discussion regarding the Arch User Repository (AUR) and Trusted User"
"Maintainer structure takes place on %saur-general%s. For discussion relating" " structure takes place on %saur-general%s. For discussion relating to the "
" to the development of the AUR web interface, use the %saur-dev%s mailing " "development of the AUR web interface, use the %saur-dev%s mailing list."
"list."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -322,8 +320,8 @@ msgstr ""
msgid "" msgid ""
"If you find a bug in the AUR web interface, please fill out a bug report on " "If you find a bug in the AUR web interface, please fill out a bug report on "
"our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface" "our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface"
" %sonly%s. To report packaging bugs contact the maintainer or leave a " " %sonly%s. To report packaging bugs contact the package maintainer or leave "
"comment on the appropriate package page." "a comment on the appropriate package page."
msgstr "" msgstr ""
#: html/home.php #: html/home.php
@ -524,7 +522,7 @@ msgid "Delete"
msgstr "" msgstr ""
#: html/pkgdel.php #: html/pkgdel.php
msgid "Only Package Maintainers and Developers can delete packages." msgid "Only Trusted Users and Developers can delete packages."
msgstr "" msgstr ""
#: html/pkgdisown.php template/pkgbase_actions.php #: html/pkgdisown.php template/pkgbase_actions.php
@ -565,7 +563,7 @@ msgid "Disown"
msgstr "" msgstr ""
#: html/pkgdisown.php #: html/pkgdisown.php
msgid "Only Package Maintainers and Developers can disown packages." msgid "Only Trusted Users and Developers can disown packages."
msgstr "" msgstr ""
#: html/pkgflagcomment.php #: html/pkgflagcomment.php
@ -655,7 +653,7 @@ msgid "Merge"
msgstr "" msgstr ""
#: html/pkgmerge.php #: html/pkgmerge.php
msgid "Only Package Maintainers and Developers can merge packages." msgid "Only Trusted Users and Developers can merge packages."
msgstr "" msgstr ""
#: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php #: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php
@ -713,7 +711,7 @@ msgid "I accept the terms and conditions above."
msgstr "" msgstr ""
#: html/tu.php template/account_details.php template/header.php #: html/tu.php template/account_details.php template/header.php
msgid "Package Maintainer" msgid "Trusted User"
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -725,7 +723,7 @@ msgid "Voting is closed for this proposal."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
msgid "Only Package Maintainers are allowed to vote." msgid "Only Trusted Users are allowed to vote."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -1221,7 +1219,7 @@ msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
#: template/search_accounts_form.php #: template/search_accounts_form.php
msgid "Package Maintainer & Developer" msgid "Trusted User & Developer"
msgstr "" msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
@ -1324,6 +1322,10 @@ msgstr ""
msgid "Normal user" msgid "Normal user"
msgstr "" msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php
msgid "Trusted user"
msgstr ""
#: template/account_edit_form.php template/search_accounts_form.php #: template/account_edit_form.php template/search_accounts_form.php
msgid "Account Suspended" msgid "Account Suspended"
msgstr "" msgstr ""
@ -1396,15 +1398,6 @@ msgid ""
" the Arch User Repository." " the Arch User Repository."
msgstr "" msgstr ""
#: templates/partials/account_form.html
msgid ""
"Specify multiple SSH Keys separated by new line, empty lines are ignored."
msgstr ""
#: templates/partials/account_form.html
msgid "Hide deleted comments"
msgstr ""
#: template/account_edit_form.php #: template/account_edit_form.php
msgid "SSH Public Key" msgid "SSH Public Key"
msgstr "" msgstr ""
@ -1828,22 +1821,22 @@ msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a deletion request, you ask a Package Maintainer to delete the" "By submitting a deletion request, you ask a Trusted User to delete the "
" package base. This type of request should be used for duplicates, software " "package base. This type of request should be used for duplicates, software "
"abandoned by upstream, as well as illegal and irreparably broken packages." "abandoned by upstream, as well as illegal and irreparably broken packages."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a merge request, you ask a Package Maintainer to delete the " "By submitting a merge request, you ask a Trusted User to delete the package "
"package base and transfer its votes and comments to another package base. " "base and transfer its votes and comments to another package base. Merging a "
"Merging a package does not affect the corresponding Git repositories. Make " "package does not affect the corresponding Git repositories. Make sure you "
"sure you update the Git history of the target package yourself." "update the Git history of the target package yourself."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting an orphan request, you ask a Package Maintainer to disown the " "By submitting an orphan request, you ask a Trusted User to disown the "
"package base. Please only do this if the package needs maintainer action, " "package base. Please only do this if the package needs maintainer action, "
"the maintainer is MIA and you already tried to contact the maintainer " "the maintainer is MIA and you already tried to contact the maintainer "
"previously." "previously."
@ -2100,7 +2093,7 @@ msgid "Registered Users"
msgstr "" msgstr ""
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Package Maintainers" msgid "Trusted Users"
msgstr "" msgstr ""
#: template/stats/updates_table.php #: template/stats/updates_table.php
@ -2286,7 +2279,7 @@ msgstr ""
#: scripts/notify.py #: scripts/notify.py
#, python-brace-format #, python-brace-format
msgid "Package Maintainer Vote Reminder: Proposal {id}" msgid "TU Vote Reminder: Proposal {id}"
msgstr "" msgstr ""
#: scripts/notify.py #: scripts/notify.py
@ -2340,35 +2333,3 @@ msgid ""
"This action will close any pending package requests related to it. If " "This action will close any pending package requests related to it. If "
"%sComments%s are omitted, a closure comment will be autogenerated." "%sComments%s are omitted, a closure comment will be autogenerated."
msgstr "" msgstr ""
#: templates/partials/tu/proposal/details.html
msgid "assigned"
msgstr ""
#: templaets/partials/packages/package_metadata.html
msgid "Show %d more"
msgstr ""
#: templates/partials/packages/package_metadata.html
msgid "dependencies"
msgstr ""
#: aurweb/routers/accounts.py
msgid "The account has not been deleted, check the confirmation checkbox."
msgstr ""
#: templates/partials/packages/comment_form.html
msgid "Cancel"
msgstr ""
#: templates/requests.html
msgid "Package name"
msgstr ""
#: templates/partials/account_form.html
msgid ""
"Note that if you hide your email address, it'll end up on the BCC list for "
"any request notifications. In case someone replies to these notifications, "
"you won't receive an email. However, replies are typically sent to the "
"mailing-list and would then be visible in the archive."
msgstr ""

127
po/ca.po
View file

@ -14,7 +14,7 @@ msgstr ""
"POT-Creation-Date: 2020-01-31 09:29+0100\n" "POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2011-04-10 13:21+0000\n" "PO-Revision-Date: 2011-04-10 13:21+0000\n"
"Last-Translator: Ícar <icar.nin@gmail.com>, 2021\n" "Last-Translator: Ícar <icar.nin@gmail.com>, 2021\n"
"Language-Team: Catalan (http://app.transifex.com/lfleischer/aurweb/language/ca/)\n" "Language-Team: Catalan (http://www.transifex.com/lfleischer/aurweb/language/ca/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -135,16 +135,16 @@ msgid "Type"
msgstr "Tipus" msgstr "Tipus"
#: html/addvote.php #: html/addvote.php
msgid "Addition of a Package Maintainer" msgid "Addition of a TU"
msgstr "" msgstr "Adició d'un TU"
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer" msgid "Removal of a TU"
msgstr "" msgstr "Elimincació d'un TU"
#: html/addvote.php #: html/addvote.php
msgid "Removal of a Package Maintainer (undeclared inactivity)" msgid "Removal of a TU (undeclared inactivity)"
msgstr "" msgstr "Elimincació d'un TU (inactivitat no declarada)"
#: html/addvote.php #: html/addvote.php
msgid "Amendment of Bylaws" msgid "Amendment of Bylaws"
@ -201,10 +201,9 @@ msgstr "Cerca paquets que co-mantinc"
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"Welcome to the AUR! Please read the %sAUR User Guidelines%s for more " "Welcome to the AUR! Please read the %sAUR User Guidelines%s and %sAUR TU "
"information and the %sAUR Submission Guidelines%s if you want to contribute " "Guidelines%s for more information."
"a PKGBUILD." msgstr "Benvingut a l'AUR! Si us plau, llegiu les %sdirectrius d'usuari d'AUR%s i les %sdirectrius de TU (usuari de confiança) d'AUR%s per més informació."
msgstr ""
#: html/home.php #: html/home.php
#, php-format #, php-format
@ -218,8 +217,8 @@ msgid "Remember to vote for your favourite packages!"
msgstr "Recordeu votar els vostres paquets preferits!" msgstr "Recordeu votar els vostres paquets preferits!"
#: html/home.php #: html/home.php
msgid "Some packages may be provided as binaries in [extra]." msgid "Some packages may be provided as binaries in [community]."
msgstr "Alguns paquets poden ser oferts com binaris a [extra]." msgstr "Alguns paquets poden ser oferts com binaris a [community]."
#: html/home.php #: html/home.php
msgid "DISCLAIMER" msgid "DISCLAIMER"
@ -268,8 +267,8 @@ msgstr "Sol·licitud de supressió"
msgid "" msgid ""
"Request a package to be removed from the Arch User Repository. Please do not" "Request a package to be removed from the Arch User Repository. Please do not"
" use this if a package is broken and can be fixed easily. Instead, contact " " use this if a package is broken and can be fixed easily. Instead, contact "
"the maintainer and file orphan request if necessary." "the package maintainer and file orphan request if necessary."
msgstr "" msgstr "Sol·liciteu que s'elimini un paquet de l'AUR. Si us plau, no ho utilitzeu si un paquet està trencat i es pot arreglar fàcilment. En lloc d'això, poseu-vos en contacte amb el mantenidor del paquet i sol·liciteu que es se'n renegui si cal."
#: html/home.php #: html/home.php
msgid "Merge Request" msgid "Merge Request"
@ -311,11 +310,10 @@ msgstr "Discussió"
#: html/home.php #: html/home.php
#, php-format #, php-format
msgid "" msgid ""
"General discussion regarding the Arch User Repository (AUR) and Package " "General discussion regarding the Arch User Repository (AUR) and Trusted User"
"Maintainer structure takes place on %saur-general%s. For discussion relating" " structure takes place on %saur-general%s. For discussion relating to the "
" to the development of the AUR web interface, use the %saur-dev%s mailing " "development of the AUR web interface, use the %saur-dev%s mailing list."
"list." msgstr "El debat general sobre el repositori per usuaris d'Arch (AUR) i de l'estructura dels Usuaris de Confiança es realitza a %saur-general%s. Per la discussió relacionada amb el desenvolupament de la interfície web de l'AUR, utilitzeu la llista de correu %saur-dev%s."
msgstr ""
#: html/home.php #: html/home.php
msgid "Bug Reporting" msgid "Bug Reporting"
@ -326,9 +324,9 @@ msgstr "Comunicar errada"
msgid "" msgid ""
"If you find a bug in the AUR web interface, please fill out a bug report on " "If you find a bug in the AUR web interface, please fill out a bug report on "
"our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface" "our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface"
" %sonly%s. To report packaging bugs contact the maintainer or leave a " " %sonly%s. To report packaging bugs contact the package maintainer or leave "
"comment on the appropriate package page." "a comment on the appropriate package page."
msgstr "" msgstr "Si troba un error en la interfície web de l'AUR, si us plau, ompliu un informe d'error al nostre %srastrejador d'errades%s. Utilitzeu el rastrejador per reportar %snomés%s errors de l'interfície web. Per informar d'errades en els paquets contacteu directament amb el responsable del paquet o deixeu un comentari a la pàgina del paquet corresponent."
#: html/home.php #: html/home.php
msgid "Package Search" msgid "Package Search"
@ -528,8 +526,8 @@ msgid "Delete"
msgstr "Esborra" msgstr "Esborra"
#: html/pkgdel.php #: html/pkgdel.php
msgid "Only Package Maintainers and Developers can delete packages." msgid "Only Trusted Users and Developers can delete packages."
msgstr "" msgstr "Només els usuaris de confiança (TUs) i desenvolupadors poden eliminar paquets."
#: html/pkgdisown.php template/pkgbase_actions.php #: html/pkgdisown.php template/pkgbase_actions.php
msgid "Disown Package" msgid "Disown Package"
@ -569,7 +567,7 @@ msgid "Disown"
msgstr "" msgstr ""
#: html/pkgdisown.php #: html/pkgdisown.php
msgid "Only Package Maintainers and Developers can disown packages." msgid "Only Trusted Users and Developers can disown packages."
msgstr "" msgstr ""
#: html/pkgflagcomment.php #: html/pkgflagcomment.php
@ -659,8 +657,8 @@ msgid "Merge"
msgstr "Fusió" msgstr "Fusió"
#: html/pkgmerge.php #: html/pkgmerge.php
msgid "Only Package Maintainers and Developers can merge packages." msgid "Only Trusted Users and Developers can merge packages."
msgstr "" msgstr "Només el usuaris de confiança (TUs) i desenvolupadors poden fusionar paquets."
#: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php #: html/pkgreq.php template/pkgbase_actions.php template/pkgreq_form.php
msgid "Submit Request" msgid "Submit Request"
@ -717,8 +715,8 @@ msgid "I accept the terms and conditions above."
msgstr "" msgstr ""
#: html/tu.php template/account_details.php template/header.php #: html/tu.php template/account_details.php template/header.php
msgid "Package Maintainer" msgid "Trusted User"
msgstr "" msgstr "Usuari de Confiança"
#: html/tu.php #: html/tu.php
msgid "Could not retrieve proposal details." msgid "Could not retrieve proposal details."
@ -729,7 +727,7 @@ msgid "Voting is closed for this proposal."
msgstr "La votació es va tancar per a aquesta proposta." msgstr "La votació es va tancar per a aquesta proposta."
#: html/tu.php #: html/tu.php
msgid "Only Package Maintainers are allowed to vote." msgid "Only Trusted Users are allowed to vote."
msgstr "" msgstr ""
#: html/tu.php #: html/tu.php
@ -1225,7 +1223,7 @@ msgstr "Desenvolupador"
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
#: template/search_accounts_form.php #: template/search_accounts_form.php
msgid "Package Maintainer & Developer" msgid "Trusted User & Developer"
msgstr "" msgstr ""
#: template/account_details.php template/account_edit_form.php #: template/account_details.php template/account_edit_form.php
@ -1328,6 +1326,10 @@ msgstr ""
msgid "Normal user" msgid "Normal user"
msgstr "Usuari normal" msgstr "Usuari normal"
#: template/account_edit_form.php template/search_accounts_form.php
msgid "Trusted user"
msgstr "Usuari de Confiança"
#: template/account_edit_form.php template/search_accounts_form.php #: template/account_edit_form.php template/search_accounts_form.php
msgid "Account Suspended" msgid "Account Suspended"
msgstr "El compte s'ha suspès" msgstr "El compte s'ha suspès"
@ -1400,15 +1402,6 @@ msgid ""
" the Arch User Repository." " the Arch User Repository."
msgstr "" msgstr ""
#: templates/partials/account_form.html
msgid ""
"Specify multiple SSH Keys separated by new line, empty lines are ignored."
msgstr ""
#: templates/partials/account_form.html
msgid "Hide deleted comments"
msgstr ""
#: template/account_edit_form.php #: template/account_edit_form.php
msgid "SSH Public Key" msgid "SSH Public Key"
msgstr "" msgstr ""
@ -1832,22 +1825,22 @@ msgstr "Combinar amb"
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a deletion request, you ask a Package Maintainer to delete the" "By submitting a deletion request, you ask a Trusted User to delete the "
" package base. This type of request should be used for duplicates, software " "package base. This type of request should be used for duplicates, software "
"abandoned by upstream, as well as illegal and irreparably broken packages." "abandoned by upstream, as well as illegal and irreparably broken packages."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting a merge request, you ask a Package Maintainer to delete the " "By submitting a merge request, you ask a Trusted User to delete the package "
"package base and transfer its votes and comments to another package base. " "base and transfer its votes and comments to another package base. Merging a "
"Merging a package does not affect the corresponding Git repositories. Make " "package does not affect the corresponding Git repositories. Make sure you "
"sure you update the Git history of the target package yourself." "update the Git history of the target package yourself."
msgstr "" msgstr ""
#: template/pkgreq_form.php #: template/pkgreq_form.php
msgid "" msgid ""
"By submitting an orphan request, you ask a Package Maintainer to disown the " "By submitting an orphan request, you ask a Trusted User to disown the "
"package base. Please only do this if the package needs maintainer action, " "package base. Please only do this if the package needs maintainer action, "
"the maintainer is MIA and you already tried to contact the maintainer " "the maintainer is MIA and you already tried to contact the maintainer "
"previously." "previously."
@ -2104,8 +2097,8 @@ msgid "Registered Users"
msgstr "Usuaris registrats" msgstr "Usuaris registrats"
#: template/stats/general_stats_table.php #: template/stats/general_stats_table.php
msgid "Package Maintainers" msgid "Trusted Users"
msgstr "" msgstr "Usuaris de Confiança"
#: template/stats/updates_table.php #: template/stats/updates_table.php
msgid "Recent Updates" msgid "Recent Updates"
@ -2290,7 +2283,7 @@ msgstr ""
#: scripts/notify.py #: scripts/notify.py
#, python-brace-format #, python-brace-format
msgid "Package Maintainer Vote Reminder: Proposal {id}" msgid "TU Vote Reminder: Proposal {id}"
msgstr "" msgstr ""
#: scripts/notify.py #: scripts/notify.py
@ -2344,35 +2337,3 @@ msgid ""
"This action will close any pending package requests related to it. If " "This action will close any pending package requests related to it. If "
"%sComments%s are omitted, a closure comment will be autogenerated." "%sComments%s are omitted, a closure comment will be autogenerated."
msgstr "" msgstr ""
#: templates/partials/tu/proposal/details.html
msgid "assigned"
msgstr ""
#: templaets/partials/packages/package_metadata.html
msgid "Show %d more"
msgstr ""
#: templates/partials/packages/package_metadata.html
msgid "dependencies"
msgstr ""
#: aurweb/routers/accounts.py
msgid "The account has not been deleted, check the confirmation checkbox."
msgstr ""
#: templates/partials/packages/comment_form.html
msgid "Cancel"
msgstr ""
#: templates/requests.html
msgid "Package name"
msgstr ""
#: templates/partials/account_form.html
msgid ""
"Note that if you hide your email address, it'll end up on the BCC list for "
"any request notifications. In case someone replies to these notifications, "
"you won't receive an email. However, replies are typically sent to the "
"mailing-list and would then be visible in the archive."
msgstr ""

Some files were not shown because too many files have changed in this diff Show more