do not use flask-sqlalchemy
- add __tablename__ for all models - use sa and orm instead of db - rollback all changes in tests - remove session in @app.teardown_appcontext
This commit is contained in:
parent
653a03ac11
commit
372466ab06
|
@ -5,7 +5,7 @@ from flask_admin.actions import action
|
|||
from flask_admin.contrib import sqla
|
||||
from flask_login import current_user, login_user
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User, ManualSubscription
|
||||
|
||||
|
||||
|
@ -99,7 +99,7 @@ class UserAdmin(SLModelView):
|
|||
"Extend trial for 1 week more?",
|
||||
)
|
||||
def extend_trial_1w(self, ids):
|
||||
for user in User.query.filter(User.id.in_(ids)):
|
||||
for user in User.filter(User.id.in_(ids)):
|
||||
if user.trial_end and user.trial_end > arrow.now():
|
||||
user.trial_end = user.trial_end.shift(weeks=1)
|
||||
else:
|
||||
|
@ -107,7 +107,7 @@ class UserAdmin(SLModelView):
|
|||
|
||||
flash(f"Extend trial for {user} to {user.trial_end}", "success")
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
@action(
|
||||
"disable_otp",
|
||||
|
@ -115,12 +115,12 @@ class UserAdmin(SLModelView):
|
|||
"Disable OTP?",
|
||||
)
|
||||
def disable_otp(self, ids):
|
||||
for user in User.query.filter(User.id.in_(ids)):
|
||||
for user in User.filter(User.id.in_(ids)):
|
||||
if user.enable_otp:
|
||||
user.enable_otp = False
|
||||
flash(f"Disable OTP for {user}", "info")
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
@action(
|
||||
"login_as",
|
||||
|
@ -132,16 +132,14 @@ class UserAdmin(SLModelView):
|
|||
flash("only 1 user can be selected", "error")
|
||||
return
|
||||
|
||||
for user in User.query.filter(User.id.in_(ids)):
|
||||
for user in User.filter(User.id.in_(ids)):
|
||||
login_user(user)
|
||||
flash(f"Login as user {user}", "success")
|
||||
return redirect("/")
|
||||
|
||||
|
||||
def manual_upgrade(way: str, ids: [int], is_giveaway: bool):
|
||||
query = User.query.filter(User.id.in_(ids))
|
||||
|
||||
for user in query.all():
|
||||
for user in User.filter(User.id.in_(ids)).all():
|
||||
manual_sub: ManualSubscription = ManualSubscription.get_by(user_id=user.id)
|
||||
if manual_sub:
|
||||
# renew existing subscription
|
||||
|
@ -149,7 +147,7 @@ def manual_upgrade(way: str, ids: [int], is_giveaway: bool):
|
|||
manual_sub.end_at = manual_sub.end_at.shift(years=1)
|
||||
else:
|
||||
manual_sub.end_at = arrow.now().shift(years=1, days=1)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"Subscription extended to {manual_sub.end_at.humanize()}", "success")
|
||||
continue
|
||||
|
||||
|
@ -211,11 +209,11 @@ class ManualSubscriptionAdmin(SLModelView):
|
|||
"Extend 1 year more?",
|
||||
)
|
||||
def extend_1y(self, ids):
|
||||
for ms in ManualSubscription.query.filter(ManualSubscription.id.in_(ids)):
|
||||
for ms in ManualSubscription.filter(ManualSubscription.id.in_(ids)):
|
||||
ms.end_at = ms.end_at.shift(years=1)
|
||||
flash(f"Extend subscription for {ms.user}", "success")
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
|
||||
class ClientAdmin(SLModelView):
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import re2 as re
|
||||
from typing import Optional
|
||||
|
||||
import re2 as re
|
||||
from email_validator import validate_email, EmailNotValidError
|
||||
from sqlalchemy.exc import IntegrityError, DataError
|
||||
|
||||
from app.config import BOUNCE_PREFIX_FOR_REPLY_PHASE
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
get_email_domain_part,
|
||||
send_cannot_create_directory_alias,
|
||||
|
@ -14,7 +15,6 @@ from app.email_utils import (
|
|||
get_email_local_part,
|
||||
)
|
||||
from app.errors import AliasInTrashError
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
Alias,
|
||||
|
@ -97,14 +97,14 @@ def try_auto_create_directory(address: str) -> Optional[Alias]:
|
|||
mailbox_id=mailboxes[0].id,
|
||||
note=f"Created by directory {directory.name}",
|
||||
)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
for i in range(1, len(mailboxes)):
|
||||
AliasMailbox.create(
|
||||
alias_id=alias.id,
|
||||
mailbox_id=mailboxes[i].id,
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return alias
|
||||
except AliasInTrashError:
|
||||
LOG.w(
|
||||
|
@ -116,7 +116,7 @@ def try_auto_create_directory(address: str) -> Optional[Alias]:
|
|||
return None
|
||||
except IntegrityError:
|
||||
LOG.w("Alias %s already exists", address)
|
||||
db.session.rollback()
|
||||
Session.rollback()
|
||||
alias = Alias.get_by(email=address)
|
||||
return alias
|
||||
|
||||
|
@ -173,13 +173,13 @@ def try_auto_create_via_domain(address: str) -> Optional[Alias]:
|
|||
mailbox_id=mailboxes[0].id,
|
||||
note=alias_note,
|
||||
)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
for i in range(1, len(mailboxes)):
|
||||
AliasMailbox.create(
|
||||
alias_id=alias.id,
|
||||
mailbox_id=mailboxes[i].id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return alias
|
||||
except AliasInTrashError:
|
||||
LOG.w(
|
||||
|
@ -191,12 +191,12 @@ def try_auto_create_via_domain(address: str) -> Optional[Alias]:
|
|||
return None
|
||||
except IntegrityError:
|
||||
LOG.w("Alias %s already exists", address)
|
||||
db.session.rollback()
|
||||
Session.rollback()
|
||||
alias = Alias.get_by(email=address)
|
||||
return alias
|
||||
except DataError:
|
||||
LOG.w("Cannot create alias %s", address)
|
||||
db.session.rollback()
|
||||
Session.rollback()
|
||||
return None
|
||||
|
||||
|
||||
|
@ -211,30 +211,30 @@ def delete_alias(alias: Alias, user: User):
|
|||
email=alias.email, domain_id=alias.custom_domain_id
|
||||
):
|
||||
LOG.d("add %s to domain %s trash", alias, alias.custom_domain_id)
|
||||
db.session.add(
|
||||
Session.add(
|
||||
DomainDeletedAlias(
|
||||
user_id=user.id, email=alias.email, domain_id=alias.custom_domain_id
|
||||
)
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
else:
|
||||
if not DeletedAlias.get_by(email=alias.email):
|
||||
LOG.d("add %s to global trash", alias)
|
||||
db.session.add(DeletedAlias(email=alias.email))
|
||||
db.session.commit()
|
||||
Session.add(DeletedAlias(email=alias.email))
|
||||
Session.commit()
|
||||
|
||||
Alias.query.filter(Alias.id == alias.id).delete()
|
||||
db.session.commit()
|
||||
Alias.filter(Alias.id == alias.id).delete()
|
||||
Session.commit()
|
||||
|
||||
|
||||
def aliases_for_mailbox(mailbox: Mailbox) -> [Alias]:
|
||||
"""
|
||||
get list of aliases for a given mailbox
|
||||
"""
|
||||
ret = set(Alias.query.filter(Alias.mailbox_id == mailbox.id).all())
|
||||
ret = set(Alias.filter(Alias.mailbox_id == mailbox.id).all())
|
||||
|
||||
for alias in (
|
||||
db.session.query(Alias)
|
||||
Session.query(Alias)
|
||||
.join(AliasMailbox, Alias.id == AliasMailbox.alias_id)
|
||||
.filter(AliasMailbox.mailbox_id == mailbox.id)
|
||||
):
|
||||
|
@ -247,7 +247,7 @@ def nb_email_log_for_mailbox(mailbox: Mailbox):
|
|||
aliases = aliases_for_mailbox(mailbox)
|
||||
alias_ids = [alias.id for alias in aliases]
|
||||
return (
|
||||
db.session.query(EmailLog)
|
||||
Session.query(EmailLog)
|
||||
.join(Contact, EmailLog.contact_id == Contact.id)
|
||||
.filter(Contact.alias_id.in_(alias_ids))
|
||||
.count()
|
||||
|
|
|
@ -4,7 +4,7 @@ import arrow
|
|||
from flask import Blueprint, request, jsonify, g
|
||||
from flask_login import current_user
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import ApiKey
|
||||
|
||||
api_bp = Blueprint(name="api", import_name=__name__, url_prefix="/api")
|
||||
|
@ -26,7 +26,7 @@ def require_api_auth(f):
|
|||
# Update api key stats
|
||||
api_key.last_used = arrow.now()
|
||||
api_key.times += 1
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
g.user = api_key.user
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from sqlalchemy import or_, func, case, and_
|
|||
from sqlalchemy.orm import joinedload
|
||||
|
||||
from app.config import PAGE_LIMIT
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import (
|
||||
Alias,
|
||||
Contact,
|
||||
|
@ -117,7 +117,7 @@ def serialize_contact(contact: Contact, existed=False) -> dict:
|
|||
def get_alias_infos_with_pagination(user, page_id=0, query=None) -> [AliasInfo]:
|
||||
ret = []
|
||||
q = (
|
||||
db.session.query(Alias)
|
||||
Session.query(Alias)
|
||||
.options(joinedload(Alias.mailbox))
|
||||
.filter(Alias.user_id == user.id)
|
||||
.order_by(Alias.created_at.desc())
|
||||
|
@ -221,7 +221,7 @@ def get_alias_infos_with_pagination_v3(
|
|||
|
||||
def get_alias_info(alias: Alias) -> AliasInfo:
|
||||
q = (
|
||||
db.session.query(Contact, EmailLog)
|
||||
Session.query(Contact, EmailLog)
|
||||
.filter(Contact.alias_id == alias.id)
|
||||
.filter(EmailLog.contact_id == Contact.id)
|
||||
)
|
||||
|
@ -251,7 +251,7 @@ def get_alias_info_v2(alias: Alias, mailbox=None) -> AliasInfo:
|
|||
mailbox = alias.mailbox
|
||||
|
||||
q = (
|
||||
db.session.query(Contact, EmailLog)
|
||||
Session.query(Contact, EmailLog)
|
||||
.filter(Contact.alias_id == alias.id)
|
||||
.filter(EmailLog.contact_id == Contact.id)
|
||||
)
|
||||
|
@ -297,7 +297,7 @@ def get_alias_info_v2(alias: Alias, mailbox=None) -> AliasInfo:
|
|||
|
||||
def get_alias_contacts(alias, page_id: int) -> [dict]:
|
||||
q = (
|
||||
Contact.query.filter_by(alias_id=alias.id)
|
||||
Contact.filter_by(alias_id=alias.id)
|
||||
.order_by(Contact.id.desc())
|
||||
.limit(PAGE_LIMIT)
|
||||
.offset(page_id * PAGE_LIMIT)
|
||||
|
@ -332,7 +332,7 @@ def get_alias_info_v3(user: User, alias_id: int) -> AliasInfo:
|
|||
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(
|
||||
Session.query(
|
||||
Alias.id,
|
||||
func.sum(case([(EmailLog.is_reply, 1)], else_=0)).label("nb_reply"),
|
||||
func.sum(
|
||||
|
@ -364,7 +364,7 @@ def construct_alias_query(user: User):
|
|||
)
|
||||
|
||||
alias_contact_subquery = (
|
||||
db.session.query(Alias.id, func.max(Contact.id).label("max_contact_id"))
|
||||
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)
|
||||
|
@ -372,7 +372,7 @@ def construct_alias_query(user: User):
|
|||
)
|
||||
|
||||
return (
|
||||
db.session.query(
|
||||
Session.query(
|
||||
Alias,
|
||||
Contact,
|
||||
EmailLog,
|
||||
|
|
|
@ -17,10 +17,10 @@ from app.api.serializer import (
|
|||
get_alias_infos_with_pagination_v3,
|
||||
)
|
||||
from app.dashboard.views.alias_log import get_alias_log
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
generate_reply_email,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import Alias, Contact, Mailbox, AliasMailbox
|
||||
from app.utils import sanitize_email
|
||||
|
@ -164,7 +164,7 @@ def toggle_alias(alias_id):
|
|||
return jsonify(error="Forbidden"), 403
|
||||
|
||||
alias.enabled = not alias.enabled
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(enabled=alias.enabled), 200
|
||||
|
||||
|
@ -280,8 +280,8 @@ def update_alias(alias_id):
|
|||
|
||||
# <<< update alias mailboxes >>>
|
||||
# first remove all existing alias-mailboxes links
|
||||
AliasMailbox.query.filter_by(alias_id=alias.id).delete()
|
||||
db.session.flush()
|
||||
AliasMailbox.filter_by(alias_id=alias.id).delete()
|
||||
Session.flush()
|
||||
|
||||
# then add all new mailboxes
|
||||
for i, mailbox in enumerate(mailboxes):
|
||||
|
@ -310,7 +310,7 @@ def update_alias(alias_id):
|
|||
changed = True
|
||||
|
||||
if changed:
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(ok=True), 200
|
||||
|
||||
|
@ -422,7 +422,7 @@ def create_contact_route(alias_id):
|
|||
)
|
||||
|
||||
LOG.d("create reverse-alias for %s %s", contact_addr, alias)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(**serialize_contact(contact)), 201
|
||||
|
||||
|
@ -444,6 +444,6 @@ def delete_contact(contact_id):
|
|||
return jsonify(error="Forbidden"), 403
|
||||
|
||||
Contact.delete(contact_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(deleted=True), 200
|
||||
|
|
|
@ -5,7 +5,7 @@ from app.api.base import api_bp, require_api_auth
|
|||
from app.dashboard.views.custom_alias import (
|
||||
get_available_suffixes,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import AliasUsedOn, Alias, User
|
||||
from app.utils import convert_to_id
|
||||
|
@ -43,7 +43,7 @@ def options_v4():
|
|||
if hostname:
|
||||
# put the latest used alias first
|
||||
q = (
|
||||
db.session.query(AliasUsedOn, Alias, User)
|
||||
Session.query(AliasUsedOn, Alias, User)
|
||||
.filter(
|
||||
AliasUsedOn.alias_id == Alias.id,
|
||||
Alias.user_id == user.id,
|
||||
|
@ -114,7 +114,7 @@ def options_v5():
|
|||
if hostname:
|
||||
# put the latest used alias first
|
||||
q = (
|
||||
db.session.query(AliasUsedOn, Alias, User)
|
||||
Session.query(AliasUsedOn, Alias, User)
|
||||
.filter(
|
||||
AliasUsedOn.alias_id == Alias.id,
|
||||
Alias.user_id == user.id,
|
||||
|
|
|
@ -9,7 +9,7 @@ from requests import RequestException
|
|||
|
||||
from app.api.base import api_bp, require_api_auth
|
||||
from app.config import APPLE_API_SECRET, MACAPP_APPLE_API_SECRET
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import PlanEnum, AppleSubscription
|
||||
|
||||
|
@ -279,7 +279,7 @@ def apple_update_notification():
|
|||
apple_sub.receipt_data = data["unified_receipt"]["latest_receipt"]
|
||||
apple_sub.expires_date = expires_date
|
||||
apple_sub.plan = plan
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return jsonify(ok=True), 200
|
||||
else:
|
||||
LOG.w(
|
||||
|
@ -544,6 +544,6 @@ def verify_receipt(receipt_data, user, password) -> Optional[AppleSubscription]:
|
|||
plan=plan,
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return apple_sub
|
||||
|
|
|
@ -11,13 +11,14 @@ from app import email_utils
|
|||
from app.api.base import api_bp
|
||||
from app.config import FLASK_SECRET, DISABLE_REGISTRATION
|
||||
from app.dashboard.views.setting import send_reset_password_email
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
email_can_be_used_as_mailbox,
|
||||
personal_email_already_used,
|
||||
send_email,
|
||||
render,
|
||||
)
|
||||
from app.extensions import db, limiter
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import User, ApiKey, SocialAuth, AccountActivation
|
||||
from app.utils import sanitize_email
|
||||
|
@ -98,12 +99,12 @@ def auth_register():
|
|||
|
||||
LOG.d("create user %s", email)
|
||||
user = User.create(email=email, name="", password=password)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
|
||||
# create activation code
|
||||
code = "".join([str(random.randint(0, 9)) for _ in range(6)])
|
||||
AccountActivation.create(user_id=user.id, code=code)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_email(
|
||||
email,
|
||||
|
@ -155,13 +156,13 @@ def auth_activate():
|
|||
if account_activation.code != code:
|
||||
# decrement nb tries
|
||||
account_activation.tries -= 1
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
# Trigger rate limiter
|
||||
g.deduct_limit = True
|
||||
|
||||
if account_activation.tries == 0:
|
||||
AccountActivation.delete(account_activation.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return jsonify(error="Too many wrong tries"), 410
|
||||
|
||||
return jsonify(error="Wrong email or code"), 400
|
||||
|
@ -169,7 +170,7 @@ def auth_activate():
|
|||
LOG.d("activate user %s", user)
|
||||
user.activated = True
|
||||
AccountActivation.delete(account_activation.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(msg="Account is activated, user can login now"), 200
|
||||
|
||||
|
@ -198,12 +199,12 @@ def auth_reactivate():
|
|||
account_activation = AccountActivation.get_by(user_id=user.id)
|
||||
if account_activation:
|
||||
AccountActivation.delete(account_activation.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create activation code
|
||||
code = "".join([str(random.randint(0, 9)) for _ in range(6)])
|
||||
AccountActivation.create(user_id=user.id, code=code)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_email(
|
||||
email,
|
||||
|
@ -255,12 +256,12 @@ def auth_facebook():
|
|||
|
||||
LOG.d("create facebook user with %s", user_info)
|
||||
user = User.create(email=email, name=user_info["name"], activated=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
email_utils.send_welcome_email(user)
|
||||
|
||||
if not SocialAuth.get_by(user_id=user.id, social="facebook"):
|
||||
SocialAuth.create(user_id=user.id, social="facebook")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(**auth_payload(user, device)), 200
|
||||
|
||||
|
@ -308,12 +309,12 @@ def auth_google():
|
|||
|
||||
LOG.d("create Google user with %s", user_info)
|
||||
user = User.create(email=email, name="", activated=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
email_utils.send_welcome_email(user)
|
||||
|
||||
if not SocialAuth.get_by(user_id=user.id, social="google"):
|
||||
SocialAuth.create(user_id=user.id, social="google")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(**auth_payload(user, device)), 200
|
||||
|
||||
|
@ -331,7 +332,7 @@ def auth_payload(user, device) -> dict:
|
|||
if not api_key:
|
||||
LOG.d("create new api key for %s and %s", user, device)
|
||||
api_key = ApiKey.create(user.id, device)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
ret["mfa_key"] = None
|
||||
ret["api_key"] = api_key.code
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from itsdangerous import Signer
|
|||
|
||||
from app.api.base import api_bp
|
||||
from app.config import FLASK_SECRET
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import User, ApiKey
|
||||
|
||||
|
@ -61,7 +61,7 @@ def auth_mfa():
|
|||
if not api_key:
|
||||
LOG.d("create new api key for %s and %s", user, device)
|
||||
api_key = ApiKey.create(user.id, device)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
ret["api_key"] = api_key.code
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from flask import g, request
|
|||
from flask import jsonify
|
||||
|
||||
from app.api.base import api_bp, require_api_auth
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import CustomDomain, DomainDeletedAlias, Mailbox, DomainMailbox
|
||||
|
||||
|
||||
|
@ -108,8 +108,8 @@ def update_custom_domain(custom_domain_id):
|
|||
mailboxes.append(mailbox)
|
||||
|
||||
# first remove all existing domain-mailboxes links
|
||||
DomainMailbox.query.filter_by(domain_id=custom_domain.id).delete()
|
||||
db.session.flush()
|
||||
DomainMailbox.filter_by(domain_id=custom_domain.id).delete()
|
||||
Session.flush()
|
||||
|
||||
for mailbox in mailboxes:
|
||||
DomainMailbox.create(domain_id=custom_domain.id, mailbox_id=mailbox.id)
|
||||
|
@ -117,6 +117,6 @@ def update_custom_domain(custom_domain_id):
|
|||
changed = True
|
||||
|
||||
if changed:
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(ok=True), 200
|
||||
|
|
|
@ -7,12 +7,12 @@ from flask import request
|
|||
from app.api.base import api_bp, require_api_auth
|
||||
from app.dashboard.views.mailbox import send_verification_email
|
||||
from app.dashboard.views.mailbox_detail import verify_mailbox_change
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
mailbox_already_used,
|
||||
email_can_be_used_as_mailbox,
|
||||
is_valid_email,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.models import Mailbox
|
||||
from app.utils import sanitize_email
|
||||
|
||||
|
@ -58,7 +58,7 @@ def create_mailbox():
|
|||
)
|
||||
else:
|
||||
new_mailbox = Mailbox.create(email=mailbox_email, user_id=user.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_verification_email(user, new_mailbox)
|
||||
|
||||
|
@ -89,7 +89,7 @@ def delete_mailbox(mailbox_id):
|
|||
return jsonify(error="You cannot delete the default mailbox"), 400
|
||||
|
||||
Mailbox.delete(mailbox_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(deleted=True), 200
|
||||
|
||||
|
@ -158,7 +158,7 @@ def update_mailbox(mailbox_id):
|
|||
changed = True
|
||||
|
||||
if changed:
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(updated=True), 200
|
||||
|
||||
|
@ -190,7 +190,7 @@ def get_mailboxes_v2():
|
|||
user = g.user
|
||||
mailboxes = []
|
||||
|
||||
for mailbox in Mailbox.query.filter_by(user_id=user.id):
|
||||
for mailbox in Mailbox.filter_by(user_id=user.id):
|
||||
mailboxes.append(mailbox)
|
||||
|
||||
return (
|
||||
|
|
|
@ -10,7 +10,8 @@ from app.api.serializer import (
|
|||
)
|
||||
from app.config import MAX_NB_EMAIL_FREE_PLAN, ALIAS_LIMIT
|
||||
from app.dashboard.views.custom_alias import verify_prefix_suffix, signer
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
Alias,
|
||||
|
@ -108,11 +109,11 @@ def new_custom_alias_v2():
|
|||
custom_domain_id=custom_domain_id,
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
if hostname:
|
||||
AliasUsedOn.create(alias_id=alias.id, hostname=hostname, user_id=alias.user_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return (
|
||||
jsonify(alias=full_alias, **serialize_alias_info_v2(get_alias_info_v2(alias))),
|
||||
|
@ -217,7 +218,7 @@ def new_custom_alias_v3():
|
|||
mailbox_id=mailboxes[0].id,
|
||||
custom_domain_id=custom_domain_id,
|
||||
)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
|
||||
for i in range(1, len(mailboxes)):
|
||||
AliasMailbox.create(
|
||||
|
@ -225,11 +226,11 @@ def new_custom_alias_v3():
|
|||
mailbox_id=mailboxes[i].id,
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
if hostname:
|
||||
AliasUsedOn.create(alias_id=alias.id, hostname=hostname, user_id=alias.user_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return (
|
||||
jsonify(alias=full_alias, **serialize_alias_info_v2(get_alias_info_v2(alias))),
|
||||
|
|
|
@ -7,7 +7,8 @@ from app.api.serializer import (
|
|||
serialize_alias_info_v2,
|
||||
)
|
||||
from app.config import MAX_NB_EMAIL_FREE_PLAN, ALIAS_LIMIT
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import Alias, AliasUsedOn, AliasGeneratorEnum
|
||||
|
||||
|
@ -51,12 +52,12 @@ def new_random_alias():
|
|||
return jsonify(error=f"{mode} must be either word or uuid"), 400
|
||||
|
||||
alias = Alias.create_new_random(user=user, scheme=scheme, note=note)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
hostname = request.args.get("hostname")
|
||||
if hostname:
|
||||
AliasUsedOn.create(alias_id=alias.id, hostname=hostname, user_id=alias.user_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return (
|
||||
jsonify(alias=alias.email, **serialize_alias_info_v2(get_alias_info_v2(alias))),
|
||||
|
|
|
@ -4,7 +4,7 @@ from flask import request
|
|||
|
||||
from app.api.base import api_bp, require_api_auth
|
||||
from app.config import PAGE_LIMIT
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import Notification
|
||||
|
||||
|
||||
|
@ -32,7 +32,7 @@ def get_notifications():
|
|||
return jsonify(error="page must be provided in request query"), 400
|
||||
|
||||
notifications = (
|
||||
Notification.query.filter_by(user_id=user.id)
|
||||
Notification.filter_by(user_id=user.id)
|
||||
.order_by(Notification.read, Notification.created_at.desc())
|
||||
.limit(PAGE_LIMIT + 1) # load a record more to know whether there's more
|
||||
.offset(page * PAGE_LIMIT)
|
||||
|
@ -76,6 +76,6 @@ def mark_as_read(notification_id):
|
|||
return jsonify(error="Forbidden"), 403
|
||||
|
||||
notification.read = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(done=True), 200
|
||||
|
|
|
@ -2,7 +2,7 @@ import arrow
|
|||
from flask import jsonify, g, request
|
||||
|
||||
from app.api.base import api_bp, require_api_auth
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
User,
|
||||
|
@ -93,7 +93,7 @@ def update_setting():
|
|||
user.default_alias_custom_domain_id = custom_domain.id
|
||||
user.default_alias_public_domain_id = None
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return jsonify(setting_to_dict(user))
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from flask_login import logout_user
|
|||
from app import s3
|
||||
from app.api.base import api_bp, require_api_auth
|
||||
from app.config import SESSION_COOKIE_NAME
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import ApiKey, File, User
|
||||
from app.utils import random_string
|
||||
|
||||
|
@ -56,24 +56,24 @@ def update_user_info():
|
|||
if user.profile_picture_id:
|
||||
file = user.profile_picture
|
||||
user.profile_picture_id = None
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
if file:
|
||||
File.delete(file.id)
|
||||
s3.delete(file.path)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
else:
|
||||
raw_data = base64.decodebytes(data["profile_picture"].encode())
|
||||
file_path = random_string(30)
|
||||
file = File.create(user_id=user.id, path=file_path)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
s3.upload_from_bytesio(file_path, BytesIO(raw_data))
|
||||
user.profile_picture_id = file.id
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
|
||||
if "name" in data:
|
||||
user.name = data["name"]
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(user_to_dict(user))
|
||||
|
||||
|
@ -95,7 +95,7 @@ def create_api_key():
|
|||
device = data.get("device")
|
||||
|
||||
api_key = ApiKey.create(user_id=g.user.id, name=device)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(api_key=api_key.code), 201
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ from flask_login import login_user, current_user
|
|||
|
||||
from app import email_utils
|
||||
from app.auth.base import auth_bp
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import ActivationCode
|
||||
|
||||
|
@ -50,7 +51,7 @@ def activate():
|
|||
|
||||
# activation code is to be used only once
|
||||
ActivationCode.delete(activation_code.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash("Your account has been activated", "success")
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from flask import request, flash, render_template, redirect, url_for
|
|||
from flask_login import login_user
|
||||
|
||||
from app.auth.base import auth_bp
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import EmailChange
|
||||
|
||||
|
||||
|
@ -18,14 +18,14 @@ def change_email():
|
|||
if email_change.is_expired():
|
||||
# delete the expired email
|
||||
EmailChange.delete(email_change.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return render_template("auth/change_email.html")
|
||||
|
||||
user = email_change.user
|
||||
user.email = email_change.new_email
|
||||
|
||||
EmailChange.delete(email_change.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash("Your new email has been updated", "success")
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ from app.config import (
|
|||
FACEBOOK_CLIENT_ID,
|
||||
FACEBOOK_CLIENT_SECRET,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import User, SocialAuth
|
||||
from .login_utils import after_login
|
||||
|
@ -102,7 +102,7 @@ def facebook_callback():
|
|||
LOG.d("set user profile picture to %s", picture_url)
|
||||
file = create_file_from_url(user, picture_url)
|
||||
user.profile_picture_id = file.id
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
else:
|
||||
flash(
|
||||
|
@ -122,6 +122,6 @@ def facebook_callback():
|
|||
|
||||
if not SocialAuth.get_by(user_id=user.id, social="facebook"):
|
||||
SocialAuth.create(user_id=user.id, social="facebook")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return after_login(user, next_url)
|
||||
|
|
|
@ -19,7 +19,8 @@ from wtforms import HiddenField, validators, BooleanField
|
|||
from app.auth.base import auth_bp
|
||||
from app.config import MFA_USER_ID
|
||||
from app.config import RP_ID, URL
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import User, Fido, MfaBrowser
|
||||
|
||||
|
@ -102,7 +103,7 @@ def fido():
|
|||
auto_activate = False
|
||||
else:
|
||||
user.fido_sign_count = new_sign_count
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
del session[MFA_USER_ID]
|
||||
|
||||
login_user(user)
|
||||
|
@ -113,7 +114,7 @@ def fido():
|
|||
|
||||
if fido_token_form.remember.data:
|
||||
browser = MfaBrowser.create_new(user=user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
response.set_cookie(
|
||||
"mfa",
|
||||
value=browser.token,
|
||||
|
|
|
@ -4,7 +4,7 @@ from requests_oauthlib import OAuth2Session
|
|||
from app.auth.base import auth_bp
|
||||
from app.auth.views.login_utils import after_login
|
||||
from app.config import GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, URL
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import User, SocialAuth
|
||||
from app.utils import encode_url, sanitize_email
|
||||
|
@ -94,7 +94,7 @@ def github_callback():
|
|||
|
||||
if not SocialAuth.get_by(user_id=user.id, social="github"):
|
||||
SocialAuth.create(user_id=user.id, social="github")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# The activation link contains the original page, for ex authorize page
|
||||
next_url = request.args.get("next") if request.args else None
|
||||
|
|
|
@ -4,7 +4,7 @@ from requests_oauthlib import OAuth2Session
|
|||
from app import s3
|
||||
from app.auth.base import auth_bp
|
||||
from app.config import URL, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import User, File, SocialAuth
|
||||
from app.utils import random_string, sanitize_email
|
||||
|
@ -89,7 +89,7 @@ def google_callback():
|
|||
LOG.d("set user profile picture to %s", picture_url)
|
||||
file = create_file_from_url(user, picture_url)
|
||||
user.profile_picture_id = file.id
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
else:
|
||||
flash(
|
||||
"Sorry you cannot sign up via Google, please use email/password sign-up instead",
|
||||
|
@ -108,7 +108,7 @@ def google_callback():
|
|||
|
||||
if not SocialAuth.get_by(user_id=user.id, social="google"):
|
||||
SocialAuth.create(user_id=user.id, social="google")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return after_login(user, next_url)
|
||||
|
||||
|
@ -119,7 +119,7 @@ def create_file_from_url(user, url) -> File:
|
|||
|
||||
s3.upload_from_url(url, file_path)
|
||||
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
LOG.d("upload file %s to s3", file)
|
||||
|
||||
return file
|
||||
|
|
|
@ -15,7 +15,8 @@ from wtforms import BooleanField, StringField, validators
|
|||
|
||||
from app.auth.base import auth_bp
|
||||
from app.config import MFA_USER_ID, URL
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.models import User, MfaBrowser
|
||||
|
||||
|
||||
|
@ -67,7 +68,7 @@ def mfa():
|
|||
if totp.verify(token) and user.last_otp != token:
|
||||
del session[MFA_USER_ID]
|
||||
user.last_otp = token
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
login_user(user)
|
||||
flash(f"Welcome back!", "success")
|
||||
|
@ -77,7 +78,7 @@ def mfa():
|
|||
|
||||
if otp_token_form.remember.data:
|
||||
browser = MfaBrowser.create_new(user=user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
response.set_cookie(
|
||||
"mfa",
|
||||
value=browser.token,
|
||||
|
|
|
@ -6,7 +6,8 @@ from wtforms import StringField, validators
|
|||
|
||||
from app.auth.base import auth_bp
|
||||
from app.config import MFA_USER_ID
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import User, RecoveryCode
|
||||
|
||||
|
@ -54,7 +55,7 @@ def recovery_route():
|
|||
|
||||
recovery_code.used = True
|
||||
recovery_code.used_at = arrow.now()
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# User comes to login page from another page
|
||||
if next_url:
|
||||
|
|
|
@ -8,11 +8,11 @@ from app import email_utils, config
|
|||
from app.auth.base import auth_bp
|
||||
from app.auth.views.login_utils import get_referral
|
||||
from app.config import URL, HCAPTCHA_SECRET, HCAPTCHA_SITEKEY
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
email_can_be_used_as_mailbox,
|
||||
personal_email_already_used,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import User, ActivationCode
|
||||
from app.utils import random_string, encode_url, sanitize_email
|
||||
|
@ -81,7 +81,7 @@ def register():
|
|||
password=form.password.data,
|
||||
referral=get_referral(),
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
try:
|
||||
send_activation_email(user, next_url)
|
||||
|
@ -102,7 +102,7 @@ def register():
|
|||
def send_activation_email(user, next_url):
|
||||
# the activation code is valid for 1h
|
||||
activation = ActivationCode.create(user_id=user.id, code=random_string(30))
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Send user activation email
|
||||
activation_link = f"{URL}/auth/activate?code={activation.code}"
|
||||
|
|
|
@ -6,7 +6,8 @@ from wtforms import StringField, validators
|
|||
|
||||
from app.auth.base import auth_bp
|
||||
from app.auth.views.login_utils import after_login
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.models import ResetPasswordCode
|
||||
|
||||
|
||||
|
@ -64,7 +65,7 @@ def reset_password():
|
|||
# change the alternative_id to log user out on other browsers
|
||||
user.alternative_id = str(uuid.uuid4())
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# do not use login_user(user) here
|
||||
# to make sure user needs to go through MFA if enabled
|
||||
|
|
|
@ -10,12 +10,12 @@ from wtforms import StringField, validators, ValidationError
|
|||
|
||||
from app.config import PAGE_LIMIT
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
is_valid_email,
|
||||
generate_reply_email,
|
||||
parse_full_address,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import Alias, Contact, EmailLog
|
||||
|
||||
|
@ -64,7 +64,7 @@ def get_contact_infos(
|
|||
) -> [ContactInfo]:
|
||||
"""if contact_id is set, only return the contact info for this contact"""
|
||||
sub = (
|
||||
db.session.query(
|
||||
Session.query(
|
||||
Contact.id,
|
||||
func.sum(case([(EmailLog.is_reply, 1)], else_=0)).label("nb_reply"),
|
||||
func.sum(
|
||||
|
@ -94,7 +94,7 @@ def get_contact_infos(
|
|||
)
|
||||
|
||||
q = (
|
||||
db.session.query(
|
||||
Session.query(
|
||||
Contact,
|
||||
EmailLog,
|
||||
sub.c.nb_reply,
|
||||
|
@ -221,7 +221,7 @@ def alias_contact_manager(alias_id):
|
|||
)
|
||||
|
||||
LOG.d("create reverse-alias for %s", contact_addr)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"Reverse alias for {contact_addr} is created", "success")
|
||||
|
||||
return redirect(
|
||||
|
@ -248,7 +248,7 @@ def alias_contact_manager(alias_id):
|
|||
|
||||
delete_contact_email = contact.website_email
|
||||
Contact.delete(contact_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash(
|
||||
f"Reverse-alias for {delete_contact_email} has been deleted", "success"
|
||||
|
|
|
@ -4,7 +4,7 @@ from flask_login import login_required, current_user
|
|||
|
||||
from app.config import PAGE_LIMIT
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import Alias, EmailLog, Contact
|
||||
|
||||
|
||||
|
@ -43,7 +43,7 @@ def alias_log(alias_id, page_id):
|
|||
|
||||
logs = get_alias_log(alias, page_id)
|
||||
base = (
|
||||
db.session.query(Contact, EmailLog)
|
||||
Session.query(Contact, EmailLog)
|
||||
.filter(Contact.id == EmailLog.contact_id)
|
||||
.filter(Contact.alias_id == alias.id)
|
||||
)
|
||||
|
@ -66,7 +66,7 @@ def get_alias_log(alias: Alias, page_id=0) -> [AliasLog]:
|
|||
logs: [AliasLog] = []
|
||||
|
||||
q = (
|
||||
db.session.query(Contact, EmailLog)
|
||||
Session.query(Contact, EmailLog)
|
||||
.filter(Contact.id == EmailLog.contact_id)
|
||||
.filter(Contact.alias_id == alias.id)
|
||||
.order_by(EmailLog.id.desc())
|
||||
|
|
|
@ -5,8 +5,9 @@ from flask_login import login_required, current_user
|
|||
|
||||
from app.config import URL
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.email_utils import send_email, render
|
||||
from app.extensions import db, limiter
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
Alias,
|
||||
|
@ -25,20 +26,20 @@ def transfer(alias, new_user, new_mailboxes: [Mailbox]):
|
|||
raise Exception("Cannot transfer alias that's used to receive newsletter")
|
||||
|
||||
# update user_id
|
||||
db.session.query(Contact).filter(Contact.alias_id == alias.id).update(
|
||||
Session.query(Contact).filter(Contact.alias_id == alias.id).update(
|
||||
{"user_id": new_user.id}
|
||||
)
|
||||
|
||||
db.session.query(AliasUsedOn).filter(AliasUsedOn.alias_id == alias.id).update(
|
||||
Session.query(AliasUsedOn).filter(AliasUsedOn.alias_id == alias.id).update(
|
||||
{"user_id": new_user.id}
|
||||
)
|
||||
|
||||
db.session.query(ClientUser).filter(ClientUser.alias_id == alias.id).update(
|
||||
Session.query(ClientUser).filter(ClientUser.alias_id == alias.id).update(
|
||||
{"user_id": new_user.id}
|
||||
)
|
||||
|
||||
# remove existing mailboxes from the alias
|
||||
db.session.query(AliasMailbox).filter(AliasMailbox.alias_id == alias.id).delete()
|
||||
Session.query(AliasMailbox).filter(AliasMailbox.alias_id == alias.id).delete()
|
||||
|
||||
# set mailboxes
|
||||
alias.mailbox_id = new_mailboxes.pop().id
|
||||
|
@ -71,7 +72,7 @@ def transfer(alias, new_user, new_mailboxes: [Mailbox]):
|
|||
alias.disable_pgp = False
|
||||
alias.pinned = False
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
|
||||
@dashboard_bp.route("/alias_transfer/send/<int:alias_id>/", methods=["GET", "POST"])
|
||||
|
@ -100,7 +101,7 @@ def alias_transfer_send_route(alias_id):
|
|||
if request.method == "POST":
|
||||
if request.form.get("form-name") == "create":
|
||||
alias.transfer_token = str(uuid4())
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
alias_transfer_url = (
|
||||
URL
|
||||
+ "/dashboard/alias_transfer/receive"
|
||||
|
@ -111,7 +112,7 @@ def alias_transfer_send_route(alias_id):
|
|||
# request.form.get("form-name") == "remove"
|
||||
else:
|
||||
alias.transfer_token = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
alias_transfer_url = None
|
||||
flash("Share URL deleted", "success")
|
||||
return redirect(request.url)
|
||||
|
|
|
@ -4,7 +4,7 @@ from flask_wtf import FlaskForm
|
|||
from wtforms import StringField, validators
|
||||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import ApiKey
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ class NewApiKeyForm(FlaskForm):
|
|||
@login_required
|
||||
def api_key():
|
||||
api_keys = (
|
||||
ApiKey.query.filter(ApiKey.user_id == current_user.id)
|
||||
ApiKey.filter(ApiKey.user_id == current_user.id)
|
||||
.order_by(ApiKey.created_at.desc())
|
||||
.all()
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ def api_key():
|
|||
|
||||
name = api_key.name
|
||||
ApiKey.delete(api_key_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"API Key {name} has been deleted", "success")
|
||||
|
||||
return redirect(url_for("dashboard.api_key"))
|
||||
|
@ -48,7 +48,7 @@ def api_key():
|
|||
new_api_key = ApiKey.create(
|
||||
name=new_api_key_form.name.data, user_id=current_user.id
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash(f"New API Key {new_api_key.name} has been created", "success")
|
||||
return redirect(url_for("dashboard.api_key"))
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from app.db import Session
|
||||
|
||||
"""
|
||||
List of apps that user has used via the "Sign in with SimpleLogin"
|
||||
"""
|
||||
|
@ -7,7 +9,6 @@ from flask_login import login_required, current_user
|
|||
from sqlalchemy.orm import joinedload
|
||||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.models import (
|
||||
ClientUser,
|
||||
)
|
||||
|
@ -36,7 +37,7 @@ def app_route():
|
|||
|
||||
client = client_user.client
|
||||
ClientUser.delete(client_user_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash(f"Link with {client.name} has been removed", "success")
|
||||
return redirect(request.url)
|
||||
|
|
|
@ -5,7 +5,7 @@ from flask_login import login_required, current_user
|
|||
from app import s3
|
||||
from app.config import JOB_BATCH_IMPORT
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import File, BatchImport, Job
|
||||
from app.utils import random_string
|
||||
|
@ -18,7 +18,7 @@ def batch_import_route():
|
|||
if not current_user.verified_custom_domains():
|
||||
flash("Alias batch import is only available for custom domains", "warning")
|
||||
|
||||
batch_imports = BatchImport.query.filter_by(user_id=current_user.id).all()
|
||||
batch_imports = BatchImport.filter_by(user_id=current_user.id).all()
|
||||
|
||||
if request.method == "POST":
|
||||
alias_file = request.files["alias-file"]
|
||||
|
@ -26,11 +26,11 @@ def batch_import_route():
|
|||
file_path = random_string(20) + ".csv"
|
||||
file = File.create(user_id=current_user.id, path=file_path)
|
||||
s3.upload_from_bytesio(file_path, alias_file)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
LOG.d("upload file %s to s3 at %s", file, file_path)
|
||||
|
||||
bi = BatchImport.create(user_id=current_user.id, file_id=file.id)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
LOG.d("Add a batch import job %s for %s", bi, current_user)
|
||||
|
||||
# Schedule batch import job
|
||||
|
@ -39,7 +39,7 @@ def batch_import_route():
|
|||
payload={"batch_import_id": bi.id},
|
||||
run_at=arrow.now(),
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash(
|
||||
"The file has been uploaded successfully and the import will start shortly",
|
||||
|
|
|
@ -3,7 +3,7 @@ from flask_login import login_required, current_user
|
|||
|
||||
from app.config import PADDLE_MONTHLY_PRODUCT_ID, PADDLE_YEARLY_PRODUCT_ID
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import Subscription, PlanEnum
|
||||
from app.paddle_utils import cancel_subscription, change_plan
|
||||
|
@ -26,7 +26,7 @@ def billing():
|
|||
|
||||
if success:
|
||||
sub.cancelled = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your subscription has been canceled successfully", "success")
|
||||
else:
|
||||
flash(
|
||||
|
@ -44,7 +44,7 @@ def billing():
|
|||
|
||||
if success:
|
||||
sub.plan = PlanEnum.monthly
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your subscription has been updated", "success")
|
||||
else:
|
||||
if msg:
|
||||
|
@ -65,7 +65,7 @@ def billing():
|
|||
|
||||
if success:
|
||||
sub.plan = PlanEnum.yearly
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your subscription has been updated", "success")
|
||||
else:
|
||||
if msg:
|
||||
|
|
|
@ -2,7 +2,7 @@ from flask import render_template, request, redirect, url_for, flash
|
|||
from flask_login import login_required, current_user
|
||||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import Contact
|
||||
from app.pgp_utils import PGPException, load_public_key_and_check
|
||||
|
||||
|
@ -34,7 +34,7 @@ def contact_detail_route(contact_id):
|
|||
except PGPException:
|
||||
flash("Cannot add the public key, please verify it", "error")
|
||||
else:
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(
|
||||
f"PGP public key for {contact.email} is saved successfully",
|
||||
"success",
|
||||
|
@ -46,7 +46,7 @@ def contact_detail_route(contact_id):
|
|||
# Free user can decide to remove contact PGP key
|
||||
contact.pgp_public_key = None
|
||||
contact.pgp_finger_print = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"PGP public key for {contact.email} is removed", "success")
|
||||
return redirect(
|
||||
url_for("dashboard.contact_detail_route", contact_id=contact_id)
|
||||
|
|
|
@ -6,8 +6,8 @@ from wtforms import StringField, validators
|
|||
|
||||
from app.config import ADMIN_EMAIL
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.email_utils import send_email
|
||||
from app.extensions import db
|
||||
from app.models import (
|
||||
ManualSubscription,
|
||||
Coupon,
|
||||
|
@ -57,7 +57,7 @@ def coupon_route():
|
|||
if coupon and not coupon.used:
|
||||
coupon.used_by_user_id = current_user.id
|
||||
coupon.used = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
manual_sub: ManualSubscription = ManualSubscription.get_by(
|
||||
user_id=current_user.id
|
||||
|
@ -68,7 +68,7 @@ def coupon_route():
|
|||
manual_sub.end_at = manual_sub.end_at.shift(years=coupon.nb_year)
|
||||
else:
|
||||
manual_sub.end_at = arrow.now().shift(years=coupon.nb_year, days=1)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(
|
||||
f"Your current subscription is extended to {manual_sub.end_at.humanize()}",
|
||||
"success",
|
||||
|
|
|
@ -13,7 +13,8 @@ from app.config import (
|
|||
ALIAS_LIMIT,
|
||||
)
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
Alias,
|
||||
|
@ -307,10 +308,10 @@ def custom_alias():
|
|||
mailbox_id=mailboxes[0].id,
|
||||
custom_domain_id=custom_domain_id,
|
||||
)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
except IntegrityError:
|
||||
LOG.w("Alias %s already exists", full_alias)
|
||||
db.session.rollback()
|
||||
Session.rollback()
|
||||
flash("Unknown error, please retry", "error")
|
||||
return redirect(url_for("dashboard.custom_alias"))
|
||||
|
||||
|
@ -320,7 +321,7 @@ def custom_alias():
|
|||
mailbox_id=mailboxes[i].id,
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"Alias {full_alias} has been created", "success")
|
||||
|
||||
return redirect(url_for("dashboard.index", highlight_alias_id=alias.id))
|
||||
|
|
|
@ -5,8 +5,8 @@ from wtforms import StringField, validators
|
|||
|
||||
from app.config import EMAIL_SERVERS_WITH_PRIORITY
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.email_utils import get_email_domain_part
|
||||
from app.extensions import db
|
||||
from app.models import CustomDomain, Mailbox, DomainMailbox, SLDomain
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ class NewCustomDomainForm(FlaskForm):
|
|||
@dashboard_bp.route("/custom_domain", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def custom_domain():
|
||||
custom_domains = CustomDomain.query.filter_by(user_id=current_user.id).all()
|
||||
custom_domains = CustomDomain.filter_by(user_id=current_user.id).all()
|
||||
mailboxes = current_user.mailboxes()
|
||||
new_custom_domain_form = NewCustomDomainForm()
|
||||
|
||||
|
@ -54,7 +54,7 @@ def custom_domain():
|
|||
new_custom_domain = CustomDomain.create(
|
||||
domain=new_domain, user_id=current_user.id
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
mailbox_ids = request.form.getlist("mailbox_ids")
|
||||
if mailbox_ids:
|
||||
|
@ -76,7 +76,7 @@ def custom_domain():
|
|||
domain_id=new_custom_domain.id, mailbox_id=mailbox.id
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash(
|
||||
f"New domain {new_custom_domain.domain} is created", "success"
|
||||
|
|
|
@ -10,7 +10,7 @@ from app.config import (
|
|||
BOUNCE_PREFIX_FOR_REPLY_PHASE,
|
||||
)
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import Directory, Mailbox, DirectoryMailbox
|
||||
|
||||
|
||||
|
@ -24,7 +24,7 @@ class NewDirForm(FlaskForm):
|
|||
@login_required
|
||||
def directory():
|
||||
dirs = (
|
||||
Directory.query.filter_by(user_id=current_user.id)
|
||||
Directory.filter_by(user_id=current_user.id)
|
||||
.order_by(Directory.created_at.desc())
|
||||
.all()
|
||||
)
|
||||
|
@ -47,7 +47,7 @@ def directory():
|
|||
|
||||
name = dir.name
|
||||
Directory.delete(dir_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"Directory {name} has been deleted", "success")
|
||||
|
||||
return redirect(url_for("dashboard.directory"))
|
||||
|
@ -67,7 +67,7 @@ def directory():
|
|||
dir.disabled = True
|
||||
flash(f"On-the-fly is disabled for {dir.name}", "warning")
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return redirect(url_for("dashboard.directory"))
|
||||
|
||||
|
@ -98,13 +98,13 @@ def directory():
|
|||
return redirect(url_for("dashboard.directory"))
|
||||
|
||||
# first remove all existing directory-mailboxes links
|
||||
DirectoryMailbox.query.filter_by(directory_id=dir.id).delete()
|
||||
db.session.flush()
|
||||
DirectoryMailbox.filter_by(directory_id=dir.id).delete()
|
||||
Session.flush()
|
||||
|
||||
for mailbox in mailboxes:
|
||||
DirectoryMailbox.create(directory_id=dir.id, mailbox_id=mailbox.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"Directory {dir.name} has been updated", "success")
|
||||
|
||||
return redirect(url_for("dashboard.directory"))
|
||||
|
@ -141,7 +141,7 @@ def directory():
|
|||
new_dir = Directory.create(
|
||||
name=new_dir_name, user_id=current_user.id
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
mailbox_ids = request.form.getlist("mailbox_ids")
|
||||
if mailbox_ids:
|
||||
# check if mailbox is not tempered with
|
||||
|
@ -162,7 +162,7 @@ def directory():
|
|||
directory_id=new_dir.id, mailbox_id=mailbox.id
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash(f"Directory {new_dir.name} is created", "success")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import re2 as re
|
||||
from threading import Thread
|
||||
|
||||
import re2 as re
|
||||
from flask import render_template, request, redirect, url_for, flash
|
||||
from flask_login import login_required, current_user
|
||||
from flask_wtf import FlaskForm
|
||||
|
@ -8,6 +8,7 @@ from wtforms import StringField, validators, IntegerField
|
|||
|
||||
from app.config import EMAIL_SERVERS_WITH_PRIORITY, EMAIL_DOMAIN
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.dns_utils import (
|
||||
get_mx_domains,
|
||||
get_spf_domain,
|
||||
|
@ -15,7 +16,6 @@ from app.dns_utils import (
|
|||
get_cname_record,
|
||||
)
|
||||
from app.email_utils import send_email
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
CustomDomain,
|
||||
|
@ -40,7 +40,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
# generate a domain ownership txt token if needed
|
||||
if not custom_domain.ownership_verified and not custom_domain.ownership_txt_token:
|
||||
custom_domain.ownership_txt_token = random_string(30)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
spf_record = f"v=spf1 include:{EMAIL_DOMAIN} ~all"
|
||||
|
||||
|
@ -62,7 +62,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
"success",
|
||||
)
|
||||
custom_domain.ownership_verified = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return redirect(
|
||||
url_for(
|
||||
"dashboard.domain_detail_dns",
|
||||
|
@ -92,7 +92,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
"success",
|
||||
)
|
||||
custom_domain.verified = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return redirect(
|
||||
url_for(
|
||||
"dashboard.domain_detail_dns", custom_domain_id=custom_domain.id
|
||||
|
@ -102,7 +102,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
spf_domains = get_spf_domain(custom_domain.domain)
|
||||
if EMAIL_DOMAIN in spf_domains:
|
||||
custom_domain.spf_verified = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("SPF is setup correctly", "success")
|
||||
return redirect(
|
||||
url_for(
|
||||
|
@ -111,7 +111,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
)
|
||||
else:
|
||||
custom_domain.spf_verified = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(
|
||||
f"SPF: {EMAIL_DOMAIN} is not included in your SPF record.",
|
||||
"warning",
|
||||
|
@ -124,7 +124,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
if dkim_record == dkim_cname:
|
||||
flash("DKIM is setup correctly.", "success")
|
||||
custom_domain.dkim_verified = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return redirect(
|
||||
url_for(
|
||||
|
@ -133,7 +133,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
)
|
||||
else:
|
||||
custom_domain.dkim_verified = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("DKIM: the CNAME record is not correctly set", "warning")
|
||||
dkim_ok = False
|
||||
dkim_errors = [dkim_record or "[Empty]"]
|
||||
|
@ -142,7 +142,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
txt_records = get_txt_record("_dmarc." + custom_domain.domain)
|
||||
if dmarc_record in txt_records:
|
||||
custom_domain.dmarc_verified = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("DMARC is setup correctly", "success")
|
||||
return redirect(
|
||||
url_for(
|
||||
|
@ -151,7 +151,7 @@ def domain_detail_dns(custom_domain_id):
|
|||
)
|
||||
else:
|
||||
custom_domain.dmarc_verified = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(
|
||||
"DMARC: The TXT record is not correctly set",
|
||||
"warning",
|
||||
|
@ -179,7 +179,7 @@ def domain_detail(custom_domain_id):
|
|||
if request.method == "POST":
|
||||
if request.form.get("form-name") == "switch-catch-all":
|
||||
custom_domain.catch_all = not custom_domain.catch_all
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
if custom_domain.catch_all:
|
||||
flash(
|
||||
|
@ -197,14 +197,14 @@ def domain_detail(custom_domain_id):
|
|||
elif request.form.get("form-name") == "set-name":
|
||||
if request.form.get("action") == "save":
|
||||
custom_domain.name = request.form.get("alias-name").replace("\n", "")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(
|
||||
f"Default alias name for Domain {custom_domain.domain} has been set",
|
||||
"success",
|
||||
)
|
||||
else:
|
||||
custom_domain.name = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(
|
||||
f"Default alias name for Domain {custom_domain.domain} has been removed",
|
||||
"info",
|
||||
|
@ -217,7 +217,7 @@ def domain_detail(custom_domain_id):
|
|||
custom_domain.random_prefix_generation = (
|
||||
not custom_domain.random_prefix_generation
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
if custom_domain.random_prefix_generation:
|
||||
flash(
|
||||
|
@ -260,13 +260,13 @@ def domain_detail(custom_domain_id):
|
|||
)
|
||||
|
||||
# first remove all existing domain-mailboxes links
|
||||
DomainMailbox.query.filter_by(domain_id=custom_domain.id).delete()
|
||||
db.session.flush()
|
||||
DomainMailbox.filter_by(domain_id=custom_domain.id).delete()
|
||||
Session.flush()
|
||||
|
||||
for mailbox in mailboxes:
|
||||
DomainMailbox.create(domain_id=custom_domain.id, mailbox_id=mailbox.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"{custom_domain.domain} mailboxes has been updated", "success")
|
||||
|
||||
return redirect(
|
||||
|
@ -302,7 +302,7 @@ def delete_domain(custom_domain_id: int):
|
|||
user = custom_domain.user
|
||||
|
||||
CustomDomain.delete(custom_domain.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Domain %s deleted", domain_name)
|
||||
|
||||
|
@ -328,7 +328,7 @@ def domain_detail_trash(custom_domain_id):
|
|||
if request.method == "POST":
|
||||
if request.form.get("form-name") == "empty-all":
|
||||
DomainDeletedAlias.filter_by(domain_id=custom_domain.id).delete()
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash("All deleted aliases can now be re-created", "success")
|
||||
return redirect(
|
||||
|
@ -349,7 +349,7 @@ def domain_detail_trash(custom_domain_id):
|
|||
)
|
||||
|
||||
DomainDeletedAlias.delete(deleted_alias.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(
|
||||
f"{deleted_alias.email} can now be re-created",
|
||||
"success",
|
||||
|
@ -477,7 +477,7 @@ def domain_detail_auto_create(custom_domain_id):
|
|||
auto_create_rule_id=rule.id, mailbox_id=mailbox.id
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash("New auto create rule has been created", "success")
|
||||
|
||||
|
@ -502,7 +502,7 @@ def domain_detail_auto_create(custom_domain_id):
|
|||
|
||||
rule_order = rule.order
|
||||
AutoCreateRule.delete(rule_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"Rule #{rule_order} has been deleted", "success")
|
||||
return redirect(
|
||||
url_for(
|
||||
|
|
|
@ -5,7 +5,7 @@ from wtforms import HiddenField, validators
|
|||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.dashboard.views.enter_sudo import sudo_required
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import RecoveryCode, Fido
|
||||
|
||||
|
@ -34,7 +34,7 @@ def fido_manage():
|
|||
return redirect(url_for("dashboard.fido_manage"))
|
||||
|
||||
Fido.delete(fido_key.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d(f"FIDO Key ID={fido_key.id} Removed")
|
||||
flash(f"Key {fido_key.name} successfully unlinked", "success")
|
||||
|
@ -42,7 +42,7 @@ def fido_manage():
|
|||
# Disable FIDO for the user if all keys have been deleted
|
||||
if not Fido.filter_by(uuid=current_user.fido_uuid).all():
|
||||
current_user.fido_uuid = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# user does not have any 2FA enabled left, delete all recovery codes
|
||||
if not current_user.two_factor_authentication_enabled():
|
||||
|
|
|
@ -11,7 +11,7 @@ from wtforms import StringField, HiddenField, validators
|
|||
from app.config import RP_ID, URL
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.dashboard.views.enter_sudo import sudo_required
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import Fido, RecoveryCode
|
||||
|
||||
|
@ -61,7 +61,7 @@ def fido_setup():
|
|||
|
||||
if current_user.fido_uuid is None:
|
||||
current_user.fido_uuid = fido_uuid
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
|
||||
Fido.create(
|
||||
credential_id=str(fido_credential.credential_id, "utf-8"),
|
||||
|
@ -70,14 +70,14 @@ def fido_setup():
|
|||
sign_count=fido_credential.sign_count,
|
||||
name=fido_token_form.key_name.data,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d(
|
||||
f"credential_id={str(fido_credential.credential_id, 'utf-8')} added for {fido_uuid}"
|
||||
)
|
||||
|
||||
flash("Security key has been activated", "success")
|
||||
if not RecoveryCode.query.filter_by(user_id=current_user.id).all():
|
||||
if not RecoveryCode.filter_by(user_id=current_user.id).all():
|
||||
return redirect(url_for("dashboard.recovery_code_route"))
|
||||
else:
|
||||
return redirect(url_for("dashboard.fido_manage"))
|
||||
|
|
|
@ -7,7 +7,8 @@ from app import alias_utils
|
|||
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.dashboard.base import dashboard_bp
|
||||
from app.extensions import db, limiter
|
||||
from app.db import Session
|
||||
from app.extensions import limiter
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
Alias,
|
||||
|
@ -26,19 +27,19 @@ class Stats:
|
|||
|
||||
|
||||
def get_stats(user: User) -> Stats:
|
||||
nb_alias = Alias.query.filter_by(user_id=user.id).count()
|
||||
nb_alias = Alias.filter_by(user_id=user.id).count()
|
||||
nb_forward = (
|
||||
db.session.query(EmailLog)
|
||||
Session.query(EmailLog)
|
||||
.filter_by(user_id=user.id, is_reply=False, blocked=False, bounced=False)
|
||||
.count()
|
||||
)
|
||||
nb_reply = (
|
||||
db.session.query(EmailLog)
|
||||
Session.query(EmailLog)
|
||||
.filter_by(user_id=user.id, is_reply=True, blocked=False, bounced=False)
|
||||
.count()
|
||||
)
|
||||
nb_block = (
|
||||
db.session.query(EmailLog)
|
||||
Session.query(EmailLog)
|
||||
.filter_by(user_id=user.id, is_reply=False, blocked=True, bounced=False)
|
||||
.count()
|
||||
)
|
||||
|
@ -92,7 +93,7 @@ def index():
|
|||
|
||||
alias.mailbox_id = current_user.default_mailbox_id
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("create new random alias %s for user %s", alias, current_user)
|
||||
flash(f"Alias {alias.email} has been created", "success")
|
||||
|
@ -130,7 +131,7 @@ def index():
|
|||
flash(f"Alias {email} has been deleted", "success")
|
||||
elif request.form.get("form-name") == "disable-alias":
|
||||
alias.enabled = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"Alias {alias.email} has been disabled", "success")
|
||||
|
||||
return redirect(
|
||||
|
@ -146,7 +147,7 @@ def index():
|
|||
|
||||
# to make sure not showing intro to user again
|
||||
current_user.intro_shown = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
stats = get_stats(current_user)
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ from wtforms import StringField, validators
|
|||
|
||||
from app.config import ADMIN_EMAIL
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.email_utils import send_email
|
||||
from app.extensions import db
|
||||
from app.models import LifetimeCoupon
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ def lifetime_licence():
|
|||
current_user.lifetime_coupon_id = coupon.id
|
||||
if coupon.paid:
|
||||
current_user.paid_lifetime = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# notify admin
|
||||
send_email(
|
||||
|
|
|
@ -9,6 +9,7 @@ from wtforms.fields.html5 import EmailField
|
|||
|
||||
from app.config import MAILBOX_SECRET, URL
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
email_can_be_used_as_mailbox,
|
||||
mailbox_already_used,
|
||||
|
@ -16,7 +17,6 @@ from app.email_utils import (
|
|||
send_email,
|
||||
is_valid_email,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import Mailbox
|
||||
|
||||
|
@ -31,7 +31,7 @@ class NewMailboxForm(FlaskForm):
|
|||
@login_required
|
||||
def mailbox_route():
|
||||
mailboxes = (
|
||||
Mailbox.query.filter_by(user_id=current_user.id)
|
||||
Mailbox.filter_by(user_id=current_user.id)
|
||||
.order_by(Mailbox.created_at.desc())
|
||||
.all()
|
||||
)
|
||||
|
@ -77,7 +77,7 @@ def mailbox_route():
|
|||
return redirect(url_for("dashboard.mailbox_route"))
|
||||
|
||||
current_user.default_mailbox_id = mailbox.id
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"Mailbox {mailbox.email} is set as Default Mailbox", "success")
|
||||
|
||||
return redirect(url_for("dashboard.mailbox_route"))
|
||||
|
@ -102,7 +102,7 @@ def mailbox_route():
|
|||
new_mailbox = Mailbox.create(
|
||||
email=mailbox_email, user_id=current_user.id
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_verification_email(current_user, new_mailbox)
|
||||
|
||||
|
@ -136,7 +136,7 @@ def delete_mailbox(mailbox_id: int):
|
|||
user = mailbox.user
|
||||
|
||||
Mailbox.delete(mailbox_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
LOG.d("Mailbox %s %s deleted", mailbox_id, mailbox_email)
|
||||
|
||||
send_email(
|
||||
|
@ -191,7 +191,7 @@ def mailbox_verify():
|
|||
return redirect(url_for("dashboard.mailbox_route"))
|
||||
|
||||
mailbox.verified = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Mailbox %s is verified", mailbox)
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ from wtforms.fields.html5 import EmailField
|
|||
from app.config import ENFORCE_SPF, MAILBOX_SECRET
|
||||
from app.config import URL
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.email_utils import email_can_be_used_as_mailbox
|
||||
from app.email_utils import mailbox_already_used, render, send_email
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import Alias, AuthorizedAddress
|
||||
from app.models import Mailbox
|
||||
|
@ -57,7 +57,7 @@ def mailbox_detail_route(mailbox_id):
|
|||
flash("You cannot use this email address as your mailbox", "error")
|
||||
else:
|
||||
mailbox.new_email = new_email
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
try:
|
||||
verify_mailbox_change(current_user, mailbox, new_email)
|
||||
|
@ -82,7 +82,7 @@ def mailbox_detail_route(mailbox_id):
|
|||
mailbox.force_spf = (
|
||||
True if request.form.get("spf-status") == "on" else False
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(
|
||||
"SPF enforcement was " + "enabled"
|
||||
if request.form.get("spf-status")
|
||||
|
@ -118,7 +118,7 @@ def mailbox_detail_route(mailbox_id):
|
|||
else:
|
||||
address = authorized_address.email
|
||||
AuthorizedAddress.delete(authorized_address_id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash(f"{address} has been deleted", "success")
|
||||
|
||||
return redirect(
|
||||
|
@ -140,7 +140,7 @@ def mailbox_detail_route(mailbox_id):
|
|||
except PGPException:
|
||||
flash("Cannot add the public key, please verify it", "error")
|
||||
else:
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your PGP public key is saved successfully", "success")
|
||||
return redirect(
|
||||
url_for("dashboard.mailbox_detail_route", mailbox_id=mailbox_id)
|
||||
|
@ -150,7 +150,7 @@ def mailbox_detail_route(mailbox_id):
|
|||
mailbox.pgp_public_key = None
|
||||
mailbox.pgp_finger_print = None
|
||||
mailbox.disable_pgp = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your PGP public key is removed successfully", "success")
|
||||
return redirect(
|
||||
url_for("dashboard.mailbox_detail_route", mailbox_id=mailbox_id)
|
||||
|
@ -164,7 +164,7 @@ def mailbox_detail_route(mailbox_id):
|
|||
mailbox.disable_pgp = True
|
||||
flash(f"PGP is disabled on {mailbox.email}", "info")
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return redirect(
|
||||
url_for("dashboard.mailbox_detail_route", mailbox_id=mailbox_id)
|
||||
)
|
||||
|
@ -180,14 +180,14 @@ def mailbox_detail_route(mailbox_id):
|
|||
)
|
||||
|
||||
mailbox.generic_subject = request.form.get("generic-subject")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Generic subject for PGP-encrypted email is enabled", "success")
|
||||
return redirect(
|
||||
url_for("dashboard.mailbox_detail_route", mailbox_id=mailbox_id)
|
||||
)
|
||||
elif request.form.get("action") == "remove":
|
||||
mailbox.generic_subject = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Generic subject for PGP-encrypted email is disabled", "success")
|
||||
return redirect(
|
||||
url_for("dashboard.mailbox_detail_route", mailbox_id=mailbox_id)
|
||||
|
@ -236,7 +236,7 @@ def cancel_mailbox_change_route(mailbox_id):
|
|||
|
||||
if mailbox.new_email:
|
||||
mailbox.new_email = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your mailbox change is cancelled", "success")
|
||||
return redirect(
|
||||
url_for("dashboard.mailbox_detail_route", mailbox_id=mailbox_id)
|
||||
|
@ -274,7 +274,7 @@ def mailbox_confirm_change_route():
|
|||
|
||||
# mark mailbox as verified if the change request is sent from an unverified mailbox
|
||||
mailbox.verified = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Mailbox change %s is verified", mailbox)
|
||||
flash(f"The {mailbox.email} is updated", "success")
|
||||
|
|
|
@ -3,7 +3,7 @@ from flask_login import login_required, current_user
|
|||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.dashboard.views.enter_sudo import sudo_required
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import RecoveryCode
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ def mfa_cancel():
|
|||
if request.method == "POST":
|
||||
current_user.enable_otp = False
|
||||
current_user.otp_secret = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# user does not have any 2FA enabled left, delete all recovery codes
|
||||
if not current_user.two_factor_authentication_enabled():
|
||||
|
|
|
@ -6,7 +6,7 @@ from wtforms import StringField, validators
|
|||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.dashboard.views.enter_sudo import sudo_required
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
|
||||
|
||||
|
@ -27,7 +27,7 @@ def mfa_setup():
|
|||
if not current_user.otp_secret:
|
||||
LOG.d("Generate otp_secret for user %s", current_user)
|
||||
current_user.otp_secret = pyotp.random_base32()
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
totp = pyotp.TOTP(current_user.otp_secret)
|
||||
|
||||
|
@ -37,7 +37,7 @@ def mfa_setup():
|
|||
if totp.verify(token) and current_user.last_otp != token:
|
||||
current_user.enable_otp = True
|
||||
current_user.last_otp = token
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("MFA has been activated", "success")
|
||||
|
||||
return redirect(url_for("dashboard.recovery_code_route"))
|
||||
|
|
|
@ -13,12 +13,12 @@ def recovery_code_route():
|
|||
flash("you need to enable either TOTP or WebAuthn", "warning")
|
||||
return redirect(url_for("dashboard.index"))
|
||||
|
||||
recovery_codes = RecoveryCode.query.filter_by(user_id=current_user.id).all()
|
||||
recovery_codes = RecoveryCode.filter_by(user_id=current_user.id).all()
|
||||
if request.method == "GET" and not recovery_codes:
|
||||
# user arrives at this page for the first time
|
||||
LOG.d("%s has no recovery keys, generate", current_user)
|
||||
RecoveryCode.generate(current_user)
|
||||
recovery_codes = RecoveryCode.query.filter_by(user_id=current_user.id).all()
|
||||
recovery_codes = RecoveryCode.filter_by(user_id=current_user.id).all()
|
||||
|
||||
if request.method == "POST":
|
||||
RecoveryCode.generate(current_user)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import re2 as re
|
||||
|
||||
from flask import render_template, request, flash, redirect, url_for
|
||||
from flask_login import login_required, current_user
|
||||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import Referral, Payout
|
||||
|
||||
_REFERRAL_PATTERN = r"[0-9a-z-_]{3,}"
|
||||
|
@ -30,7 +29,7 @@ def referral_route():
|
|||
|
||||
name = request.form.get("name")
|
||||
referral = Referral.create(user_id=current_user.id, code=code, name=name)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("A new referral code has been created", "success")
|
||||
return redirect(
|
||||
url_for("dashboard.referral_route", highlight_id=referral.id)
|
||||
|
@ -40,7 +39,7 @@ def referral_route():
|
|||
referral = Referral.get(referral_id)
|
||||
if referral and referral.user_id == current_user.id:
|
||||
referral.name = request.form.get("name")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Referral name updated", "success")
|
||||
return redirect(
|
||||
url_for("dashboard.referral_route", highlight_id=referral.id)
|
||||
|
@ -50,7 +49,7 @@ def referral_route():
|
|||
referral = Referral.get(referral_id)
|
||||
if referral and referral.user_id == current_user.id:
|
||||
Referral.delete(referral.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Referral deleted", "success")
|
||||
return redirect(url_for("dashboard.referral_route"))
|
||||
|
||||
|
@ -59,7 +58,7 @@ def referral_route():
|
|||
if highlight_id:
|
||||
highlight_id = int(highlight_id)
|
||||
|
||||
referrals = Referral.query.filter_by(user_id=current_user.id).all()
|
||||
referrals = Referral.filter_by(user_id=current_user.id).all()
|
||||
# make sure the highlighted referral is the first referral
|
||||
highlight_index = None
|
||||
for ix, referral in enumerate(referrals):
|
||||
|
@ -70,6 +69,6 @@ def referral_route():
|
|||
if highlight_index:
|
||||
referrals.insert(0, referrals.pop(highlight_index))
|
||||
|
||||
payouts = Payout.query.filter_by(user_id=current_user.id).all()
|
||||
payouts = Payout.filter_by(user_id=current_user.id).all()
|
||||
|
||||
return render_template("dashboard/referral.html", **locals())
|
||||
|
|
|
@ -19,7 +19,7 @@ def refused_email_route():
|
|||
highlight_id = None
|
||||
|
||||
email_logs: [EmailLog] = (
|
||||
EmailLog.query.filter(
|
||||
EmailLog.filter(
|
||||
EmailLog.user_id == current_user.id, EmailLog.refused_email_id.isnot(None)
|
||||
)
|
||||
.order_by(EmailLog.id.desc())
|
||||
|
|
|
@ -22,11 +22,11 @@ from app.config import (
|
|||
ALIAS_RANDOM_SUFFIX_LENGTH,
|
||||
)
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
email_can_be_used_as_mailbox,
|
||||
personal_email_already_used,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
PlanEnum,
|
||||
|
@ -116,7 +116,7 @@ def setting():
|
|||
"delete the expired email change %s", other_email_change
|
||||
)
|
||||
EmailChange.delete(other_email_change.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
else:
|
||||
flash(
|
||||
"You cannot use this email address as your personal inbox.",
|
||||
|
@ -132,7 +132,7 @@ def setting():
|
|||
), # todo: make sure the code is unique
|
||||
new_email=new_email,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
send_change_email_confirmation(current_user, email_change)
|
||||
flash(
|
||||
"A confirmation email is on the way, please check your inbox",
|
||||
|
@ -145,7 +145,7 @@ def setting():
|
|||
# update user info
|
||||
if form.name.data != current_user.name:
|
||||
current_user.name = form.name.data
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
profile_updated = True
|
||||
|
||||
if form.profile_picture.data:
|
||||
|
@ -156,11 +156,11 @@ def setting():
|
|||
file_path, BytesIO(form.profile_picture.data.read())
|
||||
)
|
||||
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
LOG.d("upload file %s to s3", file)
|
||||
|
||||
current_user.profile_picture_id = file.id
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
profile_updated = True
|
||||
|
||||
if profile_updated:
|
||||
|
@ -181,7 +181,7 @@ def setting():
|
|||
current_user.notification = True
|
||||
else:
|
||||
current_user.notification = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your notification preference has been updated", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
|
||||
|
@ -212,7 +212,7 @@ def setting():
|
|||
scheme = int(request.form.get("alias-generator-scheme"))
|
||||
if AliasGeneratorEnum.has_value(scheme):
|
||||
current_user.alias_generator = scheme
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your preference has been updated", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
|
||||
|
@ -249,7 +249,7 @@ def setting():
|
|||
current_user.default_alias_custom_domain_id = None
|
||||
current_user.default_alias_public_domain_id = None
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your preference has been updated", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
|
||||
|
@ -257,7 +257,7 @@ def setting():
|
|||
scheme = int(request.form.get("random-alias-suffix-generator"))
|
||||
if AliasSuffixEnum.has_value(scheme):
|
||||
current_user.random_alias_suffix = scheme
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your preference has been updated", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
|
||||
|
@ -266,9 +266,9 @@ def setting():
|
|||
if SenderFormatEnum.has_value(sender_format):
|
||||
current_user.sender_format = sender_format
|
||||
current_user.sender_format_updated_at = arrow.now()
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your sender format preference has been updated", "success")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
|
||||
elif request.form.get("form-name") == "replace-ra":
|
||||
|
@ -277,7 +277,7 @@ def setting():
|
|||
current_user.replace_reverse_alias = True
|
||||
else:
|
||||
current_user.replace_reverse_alias = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your preference has been updated", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
|
||||
|
@ -287,7 +287,7 @@ def setting():
|
|||
current_user.include_sender_in_reverse_alias = True
|
||||
else:
|
||||
current_user.include_sender_in_reverse_alias = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your preference has been updated", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
|
||||
|
@ -297,7 +297,7 @@ def setting():
|
|||
current_user.expand_alias_info = True
|
||||
else:
|
||||
current_user.expand_alias_info = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your preference has been updated", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
elif request.form.get("form-name") == "ignore-loop-email":
|
||||
|
@ -306,7 +306,7 @@ def setting():
|
|||
current_user.ignore_loop_email = True
|
||||
else:
|
||||
current_user.ignore_loop_email = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your preference has been updated", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
|
||||
|
@ -344,7 +344,7 @@ def send_reset_password_email(user):
|
|||
reset_password_code = ResetPasswordCode.create(
|
||||
user_id=user.id, code=random_string(60)
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
reset_password_link = f"{URL}/auth/reset_password?code={reset_password_code.code}"
|
||||
|
||||
|
@ -368,7 +368,7 @@ def resend_email_change():
|
|||
if email_change:
|
||||
# extend email change expiration
|
||||
email_change.expired = arrow.now().shift(hours=12)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_change_email_confirmation(current_user, email_change)
|
||||
flash("A confirmation email is on the way, please check your inbox", "success")
|
||||
|
@ -386,7 +386,7 @@ def cancel_email_change():
|
|||
email_change = EmailChange.get_by(user_id=current_user.id)
|
||||
if email_change:
|
||||
EmailChange.delete(email_change.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
flash("Your email change is cancelled", "success")
|
||||
return redirect(url_for("dashboard.setting"))
|
||||
else:
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from app.db import Session
|
||||
|
||||
"""
|
||||
Allow user to "unsubscribe", aka block an email alias
|
||||
"""
|
||||
|
@ -6,7 +8,6 @@ from flask import redirect, url_for, flash, request, render_template
|
|||
from flask_login import login_required, current_user
|
||||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.extensions import db
|
||||
from app.models import Alias
|
||||
|
||||
|
||||
|
@ -29,7 +30,7 @@ def unsubscribe(alias_id):
|
|||
if request.method == "POST":
|
||||
alias.enabled = False
|
||||
flash(f"Alias {alias.email} has been blocked", "success")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return redirect(url_for("dashboard.index", highlight_alias_id=alias.id))
|
||||
else: # ask user confirmation
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import scoped_session
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from app.config import DB_URI
|
||||
|
||||
engine = create_engine(DB_URI)
|
||||
connection = engine.connect()
|
||||
|
||||
Session = scoped_session(sessionmaker(bind=connection))
|
|
@ -8,9 +8,9 @@ from wtforms import StringField, validators, TextAreaField
|
|||
|
||||
from app import s3
|
||||
from app.config import ADMIN_EMAIL
|
||||
from app.db import Session
|
||||
from app.developer.base import developer_bp
|
||||
from app.email_utils import send_email
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import Client, RedirectUri, File
|
||||
from app.utils import random_string
|
||||
|
@ -55,13 +55,13 @@ def client_detail(client_id):
|
|||
|
||||
s3.upload_from_bytesio(file_path, BytesIO(form.icon.data.read()))
|
||||
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
LOG.d("upload file %s to s3", file)
|
||||
|
||||
client.icon_id = file.id
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash(f"{client.name} has been updated", "success")
|
||||
|
||||
|
@ -69,7 +69,7 @@ def client_detail(client_id):
|
|||
|
||||
if action == "submit" and approval_form.validate_on_submit():
|
||||
client.description = approval_form.description.data
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_email(
|
||||
ADMIN_EMAIL,
|
||||
|
@ -127,7 +127,7 @@ def client_detail_oauth_setting(client_id):
|
|||
for uri in uris:
|
||||
RedirectUri.create(client_id=client_id, uri=uri)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash(f"{client.name} has been updated", "success")
|
||||
|
||||
|
@ -178,7 +178,7 @@ def client_detail_advanced(client_id):
|
|||
# delete client
|
||||
client_name = client.name
|
||||
Client.delete(client.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
LOG.d("Remove client %s", client)
|
||||
flash(f"{client_name} has been deleted", "success")
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ from flask_login import current_user, login_required
|
|||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, validators
|
||||
|
||||
from app.db import Session
|
||||
from app.developer.base import developer_bp
|
||||
from app.extensions import db
|
||||
from app.models import Client
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ def new_client():
|
|||
|
||||
if form.validate_on_submit():
|
||||
client = Client.create_new(form.name.data, current_user.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
flash("Your app has been created", "success")
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ from app.config import (
|
|||
MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS,
|
||||
MAX_ACTIVITY_DURING_MINUTE_PER_MAILBOX,
|
||||
)
|
||||
from app.db import Session
|
||||
from app.email_utils import is_reply_email
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import Alias, EmailLog, Contact
|
||||
|
||||
|
@ -16,7 +16,7 @@ def rate_limited_for_alias(alias: Alias) -> bool:
|
|||
|
||||
# get the nb of activity on this alias
|
||||
nb_activity = (
|
||||
db.session.query(EmailLog)
|
||||
Session.query(EmailLog)
|
||||
.join(Contact, EmailLog.contact_id == Contact.id)
|
||||
.filter(
|
||||
Contact.alias_id == alias.id,
|
||||
|
@ -42,7 +42,7 @@ def rate_limited_for_mailbox(alias: Alias) -> bool:
|
|||
|
||||
# get nb of activity on this mailbox
|
||||
nb_activity = (
|
||||
db.session.query(EmailLog)
|
||||
Session.query(EmailLog)
|
||||
.join(Contact, EmailLog.contact_id == Contact.id)
|
||||
.join(Alias, Contact.alias_id == Alias.id)
|
||||
.filter(
|
||||
|
|
|
@ -53,9 +53,9 @@ from app.config import (
|
|||
TEMP_DIR,
|
||||
ALIAS_AUTOMATIC_DISABLE,
|
||||
)
|
||||
from app.db import Session
|
||||
from app.dns_utils import get_mx_domains
|
||||
from app.email import headers
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
Mailbox,
|
||||
|
@ -324,7 +324,7 @@ def send_email_with_rate_control(
|
|||
to_email = sanitize_email(to_email)
|
||||
min_dt = arrow.now().shift(days=-1 * nb_day)
|
||||
nb_alert = (
|
||||
SentAlert.query.filter_by(alert_type=alert_type, to_email=to_email)
|
||||
SentAlert.filter_by(alert_type=alert_type, to_email=to_email)
|
||||
.filter(SentAlert.created_at > min_dt)
|
||||
.count()
|
||||
)
|
||||
|
@ -340,7 +340,7 @@ def send_email_with_rate_control(
|
|||
return False
|
||||
|
||||
SentAlert.create(user_id=user.id, alert_type=alert_type, to_email=to_email)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
if ignore_smtp_error:
|
||||
try:
|
||||
|
@ -369,9 +369,7 @@ def send_email_at_most_times(
|
|||
Return true if the email is sent, otherwise False
|
||||
"""
|
||||
to_email = sanitize_email(to_email)
|
||||
nb_alert = SentAlert.query.filter_by(
|
||||
alert_type=alert_type, to_email=to_email
|
||||
).count()
|
||||
nb_alert = SentAlert.filter_by(alert_type=alert_type, to_email=to_email).count()
|
||||
|
||||
if nb_alert >= max_times:
|
||||
LOG.w(
|
||||
|
@ -383,7 +381,7 @@ def send_email_at_most_times(
|
|||
return False
|
||||
|
||||
SentAlert.create(user_id=user.id, alert_type=alert_type, to_email=to_email)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
send_email(to_email, subject, plaintext, html)
|
||||
return True
|
||||
|
||||
|
@ -1036,7 +1034,7 @@ def should_disable(alias: Alias) -> bool:
|
|||
|
||||
yesterday = arrow.now().shift(days=-1)
|
||||
nb_bounced_last_24h = (
|
||||
db.session.query(EmailLog)
|
||||
Session.query(EmailLog)
|
||||
.filter(
|
||||
EmailLog.bounced.is_(True),
|
||||
EmailLog.is_reply.is_(False),
|
||||
|
@ -1054,7 +1052,7 @@ def should_disable(alias: Alias) -> bool:
|
|||
elif nb_bounced_last_24h > 5:
|
||||
one_week_ago = arrow.now().shift(days=-8)
|
||||
nb_bounced_7d_1d = (
|
||||
db.session.query(EmailLog)
|
||||
Session.query(EmailLog)
|
||||
.filter(
|
||||
EmailLog.bounced.is_(True),
|
||||
EmailLog.is_reply.is_(False),
|
||||
|
@ -1075,7 +1073,7 @@ def should_disable(alias: Alias) -> bool:
|
|||
# alias level
|
||||
# if bounces at least 9 days in the last 10 days -> disable alias
|
||||
query = (
|
||||
db.session.query(
|
||||
Session.query(
|
||||
func.date(EmailLog.created_at).label("date"),
|
||||
func.count(EmailLog.id).label("count"),
|
||||
)
|
||||
|
@ -1097,7 +1095,7 @@ def should_disable(alias: Alias) -> bool:
|
|||
|
||||
# account level
|
||||
query = (
|
||||
db.session.query(
|
||||
Session.query(
|
||||
func.date(EmailLog.created_at).label("date"),
|
||||
func.count(EmailLog.id).label("count"),
|
||||
)
|
||||
|
|
|
@ -3,8 +3,8 @@ import csv
|
|||
import requests
|
||||
|
||||
from app import s3
|
||||
from app.db import Session
|
||||
from app.email_utils import get_email_domain_part
|
||||
from app.extensions import db
|
||||
from app.models import (
|
||||
Alias,
|
||||
AliasMailbox,
|
||||
|
@ -23,7 +23,7 @@ def handle_batch_import(batch_import: BatchImport):
|
|||
user = batch_import.user
|
||||
|
||||
batch_import.processed = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Start batch import for %s %s", batch_import, user)
|
||||
file_url = s3.get_url(batch_import.file.path)
|
||||
|
@ -97,5 +97,5 @@ def import_from_csv(batch_import: BatchImport, user: User, lines):
|
|||
AliasMailbox.create(
|
||||
alias_id=alias.id, mailbox_id=mailboxes[i], commit=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
LOG.d("Add %s to mailbox %s", alias, mailboxes[i])
|
||||
|
|
1163
app/models.py
1163
app/models.py
File diff suppressed because it is too large
Load Diff
|
@ -8,7 +8,7 @@ from itsdangerous import SignatureExpired
|
|||
from app.alias_utils import check_alias_prefix
|
||||
from app.config import EMAIL_DOMAIN
|
||||
from app.dashboard.views.custom_alias import signer, get_available_suffixes
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.jose_utils import make_id_token
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
|
@ -206,7 +206,7 @@ def authorize():
|
|||
if domain:
|
||||
alias.custom_domain_id = domain.id
|
||||
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
flash(f"Alias {full_alias} has been created", "success")
|
||||
# only happen if the request has been "hacked"
|
||||
else:
|
||||
|
@ -224,7 +224,7 @@ def authorize():
|
|||
user_id=current_user.id,
|
||||
mailbox_id=current_user.default_mailbox_id,
|
||||
)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
|
||||
suggested_name = request.form.get("suggested-name")
|
||||
custom_name = request.form.get("custom-name")
|
||||
|
@ -247,7 +247,7 @@ def authorize():
|
|||
LOG.d("use default avatar for user %s client %s", current_user, client)
|
||||
client_user.default_avatar = True
|
||||
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
LOG.d("create client-user for client %s, user %s", client, current_user)
|
||||
|
||||
redirect_args = {}
|
||||
|
@ -284,7 +284,7 @@ def authorize():
|
|||
access_token=generate_access_token(),
|
||||
response_type=response_types_to_str(response_types),
|
||||
)
|
||||
db.session.add(oauth_token)
|
||||
Session.add(oauth_token)
|
||||
redirect_args["access_token"] = oauth_token.access_token
|
||||
|
||||
if ResponseType.ID_TOKEN in response_types:
|
||||
|
@ -295,7 +295,7 @@ def authorize():
|
|||
auth_code.code if auth_code else None,
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# should all params appended the url using fragment (#) or query
|
||||
fragment = False
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from flask import request, jsonify
|
||||
from flask_cors import cross_origin
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.jose_utils import make_id_token
|
||||
from app.log import LOG
|
||||
from app.models import Client, AuthorizationCode, OauthToken, ClientUser
|
||||
|
@ -49,7 +49,7 @@ def token():
|
|||
return jsonify(error=f"no such authorization code {code}"), 400
|
||||
elif auth_code.is_expired():
|
||||
AuthorizationCode.delete(auth_code.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
LOG.d("delete expired authorization code:%s", auth_code)
|
||||
return jsonify(error=f"{code} already expired"), 400
|
||||
|
||||
|
@ -94,6 +94,6 @@ def token():
|
|||
# Auth code can be used only once
|
||||
AuthorizationCode.delete(auth_code.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
return jsonify(res)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from flask import request, jsonify
|
||||
from flask_cors import cross_origin
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import OauthToken, ClientUser
|
||||
from app.oauth.base import oauth_bp
|
||||
|
@ -27,7 +27,7 @@ def user_info():
|
|||
elif oauth_token.is_expired():
|
||||
LOG.d("delete oauth token %s", oauth_token)
|
||||
OauthToken.delete(oauth_token.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return jsonify(error="Expired access token"), 400
|
||||
|
||||
client_user = ClientUser.get_or_create(
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import unicodedata
|
||||
|
||||
import bcrypt
|
||||
|
||||
from app.extensions import db
|
||||
import sqlalchemy as sa
|
||||
import unicodedata
|
||||
|
||||
_NORMALIZATION_FORM = "NFKC"
|
||||
|
||||
|
||||
class PasswordOracle:
|
||||
password = db.Column(db.String(128), nullable=True)
|
||||
password = sa.Column(sa.String(128), nullable=True)
|
||||
|
||||
def set_password(self, password):
|
||||
password = unicodedata.normalize(_NORMALIZATION_FORM, password)
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
https://github.com/petermat/spamassassin_client
|
||||
"""
|
||||
import logging
|
||||
import re2 as re
|
||||
import select
|
||||
import socket
|
||||
from io import BytesIO
|
||||
|
||||
import re2 as re
|
||||
import select
|
||||
|
||||
from app.log import LOG
|
||||
|
||||
divider_pattern = re.compile(br"^(.*?)\r?\n(.*?)\r?\n\r?\n", re.DOTALL)
|
||||
|
|
122
cron.py
122
cron.py
|
@ -22,6 +22,7 @@ from app.config import (
|
|||
HIBP_API_KEYS,
|
||||
HIBP_SCAN_INTERVAL_DAYS,
|
||||
)
|
||||
from app.db import Session
|
||||
from app.dns_utils import get_mx_domains
|
||||
from app.email_utils import (
|
||||
send_email,
|
||||
|
@ -33,7 +34,6 @@ from app.email_utils import (
|
|||
is_valid_email,
|
||||
get_email_domain_part,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
Subscription,
|
||||
|
@ -63,7 +63,7 @@ from server import create_app
|
|||
|
||||
|
||||
def notify_trial_end():
|
||||
for user in User.query.filter(
|
||||
for user in User.filter(
|
||||
User.activated.is_(True), User.trial_end.isnot(None), User.lifetime.is_(False)
|
||||
).all():
|
||||
if user.in_trial() and arrow.now().shift(
|
||||
|
@ -78,27 +78,27 @@ def delete_logs():
|
|||
delete_refused_emails()
|
||||
delete_old_monitoring()
|
||||
|
||||
for t in TransactionalEmail.query.filter(
|
||||
for t in TransactionalEmail.filter(
|
||||
TransactionalEmail.created_at < arrow.now().shift(days=-7)
|
||||
):
|
||||
TransactionalEmail.delete(t.id)
|
||||
|
||||
for b in Bounce.query.filter(Bounce.created_at < arrow.now().shift(days=-7)):
|
||||
for b in Bounce.filter(Bounce.created_at < arrow.now().shift(days=-7)):
|
||||
Bounce.delete(b.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Delete EmailLog older than 2 weeks")
|
||||
|
||||
max_dt = arrow.now().shift(weeks=-2)
|
||||
nb_deleted = EmailLog.query.filter(EmailLog.created_at < max_dt).delete()
|
||||
db.session.commit()
|
||||
nb_deleted = EmailLog.filter(EmailLog.created_at < max_dt).delete()
|
||||
Session.commit()
|
||||
|
||||
LOG.i("Delete %s email logs", nb_deleted)
|
||||
|
||||
|
||||
def delete_refused_emails():
|
||||
for refused_email in RefusedEmail.query.filter_by(deleted=False).all():
|
||||
for refused_email in RefusedEmail.filter_by(deleted=False).all():
|
||||
if arrow.now().shift(days=1) > refused_email.delete_at >= arrow.now():
|
||||
LOG.d("Delete refused email %s", refused_email)
|
||||
if refused_email.path:
|
||||
|
@ -109,14 +109,14 @@ def delete_refused_emails():
|
|||
# do not set path and full_report_path to null
|
||||
# so we can check later that the files are indeed deleted
|
||||
refused_email.deleted = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Finish delete_refused_emails")
|
||||
|
||||
|
||||
def notify_premium_end():
|
||||
"""sent to user who has canceled their subscription and who has their subscription ending soon"""
|
||||
for sub in Subscription.query.filter_by(cancelled=True).all():
|
||||
for sub in Subscription.filter_by(cancelled=True).all():
|
||||
if (
|
||||
arrow.now().shift(days=3).date()
|
||||
> sub.next_bill_date
|
||||
|
@ -146,7 +146,7 @@ def notify_premium_end():
|
|||
|
||||
|
||||
def notify_manual_sub_end():
|
||||
for manual_sub in ManualSubscription.query.all():
|
||||
for manual_sub in ManualSubscription.all():
|
||||
need_reminder = False
|
||||
if arrow.now().shift(days=14) > manual_sub.end_at > arrow.now().shift(days=13):
|
||||
need_reminder = True
|
||||
|
@ -172,7 +172,7 @@ def notify_manual_sub_end():
|
|||
)
|
||||
|
||||
extend_subscription_url = URL + "/dashboard/coinbase_checkout"
|
||||
for coinbase_subscription in CoinbaseSubscription.query.all():
|
||||
for coinbase_subscription in CoinbaseSubscription.all():
|
||||
need_reminder = False
|
||||
if (
|
||||
arrow.now().shift(days=14)
|
||||
|
@ -211,7 +211,7 @@ def notify_manual_sub_end():
|
|||
def poll_apple_subscription():
|
||||
"""Poll Apple API to update AppleSubscription"""
|
||||
# todo: only near the end of the subscription
|
||||
for apple_sub in AppleSubscription.query.all():
|
||||
for apple_sub in AppleSubscription.all():
|
||||
user = apple_sub.user
|
||||
verify_receipt(apple_sub.receipt_data, user, APPLE_API_SECRET)
|
||||
verify_receipt(apple_sub.receipt_data, user, MACAPP_APPLE_API_SECRET)
|
||||
|
@ -224,49 +224,49 @@ def compute_metric2() -> Metric2:
|
|||
_24h_ago = now.shift(days=-1)
|
||||
|
||||
nb_referred_user_paid = 0
|
||||
for user in User.query.filter(User.referral_id.isnot(None)):
|
||||
for user in User.filter(User.referral_id.isnot(None)):
|
||||
if user.is_paid():
|
||||
nb_referred_user_paid += 1
|
||||
|
||||
return Metric2.create(
|
||||
date=now,
|
||||
# user stats
|
||||
nb_user=User.query.count(),
|
||||
nb_activated_user=User.query.filter_by(activated=True).count(),
|
||||
nb_user=User.count(),
|
||||
nb_activated_user=User.filter_by(activated=True).count(),
|
||||
# subscription stats
|
||||
nb_premium=Subscription.query.filter(Subscription.cancelled.is_(False)).count(),
|
||||
nb_cancelled_premium=Subscription.query.filter(
|
||||
nb_premium=Subscription.filter(Subscription.cancelled.is_(False)).count(),
|
||||
nb_cancelled_premium=Subscription.filter(
|
||||
Subscription.cancelled.is_(True)
|
||||
).count(),
|
||||
# todo: filter by expires_date > now
|
||||
nb_apple_premium=AppleSubscription.query.count(),
|
||||
nb_manual_premium=ManualSubscription.query.filter(
|
||||
nb_apple_premium=AppleSubscription.count(),
|
||||
nb_manual_premium=ManualSubscription.filter(
|
||||
ManualSubscription.end_at > now,
|
||||
ManualSubscription.is_giveaway.is_(False),
|
||||
).count(),
|
||||
nb_coinbase_premium=CoinbaseSubscription.query.filter(
|
||||
nb_coinbase_premium=CoinbaseSubscription.filter(
|
||||
CoinbaseSubscription.end_at > now
|
||||
).count(),
|
||||
# referral stats
|
||||
nb_referred_user=User.query.filter(User.referral_id.isnot(None)).count(),
|
||||
nb_referred_user=User.filter(User.referral_id.isnot(None)).count(),
|
||||
nb_referred_user_paid=nb_referred_user_paid,
|
||||
nb_alias=Alias.query.count(),
|
||||
nb_alias=Alias.count(),
|
||||
# email log stats
|
||||
nb_forward_last_24h=EmailLog.query.filter(EmailLog.created_at > _24h_ago)
|
||||
nb_forward_last_24h=EmailLog.filter(EmailLog.created_at > _24h_ago)
|
||||
.filter_by(bounced=False, is_spam=False, is_reply=False, blocked=False)
|
||||
.count(),
|
||||
nb_bounced_last_24h=EmailLog.query.filter(EmailLog.created_at > _24h_ago)
|
||||
nb_bounced_last_24h=EmailLog.filter(EmailLog.created_at > _24h_ago)
|
||||
.filter_by(bounced=True)
|
||||
.count(),
|
||||
nb_reply_last_24h=EmailLog.query.filter(EmailLog.created_at > _24h_ago)
|
||||
nb_reply_last_24h=EmailLog.filter(EmailLog.created_at > _24h_ago)
|
||||
.filter_by(is_reply=True)
|
||||
.count(),
|
||||
nb_block_last_24h=EmailLog.query.filter(EmailLog.created_at > _24h_ago)
|
||||
nb_block_last_24h=EmailLog.filter(EmailLog.created_at > _24h_ago)
|
||||
.filter_by(blocked=True)
|
||||
.count(),
|
||||
# other stats
|
||||
nb_verified_custom_domain=CustomDomain.query.filter_by(verified=True).count(),
|
||||
nb_app=Client.query.count(),
|
||||
nb_verified_custom_domain=CustomDomain.filter_by(verified=True).count(),
|
||||
nb_app=Client.count(),
|
||||
commit=True,
|
||||
)
|
||||
|
||||
|
@ -309,7 +309,7 @@ def bounce_report() -> List[Tuple[str, int]]:
|
|||
"""
|
||||
min_dt = arrow.now().shift(days=-1)
|
||||
query = (
|
||||
db.session.query(User.email, func.count(EmailLog.id).label("count"))
|
||||
Session.query(User.email, func.count(EmailLog.id).label("count"))
|
||||
.join(EmailLog, EmailLog.user_id == User.id)
|
||||
.filter(EmailLog.bounced, EmailLog.created_at > min_dt)
|
||||
.group_by(User.email)
|
||||
|
@ -354,7 +354,7 @@ def alias_creation_report() -> List[Tuple[str, int]]:
|
|||
"""
|
||||
min_dt = arrow.now().shift(days=-7)
|
||||
query = (
|
||||
db.session.query(
|
||||
Session.query(
|
||||
User.email,
|
||||
func.count(Alias.id).label("count"),
|
||||
func.date(Alias.created_at).label("date"),
|
||||
|
@ -381,7 +381,7 @@ def stats():
|
|||
|
||||
stats_today = compute_metric2()
|
||||
stats_yesterday = (
|
||||
Metric2.query.filter(Metric2.date < stats_today.date)
|
||||
Metric2.filter(Metric2.date < stats_today.date)
|
||||
.order_by(Metric2.date.desc())
|
||||
.first()
|
||||
)
|
||||
|
@ -442,13 +442,13 @@ nb_referred_user_upgrade: {stats_today.nb_referred_user_paid} - {increase_percen
|
|||
|
||||
def migrate_domain_trash():
|
||||
"""Move aliases from global trash to domain trash if applicable"""
|
||||
for deleted_alias in DeletedAlias.query.all():
|
||||
for deleted_alias in DeletedAlias.all():
|
||||
alias_domain = get_email_domain_part(deleted_alias.email)
|
||||
if not SLDomain.get_by(domain=alias_domain):
|
||||
custom_domain = CustomDomain.get_by(domain=alias_domain)
|
||||
if custom_domain:
|
||||
LOG.e("move %s to domain %s trash", deleted_alias, custom_domain)
|
||||
db.session.add(
|
||||
Session.add(
|
||||
DomainDeletedAlias(
|
||||
user_id=custom_domain.user_id,
|
||||
email=deleted_alias.email,
|
||||
|
@ -458,13 +458,13 @@ def migrate_domain_trash():
|
|||
)
|
||||
DeletedAlias.delete(deleted_alias.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
|
||||
def set_custom_domain_for_alias():
|
||||
"""Go through all aliases and make sure custom_domain is correctly set"""
|
||||
sl_domains = [sl_domain.domain for sl_domain in SLDomain.query.all()]
|
||||
for alias in Alias.query.filter(Alias.custom_domain_id.is_(None)):
|
||||
sl_domains = [sl_domain.domain for sl_domain in SLDomain.all()]
|
||||
for alias in Alias.filter(Alias.custom_domain_id.is_(None)):
|
||||
if (
|
||||
not any(alias.email.endswith(f"@{sl_domain}") for sl_domain in sl_domains)
|
||||
and not alias.custom_domain_id
|
||||
|
@ -477,7 +477,7 @@ def set_custom_domain_for_alias():
|
|||
else: # phantom domain
|
||||
LOG.d("phantom domain %s %s %s", alias.user, alias, alias.enabled)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
|
||||
def sanity_check():
|
||||
|
@ -487,7 +487,7 @@ def sanity_check():
|
|||
- detect if there's mailbox that's using a invalid domain
|
||||
"""
|
||||
mailbox_ids = (
|
||||
db.session.query(Mailbox.id)
|
||||
Session.query(Mailbox.id)
|
||||
.filter(Mailbox.verified.is_(True), Mailbox.disabled.is_(False))
|
||||
.all()
|
||||
)
|
||||
|
@ -544,23 +544,23 @@ def sanity_check():
|
|||
else: # reset nb check
|
||||
mailbox.nb_failed_checks = 0
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
for user in User.filter_by(activated=True).all():
|
||||
if sanitize_email(user.email) != user.email:
|
||||
LOG.e("%s does not have sanitized email", user)
|
||||
|
||||
for alias in Alias.query.all():
|
||||
for alias in Alias.all():
|
||||
if sanitize_email(alias.email) != alias.email:
|
||||
LOG.e("Alias %s email not sanitized", alias)
|
||||
|
||||
if alias.name and "\n" in alias.name:
|
||||
alias.name = alias.name.replace("\n", "")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
LOG.e("Alias %s name contains linebreak %s", alias, alias.name)
|
||||
|
||||
contact_email_sanity_date = arrow.get("2021-01-12")
|
||||
for contact in Contact.query.all():
|
||||
for contact in Contact.all():
|
||||
if sanitize_email(contact.reply_email) != contact.reply_email:
|
||||
LOG.e("Contact %s reply-email not sanitized", contact)
|
||||
|
||||
|
@ -573,13 +573,13 @@ def sanity_check():
|
|||
if not contact.invalid_email and not is_valid_email(contact.website_email):
|
||||
LOG.e("%s invalid email", contact)
|
||||
contact.invalid_email = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
for mailbox in Mailbox.query.all():
|
||||
for mailbox in Mailbox.all():
|
||||
if sanitize_email(mailbox.email) != mailbox.email:
|
||||
LOG.e("Mailbox %s address not sanitized", mailbox)
|
||||
|
||||
for contact in Contact.query.all():
|
||||
for contact in Contact.all():
|
||||
if normalize_reply_email(contact.reply_email) != contact.reply_email:
|
||||
LOG.e(
|
||||
"Contact %s reply email is not normalized %s",
|
||||
|
@ -587,7 +587,7 @@ def sanity_check():
|
|||
contact.reply_email,
|
||||
)
|
||||
|
||||
for domain in CustomDomain.query.all():
|
||||
for domain in CustomDomain.all():
|
||||
if domain.name and "\n" in domain.name:
|
||||
LOG.e("Domain %s name contain linebreak %s", domain, domain.name)
|
||||
|
||||
|
@ -600,9 +600,7 @@ def sanity_check():
|
|||
def check_custom_domain():
|
||||
LOG.d("Check verified domain for DNS issues")
|
||||
|
||||
for custom_domain in CustomDomain.query.filter_by(
|
||||
verified=True
|
||||
): # type: CustomDomain
|
||||
for custom_domain in CustomDomain.filter_by(verified=True): # type: CustomDomain
|
||||
mx_domains = get_mx_domains(custom_domain.domain)
|
||||
|
||||
if sorted(mx_domains) != sorted(EMAIL_SERVERS_WITH_PRIORITY):
|
||||
|
@ -644,7 +642,7 @@ def check_custom_domain():
|
|||
# reset checks
|
||||
custom_domain.nb_failed_checks = 0
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
|
||||
def delete_old_monitoring():
|
||||
|
@ -652,8 +650,8 @@ def delete_old_monitoring():
|
|||
Delete old monitoring records
|
||||
"""
|
||||
max_time = arrow.now().shift(days=-30)
|
||||
nb_row = Monitoring.query.filter(Monitoring.created_at < max_time).delete()
|
||||
db.session.commit()
|
||||
nb_row = Monitoring.filter(Monitoring.created_at < max_time).delete()
|
||||
Session.commit()
|
||||
LOG.d("delete monitoring records older than %s, nb row %s", max_time, nb_row)
|
||||
|
||||
|
||||
|
@ -713,8 +711,8 @@ async def _hibp_check(api_key, queue):
|
|||
return
|
||||
|
||||
alias.hibp_last_check = arrow.utcnow()
|
||||
db.session.add(alias)
|
||||
db.session.commit()
|
||||
Session.add(alias)
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Updated breaches info for %s", alias)
|
||||
|
||||
|
@ -738,14 +736,14 @@ async def check_hibp():
|
|||
hibp_entry.date = arrow.get(entry["BreachDate"])
|
||||
hibp_entry.description = entry["Description"]
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
LOG.d("Updated list of known breaches")
|
||||
|
||||
LOG.d("Preparing list of aliases to check")
|
||||
queue = asyncio.Queue()
|
||||
max_date = arrow.now().shift(days=-HIBP_SCAN_INTERVAL_DAYS)
|
||||
for alias in (
|
||||
Alias.query.filter(
|
||||
Alias.filter(
|
||||
or_(Alias.hibp_last_check.is_(None), Alias.hibp_last_check < max_date)
|
||||
)
|
||||
.filter(Alias.enabled)
|
||||
|
@ -782,19 +780,19 @@ def notify_hibp():
|
|||
"""
|
||||
# to get a list of users that have at least a breached alias
|
||||
alias_query = (
|
||||
db.session.query(Alias)
|
||||
Session.query(Alias)
|
||||
.options(joinedload(Alias.hibp_breaches))
|
||||
.filter(Alias.hibp_breaches.any())
|
||||
.filter(Alias.id.notin_(db.session.query(HibpNotifiedAlias.alias_id)))
|
||||
.filter(Alias.id.notin_(Session.query(HibpNotifiedAlias.alias_id)))
|
||||
.distinct(Alias.user_id)
|
||||
.all()
|
||||
)
|
||||
|
||||
user_ids = [alias.user_id for alias in alias_query]
|
||||
|
||||
for user in User.query.filter(User.id.in_(user_ids)):
|
||||
for user in User.filter(User.id.in_(user_ids)):
|
||||
breached_aliases = (
|
||||
db.session.query(Alias)
|
||||
Session.query(Alias)
|
||||
.options(joinedload(Alias.hibp_breaches))
|
||||
.filter(Alias.hibp_breaches.any(), Alias.user_id == user.id)
|
||||
.all()
|
||||
|
@ -824,7 +822,7 @@ def notify_hibp():
|
|||
# add the breached aliases to HibpNotifiedAlias to avoid sending another email
|
||||
for alias in breached_aliases:
|
||||
HibpNotifiedAlias.create(user_id=user.id, alias_id=alias.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -85,6 +85,7 @@ from app.config import (
|
|||
ALERT_YAHOO_COMPLAINT,
|
||||
TEMP_DIR,
|
||||
)
|
||||
from app.db import Session
|
||||
from app.email import status, headers
|
||||
from app.email.rate_limit import rate_limited
|
||||
from app.email.spam import get_spam_score
|
||||
|
@ -123,7 +124,6 @@ from app.email_utils import (
|
|||
parse_full_address,
|
||||
get_orig_message_from_yahoo_complaint,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG, set_message_id
|
||||
from app.models import (
|
||||
Alias,
|
||||
|
@ -141,7 +141,6 @@ from app.utils import sanitize_email
|
|||
from init_app import load_pgp_public_keys
|
||||
from server import create_app, create_light_app
|
||||
|
||||
|
||||
newrelic_app = None
|
||||
if NEWRELIC_CONFIG_PATH:
|
||||
newrelic.agent.initialize(NEWRELIC_CONFIG_PATH)
|
||||
|
@ -157,10 +156,7 @@ def new_app():
|
|||
@app.teardown_appcontext
|
||||
def shutdown_session(response_or_exc):
|
||||
# same as shutdown_session() in flask-sqlalchemy but this is not enough
|
||||
db.session.remove()
|
||||
|
||||
# dispose the engine too
|
||||
db.engine.dispose()
|
||||
Session.remove()
|
||||
|
||||
return app
|
||||
|
||||
|
@ -210,7 +206,7 @@ def get_or_create_contact(from_header: str, mail_from: str, alias: Alias) -> Con
|
|||
contact_name,
|
||||
)
|
||||
contact.name = contact_name
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# contact created in the past does not have mail_from and from_header field
|
||||
if not contact.mail_from and mail_from:
|
||||
|
@ -221,7 +217,7 @@ def get_or_create_contact(from_header: str, mail_from: str, alias: Alias) -> Con
|
|||
mail_from,
|
||||
)
|
||||
contact.mail_from = mail_from
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
else:
|
||||
LOG.d(
|
||||
"create contact %s for alias %s",
|
||||
|
@ -244,10 +240,10 @@ def get_or_create_contact(from_header: str, mail_from: str, alias: Alias) -> Con
|
|||
LOG.d("Create a contact with invalid email for %s", alias)
|
||||
contact.invalid_email = True
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
except IntegrityError:
|
||||
LOG.w("Contact %s %s already exist", alias, contact_email)
|
||||
db.session.rollback()
|
||||
Session.rollback()
|
||||
contact = Contact.get_by(alias_id=alias.id, website_email=contact_email)
|
||||
|
||||
return contact
|
||||
|
@ -291,10 +287,10 @@ def get_or_create_reply_to_contact(
|
|||
name=contact_name,
|
||||
reply_email=generate_reply_email(contact_address, alias.user),
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
except IntegrityError:
|
||||
LOG.w("Contact %s %s already exist", alias, contact_address)
|
||||
db.session.rollback()
|
||||
Session.rollback()
|
||||
contact = Contact.get_by(alias_id=alias.id, website_email=contact_address)
|
||||
|
||||
return contact
|
||||
|
@ -341,7 +337,7 @@ def replace_header_when_forward(msg: Message, alias: Alias, header: str):
|
|||
full_address.display_name,
|
||||
)
|
||||
contact.name = full_address.display_name
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
else:
|
||||
LOG.d(
|
||||
"create contact for alias %s and email %s, header %s",
|
||||
|
@ -359,10 +355,10 @@ def replace_header_when_forward(msg: Message, alias: Alias, header: str):
|
|||
reply_email=generate_reply_email(contact_email, alias.user),
|
||||
is_cc=header.lower() == "cc",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
except IntegrityError:
|
||||
LOG.w("Contact %s %s already exist", alias, contact_email)
|
||||
db.session.rollback()
|
||||
Session.rollback()
|
||||
contact = Contact.get_by(alias_id=alias.id, website_email=contact_email)
|
||||
|
||||
new_addrs.append(contact.new_addr())
|
||||
|
@ -501,7 +497,7 @@ def handle_email_sent_to_ourself(alias, mailbox, msg: Message, user):
|
|||
refused_email = RefusedEmail.create(
|
||||
path=None, full_report_path=full_report_path, user_id=alias.user_id
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
LOG.d("Create refused email %s", refused_email)
|
||||
# link available for 6 days as it gets deleted in 7 days
|
||||
refused_email_url = refused_email.get_url(expires_in=518400)
|
||||
|
@ -588,7 +584,7 @@ def handle_forward(envelope, msg: Message, rcpt_to: str) -> List[Tuple[bool, str
|
|||
alias_id=contact.alias_id,
|
||||
commit=True,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
# do not return 5** to allow user to receive emails later when alias is enabled
|
||||
return [(True, status.E200)]
|
||||
|
||||
|
@ -695,7 +691,7 @@ def forward_email_to_mailbox(
|
|||
spam_report,
|
||||
)
|
||||
email_log.spam_score = spam_score
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
if (user.max_spam_score and spam_score > user.max_spam_score) or (
|
||||
not user.max_spam_score and spam_score > MAX_SPAM_SCORE
|
||||
|
@ -716,7 +712,7 @@ def forward_email_to_mailbox(
|
|||
)
|
||||
email_log.is_spam = True
|
||||
email_log.spam_status = spam_status
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
handle_spam(contact, alias, msg, user, mailbox, email_log)
|
||||
return False, status.E519
|
||||
|
@ -846,7 +842,7 @@ def forward_email_to_mailbox(
|
|||
else:
|
||||
return False, status.E521
|
||||
else:
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
return True, status.E200
|
||||
|
||||
|
||||
|
@ -963,7 +959,7 @@ def handle_reply(envelope, msg: Message, rcpt_to: str) -> (bool, str):
|
|||
|
||||
email_log.is_spam = True
|
||||
email_log.spam_status = spam_status
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
handle_spam(contact, alias, msg, user, mailbox, email_log, is_reply=True)
|
||||
return False, status.E506
|
||||
|
@ -1003,11 +999,11 @@ def handle_reply(envelope, msg: Message, rcpt_to: str) -> (bool, str):
|
|||
)
|
||||
# to not save the email_log
|
||||
EmailLog.delete(email_log.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
# return 421 so the client can retry later
|
||||
return False, status.E402
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# make the email comes from alias
|
||||
from_header = alias.email
|
||||
|
@ -1065,7 +1061,7 @@ def handle_reply(envelope, msg: Message, rcpt_to: str) -> (bool, str):
|
|||
)
|
||||
except Exception:
|
||||
# to not save the email_log
|
||||
db.session.rollback()
|
||||
Session.rollback()
|
||||
|
||||
LOG.w("Cannot send email from %s to %s", alias, contact)
|
||||
send_email(
|
||||
|
@ -1218,13 +1214,13 @@ def handle_bounce_forward_phase(msg: Message, email_log: EmailLog):
|
|||
refused_email = RefusedEmail.create(
|
||||
path=file_path, full_report_path=full_report_path, user_id=user.id
|
||||
)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
LOG.d("Create refused email %s", refused_email)
|
||||
|
||||
email_log.bounced = True
|
||||
email_log.refused_email_id = refused_email.id
|
||||
email_log.bounced_mailbox_id = mailbox.id
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
refused_email_url = f"{URL}/dashboard/refused_email?highlight_id={email_log.id}"
|
||||
|
||||
|
@ -1268,7 +1264,7 @@ def handle_bounce_forward_phase(msg: Message, email_log: EmailLog):
|
|||
alias,
|
||||
)
|
||||
alias.enabled = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_email_with_rate_control(
|
||||
user,
|
||||
|
@ -1411,7 +1407,7 @@ def handle_bounce_reply_phase(envelope, msg: Message, email_log: EmailLog):
|
|||
|
||||
email_log.bounced_mailbox_id = mailbox.id
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
refused_email_url = f"{URL}/dashboard/refused_email?highlight_id={email_log.id}"
|
||||
|
||||
|
@ -1469,10 +1465,10 @@ def handle_spam(
|
|||
refused_email = RefusedEmail.create(
|
||||
path=file_path, full_report_path=full_report_path, user_id=user.id
|
||||
)
|
||||
db.session.flush()
|
||||
Session.flush()
|
||||
|
||||
email_log.refused_email_id = refused_email.id
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Create spam email %s", refused_email)
|
||||
|
||||
|
@ -1574,7 +1570,7 @@ def handle_unsubscribe(envelope: Envelope, msg: Message) -> str:
|
|||
|
||||
# Sender is owner of this alias
|
||||
alias.enabled = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
user = alias.user
|
||||
|
||||
enable_alias_url = URL + f"/dashboard/?highlight_alias_id={alias.id}"
|
||||
|
@ -1611,7 +1607,7 @@ def handle_unsubscribe_user(user_id: int, mail_from: str) -> str:
|
|||
return status.E511
|
||||
|
||||
user.notification = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_email(
|
||||
user.email,
|
||||
|
@ -1676,7 +1672,7 @@ def handle_bounce(envelope, email_log: EmailLog, msg: Message) -> str:
|
|||
alias = contact.alias
|
||||
|
||||
email_log.auto_replied = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# replace the BOUNCE_EMAIL by alias in To field
|
||||
add_or_replace_header(msg, "To", alias.email)
|
||||
|
@ -1871,8 +1867,8 @@ def handle(envelope: Envelope) -> str:
|
|||
"total number email log on %s, %s is %s, %s",
|
||||
alias,
|
||||
alias.user,
|
||||
EmailLog.query.filter(EmailLog.alias_id == alias.id).count(),
|
||||
EmailLog.query.filter(EmailLog.user_id == alias.user_id).count(),
|
||||
EmailLog.filter(EmailLog.alias_id == alias.id).count(),
|
||||
EmailLog.filter(EmailLog.user_id == alias.user_id).count(),
|
||||
)
|
||||
|
||||
if should_ignore_bounce(envelope.mail_from):
|
||||
|
|
15
init_app.py
15
init_app.py
|
@ -1,15 +1,14 @@
|
|||
"""Initial loading script"""
|
||||
from app.config import ALIAS_DOMAINS, PREMIUM_ALIAS_DOMAINS
|
||||
from app.models import Mailbox, Contact, SLDomain
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.extensions import db
|
||||
from app.models import Mailbox, Contact, SLDomain
|
||||
from app.pgp_utils import load_public_key
|
||||
from server import create_app
|
||||
|
||||
|
||||
def load_pgp_public_keys():
|
||||
"""Load PGP public key to keyring"""
|
||||
for mailbox in Mailbox.query.filter(Mailbox.pgp_public_key.isnot(None)).all():
|
||||
for mailbox in Mailbox.filter(Mailbox.pgp_public_key.isnot(None)).all():
|
||||
LOG.d("Load PGP key for mailbox %s", mailbox)
|
||||
fingerprint = load_public_key(mailbox.pgp_public_key)
|
||||
|
||||
|
@ -17,9 +16,9 @@ def load_pgp_public_keys():
|
|||
if fingerprint != mailbox.pgp_finger_print:
|
||||
LOG.e("fingerprint %s different for mailbox %s", fingerprint, mailbox)
|
||||
mailbox.pgp_finger_print = fingerprint
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
for contact in Contact.query.filter(Contact.pgp_public_key.isnot(None)).all():
|
||||
for contact in Contact.filter(Contact.pgp_public_key.isnot(None)).all():
|
||||
LOG.d("Load PGP key for %s", contact)
|
||||
fingerprint = load_public_key(contact.pgp_public_key)
|
||||
|
||||
|
@ -28,7 +27,7 @@ def load_pgp_public_keys():
|
|||
LOG.e("fingerprint %s different for contact %s", fingerprint, contact)
|
||||
contact.pgp_finger_print = fingerprint
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
LOG.d("Finish load_pgp_public_keys")
|
||||
|
||||
|
@ -48,7 +47,7 @@ def add_sl_domains():
|
|||
LOG.i("Add %s to SL domain", premium_domain)
|
||||
SLDomain.create(domain=premium_domain, premium_only=True)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -13,11 +13,11 @@ from app.config import (
|
|||
JOB_BATCH_IMPORT,
|
||||
JOB_DELETE_ACCOUNT,
|
||||
)
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
send_email,
|
||||
render,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.import_utils import handle_batch_import
|
||||
from app.log import LOG
|
||||
from app.models import User, Job, BatchImport
|
||||
|
@ -32,10 +32,7 @@ def new_app():
|
|||
@app.teardown_appcontext
|
||||
def shutdown_session(response_or_exc):
|
||||
# same as shutdown_session() in flask-sqlalchemy but this is not enough
|
||||
db.session.remove()
|
||||
|
||||
# dispose the engine too
|
||||
db.engine.dispose()
|
||||
Session.remove()
|
||||
|
||||
return app
|
||||
|
||||
|
@ -109,14 +106,14 @@ if __name__ == "__main__":
|
|||
app = new_app()
|
||||
|
||||
with app.app_context():
|
||||
for job in Job.query.filter(
|
||||
for job in Job.filter(
|
||||
Job.taken.is_(False), Job.run_at > min_dt, Job.run_at <= max_dt
|
||||
).all():
|
||||
LOG.d("Take job %s", job)
|
||||
|
||||
# mark the job as taken, whether it will be executed successfully or not
|
||||
job.taken = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
if job.name == JOB_ONBOARDING_1:
|
||||
user_id = job.payload.get("user_id")
|
||||
|
@ -161,7 +158,7 @@ if __name__ == "__main__":
|
|||
user_email = user.email
|
||||
LOG.w("Delete user %s", user)
|
||||
User.delete(user.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_email(
|
||||
user_email,
|
||||
|
|
|
@ -2,7 +2,7 @@ import os
|
|||
from time import sleep
|
||||
|
||||
from app.config import HOST
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.log import LOG
|
||||
from app.models import Monitoring
|
||||
from server import create_app
|
||||
|
@ -32,7 +32,7 @@ def get_stats():
|
|||
active_queue=active_queue,
|
||||
deferred_queue=deferred_queue,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
global _nb_failed
|
||||
# alert when too many emails in incoming + active queue
|
||||
|
|
80
server.py
80
server.py
|
@ -71,10 +71,11 @@ from app.config import (
|
|||
ROOT_DIR,
|
||||
)
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.db import Session
|
||||
from app.developer.base import developer_bp
|
||||
from app.discover.base import discover_bp
|
||||
from app.email_utils import send_email, render
|
||||
from app.extensions import db, login_manager, migrate, limiter
|
||||
from app.extensions import login_manager, migrate, limiter
|
||||
from app.jose_utils import get_jwk_key
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
|
@ -129,8 +130,6 @@ def create_light_app() -> Flask:
|
|||
app.config["SQLALCHEMY_DATABASE_URI"] = DB_URI
|
||||
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
||||
|
||||
db.init_app(app)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
|
@ -200,6 +199,10 @@ def create_app() -> Flask:
|
|||
session.permanent = True
|
||||
app.permanent_session_lifetime = timedelta(days=7)
|
||||
|
||||
@app.teardown_appcontext
|
||||
def cleanup(resp_or_exc):
|
||||
Session.remove()
|
||||
|
||||
return app
|
||||
|
||||
|
||||
|
@ -219,7 +222,7 @@ def fake_data():
|
|||
fido_uuid=None,
|
||||
)
|
||||
user.trial_end = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# add a profile picture
|
||||
file_path = "profile_pic.svg"
|
||||
|
@ -230,11 +233,11 @@ def fake_data():
|
|||
)
|
||||
file = File.create(user_id=user.id, path=file_path, commit=True)
|
||||
user.profile_picture_id = file.id
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create a bounced email
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
bounce_email_file_path = "bounce.eml"
|
||||
s3.upload_email_from_bytesio(
|
||||
|
@ -298,7 +301,7 @@ def fake_data():
|
|||
pgp_public_key=pgp_public_key,
|
||||
)
|
||||
m1.pgp_finger_print = load_public_key(pgp_public_key)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# example@example.com is in a LOT of data breaches
|
||||
Alias.create(email="example@example.com", user_id=user.id, mailbox_id=m1.id)
|
||||
|
@ -314,14 +317,14 @@ def fake_data():
|
|||
user_id=user.id,
|
||||
mailbox_id=user.default_mailbox_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
if i % 5 == 0:
|
||||
if i % 2 == 0:
|
||||
AliasMailbox.create(alias_id=a.id, mailbox_id=user.default_mailbox_id)
|
||||
else:
|
||||
AliasMailbox.create(alias_id=a.id, mailbox_id=m1.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# some aliases don't have any activity
|
||||
# if i % 3 != 0:
|
||||
|
@ -331,18 +334,18 @@ def fake_data():
|
|||
# website_email=f"contact{i}@example.com",
|
||||
# reply_email=f"rep{i}@sl.local",
|
||||
# )
|
||||
# db.session.commit()
|
||||
# Session.commit()
|
||||
# for _ in range(3):
|
||||
# EmailLog.create(user_id=user.id, contact_id=contact.id, alias_id=contact.alias_id)
|
||||
# db.session.commit()
|
||||
# Session.commit()
|
||||
|
||||
# have some disabled alias
|
||||
if i % 5 == 0:
|
||||
a.enabled = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
custom_domain1 = CustomDomain.create(user_id=user.id, domain="ab.cd", verified=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
Alias.create(
|
||||
user_id=user.id,
|
||||
|
@ -362,13 +365,13 @@ def fake_data():
|
|||
|
||||
Directory.create(user_id=user.id, name="abcd")
|
||||
Directory.create(user_id=user.id, name="xyzt")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Create a client
|
||||
client1 = Client.create_new(name="Demo", user_id=user.id)
|
||||
client1.oauth_client_id = "client-id"
|
||||
client1.oauth_client_secret = "client-secret"
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
RedirectUri.create(
|
||||
client_id=client1.id, uri="https://your-website.com/oauth-callback"
|
||||
|
@ -377,7 +380,7 @@ def fake_data():
|
|||
client2 = Client.create_new(name="Demo 2", user_id=user.id)
|
||||
client2.oauth_client_id = "client-id2"
|
||||
client2.oauth_client_secret = "client-secret2"
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
ClientUser.create(user_id=user.id, client_id=client1.id, name="Fake Name")
|
||||
|
||||
|
@ -392,11 +395,11 @@ def fake_data():
|
|||
number_upgraded_account=200,
|
||||
payment_method="PayPal",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
for i in range(6):
|
||||
Notification.create(user_id=user.id, message=f"""Hey hey <b>{i}</b> """ * 10)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
user2 = User.create(
|
||||
email="winston@continental.com",
|
||||
|
@ -405,7 +408,7 @@ def fake_data():
|
|||
referral_id=referral.id,
|
||||
)
|
||||
Mailbox.create(user_id=user2.id, email="winston2@high.table", verified=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
ManualSubscription.create(
|
||||
user_id=user2.id,
|
||||
|
@ -695,7 +698,7 @@ def setup_paddle_callback(app: Flask):
|
|||
|
||||
LOG.d("User %s upgrades!", user)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
elif request.form.get("alert_name") == "subscription_payment_succeeded":
|
||||
subscription_id = request.form.get("subscription_id")
|
||||
|
@ -710,7 +713,7 @@ def setup_paddle_callback(app: Flask):
|
|||
request.form.get("next_bill_date"), "YYYY-MM-DD"
|
||||
).date()
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
elif request.form.get("alert_name") == "subscription_cancelled":
|
||||
subscription_id = request.form.get("subscription_id")
|
||||
|
@ -728,7 +731,7 @@ def setup_paddle_callback(app: Flask):
|
|||
sub.event_time = arrow.now()
|
||||
|
||||
sub.cancelled = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
user = sub.user
|
||||
|
||||
|
@ -774,7 +777,7 @@ def setup_paddle_callback(app: Flask):
|
|||
# make sure to set the new plan as not-cancelled
|
||||
sub.cancelled = False
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
else:
|
||||
return "No such subscription", 400
|
||||
return "OK"
|
||||
|
@ -847,7 +850,7 @@ def handle_coinbase_event(event) -> bool:
|
|||
else: # already expired subscription
|
||||
coinbase_subscription.end_at = arrow.now().shift(years=1)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
send_email(
|
||||
user.email,
|
||||
|
@ -867,7 +870,6 @@ def handle_coinbase_event(event) -> bool:
|
|||
|
||||
def init_extensions(app: Flask):
|
||||
login_manager.init_app(app)
|
||||
db.init_app(app)
|
||||
migrate.init_app(app)
|
||||
|
||||
|
||||
|
@ -875,17 +877,17 @@ def init_admin(app):
|
|||
admin = Admin(name="SimpleLogin", template_mode="bootstrap4")
|
||||
|
||||
admin.init_app(app, index_view=SLAdminIndexView())
|
||||
admin.add_view(UserAdmin(User, db.session))
|
||||
admin.add_view(AliasAdmin(Alias, db.session))
|
||||
admin.add_view(MailboxAdmin(Mailbox, db.session))
|
||||
admin.add_view(EmailLogAdmin(EmailLog, db.session))
|
||||
admin.add_view(LifetimeCouponAdmin(LifetimeCoupon, db.session))
|
||||
admin.add_view(CouponAdmin(Coupon, db.session))
|
||||
admin.add_view(ManualSubscriptionAdmin(ManualSubscription, db.session))
|
||||
admin.add_view(ClientAdmin(Client, db.session))
|
||||
admin.add_view(CustomDomainAdmin(CustomDomain, db.session))
|
||||
admin.add_view(ReferralAdmin(Referral, db.session))
|
||||
admin.add_view(PayoutAdmin(Payout, db.session))
|
||||
admin.add_view(UserAdmin(User, Session))
|
||||
admin.add_view(AliasAdmin(Alias, Session))
|
||||
admin.add_view(MailboxAdmin(Mailbox, Session))
|
||||
admin.add_view(EmailLogAdmin(EmailLog, Session))
|
||||
admin.add_view(LifetimeCouponAdmin(LifetimeCoupon, Session))
|
||||
admin.add_view(CouponAdmin(Coupon, Session))
|
||||
admin.add_view(ManualSubscriptionAdmin(ManualSubscription, Session))
|
||||
admin.add_view(ClientAdmin(Client, Session))
|
||||
admin.add_view(CustomDomainAdmin(CustomDomain, Session))
|
||||
admin.add_view(ReferralAdmin(Referral, Session))
|
||||
admin.add_view(PayoutAdmin(Payout, Session))
|
||||
|
||||
|
||||
def register_custom_commands(app):
|
||||
|
@ -900,12 +902,12 @@ def register_custom_commands(app):
|
|||
def fill_up_email_log_alias():
|
||||
"""Fill up email_log.alias_id column"""
|
||||
# split all emails logs into 1000-size trunks
|
||||
nb_email_log = EmailLog.query.count()
|
||||
nb_email_log = EmailLog.count()
|
||||
LOG.d("total trunks %s", nb_email_log // 1000 + 2)
|
||||
for trunk in reversed(range(1, nb_email_log // 1000 + 2)):
|
||||
nb_update = 0
|
||||
for email_log, contact in (
|
||||
db.session.query(EmailLog, Contact)
|
||||
Session.query(EmailLog, Contact)
|
||||
.filter(EmailLog.contact_id == Contact.id)
|
||||
.filter(EmailLog.id <= trunk * 1000)
|
||||
.filter(EmailLog.id > (trunk - 1) * 1000)
|
||||
|
@ -915,7 +917,7 @@ def register_custom_commands(app):
|
|||
nb_update += 1
|
||||
|
||||
LOG.d("finish trunk %s, update %s email logs", trunk, nb_update)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
@app.cli.command("dummy-data")
|
||||
def dummy_data():
|
||||
|
|
12
shell.py
12
shell.py
|
@ -1,3 +1,5 @@
|
|||
from app.db import Session
|
||||
from app.db import Session
|
||||
from time import sleep
|
||||
|
||||
import flask_migrate
|
||||
|
@ -34,7 +36,7 @@ def create_db():
|
|||
def change_password(user_id, new_password):
|
||||
user = User.get(user_id)
|
||||
user.set_password(new_password)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
|
||||
def reset_db():
|
||||
|
@ -44,7 +46,7 @@ def reset_db():
|
|||
|
||||
|
||||
def send_mailbox_newsletter():
|
||||
for user in User.query.order_by(User.id).all():
|
||||
for user in User.order_by(User.id).all():
|
||||
if user.notification and user.activated:
|
||||
try:
|
||||
LOG.d("Send newsletter to %s", user)
|
||||
|
@ -60,7 +62,7 @@ def send_mailbox_newsletter():
|
|||
|
||||
|
||||
def send_pgp_newsletter():
|
||||
for user in User.query.order_by(User.id).all():
|
||||
for user in User.order_by(User.id).all():
|
||||
if user.notification and user.activated:
|
||||
try:
|
||||
LOG.d("Send PGP newsletter to %s", user)
|
||||
|
@ -77,7 +79,7 @@ def send_pgp_newsletter():
|
|||
|
||||
def send_mobile_newsletter():
|
||||
count = 0
|
||||
for user in User.query.order_by(User.id).all():
|
||||
for user in User.order_by(User.id).all():
|
||||
if user.notification and user.activated:
|
||||
count += 1
|
||||
try:
|
||||
|
@ -104,7 +106,7 @@ def disable_mailbox(mailbox_id):
|
|||
for alias in mailbox.aliases:
|
||||
alias.enabled = False
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
email_msg = f"""Hi,
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.config import PAGE_LIMIT
|
||||
from app.db import Session
|
||||
from app.email_utils import is_reply_email
|
||||
from app.extensions import db
|
||||
from app.models import User, ApiKey, Alias, Contact, EmailLog, Mailbox
|
||||
from tests.utils import login
|
||||
|
||||
|
@ -18,7 +18,7 @@ def test_get_aliases_error_without_pagination(flask_client):
|
|||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for("api.get_aliases"), headers={"Authentication": api_key.code}
|
||||
|
@ -39,12 +39,12 @@ def test_get_aliases_with_pagination(flask_client):
|
|||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create more aliases than PAGE_LIMIT
|
||||
for _ in range(PAGE_LIMIT + 1):
|
||||
Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# get aliases on the 1st page, should return PAGE_LIMIT aliases
|
||||
r = flask_client.get(
|
||||
|
@ -79,16 +79,16 @@ def test_get_aliases_query(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create more aliases than PAGE_LIMIT
|
||||
Alias.create_new(user, "prefix1")
|
||||
Alias.create_new(user, "prefix2")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# get aliases without query, should return 3 aliases as one alias is created when user is created
|
||||
r = flask_client.get(
|
||||
|
@ -111,15 +111,15 @@ def test_get_aliases_v2(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
a0 = Alias.create_new(user, "prefix0")
|
||||
a1 = Alias.create_new(user, "prefix1")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# << Aliases have no activity >>
|
||||
r = flask_client.get(
|
||||
|
@ -154,13 +154,13 @@ def test_get_aliases_v2(flask_client):
|
|||
website_email="c0@example.com",
|
||||
reply_email="re0@SL",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
EmailLog.create(
|
||||
contact_id=c0.id,
|
||||
user_id=user.id,
|
||||
alias_id=c0.alias_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# a1 has more recent activity
|
||||
c1 = Contact.create(
|
||||
|
@ -169,13 +169,13 @@ def test_get_aliases_v2(flask_client):
|
|||
website_email="c1@example.com",
|
||||
reply_email="re1@SL",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
EmailLog.create(
|
||||
contact_id=c1.id,
|
||||
user_id=user.id,
|
||||
alias_id=c1.alias_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# get aliases v2
|
||||
r = flask_client.get(
|
||||
|
@ -199,14 +199,14 @@ def test_delete_alias(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.delete(
|
||||
url_for("api.delete_alias", alias_id=alias.id),
|
||||
|
@ -221,14 +221,14 @@ def test_toggle_alias(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.toggle_alias", alias_id=alias.id),
|
||||
|
@ -243,14 +243,14 @@ def test_alias_activities(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create some alias log
|
||||
contact = Contact.create(
|
||||
|
@ -259,7 +259,7 @@ def test_alias_activities(flask_client):
|
|||
alias_id=alias.id,
|
||||
user_id=alias.user_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
for _ in range(int(PAGE_LIMIT / 2)):
|
||||
EmailLog.create(
|
||||
|
@ -304,14 +304,14 @@ def test_update_alias(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.put(
|
||||
url_for("api.update_alias", alias_id=alias.id),
|
||||
|
@ -326,16 +326,16 @@ def test_update_alias_mailbox(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
mb = Mailbox.create(user_id=user.id, email="ab@cd.com", verified=True)
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.put(
|
||||
url_for("api.update_alias", alias_id=alias.id),
|
||||
|
@ -358,14 +358,14 @@ def test_update_alias_name(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.put(
|
||||
url_for("api.update_alias", alias_id=alias.id),
|
||||
|
@ -391,17 +391,17 @@ def test_update_alias_mailboxes(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
mb1 = Mailbox.create(user_id=user.id, email="ab1@cd.com", verified=True)
|
||||
mb2 = Mailbox.create(user_id=user.id, email="ab2@cd.com", verified=True)
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.put(
|
||||
url_for("api.update_alias", alias_id=alias.id),
|
||||
|
@ -428,14 +428,14 @@ def test_update_disable_pgp(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
assert not alias.disable_pgp
|
||||
|
||||
r = flask_client.put(
|
||||
|
@ -468,14 +468,14 @@ def test_alias_contacts(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create some alias log
|
||||
for i in range(PAGE_LIMIT + 1):
|
||||
|
@ -485,7 +485,7 @@ def test_alias_contacts(flask_client):
|
|||
alias_id=alias.id,
|
||||
user_id=alias.user_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
EmailLog.create(
|
||||
contact_id=contact.id,
|
||||
|
@ -493,7 +493,7 @@ def test_alias_contacts(flask_client):
|
|||
user_id=contact.user_id,
|
||||
alias_id=contact.alias_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for("api.get_alias_contacts_route", alias_id=alias.id, page_id=0),
|
||||
|
@ -523,14 +523,14 @@ def test_create_contact_route(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.create_contact_route", alias_id=alias.id),
|
||||
|
@ -560,7 +560,7 @@ def test_create_contact_route(flask_client):
|
|||
|
||||
def test_create_contact_route_empty_contact_address(flask_client):
|
||||
login(flask_client)
|
||||
alias = Alias.query.first()
|
||||
alias = Alias.first()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.create_contact_route", alias_id=alias.id),
|
||||
|
@ -573,7 +573,7 @@ def test_create_contact_route_empty_contact_address(flask_client):
|
|||
|
||||
def test_create_contact_route_invalid_contact_email(flask_client):
|
||||
login(flask_client)
|
||||
alias = Alias.query.first()
|
||||
alias = Alias.first()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.create_contact_route", alias_id=alias.id),
|
||||
|
@ -588,14 +588,14 @@ def test_delete_contact(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
contact = Contact.create(
|
||||
alias_id=alias.id,
|
||||
|
@ -603,7 +603,7 @@ def test_delete_contact(flask_client):
|
|||
reply_email="reply+random@sl.io",
|
||||
user_id=alias.user_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.delete(
|
||||
url_for("api.delete_contact", contact_id=contact.id),
|
||||
|
@ -618,15 +618,15 @@ def test_get_alias(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create more aliases than PAGE_LIMIT
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# get aliases on the 1st page, should return PAGE_LIMIT aliases
|
||||
r = flask_client.get(
|
||||
|
|
|
@ -2,7 +2,7 @@ import json
|
|||
|
||||
from flask import url_for
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User, ApiKey, AliasUsedOn, Alias
|
||||
|
||||
|
||||
|
@ -10,11 +10,11 @@ def test_different_scenarios_v4(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# <<< without hostname >>>
|
||||
r = flask_client.get(
|
||||
|
@ -37,11 +37,11 @@ def test_different_scenarios_v4(flask_client):
|
|||
|
||||
# <<< with recommendation >>>
|
||||
alias = Alias.create_new(user, prefix="test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
AliasUsedOn.create(
|
||||
alias_id=alias.id, hostname="www.test.com", user_id=alias.user_id
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for("api.options_v4", hostname="www.test.com"),
|
||||
|
@ -55,11 +55,11 @@ def test_different_scenarios_v4_2(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# <<< without hostname >>>
|
||||
r = flask_client.get(
|
||||
|
@ -85,11 +85,11 @@ def test_different_scenarios_v4_2(flask_client):
|
|||
|
||||
# <<< with recommendation >>>
|
||||
alias = Alias.create_new(user, prefix="test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
AliasUsedOn.create(
|
||||
alias_id=alias.id, hostname="www.test.com", user_id=alias.user_id
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for("api.options_v4", hostname="www.test.com"),
|
||||
|
@ -103,11 +103,11 @@ def test_different_scenarios_v5(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# <<< without hostname >>>
|
||||
r = flask_client.get(
|
||||
|
@ -138,11 +138,11 @@ def test_different_scenarios_v5(flask_client):
|
|||
|
||||
# <<< with recommendation >>>
|
||||
alias = Alias.create_new(user, prefix="test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
AliasUsedOn.create(
|
||||
alias_id=alias.id, hostname="www.test.com", user_id=alias.user_id
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for("api.options_v4", hostname="www.test.com"),
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,8 @@
|
|||
import unicodedata
|
||||
|
||||
import pytest
|
||||
import unicodedata
|
||||
from flask import url_for
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User, AccountActivation
|
||||
|
||||
PASSWORD_1 = "Aurélie"
|
||||
|
@ -20,7 +19,7 @@ def test_auth_login_success(flask_client, mfa: bool):
|
|||
activated=True,
|
||||
enable_otp=mfa,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.auth_login"),
|
||||
|
@ -49,7 +48,7 @@ def test_auth_login_device_exist(flask_client):
|
|||
User.create(
|
||||
email="abcd@gmail.com", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.auth_login"),
|
||||
|
@ -138,7 +137,7 @@ def test_auth_activate_user_already_activated(flask_client):
|
|||
User.create(
|
||||
email="abcd@gmail.com", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.auth_activate"), json={"email": "abcd@gmail.com", "code": "123456"}
|
||||
|
@ -214,7 +213,7 @@ def test_auth_activate_too_many_wrong_code(flask_client):
|
|||
|
||||
def test_auth_reactivate_success(flask_client):
|
||||
User.create(email="abcd@gmail.com", password="password", name="Test User")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.auth_reactivate"), json={"email": "abcd@gmail.com"}
|
||||
|
@ -232,7 +231,7 @@ def test_auth_login_forgot_password(flask_client):
|
|||
User.create(
|
||||
email="abcd@gmail.com", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.forgot_password"),
|
||||
|
|
|
@ -3,7 +3,7 @@ from flask import url_for
|
|||
from itsdangerous import Signer
|
||||
|
||||
from app.config import FLASK_SECRET
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ def test_auth_mfa_success(flask_client):
|
|||
enable_otp=True,
|
||||
otp_secret="base32secret3232",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
totp = pyotp.TOTP(user.otp_secret)
|
||||
s = Signer(FLASK_SECRET)
|
||||
|
@ -42,7 +42,7 @@ def test_auth_wrong_mfa_key(flask_client):
|
|||
enable_otp=True,
|
||||
otp_secret="base32secret3232",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
totp = pyotp.TOTP(user.otp_secret)
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from flask import url_for
|
||||
|
||||
from app import alias_utils
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.import_utils import import_from_csv
|
||||
from app.models import (
|
||||
User,
|
||||
CustomDomain,
|
||||
|
@ -11,7 +12,6 @@ from app.models import (
|
|||
BatchImport,
|
||||
File,
|
||||
)
|
||||
from app.import_utils import import_from_csv
|
||||
from tests.utils import login
|
||||
|
||||
|
||||
|
@ -21,14 +21,14 @@ def test_export(flask_client):
|
|||
user2 = User.create(
|
||||
email="x@y.z", password="password", name="Wrong user", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Remove onboarding aliases
|
||||
for alias in Alias.filter_by(user_id=user1.id).all():
|
||||
alias_utils.delete_alias(alias, user1)
|
||||
for alias in Alias.filter_by(user_id=user2.id).all():
|
||||
alias_utils.delete_alias(alias, user2)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Create domains
|
||||
CustomDomain.create(
|
||||
|
@ -37,7 +37,7 @@ def test_export(flask_client):
|
|||
CustomDomain.create(
|
||||
user_id=user2.id, domain="bad-destionation-domain.com", verified=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Create mailboxes
|
||||
mailbox1 = Mailbox.create(
|
||||
|
@ -51,7 +51,7 @@ def test_export(flask_client):
|
|||
email="baddestination@bad-destination-domain.com",
|
||||
verified=True,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Create aliases
|
||||
Alias.create(
|
||||
|
@ -72,14 +72,14 @@ def test_export(flask_client):
|
|||
note="Should not appear",
|
||||
mailbox_id=badmailbox1.id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Add second mailbox to an alias
|
||||
AliasMailbox.create(
|
||||
alias_id=alias2.id,
|
||||
mailbox_id=mailbox2.id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Export
|
||||
r = flask_client.get(url_for("api.export_aliases"))
|
||||
|
@ -128,7 +128,7 @@ def test_import_no_mailboxes(flask_client):
|
|||
CustomDomain.create(
|
||||
user_id=user.id, domain="my-domain.com", ownership_verified=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias_data = [
|
||||
"alias,note",
|
||||
|
@ -180,7 +180,7 @@ def test_import(flask_client):
|
|||
CustomDomain.create(
|
||||
user_id=user.id, domain="my-destination-domain.com", ownership_verified=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Create mailboxes
|
||||
mailbox1 = Mailbox.create(
|
||||
|
@ -189,7 +189,7 @@ def test_import(flask_client):
|
|||
mailbox2 = Mailbox.create(
|
||||
user_id=user.id, email="destination2@my-destination-domain.com", verified=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias_data = [
|
||||
"alias,note,mailboxes",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import Mailbox
|
||||
from tests.utils import login
|
||||
|
||||
|
@ -34,7 +34,7 @@ def test_create_mailbox(flask_client):
|
|||
def test_create_mailbox_fail_for_free_user(flask_client):
|
||||
user = login(flask_client)
|
||||
user.trial_end = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
"/api/mailboxes",
|
||||
|
@ -50,7 +50,7 @@ def test_delete_mailbox(flask_client):
|
|||
|
||||
# create a mailbox
|
||||
mb = Mailbox.create(user_id=user.id, email="mb@gmail.com")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.delete(
|
||||
f"/api/mailboxes/{mb.id}",
|
||||
|
@ -88,7 +88,7 @@ def test_set_mailbox_as_default(flask_client):
|
|||
|
||||
# <<< Cannot set an unverified mailbox as default >>>
|
||||
mb.verified = False
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.put(
|
||||
f"/api/mailboxes/{mb.id}",
|
||||
|
@ -104,7 +104,7 @@ def test_update_mailbox_email(flask_client):
|
|||
|
||||
# create a mailbox
|
||||
mb = Mailbox.create(user_id=user.id, email="mb@gmail.com")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.put(
|
||||
f"/api/mailboxes/{mb.id}",
|
||||
|
@ -122,7 +122,7 @@ def test_cancel_mailbox_email_change(flask_client):
|
|||
|
||||
# create a mailbox
|
||||
mb = Mailbox.create(user_id=user.id, email="mb@gmail.com")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# update mailbox email
|
||||
r = flask_client.put(
|
||||
|
@ -150,7 +150,7 @@ def test_get_mailboxes(flask_client):
|
|||
|
||||
Mailbox.create(user_id=user.id, email="m1@example.com", verified=True)
|
||||
Mailbox.create(user_id=user.id, email="m2@example.com", verified=False)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
"/api/mailboxes",
|
||||
|
@ -173,7 +173,7 @@ def test_get_mailboxes_v2(flask_client):
|
|||
|
||||
Mailbox.create(user_id=user.id, email="m1@example.com", verified=True)
|
||||
Mailbox.create(user_id=user.id, email="m2@example.com", verified=False)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
"/api/v2/mailboxes",
|
||||
|
|
|
@ -3,7 +3,7 @@ from flask import g
|
|||
from app.alias_utils import delete_alias
|
||||
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
|
||||
from app.dashboard.views.custom_alias import signer
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import Alias, CustomDomain, Mailbox, AliasUsedOn
|
||||
from app.utils import random_word
|
||||
from tests.utils import login
|
||||
|
@ -86,13 +86,13 @@ def test_full_payload(flask_client):
|
|||
|
||||
# create another mailbox
|
||||
mb = Mailbox.create(user_id=user.id, email="abcd@gmail.com", verified=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
word = random_word()
|
||||
suffix = f".{word}@{EMAIL_DOMAIN}"
|
||||
signed_suffix = signer.sign(suffix).decode()
|
||||
|
||||
assert AliasUsedOn.query.count() == 0
|
||||
assert AliasUsedOn.count() == 0
|
||||
|
||||
r = flask_client.post(
|
||||
"/api/v3/alias/custom/new?hostname=example.com",
|
||||
|
@ -146,7 +146,7 @@ def test_custom_domain_alias(flask_client):
|
|||
def test_out_of_quota(flask_client):
|
||||
user = login(flask_client)
|
||||
user.trial_end = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create MAX_NB_EMAIL_FREE_PLAN custom alias to run out of quota
|
||||
for _ in range(MAX_NB_EMAIL_FREE_PLAN):
|
||||
|
|
|
@ -3,7 +3,7 @@ import uuid
|
|||
from flask import url_for, g
|
||||
|
||||
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import Alias
|
||||
from tests.utils import login
|
||||
|
||||
|
@ -60,7 +60,7 @@ def test_custom_mode(flask_client):
|
|||
def test_out_of_quota(flask_client):
|
||||
user = login(flask_client)
|
||||
user.trial_end = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create MAX_NB_EMAIL_FREE_PLAN random alias to run out of quota
|
||||
for _ in range(MAX_NB_EMAIL_FREE_PLAN):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User, ApiKey, Notification
|
||||
|
||||
|
||||
|
@ -8,16 +8,16 @@ def test_get_notifications(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create some notifications
|
||||
Notification.create(user_id=user.id, message="Test message 1")
|
||||
Notification.create(user_id=user.id, message="Test message 2")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for("api.get_notifications", page=0),
|
||||
|
@ -46,14 +46,14 @@ def test_mark_notification_as_read(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
Notification.create(id=1, user_id=user.id, message="Test message 1")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.mark_as_read", notification_id=1),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from app.api.serializer import get_alias_infos_with_pagination_v3
|
||||
from app.config import PAGE_LIMIT
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User, Alias, Mailbox, Contact
|
||||
from tests.utils import create_user
|
||||
|
||||
|
@ -75,7 +75,7 @@ def test_get_alias_infos_with_pagination_v3_query_alias_mailboxes(flask_client):
|
|||
alias = Alias.first()
|
||||
mb = Mailbox.create(user_id=user.id, email="mb@gmail.com")
|
||||
alias._mailboxes.append(mb)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias_infos = get_alias_infos_with_pagination_v3(user, mailbox_id=mb.id)
|
||||
assert len(alias_infos) == 1
|
||||
|
@ -96,7 +96,7 @@ def test_get_alias_infos_with_pagination_v3_query_alias_note(flask_client):
|
|||
|
||||
alias = Alias.first()
|
||||
alias.note = "test note"
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias_infos = get_alias_infos_with_pagination_v3(user, query="test note")
|
||||
assert len(alias_infos) == 1
|
||||
|
@ -114,7 +114,7 @@ def test_get_alias_infos_with_pagination_v3_query_alias_name(flask_client):
|
|||
|
||||
alias = Alias.first()
|
||||
alias.name = "Test Name"
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias_infos = get_alias_infos_with_pagination_v3(user, query="test name")
|
||||
assert len(alias_infos) == 1
|
||||
|
@ -135,7 +135,7 @@ def test_get_alias_infos_with_pagination_v3_no_duplicate(flask_client):
|
|||
alias = Alias.first()
|
||||
mb = Mailbox.create(user_id=user.id, email="mb@gmail.com")
|
||||
alias._mailboxes.append(mb)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias_infos = get_alias_infos_with_pagination_v3(user)
|
||||
assert len(alias_infos) == 1
|
||||
|
@ -182,7 +182,7 @@ def test_get_alias_infos_pinned_alias(flask_client):
|
|||
for i in range(2 * PAGE_LIMIT):
|
||||
Alias.create_new_random(user)
|
||||
|
||||
first_alias = Alias.query.order_by(Alias.id).first()
|
||||
first_alias = Alias.order_by(Alias.id).first()
|
||||
|
||||
# should return PAGE_LIMIT alias
|
||||
alias_infos = get_alias_infos_with_pagination_v3(user)
|
||||
|
@ -192,7 +192,7 @@ def test_get_alias_infos_pinned_alias(flask_client):
|
|||
|
||||
# pin the first alias
|
||||
first_alias.pinned = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias_infos = get_alias_infos_with_pagination_v3(user)
|
||||
# now first_alias is the first result
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User, ApiKey
|
||||
from tests.utils import login
|
||||
|
||||
|
@ -9,11 +9,11 @@ def test_user_in_trial(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create api_key
|
||||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for("api.user_info"), headers={"Authentication": api_key.code}
|
||||
|
@ -42,7 +42,7 @@ def test_wrong_api_key(flask_client):
|
|||
def test_create_api_key(flask_client):
|
||||
# create user, user is activated
|
||||
User.create(email="a@b.c", password="password", name="Test User", activated=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# login user
|
||||
flask_client.post(
|
||||
|
@ -61,7 +61,7 @@ def test_create_api_key(flask_client):
|
|||
def test_logout(flask_client):
|
||||
# create user, user is activated
|
||||
User.create(email="a@b.c", password="password", name="Test User", activated=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# login user
|
||||
flask_client.post(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@ def test_unactivated_user_login(flask_client):
|
|||
|
||||
# create user, user is not activated
|
||||
User.create(email="a@b.c", password="password", name="Test User")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("auth.login"),
|
||||
|
@ -29,7 +29,7 @@ def test_activated_user_login(flask_client):
|
|||
|
||||
# create user, user is activated
|
||||
User.create(email="a@b.c", password="password", name="Test User", activated=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("auth.login"),
|
||||
|
|
|
@ -2,18 +2,20 @@ import os
|
|||
|
||||
# use the tests/test.env config fle
|
||||
# flake8: noqa: E402
|
||||
import sqlalchemy
|
||||
|
||||
os.environ["CONFIG"] = os.path.abspath(
|
||||
os.path.join(os.path.dirname(os.path.dirname(__file__)), "tests/test.env")
|
||||
)
|
||||
import sqlalchemy
|
||||
|
||||
from app.db import Session, engine, connection
|
||||
from app.models import Base
|
||||
|
||||
from psycopg2 import errors
|
||||
from psycopg2.errorcodes import DEPENDENT_OBJECTS_STILL_EXIST
|
||||
|
||||
import pytest
|
||||
|
||||
from app.extensions import db
|
||||
from server import create_app
|
||||
from init_app import add_sl_domains
|
||||
|
||||
|
@ -24,7 +26,7 @@ app.config["SERVER_NAME"] = "sl.test"
|
|||
|
||||
with app.app_context():
|
||||
# enable pg_trgm extension
|
||||
with db.engine.connect() as conn:
|
||||
with engine.connect() as conn:
|
||||
try:
|
||||
conn.execute("DROP EXTENSION if exists pg_trgm")
|
||||
conn.execute("CREATE EXTENSION pg_trgm")
|
||||
|
@ -33,7 +35,7 @@ with app.app_context():
|
|||
print(">>> pg_trgm can't be dropped, ignore")
|
||||
conn.execute("Rollback")
|
||||
|
||||
db.create_all()
|
||||
Base.metadata.create_all(engine)
|
||||
|
||||
add_sl_domains()
|
||||
|
||||
|
@ -45,20 +47,14 @@ def flask_app():
|
|||
|
||||
@pytest.fixture
|
||||
def flask_client():
|
||||
with app.app_context():
|
||||
# replace db.session to that we can rollback all commits that can be made during a test
|
||||
# inspired from http://alexmic.net/flask-sqlalchemy-pytest/
|
||||
connection = db.engine.connect()
|
||||
transaction = connection.begin()
|
||||
options = dict(bind=connection, binds={})
|
||||
session = db.create_scoped_session(options=options)
|
||||
db.session = session
|
||||
transaction = connection.begin()
|
||||
|
||||
with app.app_context():
|
||||
try:
|
||||
client = app.test_client()
|
||||
yield client
|
||||
finally:
|
||||
# roll back all commits made during a test
|
||||
transaction.rollback()
|
||||
connection.close()
|
||||
session.remove()
|
||||
Session.rollback()
|
||||
Session.close()
|
||||
|
|
|
@ -11,7 +11,7 @@ def test_add_contact_success(flask_client):
|
|||
login(flask_client)
|
||||
alias = Alias.first()
|
||||
|
||||
assert Contact.query.count() == 0
|
||||
assert Contact.count() == 0
|
||||
|
||||
# <<< Create a new contact >>>
|
||||
flask_client.post(
|
||||
|
@ -23,7 +23,7 @@ def test_add_contact_success(flask_client):
|
|||
follow_redirects=True,
|
||||
)
|
||||
# a new contact is added
|
||||
assert Contact.query.count() == 1
|
||||
assert Contact.count() == 1
|
||||
contact = Contact.first()
|
||||
assert contact.website_email == "abcd@gmail.com"
|
||||
|
||||
|
@ -37,8 +37,8 @@ def test_add_contact_success(flask_client):
|
|||
follow_redirects=True,
|
||||
)
|
||||
# a new contact is added
|
||||
assert Contact.query.count() == 2
|
||||
contact = Contact.query.filter(Contact.id != contact.id).first()
|
||||
assert Contact.count() == 2
|
||||
contact = Contact.filter(Contact.id != contact.id).first()
|
||||
assert contact.website_email == "another@gmail.com"
|
||||
assert contact.name == "First Last"
|
||||
|
||||
|
@ -53,5 +53,5 @@ def test_add_contact_success(flask_client):
|
|||
)
|
||||
|
||||
# no new contact is added
|
||||
assert Contact.query.count() == 2
|
||||
assert Contact.count() == 2
|
||||
assert "Invalid email format. Email must be either email@example.com" in str(r.data)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from app.dashboard.views import alias_transfer
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import (
|
||||
Alias,
|
||||
Mailbox,
|
||||
|
@ -14,7 +14,7 @@ def test_alias_transfer(flask_client):
|
|||
mb = Mailbox.create(user_id=user.id, email="mb@gmail.com", commit=True)
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
AliasMailbox.create(alias_id=alias.id, mailbox_id=mb.id, commit=True)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ from app.dashboard.views.custom_alias import (
|
|||
get_available_suffixes,
|
||||
AliasSuffix,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import (
|
||||
Mailbox,
|
||||
CustomDomain,
|
||||
|
@ -46,13 +46,13 @@ def test_add_alias_success(flask_client):
|
|||
assert r.status_code == 200
|
||||
assert f"Alias prefix.12345@{EMAIL_DOMAIN} has been created" in str(r.data)
|
||||
|
||||
alias = Alias.query.order_by(Alias.created_at.desc()).first()
|
||||
alias = Alias.order_by(Alias.created_at.desc()).first()
|
||||
assert not alias._mailboxes
|
||||
|
||||
|
||||
def test_add_alias_multiple_mailboxes(flask_client):
|
||||
user = login(flask_client)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias_suffix = AliasSuffix(
|
||||
is_custom=False,
|
||||
|
@ -64,7 +64,7 @@ def test_add_alias_multiple_mailboxes(flask_client):
|
|||
|
||||
# create with a multiple mailboxes
|
||||
mb1 = Mailbox.create(user_id=user.id, email="m1@example.com", verified=True)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("dashboard.custom_alias"),
|
||||
|
@ -78,18 +78,18 @@ def test_add_alias_multiple_mailboxes(flask_client):
|
|||
assert r.status_code == 200
|
||||
assert f"Alias prefix.12345@{EMAIL_DOMAIN} has been created" in str(r.data)
|
||||
|
||||
alias = Alias.query.order_by(Alias.created_at.desc()).first()
|
||||
alias = Alias.order_by(Alias.created_at.desc()).first()
|
||||
assert alias._mailboxes
|
||||
|
||||
|
||||
def test_not_show_unverified_mailbox(flask_client):
|
||||
"""make sure user unverified mailbox is not shown to user"""
|
||||
user = login(flask_client)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
Mailbox.create(user_id=user.id, email="m1@example.com", verified=True)
|
||||
Mailbox.create(user_id=user.id, email="m2@example.com", verified=False)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(url_for("dashboard.custom_alias"))
|
||||
|
||||
|
@ -99,7 +99,7 @@ def test_not_show_unverified_mailbox(flask_client):
|
|||
|
||||
def test_verify_prefix_suffix(flask_client):
|
||||
user = login(flask_client)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
CustomDomain.create(user_id=user.id, domain="test.com", verified=True)
|
||||
|
||||
|
@ -128,7 +128,7 @@ def test_available_suffixes(flask_client):
|
|||
def test_available_suffixes_default_domain(flask_client):
|
||||
user = login(flask_client)
|
||||
|
||||
sl_domain = SLDomain.query.first()
|
||||
sl_domain = SLDomain.first()
|
||||
CustomDomain.create(user_id=user.id, domain="test.com", verified=True, commit=True)
|
||||
|
||||
user.default_alias_public_domain_id = sl_domain.id
|
||||
|
@ -166,7 +166,7 @@ def test_available_suffixes_random_prefix_generation(flask_client):
|
|||
|
||||
def test_add_already_existed_alias(flask_client):
|
||||
user = login(flask_client)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
another_user = User.create(
|
||||
email="a2@b.c",
|
||||
|
@ -208,7 +208,7 @@ def test_add_already_existed_alias(flask_client):
|
|||
|
||||
def test_add_alias_in_global_trash(flask_client):
|
||||
user = login(flask_client)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
another_user = User.create(
|
||||
email="a2@b.c",
|
||||
|
@ -233,9 +233,9 @@ def test_add_alias_in_global_trash(flask_client):
|
|||
commit=True,
|
||||
)
|
||||
|
||||
assert DeletedAlias.query.count() == 0
|
||||
assert DeletedAlias.count() == 0
|
||||
delete_alias(alias, another_user)
|
||||
assert DeletedAlias.query.count() == 1
|
||||
assert DeletedAlias.count() == 1
|
||||
|
||||
# create the same alias, should return error
|
||||
r = flask_client.post(
|
||||
|
@ -267,9 +267,9 @@ def test_add_alias_in_custom_domain_trash(flask_client):
|
|||
commit=True,
|
||||
)
|
||||
|
||||
assert DomainDeletedAlias.query.count() == 0
|
||||
assert DomainDeletedAlias.count() == 0
|
||||
delete_alias(alias, user)
|
||||
assert DomainDeletedAlias.query.count() == 1
|
||||
assert DomainDeletedAlias.count() == 1
|
||||
|
||||
# create the same alias, should return error
|
||||
suffix = "@ab.cd"
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from tests.utils import login
|
||||
|
||||
|
||||
def test_add_domain_success(flask_client):
|
||||
user = login(flask_client)
|
||||
user.lifetime = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("dashboard.custom_domain"),
|
||||
|
@ -23,7 +23,7 @@ def test_add_domain_same_as_user_email(flask_client):
|
|||
"""cannot add domain if user personal email uses this domain"""
|
||||
user = login(flask_client)
|
||||
user.lifetime = True
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("dashboard.custom_domain"),
|
||||
|
|
|
@ -8,7 +8,7 @@ from tests.utils import login
|
|||
|
||||
def test_create_random_alias_success(flask_client):
|
||||
login(flask_client)
|
||||
assert Alias.query.count() == 1
|
||||
assert Alias.count() == 1
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("dashboard.index"),
|
||||
|
@ -16,7 +16,7 @@ def test_create_random_alias_success(flask_client):
|
|||
follow_redirects=True,
|
||||
)
|
||||
assert r.status_code == 200
|
||||
assert Alias.query.count() == 2
|
||||
assert Alias.count() == 2
|
||||
|
||||
|
||||
def test_too_many_requests(flask_client):
|
||||
|
|
|
@ -2,7 +2,7 @@ from app.config import (
|
|||
MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS,
|
||||
MAX_ACTIVITY_DURING_MINUTE_PER_MAILBOX,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.email.rate_limit import (
|
||||
rate_limited_forward_phase,
|
||||
rate_limited_for_alias,
|
||||
|
@ -16,11 +16,11 @@ def test_rate_limited_forward_phase_for_alias(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# no rate limiting for a new alias
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
assert not rate_limited_for_alias(alias)
|
||||
|
||||
# rate limit when there's a previous activity on alias
|
||||
|
@ -30,14 +30,14 @@ def test_rate_limited_forward_phase_for_alias(flask_client):
|
|||
website_email="contact@example.com",
|
||||
reply_email="rep@sl.local",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS + 1):
|
||||
EmailLog.create(
|
||||
user_id=user.id,
|
||||
contact_id=contact.id,
|
||||
alias_id=contact.alias_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
assert rate_limited_for_alias(alias)
|
||||
|
||||
|
@ -46,10 +46,10 @@ def test_rate_limited_forward_phase_for_mailbox(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
contact = Contact.create(
|
||||
user_id=user.id,
|
||||
|
@ -57,14 +57,14 @@ def test_rate_limited_forward_phase_for_mailbox(flask_client):
|
|||
website_email="contact@example.com",
|
||||
reply_email="rep@sl.local",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_MAILBOX + 1):
|
||||
EmailLog.create(
|
||||
user_id=user.id,
|
||||
contact_id=contact.id,
|
||||
alias_id=contact.alias_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
EmailLog.create(
|
||||
user_id=user.id,
|
||||
|
@ -75,7 +75,7 @@ def test_rate_limited_forward_phase_for_mailbox(flask_client):
|
|||
# Create another alias with the same mailbox
|
||||
# will be rate limited as there's a previous activity on mailbox
|
||||
alias2 = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
assert rate_limited_for_mailbox(alias2)
|
||||
|
||||
|
||||
|
@ -91,10 +91,10 @@ def test_rate_limited_reply_phase(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
contact = Contact.create(
|
||||
user_id=user.id,
|
||||
|
@ -102,13 +102,13 @@ def test_rate_limited_reply_phase(flask_client):
|
|||
website_email="contact@example.com",
|
||||
reply_email="rep@sl.local",
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS + 1):
|
||||
EmailLog.create(
|
||||
user_id=user.id,
|
||||
contact_id=contact.id,
|
||||
alias_id=contact.alias_id,
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
assert rate_limited_reply_phase("rep@sl.local")
|
||||
|
|
|
@ -4,7 +4,7 @@ from urllib.parse import urlparse, parse_qs
|
|||
|
||||
from flask import url_for
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.jose_utils import verify_id_token, decode_id_token
|
||||
from app.models import Client, User, ClientUser
|
||||
from app.oauth.views.authorize import (
|
||||
|
@ -39,10 +39,10 @@ def test_construct_url():
|
|||
def test_authorize_page_non_login_user(flask_client):
|
||||
"""make sure to display login page for non-authenticated user"""
|
||||
user = User.create("test@test.com", "test user")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
client = Client.create_new("test client", user.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for(
|
||||
|
@ -63,7 +63,7 @@ def test_authorize_page_login_user_non_supported_flow(flask_client):
|
|||
"""return 400 if the flow is not supported"""
|
||||
user = login(flask_client)
|
||||
client = Client.create_new("test client", user.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# Not provide any flow
|
||||
r = flask_client.get(
|
||||
|
@ -102,7 +102,7 @@ def test_authorize_page_login_user(flask_client):
|
|||
user = login(flask_client)
|
||||
client = Client.create_new("test client", user.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for(
|
||||
|
@ -128,7 +128,7 @@ def test_authorize_code_flow_no_openid_scope(flask_client):
|
|||
user = login(flask_client)
|
||||
client = Client.create_new("test client", user.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# user allows client on the authorization page
|
||||
r = flask_client.post(
|
||||
|
@ -217,7 +217,7 @@ def test_authorize_code_flow_with_openid_scope(flask_client):
|
|||
user = login(flask_client)
|
||||
client = Client.create_new("test client", user.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# user allows client on the authorization page
|
||||
r = flask_client.post(
|
||||
|
@ -310,7 +310,7 @@ def test_authorize_token_flow(flask_client):
|
|||
user = login(flask_client)
|
||||
client = Client.create_new("test client", user.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# user allows client on the authorization page
|
||||
r = flask_client.post(
|
||||
|
@ -357,7 +357,7 @@ def test_authorize_id_token_flow(flask_client):
|
|||
user = login(flask_client)
|
||||
client = Client.create_new("test client", user.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# user allows client on the authorization page
|
||||
r = flask_client.post(
|
||||
|
@ -406,7 +406,7 @@ def test_authorize_token_id_token_flow(flask_client):
|
|||
user = login(flask_client)
|
||||
client = Client.create_new("test client", user.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# user allows client on the authorization page
|
||||
r = flask_client.post(
|
||||
|
@ -496,7 +496,7 @@ def test_authorize_code_id_token_flow(flask_client):
|
|||
user = login(flask_client)
|
||||
client = Client.create_new("test client", user.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# user allows client on the authorization page
|
||||
r = flask_client.post(
|
||||
|
@ -629,7 +629,7 @@ def test_authorize_page_invalid_client_id(flask_client):
|
|||
user = login(flask_client)
|
||||
Client.create_new("test client", user.id)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for(
|
||||
|
@ -654,7 +654,7 @@ def test_authorize_page_http_not_allowed(flask_client):
|
|||
client = Client.create_new("test client", user.id)
|
||||
client.approved = True
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for(
|
||||
|
@ -676,7 +676,7 @@ def test_authorize_page_unknown_redirect_uri(flask_client):
|
|||
client = Client.create_new("test client", user.id)
|
||||
client.approved = True
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
r = flask_client.get(
|
||||
url_for(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from app.alias_utils import delete_alias, check_alias_prefix
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User, Alias, DeletedAlias
|
||||
|
||||
|
||||
|
@ -41,8 +41,8 @@ def test_delete_alias_already_in_trash(flask_client):
|
|||
)
|
||||
|
||||
# add the alias to global trash
|
||||
db.session.add(DeletedAlias(email=alias.email))
|
||||
db.session.commit()
|
||||
Session.add(DeletedAlias(email=alias.email))
|
||||
Session.commit()
|
||||
|
||||
delete_alias(alias, user)
|
||||
assert Alias.get_by(email="first@d1.test") is None
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import pytest
|
||||
|
||||
from app.config import sl_getenv
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from email.message import EmailMessage
|
|||
import arrow
|
||||
|
||||
from app.config import MAX_ALERT_24H, EMAIL_DOMAIN, BOUNCE_EMAIL
|
||||
from app.db import Session
|
||||
from app.email_utils import (
|
||||
get_email_domain_part,
|
||||
can_create_directory_for_address,
|
||||
|
@ -31,7 +32,6 @@ from app.email_utils import (
|
|||
get_header_unicode,
|
||||
parse_full_address,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.models import User, CustomDomain, Alias, Contact, EmailLog, IgnoreBounceSender
|
||||
|
||||
# flake8: noqa: E101, W191
|
||||
|
@ -136,7 +136,7 @@ def test_send_email_with_rate_control(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
for _ in range(MAX_ALERT_24H):
|
||||
assert send_email_with_rate_control(
|
||||
|
@ -598,7 +598,7 @@ def test_should_disable(flask_client):
|
|||
include_sender_in_reverse_alias=True,
|
||||
)
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
assert not should_disable(alias)
|
||||
|
||||
|
@ -623,7 +623,7 @@ def test_should_disable(flask_client):
|
|||
|
||||
# should not affect another alias
|
||||
alias2 = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
assert not should_disable(alias2)
|
||||
|
||||
|
||||
|
@ -631,7 +631,7 @@ def test_should_disable_bounces_every_day(flask_client):
|
|||
"""if an alias has bounces every day at least 9 days in the last 10 days, disable alias"""
|
||||
user = login(flask_client)
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
assert not should_disable(alias)
|
||||
|
||||
|
@ -661,7 +661,7 @@ def test_should_disable_bounces_account(flask_client):
|
|||
user = login(flask_client)
|
||||
alias = Alias.create_new_random(user)
|
||||
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# create a lot of bounces on alias
|
||||
contact = Contact.create(
|
||||
|
@ -690,7 +690,7 @@ def test_should_disable_bounces_account(flask_client):
|
|||
def test_should_disable_bounce_consecutive_days(flask_client):
|
||||
user = login(flask_client)
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
contact = Contact.create(
|
||||
user_id=user.id,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.jose_utils import make_id_token, verify_id_token
|
||||
from app.models import ClientUser, User, Client
|
||||
|
||||
|
@ -7,15 +7,15 @@ def test_encode_decode(flask_client):
|
|||
user = User.create(
|
||||
email="a@b.c", password="password", name="Test User", activated=True
|
||||
)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
client1 = Client.create_new(name="Demo", user_id=user.id)
|
||||
client1.oauth_client_id = "client-id"
|
||||
client1.oauth_client_secret = "client-secret"
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
client_user = ClientUser.create(client_id=client1.id, user_id=user.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
jwt_token = make_id_token(client_user)
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ from uuid import UUID
|
|||
import pytest
|
||||
|
||||
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
|
||||
from app.db import Session
|
||||
from app.email_utils import parse_full_address
|
||||
from app.extensions import db
|
||||
from app.models import (
|
||||
generate_email,
|
||||
User,
|
||||
|
@ -53,7 +53,7 @@ def test_suggested_emails_for_user_who_cannot_create_new_alias(flask_client):
|
|||
# make sure user runs out of quota to create new email
|
||||
for i in range(MAX_NB_EMAIL_FREE_PLAN):
|
||||
Alias.create_new(user=user, prefix="test")
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
suggested_email, other_emails = user.suggested_emails(website_name="test")
|
||||
|
||||
|
@ -88,7 +88,7 @@ def test_website_send_to(flask_client):
|
|||
)
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# non-empty name
|
||||
c1 = Contact.create(
|
||||
|
@ -122,7 +122,7 @@ def test_new_addr(flask_client):
|
|||
)
|
||||
|
||||
alias = Alias.create_new_random(user)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
# default sender_format is 'via'
|
||||
c1 = Contact.create(
|
||||
|
@ -137,18 +137,18 @@ def test_new_addr(flask_client):
|
|||
|
||||
# Make sure email isn't duplicated if sender name equals email
|
||||
c1.name = "abcd@example.com"
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
assert c1.new_addr() == '"abcd(a)example.com" <rep@SL>'
|
||||
|
||||
# set sender_format = AT
|
||||
user.sender_format = SenderFormatEnum.AT.value
|
||||
c1.name = "First Last"
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
assert c1.new_addr() == '"First Last - abcd at example.com" <rep@SL>'
|
||||
|
||||
# unicode name
|
||||
c1.name = "Nhơn Nguyễn"
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
assert (
|
||||
c1.new_addr()
|
||||
== "=?utf-8?q?Nh=C6=A1n_Nguy=E1=BB=85n_-_abcd_at_example=2Ecom?= <rep@SL>"
|
||||
|
@ -182,11 +182,11 @@ def test_mailbox_delete(flask_client):
|
|||
|
||||
# alias has 2 mailboxes
|
||||
alias = Alias.create_new(user, "prefix", mailbox_id=m1.id)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
alias._mailboxes.append(m2)
|
||||
alias._mailboxes.append(m3)
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
assert len(alias.mailboxes) == 3
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import arrow
|
||||
|
||||
from app.extensions import db
|
||||
from app.db import Session
|
||||
from app.models import User, CoinbaseSubscription
|
||||
from server import handle_coinbase_event
|
||||
|
||||
|
@ -44,7 +44,7 @@ def test_handle_coinbase_event_extend_subscription(flask_client):
|
|||
activated=True,
|
||||
)
|
||||
user.trial_end = None
|
||||
db.session.commit()
|
||||
Session.commit()
|
||||
|
||||
cb = CoinbaseSubscription.create(
|
||||
user_id=user.id, end_at=arrow.now().shift(days=-400), commit=True
|
||||
|
|
Loading…
Reference in New Issue