add highlighted alias in case it's not included in the result
This commit is contained in:
parent
b2ac1b537d
commit
48838eb176
|
@ -7,7 +7,15 @@ from sqlalchemy.orm import joinedload
|
||||||
|
|
||||||
from app.config import PAGE_LIMIT
|
from app.config import PAGE_LIMIT
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
from app.models import Alias, Contact, EmailLog, Mailbox, AliasMailbox, CustomDomain
|
from app.models import (
|
||||||
|
Alias,
|
||||||
|
Contact,
|
||||||
|
EmailLog,
|
||||||
|
Mailbox,
|
||||||
|
AliasMailbox,
|
||||||
|
CustomDomain,
|
||||||
|
User,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -137,87 +145,7 @@ def get_alias_infos_with_pagination_v3(
|
||||||
mailbox_id=None,
|
mailbox_id=None,
|
||||||
directory_id=None,
|
directory_id=None,
|
||||||
) -> [AliasInfo]:
|
) -> [AliasInfo]:
|
||||||
# subquery on alias annotated with nb_reply, nb_blocked, nb_forward, max_created_at, latest_email_log_created_at
|
q = construct_alias_query(user)
|
||||||
alias_activity_subquery = (
|
|
||||||
db.session.query(
|
|
||||||
Alias.id,
|
|
||||||
func.sum(case([(EmailLog.is_reply, 1)], else_=0)).label("nb_reply"),
|
|
||||||
func.sum(
|
|
||||||
case(
|
|
||||||
[(and_(EmailLog.is_reply.is_(False), EmailLog.blocked), 1)],
|
|
||||||
else_=0,
|
|
||||||
)
|
|
||||||
).label("nb_blocked"),
|
|
||||||
func.sum(
|
|
||||||
case(
|
|
||||||
[
|
|
||||||
(
|
|
||||||
and_(
|
|
||||||
EmailLog.is_reply.is_(False),
|
|
||||||
EmailLog.blocked.is_(False),
|
|
||||||
),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
else_=0,
|
|
||||||
)
|
|
||||||
).label("nb_forward"),
|
|
||||||
func.max(EmailLog.created_at).label("latest_email_log_created_at"),
|
|
||||||
)
|
|
||||||
.join(EmailLog, Alias.id == EmailLog.alias_id, isouter=True)
|
|
||||||
.filter(Alias.user_id == user.id)
|
|
||||||
.group_by(Alias.id)
|
|
||||||
.subquery()
|
|
||||||
)
|
|
||||||
|
|
||||||
alias_contact_subquery = (
|
|
||||||
db.session.query(Alias.id, func.max(Contact.id).label("max_contact_id"))
|
|
||||||
.join(Contact, Alias.id == Contact.alias_id, isouter=True)
|
|
||||||
.filter(Alias.user_id == user.id)
|
|
||||||
.group_by(Alias.id)
|
|
||||||
.subquery()
|
|
||||||
)
|
|
||||||
|
|
||||||
latest_activity = case(
|
|
||||||
[
|
|
||||||
(Alias.created_at > EmailLog.created_at, Alias.created_at),
|
|
||||||
(Alias.created_at < EmailLog.created_at, EmailLog.created_at),
|
|
||||||
],
|
|
||||||
else_=Alias.created_at,
|
|
||||||
)
|
|
||||||
|
|
||||||
q = (
|
|
||||||
db.session.query(
|
|
||||||
Alias,
|
|
||||||
Contact,
|
|
||||||
EmailLog,
|
|
||||||
CustomDomain,
|
|
||||||
alias_activity_subquery.c.nb_reply,
|
|
||||||
alias_activity_subquery.c.nb_blocked,
|
|
||||||
alias_activity_subquery.c.nb_forward,
|
|
||||||
)
|
|
||||||
.options(joinedload(Alias.hibp_breaches))
|
|
||||||
.join(Contact, Alias.id == Contact.alias_id, isouter=True)
|
|
||||||
.join(CustomDomain, Alias.custom_domain_id == CustomDomain.id, isouter=True)
|
|
||||||
.join(EmailLog, Contact.id == EmailLog.contact_id, isouter=True)
|
|
||||||
.filter(Alias.id == alias_activity_subquery.c.id)
|
|
||||||
.filter(Alias.id == alias_contact_subquery.c.id)
|
|
||||||
.filter(
|
|
||||||
or_(
|
|
||||||
EmailLog.created_at
|
|
||||||
== alias_activity_subquery.c.latest_email_log_created_at,
|
|
||||||
and_(
|
|
||||||
# no email log yet for this alias
|
|
||||||
alias_activity_subquery.c.latest_email_log_created_at.is_(None),
|
|
||||||
# to make sure only 1 contact is returned in this case
|
|
||||||
or_(
|
|
||||||
Contact.id == alias_contact_subquery.c.max_contact_id,
|
|
||||||
alias_contact_subquery.c.max_contact_id.is_(None),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if query:
|
if query:
|
||||||
q = q.filter(
|
q = q.filter(
|
||||||
|
@ -262,6 +190,13 @@ def get_alias_infos_with_pagination_v3(
|
||||||
q = q.order_by(Alias.email.desc())
|
q = q.order_by(Alias.email.desc())
|
||||||
else:
|
else:
|
||||||
# default sorting
|
# default sorting
|
||||||
|
latest_activity = case(
|
||||||
|
[
|
||||||
|
(Alias.created_at > EmailLog.created_at, Alias.created_at),
|
||||||
|
(Alias.created_at < EmailLog.created_at, EmailLog.created_at),
|
||||||
|
],
|
||||||
|
else_=Alias.created_at,
|
||||||
|
)
|
||||||
q = q.order_by(latest_activity.desc())
|
q = q.order_by(latest_activity.desc())
|
||||||
|
|
||||||
q = list(q.limit(PAGE_LIMIT).offset(page_id * PAGE_LIMIT))
|
q = list(q.limit(PAGE_LIMIT).offset(page_id * PAGE_LIMIT))
|
||||||
|
@ -374,3 +309,98 @@ def get_alias_contacts(alias, page_id: int) -> [dict]:
|
||||||
res.append(serialize_contact(fe))
|
res.append(serialize_contact(fe))
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def get_alias_info_v3(user: User, alias_id: int) -> AliasInfo:
|
||||||
|
# use the same query construction in get_alias_infos_with_pagination_v3
|
||||||
|
q = construct_alias_query(user)
|
||||||
|
q = q.filter(Alias.id == alias_id)
|
||||||
|
|
||||||
|
for alias, contact, email_log, custom_domain, nb_reply, nb_blocked, nb_forward in q:
|
||||||
|
return AliasInfo(
|
||||||
|
alias=alias,
|
||||||
|
mailbox=alias.mailbox,
|
||||||
|
mailboxes=alias.mailboxes,
|
||||||
|
nb_forward=nb_forward,
|
||||||
|
nb_blocked=nb_blocked,
|
||||||
|
nb_reply=nb_reply,
|
||||||
|
latest_email_log=email_log,
|
||||||
|
latest_contact=contact,
|
||||||
|
custom_domain=custom_domain,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def construct_alias_query(user: User):
|
||||||
|
# subquery on alias annotated with nb_reply, nb_blocked, nb_forward, max_created_at, latest_email_log_created_at
|
||||||
|
alias_activity_subquery = (
|
||||||
|
db.session.query(
|
||||||
|
Alias.id,
|
||||||
|
func.sum(case([(EmailLog.is_reply, 1)], else_=0)).label("nb_reply"),
|
||||||
|
func.sum(
|
||||||
|
case(
|
||||||
|
[(and_(EmailLog.is_reply.is_(False), EmailLog.blocked), 1)],
|
||||||
|
else_=0,
|
||||||
|
)
|
||||||
|
).label("nb_blocked"),
|
||||||
|
func.sum(
|
||||||
|
case(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
and_(
|
||||||
|
EmailLog.is_reply.is_(False),
|
||||||
|
EmailLog.blocked.is_(False),
|
||||||
|
),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
else_=0,
|
||||||
|
)
|
||||||
|
).label("nb_forward"),
|
||||||
|
func.max(EmailLog.created_at).label("latest_email_log_created_at"),
|
||||||
|
)
|
||||||
|
.join(EmailLog, Alias.id == EmailLog.alias_id, isouter=True)
|
||||||
|
.filter(Alias.user_id == user.id)
|
||||||
|
.group_by(Alias.id)
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
|
||||||
|
alias_contact_subquery = (
|
||||||
|
db.session.query(Alias.id, func.max(Contact.id).label("max_contact_id"))
|
||||||
|
.join(Contact, Alias.id == Contact.alias_id, isouter=True)
|
||||||
|
.filter(Alias.user_id == user.id)
|
||||||
|
.group_by(Alias.id)
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
db.session.query(
|
||||||
|
Alias,
|
||||||
|
Contact,
|
||||||
|
EmailLog,
|
||||||
|
CustomDomain,
|
||||||
|
alias_activity_subquery.c.nb_reply,
|
||||||
|
alias_activity_subquery.c.nb_blocked,
|
||||||
|
alias_activity_subquery.c.nb_forward,
|
||||||
|
)
|
||||||
|
.options(joinedload(Alias.hibp_breaches))
|
||||||
|
.join(Contact, Alias.id == Contact.alias_id, isouter=True)
|
||||||
|
.join(CustomDomain, Alias.custom_domain_id == CustomDomain.id, isouter=True)
|
||||||
|
.join(EmailLog, Contact.id == EmailLog.contact_id, isouter=True)
|
||||||
|
.filter(Alias.id == alias_activity_subquery.c.id)
|
||||||
|
.filter(Alias.id == alias_contact_subquery.c.id)
|
||||||
|
.filter(
|
||||||
|
or_(
|
||||||
|
EmailLog.created_at
|
||||||
|
== alias_activity_subquery.c.latest_email_log_created_at,
|
||||||
|
and_(
|
||||||
|
# no email log yet for this alias
|
||||||
|
alias_activity_subquery.c.latest_email_log_created_at.is_(None),
|
||||||
|
# to make sure only 1 contact is returned in this case
|
||||||
|
or_(
|
||||||
|
Contact.id == alias_contact_subquery.c.max_contact_id,
|
||||||
|
alias_contact_subquery.c.max_contact_id.is_(None),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@ from flask import render_template, request, redirect, url_for, flash
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
from app import alias_utils
|
from app import alias_utils
|
||||||
from app.api.serializer import get_alias_infos_with_pagination_v3
|
from app.api.serializer import get_alias_infos_with_pagination_v3, get_alias_info_v3
|
||||||
from app.config import PAGE_LIMIT, ALIAS_LIMIT
|
from app.config import PAGE_LIMIT, ALIAS_LIMIT
|
||||||
from app.dashboard.base import dashboard_bp
|
from app.dashboard.base import dashboard_bp
|
||||||
from app.extensions import db, limiter
|
from app.extensions import db, limiter
|
||||||
|
@ -163,6 +163,16 @@ def index():
|
||||||
)
|
)
|
||||||
last_page = len(alias_infos) < PAGE_LIMIT
|
last_page = len(alias_infos) < PAGE_LIMIT
|
||||||
|
|
||||||
|
# add highlighted alias in case it's not included
|
||||||
|
if highlight_alias_id and highlight_alias_id not in [
|
||||||
|
alias_info.alias.id for alias_info in alias_infos
|
||||||
|
]:
|
||||||
|
highlight_alias_info = get_alias_info_v3(
|
||||||
|
current_user, alias_id=highlight_alias_id
|
||||||
|
)
|
||||||
|
if highlight_alias_info:
|
||||||
|
alias_infos.insert(0, highlight_alias_info)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"dashboard/index.html",
|
"dashboard/index.html",
|
||||||
alias_infos=alias_infos,
|
alias_infos=alias_infos,
|
||||||
|
|
Loading…
Reference in a new issue