mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
housekeep: TU rename - Table/Column names, scripts
TU_VoteInfo -> VoteInfo TU_Votes -> Votes TU_VoteInfo.ActiveTUs -> VoteInfo.ActiveUsers script: tuvotereminder -> votereminder Signed-off-by: moson <moson@archlinux.org>
This commit is contained in:
parent
25b48448d7
commit
5b366795e3
23 changed files with 234 additions and 192 deletions
2
INSTALL
2
INSTALL
|
@ -125,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-tuvotereminder'
|
*/12 * * * * bash -c 'poetry run aurweb-votereminder'
|
||||||
|
|
||||||
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:
|
||||||
|
|
||||||
|
|
|
@ -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 TUVote
|
from aurweb.models import Vote
|
||||||
|
|
||||||
return voteinfo.tu_votes.filter(TUVote.User == request.user).first()
|
return voteinfo.votes.filter(Vote.User == request.user).first()
|
||||||
|
|
||||||
|
|
||||||
@register_filter("number_format")
|
@register_filter("number_format")
|
||||||
|
|
|
@ -26,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
|
||||||
|
|
|
@ -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 TUVote(Base):
|
class Vote(Base):
|
||||||
__table__ = schema.TU_Votes
|
__table__ = schema.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(
|
||||||
_TUVoteInfo,
|
_VoteInfo,
|
||||||
backref=backref("tu_votes", lazy="dynamic"),
|
backref=backref("votes", lazy="dynamic"),
|
||||||
foreign_keys=[__table__.c.VoteID],
|
foreign_keys=[__table__.c.VoteID],
|
||||||
)
|
)
|
||||||
|
|
||||||
User = relationship(
|
User = relationship(
|
||||||
_User,
|
_User,
|
||||||
backref=backref("tu_votes", lazy="dynamic"),
|
backref=backref("votes", lazy="dynamic"),
|
||||||
foreign_keys=[__table__.c.UserID],
|
foreign_keys=[__table__.c.UserID],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,13 +30,13 @@ class TUVote(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="TU_Votes.VoteID",
|
orig="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="TU_Votes.UserID",
|
orig="Votes.UserID",
|
||||||
params=("NULL"),
|
params=("NULL"),
|
||||||
)
|
)
|
|
@ -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 TUVoteInfo(Base):
|
class VoteInfo(Base):
|
||||||
__table__ = schema.TU_VoteInfo
|
__table__ = schema.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("tu_voteinfo_set", lazy="dynamic"),
|
backref=backref("voteinfo_set", lazy="dynamic"),
|
||||||
foreign_keys=[__table__.c.SubmitterID],
|
foreign_keys=[__table__.c.SubmitterID],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,35 +30,35 @@ class TUVoteInfo(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="TU_VoteInfo.Agenda",
|
orig="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="TU_VoteInfo.User",
|
orig="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="TU_VoteInfo.Submitted",
|
orig="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="TU_VoteInfo.End",
|
orig="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="TU_VoteInfo.SubmitterID",
|
orig="VoteInfo.SubmitterID",
|
||||||
params=("NULL"),
|
params=("NULL"),
|
||||||
)
|
)
|
||||||
|
|
|
@ -87,9 +87,9 @@ async def package_maintainer(
|
||||||
context["past_by"] = past_by
|
context["past_by"] = past_by
|
||||||
|
|
||||||
current_votes = (
|
current_votes = (
|
||||||
db.query(models.TUVoteInfo)
|
db.query(models.VoteInfo)
|
||||||
.filter(models.TUVoteInfo.End > ts)
|
.filter(models.VoteInfo.End > ts)
|
||||||
.order_by(models.TUVoteInfo.Submitted.desc())
|
.order_by(models.VoteInfo.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 +99,9 @@ async def package_maintainer(
|
||||||
context["current_off"] = current_off
|
context["current_off"] = current_off
|
||||||
|
|
||||||
past_votes = (
|
past_votes = (
|
||||||
db.query(models.TUVoteInfo)
|
db.query(models.VoteInfo)
|
||||||
.filter(models.TUVoteInfo.End <= ts)
|
.filter(models.VoteInfo.End <= ts)
|
||||||
.order_by(models.TUVoteInfo.Submitted.desc())
|
.order_by(models.VoteInfo.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,21 +110,21 @@ async def package_maintainer(
|
||||||
)
|
)
|
||||||
context["past_off"] = past_off
|
context["past_off"] = past_off
|
||||||
|
|
||||||
last_vote = func.max(models.TUVote.VoteID).label("LastVote")
|
last_vote = func.max(models.Vote.VoteID).label("LastVote")
|
||||||
last_votes_by_pm = (
|
last_votes_by_pm = (
|
||||||
db.query(models.TUVote)
|
db.query(models.Vote)
|
||||||
.join(models.User)
|
.join(models.User)
|
||||||
.join(models.TUVoteInfo, models.TUVoteInfo.ID == models.TUVote.VoteID)
|
.join(models.VoteInfo, models.VoteInfo.ID == models.Vote.VoteID)
|
||||||
.filter(
|
.filter(
|
||||||
and_(
|
and_(
|
||||||
models.TUVote.VoteID == models.TUVoteInfo.ID,
|
models.Vote.VoteID == models.VoteInfo.ID,
|
||||||
models.User.ID == models.TUVote.UserID,
|
models.User.ID == models.Vote.UserID,
|
||||||
models.TUVoteInfo.End < ts,
|
models.VoteInfo.End < ts,
|
||||||
or_(models.User.AccountTypeID == 2, models.User.AccountTypeID == 4),
|
or_(models.User.AccountTypeID == 2, models.User.AccountTypeID == 4),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.with_entities(models.TUVote.UserID, last_vote, models.User.Username)
|
.with_entities(models.Vote.UserID, last_vote, models.User.Username)
|
||||||
.group_by(models.TUVote.UserID)
|
.group_by(models.Vote.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_pm"] = last_votes_by_pm.all()
|
||||||
|
@ -148,9 +148,9 @@ def render_proposal(
|
||||||
request: Request,
|
request: Request,
|
||||||
context: dict,
|
context: dict,
|
||||||
proposal: int,
|
proposal: int,
|
||||||
voteinfo: models.TUVoteInfo,
|
voteinfo: models.VoteInfo,
|
||||||
voters: typing.Iterable[models.User],
|
voters: typing.Iterable[models.User],
|
||||||
vote: models.TUVote,
|
vote: models.Vote,
|
||||||
status_code: HTTPStatus = HTTPStatus.OK,
|
status_code: HTTPStatus = HTTPStatus.OK,
|
||||||
):
|
):
|
||||||
"""Render a single PM proposal."""
|
"""Render a single PM proposal."""
|
||||||
|
@ -159,15 +159,15 @@ def render_proposal(
|
||||||
context["voters"] = voters.all()
|
context["voters"] = voters.all()
|
||||||
|
|
||||||
total = voteinfo.total_votes()
|
total = voteinfo.total_votes()
|
||||||
participation = (total / voteinfo.ActiveTUs) if voteinfo.ActiveTUs else 0
|
participation = (total / voteinfo.ActiveUsers) if voteinfo.ActiveUsers else 0
|
||||||
context["participation"] = participation
|
context["participation"] = participation
|
||||||
|
|
||||||
accepted = (voteinfo.Yes > voteinfo.ActiveTUs / 2) or (
|
accepted = (voteinfo.Yes > voteinfo.ActiveUsers / 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.TUVote.User == request.user).first() is None
|
can_vote = voters.filter(models.Vote.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():
|
||||||
|
@ -190,23 +190,21 @@ async def package_maintainer_proposal(request: Request, proposal: int):
|
||||||
context = await make_variable_context(request, "Package Maintainer")
|
context = await make_variable_context(request, "Package Maintainer")
|
||||||
proposal = int(proposal)
|
proposal = int(proposal)
|
||||||
|
|
||||||
voteinfo = (
|
voteinfo = db.query(models.VoteInfo).filter(models.VoteInfo.ID == proposal).first()
|
||||||
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.TUVote)
|
.join(models.Vote)
|
||||||
.filter(models.TUVote.VoteID == voteinfo.ID)
|
.filter(models.Vote.VoteID == voteinfo.ID)
|
||||||
)
|
)
|
||||||
vote = (
|
vote = (
|
||||||
db.query(models.TUVote)
|
db.query(models.Vote)
|
||||||
.filter(
|
.filter(
|
||||||
and_(
|
and_(
|
||||||
models.TUVote.UserID == request.user.ID,
|
models.Vote.UserID == request.user.ID,
|
||||||
models.TUVote.VoteID == voteinfo.ID,
|
models.Vote.VoteID == voteinfo.ID,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.first()
|
.first()
|
||||||
|
@ -235,23 +233,21 @@ async def package_maintainer_proposal_post(
|
||||||
context = await make_variable_context(request, "Package Maintainer")
|
context = await make_variable_context(request, "Package Maintainer")
|
||||||
proposal = int(proposal) # Make sure it's an int.
|
proposal = int(proposal) # Make sure it's an int.
|
||||||
|
|
||||||
voteinfo = (
|
voteinfo = db.query(models.VoteInfo).filter(models.VoteInfo.ID == proposal).first()
|
||||||
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.TUVote)
|
.join(models.Vote)
|
||||||
.filter(models.TUVote.VoteID == voteinfo.ID)
|
.filter(models.Vote.VoteID == voteinfo.ID)
|
||||||
)
|
)
|
||||||
vote = (
|
vote = (
|
||||||
db.query(models.TUVote)
|
db.query(models.Vote)
|
||||||
.filter(
|
.filter(
|
||||||
and_(
|
and_(
|
||||||
models.TUVote.UserID == request.user.ID,
|
models.Vote.UserID == request.user.ID,
|
||||||
models.TUVote.VoteID == voteinfo.ID,
|
models.Vote.VoteID == voteinfo.ID,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.first()
|
.first()
|
||||||
|
@ -282,7 +278,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.TUVote, User=request.user, VoteInfo=voteinfo)
|
vote = db.create(models.Vote, 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)
|
||||||
|
@ -342,10 +338,8 @@ async def package_maintainer_addvote_post(
|
||||||
|
|
||||||
utcnow = time.utcnow()
|
utcnow = time.utcnow()
|
||||||
voteinfo = (
|
voteinfo = (
|
||||||
db.query(models.TUVoteInfo)
|
db.query(models.VoteInfo)
|
||||||
.filter(
|
.filter(and_(models.VoteInfo.User == user, models.VoteInfo.End > utcnow))
|
||||||
and_(models.TUVoteInfo.User == user, models.TUVoteInfo.End > utcnow)
|
|
||||||
)
|
|
||||||
.count()
|
.count()
|
||||||
)
|
)
|
||||||
if voteinfo:
|
if voteinfo:
|
||||||
|
@ -371,7 +365,7 @@ async def package_maintainer_addvote_post(
|
||||||
# Active PM types we filter for.
|
# Active PM types we filter for.
|
||||||
types = {PACKAGE_MAINTAINER_ID, PACKAGE_MAINTAINER_AND_DEV_ID}
|
types = {PACKAGE_MAINTAINER_ID, PACKAGE_MAINTAINER_AND_DEV_ID}
|
||||||
|
|
||||||
# Create a new TUVoteInfo (proposal)!
|
# Create a new VoteInfo (proposal)!
|
||||||
with db.begin():
|
with db.begin():
|
||||||
active_pms = (
|
active_pms = (
|
||||||
db.query(User)
|
db.query(User)
|
||||||
|
@ -385,13 +379,13 @@ async def package_maintainer_addvote_post(
|
||||||
.count()
|
.count()
|
||||||
)
|
)
|
||||||
voteinfo = db.create(
|
voteinfo = db.create(
|
||||||
models.TUVoteInfo,
|
models.VoteInfo,
|
||||||
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,
|
||||||
ActiveTUs=active_pms,
|
ActiveUsers=active_pms,
|
||||||
Submitter=request.user,
|
Submitter=request.user,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -526,8 +526,8 @@ PackageRequests = Table(
|
||||||
|
|
||||||
|
|
||||||
# Vote information
|
# Vote information
|
||||||
TU_VoteInfo = Table(
|
VoteInfo = Table(
|
||||||
"TU_VoteInfo",
|
"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),
|
||||||
|
@ -546,7 +546,10 @@ TU_VoteInfo = Table(
|
||||||
"Abstain", INTEGER(unsigned=True), nullable=False, server_default=text("'0'")
|
"Abstain", INTEGER(unsigned=True), nullable=False, server_default=text("'0'")
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
"ActiveTUs", INTEGER(unsigned=True), nullable=False, server_default=text("'0'")
|
"ActiveUsers",
|
||||||
|
INTEGER(unsigned=True),
|
||||||
|
nullable=False,
|
||||||
|
server_default=text("'0'"),
|
||||||
),
|
),
|
||||||
mysql_engine="InnoDB",
|
mysql_engine="InnoDB",
|
||||||
mysql_charset="utf8mb4",
|
mysql_charset="utf8mb4",
|
||||||
|
@ -555,10 +558,10 @@ TU_VoteInfo = Table(
|
||||||
|
|
||||||
|
|
||||||
# Individual vote records
|
# Individual vote records
|
||||||
TU_Votes = Table(
|
Votes = Table(
|
||||||
"TU_Votes",
|
"Votes",
|
||||||
metadata,
|
metadata,
|
||||||
Column("VoteID", ForeignKey("TU_VoteInfo.ID", ondelete="CASCADE"), nullable=False),
|
Column("VoteID", ForeignKey("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",
|
||||||
)
|
)
|
||||||
|
|
|
@ -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.tu_vote import TUVote
|
from aurweb.models.vote import Vote
|
||||||
|
|
||||||
logger = aur_logging.get_logger(__name__)
|
logger = aur_logging.get_logger(__name__)
|
||||||
|
|
||||||
|
@ -744,11 +744,11 @@ class RequestCloseNotification(Notification):
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
|
|
||||||
class TUVoteReminderNotification(Notification):
|
class VoteReminderNotification(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(TUVote.UserID).filter(TUVote.VoteID == vote_id)
|
subquery = db.query(Vote.UserID).filter(Vote.VoteID == vote_id)
|
||||||
query = (
|
query = (
|
||||||
db.query(User)
|
db.query(User)
|
||||||
.filter(
|
.filter(
|
||||||
|
@ -799,7 +799,7 @@ def main():
|
||||||
"delete": DeleteNotification,
|
"delete": DeleteNotification,
|
||||||
"request-open": RequestOpenNotification,
|
"request-open": RequestOpenNotification,
|
||||||
"request-close": RequestCloseNotification,
|
"request-close": RequestCloseNotification,
|
||||||
"tu-vote-reminder": TUVoteReminderNotification,
|
"vote-reminder": VoteReminderNotification,
|
||||||
}
|
}
|
||||||
|
|
||||||
with db.begin():
|
with db.begin():
|
||||||
|
|
|
@ -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 TUVoteInfo
|
from aurweb.models import VoteInfo
|
||||||
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("tuvotereminder", "range_start")
|
start = aurweb.config.getint("votereminder", "range_start")
|
||||||
filter_from = now + start
|
filter_from = now + start
|
||||||
|
|
||||||
end = aurweb.config.getint("tuvotereminder", "range_end")
|
end = aurweb.config.getint("votereminder", "range_end")
|
||||||
filter_to = now + end
|
filter_to = now + end
|
||||||
|
|
||||||
query = db.query(TUVoteInfo.ID).filter(
|
query = db.query(VoteInfo.ID).filter(
|
||||||
and_(TUVoteInfo.End >= filter_from, TUVoteInfo.End <= filter_to)
|
and_(VoteInfo.End >= filter_from, VoteInfo.End <= filter_to)
|
||||||
)
|
)
|
||||||
for voteinfo in query:
|
for voteinfo in query:
|
||||||
notif = notify.TUVoteReminderNotification(voteinfo.ID)
|
notif = notify.VoteReminderNotification(voteinfo.ID)
|
||||||
notif.send()
|
notif.send()
|
||||||
|
|
||||||
|
|
|
@ -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.TUVote.__tablename__,
|
models.Vote.__tablename__,
|
||||||
models.TUVoteInfo.__tablename__,
|
models.VoteInfo.__tablename__,
|
||||||
models.User.__tablename__,
|
models.User.__tablename__,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ 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
|
||||||
|
|
||||||
[tuvotereminder]
|
[votereminder]
|
||||||
; Offsets used to determine when Package Maintainers should be reminded about
|
; Offsets used to determine when Package Maintainers 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 Package Maintainer has not yet
|
||||||
|
|
|
@ -62,7 +62,7 @@ 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-tuvotereminder sends out reminders to TUs if the voting period for a
|
* aurweb-votereminder sends out reminders if the voting period for a
|
||||||
Package Maintainer proposal ends soon.
|
Package Maintainer 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,7 +107,7 @@ 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-tuvotereminder
|
5 */12 * * * poetry run aurweb-votereminder
|
||||||
----
|
----
|
||||||
|
|
||||||
Advanced Administrative Features
|
Advanced Administrative Features
|
||||||
|
|
|
@ -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-tuvotereminder'
|
*/12 * * * * bash -c 'aurweb-votereminder'
|
||||||
|
|
47
migrations/versions/7d65d35fae45_rename_tu_tables_columns.py
Normal file
47
migrations/versions/7d65d35fae45_rename_tu_tables_columns.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
"""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",
|
||||||
|
)
|
|
@ -116,7 +116,7 @@ aurweb-notify = "aurweb.scripts.notify:main"
|
||||||
aurweb-pkgmaint = "aurweb.scripts.pkgmaint:main"
|
aurweb-pkgmaint = "aurweb.scripts.pkgmaint:main"
|
||||||
aurweb-popupdate = "aurweb.scripts.popupdate:main"
|
aurweb-popupdate = "aurweb.scripts.popupdate:main"
|
||||||
aurweb-rendercomment = "aurweb.scripts.rendercomment:main"
|
aurweb-rendercomment = "aurweb.scripts.rendercomment:main"
|
||||||
aurweb-tuvotereminder = "aurweb.scripts.tuvotereminder:main"
|
aurweb-votereminder = "aurweb.scripts.votereminder:main"
|
||||||
aurweb-usermaint = "aurweb.scripts.usermaint:main"
|
aurweb-usermaint = "aurweb.scripts.usermaint:main"
|
||||||
aurweb-config = "aurweb.scripts.config:main"
|
aurweb-config = "aurweb.scripts.config:main"
|
||||||
aurweb-adduser = "aurweb.scripts.adduser:main"
|
aurweb-adduser = "aurweb.scripts.adduser:main"
|
||||||
|
|
|
@ -357,7 +357,7 @@ for t in range(0, OPEN_PROPOSALS + CLOSE_PROPOSALS):
|
||||||
user = user_keys[random.randrange(0, len(user_keys))]
|
user = user_keys[random.randrange(0, len(user_keys))]
|
||||||
suid = packagemaintainers[random.randrange(0, len(packagemaintainers))]
|
suid = packagemaintainers[random.randrange(0, len(packagemaintainers))]
|
||||||
s = (
|
s = (
|
||||||
"INSERT INTO TU_VoteInfo (Agenda, User, Submitted, End,"
|
"INSERT INTO VoteInfo (Agenda, User, Submitted, End,"
|
||||||
" Quorum, SubmitterID) VALUES ('%s', '%s', %d, %d, 0.0, %d);\n"
|
" Quorum, SubmitterID) VALUES ('%s', '%s', %d, %d, 0.0, %d);\n"
|
||||||
)
|
)
|
||||||
s = s % (genFortune(), user, start, end, suid)
|
s = s % (genFortune(), user, start, end, suid)
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
{{ "Active" | tr }} {{ "Package Maintainers" | tr }} {{ "assigned" | tr }}:
|
{{ "Active" | tr }} {{ "Package Maintainers" | tr }} {{ "assigned" | tr }}:
|
||||||
{{ voteinfo.ActiveTUs }}
|
{{ voteinfo.ActiveUsers }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% set submitter = voteinfo.Submitter.Username %}
|
{% set submitter = voteinfo.Submitter.Username %}
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
{% if not voteinfo.is_running() %}
|
{% if not voteinfo.is_running() %}
|
||||||
<div class="field result">
|
<div class="field result">
|
||||||
{{ "Result" | tr }}:
|
{{ "Result" | tr }}:
|
||||||
{% if not voteinfo.ActiveTUs %}
|
{% if not voteinfo.ActiveUsers %}
|
||||||
<span>{{ "unknown" | tr }}</span>
|
<span>{{ "unknown" | tr }}</span>
|
||||||
{% elif accepted %}
|
{% elif accepted %}
|
||||||
<span style="color: green; font-weight: bold">
|
<span style="color: green; font-weight: bold">
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if voteinfo.ActiveTUs %}
|
{% if voteinfo.ActiveUsers %}
|
||||||
{{ (participation * 100) | number_format(2) }}%
|
{{ (participation * 100) | number_format(2) }}%
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ "unknown" | tr }}
|
{{ "unknown" | tr }}
|
||||||
|
|
|
@ -11,7 +11,7 @@ GIT_AUTH="$TOPLEVEL/aurweb/git/auth.py"
|
||||||
GIT_SERVE="$TOPLEVEL/aurweb/git/serve.py"
|
GIT_SERVE="$TOPLEVEL/aurweb/git/serve.py"
|
||||||
GIT_UPDATE="$TOPLEVEL/aurweb/git/update.py"
|
GIT_UPDATE="$TOPLEVEL/aurweb/git/update.py"
|
||||||
MKPKGLISTS="$TOPLEVEL/aurweb/scripts/mkpkglists.py"
|
MKPKGLISTS="$TOPLEVEL/aurweb/scripts/mkpkglists.py"
|
||||||
TUVOTEREMINDER="$TOPLEVEL/aurweb/scripts/tuvotereminder.py"
|
VOTEREMINDER="$TOPLEVEL/aurweb/scripts/votereminder.py"
|
||||||
PKGMAINT="$TOPLEVEL/aurweb/scripts/pkgmaint.py"
|
PKGMAINT="$TOPLEVEL/aurweb/scripts/pkgmaint.py"
|
||||||
USERMAINT="$TOPLEVEL/aurweb/scripts/usermaint.py"
|
USERMAINT="$TOPLEVEL/aurweb/scripts/usermaint.py"
|
||||||
AURBLUP="$TOPLEVEL/aurweb/scripts/aurblup.py"
|
AURBLUP="$TOPLEVEL/aurweb/scripts/aurblup.py"
|
||||||
|
|
|
@ -544,11 +544,11 @@ This is a test closure comment.
|
||||||
assert email.body == expected
|
assert email.body == expected
|
||||||
|
|
||||||
|
|
||||||
def test_pm_vote_reminders(user: User):
|
def test_vote_reminders(user: User):
|
||||||
set_tu([user])
|
set_tu([user])
|
||||||
|
|
||||||
vote_id = 1
|
vote_id = 1
|
||||||
notif = notify.TUVoteReminderNotification(vote_id)
|
notif = notify.VoteReminderNotification(vote_id)
|
||||||
notif.send()
|
notif.send()
|
||||||
assert Email.count() == 1
|
assert Email.count() == 1
|
||||||
|
|
||||||
|
@ -571,7 +571,7 @@ def test_notify_main(user: User):
|
||||||
set_tu([user])
|
set_tu([user])
|
||||||
|
|
||||||
vote_id = 1
|
vote_id = 1
|
||||||
args = ["aurweb-notify", "tu-vote-reminder", str(vote_id)]
|
args = ["aurweb-notify", "vote-reminder", str(vote_id)]
|
||||||
with mock.patch("sys.argv", args):
|
with mock.patch("sys.argv", args):
|
||||||
notify.main()
|
notify.main()
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from aurweb import config, db, filters, time
|
from aurweb import config, db, filters, time
|
||||||
from aurweb.models.account_type import DEVELOPER_ID, PACKAGE_MAINTAINER_ID, AccountType
|
from aurweb.models.account_type import DEVELOPER_ID, PACKAGE_MAINTAINER_ID, AccountType
|
||||||
from aurweb.models.tu_vote import TUVote
|
|
||||||
from aurweb.models.tu_voteinfo import TUVoteInfo
|
|
||||||
from aurweb.models.user import User
|
from aurweb.models.user import User
|
||||||
|
from aurweb.models.vote import Vote
|
||||||
|
from aurweb.models.voteinfo import VoteInfo
|
||||||
from aurweb.testing.requests import Request
|
from aurweb.testing.requests import Request
|
||||||
|
|
||||||
DATETIME_REGEX = r"^[0-9]{4}-[0-9]{2}-[0-9]{2} \(.+\)$"
|
DATETIME_REGEX = r"^[0-9]{4}-[0-9]{2}-[0-9]{2} \(.+\)$"
|
||||||
|
@ -143,7 +143,7 @@ def proposal(user, pm_user):
|
||||||
|
|
||||||
with db.begin():
|
with db.begin():
|
||||||
voteinfo = db.create(
|
voteinfo = db.create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda=agenda,
|
Agenda=agenda,
|
||||||
Quorum=0.0,
|
Quorum=0.0,
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
|
@ -210,7 +210,7 @@ def test_pm_index(client, pm_user):
|
||||||
agenda, start, end = vote
|
agenda, start, end = vote
|
||||||
vote_records.append(
|
vote_records.append(
|
||||||
db.create(
|
db.create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda=agenda,
|
Agenda=agenda,
|
||||||
User=pm_user.Username,
|
User=pm_user.Username,
|
||||||
Submitted=start,
|
Submitted=start,
|
||||||
|
@ -224,8 +224,8 @@ def test_pm_index(client, pm_user):
|
||||||
# Vote on an ended proposal.
|
# Vote on an ended proposal.
|
||||||
vote_record = vote_records[1]
|
vote_record = vote_records[1]
|
||||||
vote_record.Yes += 1
|
vote_record.Yes += 1
|
||||||
vote_record.ActiveTUs += 1
|
vote_record.ActiveUsers += 1
|
||||||
db.create(TUVote, VoteInfo=vote_record, User=pm_user)
|
db.create(Vote, VoteInfo=vote_record, User=pm_user)
|
||||||
|
|
||||||
cookies = {"AURSID": pm_user.login(Request(), "testPassword")}
|
cookies = {"AURSID": pm_user.login(Request(), "testPassword")}
|
||||||
with client as request:
|
with client as request:
|
||||||
|
@ -347,7 +347,7 @@ def test_pm_index_table_paging(client, pm_user):
|
||||||
for i in range(25):
|
for i in range(25):
|
||||||
# Create 25 current votes.
|
# Create 25 current votes.
|
||||||
db.create(
|
db.create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda=f"Agenda #{i}",
|
Agenda=f"Agenda #{i}",
|
||||||
User=pm_user.Username,
|
User=pm_user.Username,
|
||||||
Submitted=(ts - 5),
|
Submitted=(ts - 5),
|
||||||
|
@ -359,7 +359,7 @@ def test_pm_index_table_paging(client, pm_user):
|
||||||
for i in range(25):
|
for i in range(25):
|
||||||
# Create 25 past votes.
|
# Create 25 past votes.
|
||||||
db.create(
|
db.create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda=f"Agenda #{25 + i}",
|
Agenda=f"Agenda #{25 + i}",
|
||||||
User=pm_user.Username,
|
User=pm_user.Username,
|
||||||
Submitted=(ts - 1000),
|
Submitted=(ts - 1000),
|
||||||
|
@ -462,7 +462,7 @@ def test_pm_index_sorting(client, pm_user):
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
# Create 'Agenda #1' and 'Agenda #2'.
|
# Create 'Agenda #1' and 'Agenda #2'.
|
||||||
db.create(
|
db.create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda=f"Agenda #{i + 1}",
|
Agenda=f"Agenda #{i + 1}",
|
||||||
User=pm_user.Username,
|
User=pm_user.Username,
|
||||||
Submitted=(ts + 5),
|
Submitted=(ts + 5),
|
||||||
|
@ -540,21 +540,21 @@ def test_pm_index_last_votes(
|
||||||
with db.begin():
|
with db.begin():
|
||||||
# Create a proposal which has ended.
|
# Create a proposal which has ended.
|
||||||
voteinfo = db.create(
|
voteinfo = db.create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Test agenda",
|
Agenda="Test agenda",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=(ts - 1000),
|
Submitted=(ts - 1000),
|
||||||
End=(ts - 5),
|
End=(ts - 5),
|
||||||
Yes=1,
|
Yes=1,
|
||||||
No=1,
|
No=1,
|
||||||
ActiveTUs=1,
|
ActiveUsers=1,
|
||||||
Quorum=0.0,
|
Quorum=0.0,
|
||||||
Submitter=pm_user,
|
Submitter=pm_user,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a vote on it from pm_user.
|
# Create a vote on it from pm_user.
|
||||||
db.create(TUVote, VoteInfo=voteinfo, User=pm_user)
|
db.create(Vote, VoteInfo=voteinfo, User=pm_user)
|
||||||
db.create(TUVote, VoteInfo=voteinfo, User=pm_user2)
|
db.create(Vote, VoteInfo=voteinfo, User=pm_user2)
|
||||||
|
|
||||||
# Now, check that pm_user got populated in the .last-votes table.
|
# Now, check that pm_user got populated in the .last-votes table.
|
||||||
cookies = {"AURSID": pm_user.login(Request(), "testPassword")}
|
cookies = {"AURSID": pm_user.login(Request(), "testPassword")}
|
||||||
|
@ -590,7 +590,7 @@ def test_pm_proposal_not_found(client, pm_user):
|
||||||
|
|
||||||
|
|
||||||
def test_pm_proposal_unauthorized(
|
def test_pm_proposal_unauthorized(
|
||||||
client: TestClient, user: User, proposal: Tuple[User, User, TUVoteInfo]
|
client: TestClient, user: User, proposal: Tuple[User, User, VoteInfo]
|
||||||
):
|
):
|
||||||
cookies = {"AURSID": user.login(Request(), "testPassword")}
|
cookies = {"AURSID": user.login(Request(), "testPassword")}
|
||||||
endpoint = f"/package-maintainer/{proposal[2].ID}"
|
endpoint = f"/package-maintainer/{proposal[2].ID}"
|
||||||
|
@ -607,12 +607,10 @@ def test_pm_proposal_unauthorized(
|
||||||
assert response.headers.get("location") == "/package-maintainer"
|
assert response.headers.get("location") == "/package-maintainer"
|
||||||
|
|
||||||
|
|
||||||
def test_pm_running_proposal(
|
def test_pm_running_proposal(client: TestClient, proposal: Tuple[User, User, VoteInfo]):
|
||||||
client: TestClient, proposal: Tuple[User, User, TUVoteInfo]
|
|
||||||
):
|
|
||||||
pm_user, user, voteinfo = proposal
|
pm_user, user, voteinfo = proposal
|
||||||
with db.begin():
|
with db.begin():
|
||||||
voteinfo.ActiveTUs = 1
|
voteinfo.ActiveUsers = 1
|
||||||
|
|
||||||
# Initiate an authenticated GET request to /package-maintainer/{proposal_id}.
|
# Initiate an authenticated GET request to /package-maintainer/{proposal_id}.
|
||||||
proposal_id = voteinfo.ID
|
proposal_id = voteinfo.ID
|
||||||
|
@ -683,8 +681,8 @@ def test_pm_running_proposal(
|
||||||
|
|
||||||
# Create a vote.
|
# Create a vote.
|
||||||
with db.begin():
|
with db.begin():
|
||||||
db.create(TUVote, VoteInfo=voteinfo, User=pm_user)
|
db.create(Vote, VoteInfo=voteinfo, User=pm_user)
|
||||||
voteinfo.ActiveTUs += 1
|
voteinfo.ActiveUsers += 1
|
||||||
voteinfo.Yes += 1
|
voteinfo.Yes += 1
|
||||||
|
|
||||||
# Make another request now that we've voted.
|
# Make another request now that we've voted.
|
||||||
|
@ -772,8 +770,8 @@ def test_pm_proposal_vote(client, proposal):
|
||||||
# Check that the proposal record got updated.
|
# Check that the proposal record got updated.
|
||||||
assert voteinfo.Yes == yes + 1
|
assert voteinfo.Yes == yes + 1
|
||||||
|
|
||||||
# Check that the new TUVote exists.
|
# Check that the new PMVote exists.
|
||||||
vote = db.query(TUVote, TUVote.VoteInfo == voteinfo, TUVote.User == pm_user).first()
|
vote = db.query(Vote, Vote.VoteInfo == voteinfo, Vote.User == pm_user).first()
|
||||||
assert vote is not None
|
assert vote is not None
|
||||||
|
|
||||||
root = parse_root(response.text)
|
root = parse_root(response.text)
|
||||||
|
@ -784,7 +782,7 @@ def test_pm_proposal_vote(client, proposal):
|
||||||
|
|
||||||
|
|
||||||
def test_pm_proposal_vote_unauthorized(
|
def test_pm_proposal_vote_unauthorized(
|
||||||
client: TestClient, proposal: Tuple[User, User, TUVoteInfo]
|
client: TestClient, proposal: Tuple[User, User, VoteInfo]
|
||||||
):
|
):
|
||||||
pm_user, user, voteinfo = proposal
|
pm_user, user, voteinfo = proposal
|
||||||
|
|
||||||
|
@ -846,9 +844,9 @@ def test_pm_proposal_vote_already_voted(client, proposal):
|
||||||
pm_user, user, voteinfo = proposal
|
pm_user, user, voteinfo = proposal
|
||||||
|
|
||||||
with db.begin():
|
with db.begin():
|
||||||
db.create(TUVote, VoteInfo=voteinfo, User=pm_user)
|
db.create(Vote, VoteInfo=voteinfo, User=pm_user)
|
||||||
voteinfo.Yes += 1
|
voteinfo.Yes += 1
|
||||||
voteinfo.ActiveTUs += 1
|
voteinfo.ActiveUsers += 1
|
||||||
|
|
||||||
cookies = {"AURSID": pm_user.login(Request(), "testPassword")}
|
cookies = {"AURSID": pm_user.login(Request(), "testPassword")}
|
||||||
with client as request:
|
with client as request:
|
||||||
|
@ -893,7 +891,7 @@ def test_pm_addvote(client: TestClient, pm_user: User):
|
||||||
|
|
||||||
|
|
||||||
def test_pm_addvote_unauthorized(
|
def test_pm_addvote_unauthorized(
|
||||||
client: TestClient, user: User, proposal: Tuple[User, User, TUVoteInfo]
|
client: TestClient, user: User, proposal: Tuple[User, User, VoteInfo]
|
||||||
):
|
):
|
||||||
cookies = {"AURSID": user.login(Request(), "testPassword")}
|
cookies = {"AURSID": user.login(Request(), "testPassword")}
|
||||||
with client as request:
|
with client as request:
|
||||||
|
@ -931,7 +929,7 @@ def test_pm_addvote_post(client: TestClient, pm_user: User, user: User):
|
||||||
response = request.post("/addvote", data=data)
|
response = request.post("/addvote", data=data)
|
||||||
assert response.status_code == int(HTTPStatus.SEE_OTHER)
|
assert response.status_code == int(HTTPStatus.SEE_OTHER)
|
||||||
|
|
||||||
voteinfo = db.query(TUVoteInfo, TUVoteInfo.Agenda == "Blah").first()
|
voteinfo = db.query(VoteInfo, VoteInfo.Agenda == "Blah").first()
|
||||||
assert voteinfo is not None
|
assert voteinfo is not None
|
||||||
|
|
||||||
|
|
||||||
|
@ -947,7 +945,7 @@ def test_pm_addvote_post_cant_duplicate_username(
|
||||||
response = request.post("/addvote", data=data)
|
response = request.post("/addvote", data=data)
|
||||||
assert response.status_code == int(HTTPStatus.SEE_OTHER)
|
assert response.status_code == int(HTTPStatus.SEE_OTHER)
|
||||||
|
|
||||||
voteinfo = db.query(TUVoteInfo, TUVoteInfo.Agenda == "Blah").first()
|
voteinfo = db.query(VoteInfo, VoteInfo.Agenda == "Blah").first()
|
||||||
assert voteinfo is not None
|
assert voteinfo is not None
|
||||||
|
|
||||||
with client as request:
|
with client as request:
|
||||||
|
|
|
@ -3,9 +3,9 @@ from sqlalchemy.exc import IntegrityError
|
||||||
|
|
||||||
from aurweb import db, time
|
from aurweb import db, time
|
||||||
from aurweb.models.account_type import PACKAGE_MAINTAINER_ID
|
from aurweb.models.account_type import PACKAGE_MAINTAINER_ID
|
||||||
from aurweb.models.tu_vote import TUVote
|
|
||||||
from aurweb.models.tu_voteinfo import TUVoteInfo
|
|
||||||
from aurweb.models.user import User
|
from aurweb.models.user import User
|
||||||
|
from aurweb.models.vote import Vote
|
||||||
|
from aurweb.models.voteinfo import VoteInfo
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
@ -28,11 +28,11 @@ def user() -> User:
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def pm_voteinfo(user: User) -> TUVoteInfo:
|
def voteinfo(user: User) -> VoteInfo:
|
||||||
ts = time.utcnow()
|
ts = time.utcnow()
|
||||||
with db.begin():
|
with db.begin():
|
||||||
pm_voteinfo = db.create(
|
voteinfo = db.create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=ts,
|
Submitted=ts,
|
||||||
|
@ -40,24 +40,24 @@ def pm_voteinfo(user: User) -> TUVoteInfo:
|
||||||
Quorum=0.5,
|
Quorum=0.5,
|
||||||
Submitter=user,
|
Submitter=user,
|
||||||
)
|
)
|
||||||
yield pm_voteinfo
|
yield voteinfo
|
||||||
|
|
||||||
|
|
||||||
def test_pm_vote_creation(user: User, pm_voteinfo: TUVoteInfo):
|
def test_vote_creation(user: User, voteinfo: VoteInfo):
|
||||||
with db.begin():
|
with db.begin():
|
||||||
pm_vote = db.create(TUVote, User=user, VoteInfo=pm_voteinfo)
|
vote = db.create(Vote, User=user, VoteInfo=voteinfo)
|
||||||
|
|
||||||
assert pm_vote.VoteInfo == pm_voteinfo
|
assert vote.VoteInfo == voteinfo
|
||||||
assert pm_vote.User == user
|
assert vote.User == user
|
||||||
assert pm_vote in user.tu_votes
|
assert vote in user.votes
|
||||||
assert pm_vote in pm_voteinfo.tu_votes
|
assert vote in voteinfo.votes
|
||||||
|
|
||||||
|
|
||||||
def test_pm_vote_null_user_raises_exception(pm_voteinfo: TUVoteInfo):
|
def test_vote_null_user_raises_exception(voteinfo: VoteInfo):
|
||||||
with pytest.raises(IntegrityError):
|
with pytest.raises(IntegrityError):
|
||||||
TUVote(VoteInfo=pm_voteinfo)
|
Vote(VoteInfo=voteinfo)
|
||||||
|
|
||||||
|
|
||||||
def test_pm_vote_null_voteinfo_raises_exception(user: User):
|
def test_vote_null_voteinfo_raises_exception(user: User):
|
||||||
with pytest.raises(IntegrityError):
|
with pytest.raises(IntegrityError):
|
||||||
TUVote(User=user)
|
Vote(User=user)
|
||||||
|
|
|
@ -4,8 +4,8 @@ from sqlalchemy.exc import IntegrityError
|
||||||
from aurweb import db, time
|
from aurweb import db, time
|
||||||
from aurweb.db import create, rollback
|
from aurweb.db import create, rollback
|
||||||
from aurweb.models.account_type import PACKAGE_MAINTAINER_ID
|
from aurweb.models.account_type import PACKAGE_MAINTAINER_ID
|
||||||
from aurweb.models.tu_voteinfo import TUVoteInfo
|
|
||||||
from aurweb.models.user import User
|
from aurweb.models.user import User
|
||||||
|
from aurweb.models.voteinfo import VoteInfo
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
@ -27,11 +27,11 @@ def user() -> User:
|
||||||
yield user
|
yield user
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_creation(user: User):
|
def test_voteinfo_creation(user: User):
|
||||||
ts = time.utcnow()
|
ts = time.utcnow()
|
||||||
with db.begin():
|
with db.begin():
|
||||||
pm_voteinfo = create(
|
voteinfo = create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=ts,
|
Submitted=ts,
|
||||||
|
@ -39,26 +39,26 @@ def test_pm_voteinfo_creation(user: User):
|
||||||
Quorum=0.5,
|
Quorum=0.5,
|
||||||
Submitter=user,
|
Submitter=user,
|
||||||
)
|
)
|
||||||
assert bool(pm_voteinfo.ID)
|
assert bool(voteinfo.ID)
|
||||||
assert pm_voteinfo.Agenda == "Blah blah."
|
assert voteinfo.Agenda == "Blah blah."
|
||||||
assert pm_voteinfo.User == user.Username
|
assert voteinfo.User == user.Username
|
||||||
assert pm_voteinfo.Submitted == ts
|
assert voteinfo.Submitted == ts
|
||||||
assert pm_voteinfo.End == ts + 5
|
assert voteinfo.End == ts + 5
|
||||||
assert pm_voteinfo.Quorum == 0.5
|
assert voteinfo.Quorum == 0.5
|
||||||
assert pm_voteinfo.Submitter == user
|
assert voteinfo.Submitter == user
|
||||||
assert pm_voteinfo.Yes == 0
|
assert voteinfo.Yes == 0
|
||||||
assert pm_voteinfo.No == 0
|
assert voteinfo.No == 0
|
||||||
assert pm_voteinfo.Abstain == 0
|
assert voteinfo.Abstain == 0
|
||||||
assert pm_voteinfo.ActiveTUs == 0
|
assert voteinfo.ActiveUsers == 0
|
||||||
|
|
||||||
assert pm_voteinfo in user.tu_voteinfo_set
|
assert voteinfo in user.voteinfo_set
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_is_running(user: User):
|
def test_voteinfo_is_running(user: User):
|
||||||
ts = time.utcnow()
|
ts = time.utcnow()
|
||||||
with db.begin():
|
with db.begin():
|
||||||
pm_voteinfo = create(
|
voteinfo = create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=ts,
|
Submitted=ts,
|
||||||
|
@ -66,18 +66,18 @@ def test_pm_voteinfo_is_running(user: User):
|
||||||
Quorum=0.5,
|
Quorum=0.5,
|
||||||
Submitter=user,
|
Submitter=user,
|
||||||
)
|
)
|
||||||
assert pm_voteinfo.is_running() is True
|
assert voteinfo.is_running() is True
|
||||||
|
|
||||||
with db.begin():
|
with db.begin():
|
||||||
pm_voteinfo.End = ts - 5
|
voteinfo.End = ts - 5
|
||||||
assert pm_voteinfo.is_running() is False
|
assert voteinfo.is_running() is False
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_total_votes(user: User):
|
def test_voteinfo_total_votes(user: User):
|
||||||
ts = time.utcnow()
|
ts = time.utcnow()
|
||||||
with db.begin():
|
with db.begin():
|
||||||
pm_voteinfo = create(
|
voteinfo = create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=ts,
|
Submitted=ts,
|
||||||
|
@ -86,19 +86,19 @@ def test_pm_voteinfo_total_votes(user: User):
|
||||||
Submitter=user,
|
Submitter=user,
|
||||||
)
|
)
|
||||||
|
|
||||||
pm_voteinfo.Yes = 1
|
voteinfo.Yes = 1
|
||||||
pm_voteinfo.No = 3
|
voteinfo.No = 3
|
||||||
pm_voteinfo.Abstain = 5
|
voteinfo.Abstain = 5
|
||||||
|
|
||||||
# total_votes() should be the sum of Yes, No and Abstain: 1 + 3 + 5 = 9.
|
# total_votes() should be the sum of Yes, No and Abstain: 1 + 3 + 5 = 9.
|
||||||
assert pm_voteinfo.total_votes() == 9
|
assert voteinfo.total_votes() == 9
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_null_submitter_raises(user: User):
|
def test_voteinfo_null_submitter_raises(user: User):
|
||||||
with pytest.raises(IntegrityError):
|
with pytest.raises(IntegrityError):
|
||||||
with db.begin():
|
with db.begin():
|
||||||
create(
|
create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=0,
|
Submitted=0,
|
||||||
|
@ -108,11 +108,11 @@ def test_pm_voteinfo_null_submitter_raises(user: User):
|
||||||
rollback()
|
rollback()
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_null_agenda_raises(user: User):
|
def test_voteinfo_null_agenda_raises(user: User):
|
||||||
with pytest.raises(IntegrityError):
|
with pytest.raises(IntegrityError):
|
||||||
with db.begin():
|
with db.begin():
|
||||||
create(
|
create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=0,
|
Submitted=0,
|
||||||
End=0,
|
End=0,
|
||||||
|
@ -122,11 +122,11 @@ def test_pm_voteinfo_null_agenda_raises(user: User):
|
||||||
rollback()
|
rollback()
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_null_user_raises(user: User):
|
def test_voteinfo_null_user_raises(user: User):
|
||||||
with pytest.raises(IntegrityError):
|
with pytest.raises(IntegrityError):
|
||||||
with db.begin():
|
with db.begin():
|
||||||
create(
|
create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
Submitted=0,
|
Submitted=0,
|
||||||
End=0,
|
End=0,
|
||||||
|
@ -136,11 +136,11 @@ def test_pm_voteinfo_null_user_raises(user: User):
|
||||||
rollback()
|
rollback()
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_null_submitted_raises(user: User):
|
def test_voteinfo_null_submitted_raises(user: User):
|
||||||
with pytest.raises(IntegrityError):
|
with pytest.raises(IntegrityError):
|
||||||
with db.begin():
|
with db.begin():
|
||||||
create(
|
create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
End=0,
|
End=0,
|
||||||
|
@ -150,11 +150,11 @@ def test_pm_voteinfo_null_submitted_raises(user: User):
|
||||||
rollback()
|
rollback()
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_null_end_raises(user: User):
|
def test_voteinfo_null_end_raises(user: User):
|
||||||
with pytest.raises(IntegrityError):
|
with pytest.raises(IntegrityError):
|
||||||
with db.begin():
|
with db.begin():
|
||||||
create(
|
create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=0,
|
Submitted=0,
|
||||||
|
@ -164,10 +164,10 @@ def test_pm_voteinfo_null_end_raises(user: User):
|
||||||
rollback()
|
rollback()
|
||||||
|
|
||||||
|
|
||||||
def test_pm_voteinfo_null_quorum_default(user: User):
|
def test_voteinfo_null_quorum_default(user: User):
|
||||||
with db.begin():
|
with db.begin():
|
||||||
vi = create(
|
vi = create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Blah blah.",
|
Agenda="Blah blah.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
Submitted=0,
|
Submitted=0,
|
|
@ -3,17 +3,17 @@ from typing import Tuple
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from aurweb import config, db, time
|
from aurweb import config, db, time
|
||||||
from aurweb.models import TUVote, TUVoteInfo, User
|
from aurweb.models import User, Vote, VoteInfo
|
||||||
from aurweb.models.account_type import PACKAGE_MAINTAINER_ID
|
from aurweb.models.account_type import PACKAGE_MAINTAINER_ID
|
||||||
from aurweb.scripts import tuvotereminder as reminder
|
from aurweb.scripts import votereminder as reminder
|
||||||
from aurweb.testing.email import Email
|
from aurweb.testing.email import Email
|
||||||
|
|
||||||
aur_location = config.get("options", "aur_location")
|
aur_location = config.get("options", "aur_location")
|
||||||
|
|
||||||
|
|
||||||
def create_vote(user: User, voteinfo: TUVoteInfo) -> TUVote:
|
def create_vote(user: User, voteinfo: VoteInfo) -> Vote:
|
||||||
with db.begin():
|
with db.begin():
|
||||||
vote = db.create(TUVote, User=user, VoteID=voteinfo.ID)
|
vote = db.create(Vote, User=user, VoteID=voteinfo.ID)
|
||||||
return vote
|
return vote
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,11 +29,11 @@ def create_user(username: str, type_id: int):
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
def email_pieces(voteinfo: TUVoteInfo) -> Tuple[str, str]:
|
def email_pieces(voteinfo: VoteInfo) -> Tuple[str, str]:
|
||||||
"""
|
"""
|
||||||
Return a (subject, content) tuple based on voteinfo.ID
|
Return a (subject, content) tuple based on voteinfo.ID
|
||||||
|
|
||||||
:param voteinfo: TUVoteInfo instance
|
:param voteinfo: VoteInfo instance
|
||||||
:return: tuple(subject, content)
|
:return: tuple(subject, content)
|
||||||
"""
|
"""
|
||||||
subject = f"Package Maintainer Vote Reminder: Proposal {voteinfo.ID}"
|
subject = f"Package Maintainer Vote Reminder: Proposal {voteinfo.ID}"
|
||||||
|
@ -61,12 +61,12 @@ def user3() -> User:
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def voteinfo(user: User) -> TUVoteInfo:
|
def voteinfo(user: User) -> VoteInfo:
|
||||||
now = time.utcnow()
|
now = time.utcnow()
|
||||||
start = config.getint("tuvotereminder", "range_start")
|
start = config.getint("votereminder", "range_start")
|
||||||
with db.begin():
|
with db.begin():
|
||||||
voteinfo = db.create(
|
voteinfo = db.create(
|
||||||
TUVoteInfo,
|
VoteInfo,
|
||||||
Agenda="Lorem ipsum.",
|
Agenda="Lorem ipsum.",
|
||||||
User=user.Username,
|
User=user.Username,
|
||||||
End=(now + start + 1),
|
End=(now + start + 1),
|
||||||
|
@ -77,7 +77,7 @@ def voteinfo(user: User) -> TUVoteInfo:
|
||||||
yield voteinfo
|
yield voteinfo
|
||||||
|
|
||||||
|
|
||||||
def test_pm_vote_reminders(user: User, user2: User, user3: User, voteinfo: TUVoteInfo):
|
def test_vote_reminders(user: User, user2: User, user3: User, voteinfo: VoteInfo):
|
||||||
reminder.main()
|
reminder.main()
|
||||||
assert Email.count() == 3
|
assert Email.count() == 3
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ def test_pm_vote_reminders(user: User, user2: User, user3: User, voteinfo: TUVot
|
||||||
assert emails[i].body == content
|
assert emails[i].body == content
|
||||||
|
|
||||||
|
|
||||||
def test_pm_vote_reminders_only_unvoted(
|
def test_vote_reminders_only_unvoted(
|
||||||
user: User, user2: User, user3: User, voteinfo: TUVoteInfo
|
user: User, user2: User, user3: User, voteinfo: VoteInfo
|
||||||
):
|
):
|
||||||
# Vote with user2 and user3; leaving only user to be notified.
|
# Vote with user2 and user3; leaving only user to be notified.
|
||||||
create_vote(user2, voteinfo)
|
create_vote(user2, voteinfo)
|
Loading…
Add table
Reference in a new issue