Init daily metric (#1351)

* Add DailyMetric model

* increment nb_new_web_non_proton_user

* fix test

* fix test
This commit is contained in:
Son Nguyen Kim 2022-10-14 17:35:34 +02:00 committed by GitHub
parent 1fc75203f2
commit c71824c68e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 124 additions and 2 deletions

View File

@ -16,7 +16,7 @@ from app.email_utils import (
)
from app.events.auth_event import RegisterEvent
from app.log import LOG
from app.models import User, ActivationCode
from app.models import User, ActivationCode, DailyMetric
from app.utils import random_string, encode_url, sanitize_email
@ -91,6 +91,10 @@ def register():
try:
send_activation_email(user, next_url)
RegisterEvent(RegisterEvent.ActionType.success).send()
DailyMetric.get_or_create_today_metric().nb_new_web_non_proton_user += (
1
)
Session.commit()
except Exception:
flash("Invalid email, are you sure the email is correct?", "error")
RegisterEvent(RegisterEvent.ActionType.invalid_email).send()

View File

@ -1457,6 +1457,7 @@ class Alias(Base, ModelMixin):
new_alias.custom_domain_id = custom_domain.id
Session.add(new_alias)
DailyMetric.get_or_create_today_metric().nb_alias += 1
if commit:
Session.commit()
@ -2892,6 +2893,34 @@ class Metric2(Base, ModelMixin):
nb_app = sa.Column(sa.Float, nullable=True)
class DailyMetric(Base, ModelMixin):
"""
For storing daily event-based metrics.
The difference between DailyEventMetric and Metric2 is Metric2 stores the total
whereas DailyEventMetric is reset for a new day
"""
__tablename__ = "daily_metric"
date = sa.Column(sa.Date, nullable=False, unique=True)
# users who sign up via web without using "Login with Proton"
nb_new_web_non_proton_user = sa.Column(
sa.Integer, nullable=False, server_default="0", default=0
)
nb_alias = sa.Column(sa.Integer, nullable=False, server_default="0", default=0)
@staticmethod
def get_or_create_today_metric() -> DailyMetric:
today = arrow.utcnow().date()
daily_metric = DailyMetric.get_by(date=today)
if not daily_metric:
daily_metric = DailyMetric.create(
date=today, nb_new_web_non_proton_user=0, nb_alias=0
)
return daily_metric
class Bounce(Base, ModelMixin):
"""Record all bounces. Deleted after 7 days"""

View File

@ -0,0 +1,38 @@
"""empty message
Revision ID: 2c2093c82bc0
Revises: bd95b2b4217f
Create Date: 2022-10-14 16:27:49.839887
"""
import sqlalchemy_utils
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '2c2093c82bc0'
down_revision = 'bd95b2b4217f'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('daily_metric',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('created_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False),
sa.Column('updated_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=True),
sa.Column('date', sa.Date(), nullable=False),
sa.Column('nb_new_web_non_proton_user', sa.Integer(), server_default='0', nullable=False),
sa.Column('nb_alias', sa.Integer(), server_default='0', nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('date')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('daily_metric')
# ### end Alembic commands ###

View File

@ -1,8 +1,10 @@
from flask import url_for
from app.db import Session
from app.models import DailyMetric
def test_register_success(flask_client):
"""User arrives at the waiting activation page."""
r = flask_client.post(
url_for("auth.register"),
data={"email": "abcd@gmail.com", "password": "password"},
@ -10,9 +12,26 @@ def test_register_success(flask_client):
)
assert r.status_code == 200
# User arrives at the waiting activation page.
assert b"An email to validate your email is on its way" in r.data
def test_register_increment_nb_new_web_non_proton_user(flask_client):
daily_metric = DailyMetric.get_or_create_today_metric()
Session.commit()
nb_new_web_non_proton_user = daily_metric.nb_new_web_non_proton_user
r = flask_client.post(
url_for("auth.register"),
data={"email": "abcd@gmail.com", "password": "password"},
follow_redirects=True,
)
assert r.status_code == 200
new_daily_metric = DailyMetric.get_or_create_today_metric()
assert new_daily_metric.nb_new_web_non_proton_user == nb_new_web_non_proton_user + 1
def test_register_disabled(flask_client):
"""User cannot create new account when DISABLE_REGISTRATION."""
from app import config

View File

@ -19,6 +19,7 @@ from app.models import (
DomainDeletedAlias,
DeletedAlias,
SLDomain,
DailyMetric,
)
from app.utils import random_word
from tests.utils import login, random_domain, create_new_user
@ -53,6 +54,37 @@ def test_add_alias_success(flask_client):
assert not alias._mailboxes
def test_add_alias_increment_nb_daily_metric_alias(flask_client):
user = login(flask_client)
daily_metric = DailyMetric.get_or_create_today_metric()
Session.commit()
nb_alias = daily_metric.nb_alias
suffix = f".{int(random() * 100000)}@{EMAIL_DOMAIN}"
alias_suffix = AliasSuffix(
is_custom=False,
suffix=suffix,
signed_suffix=signer.sign(suffix).decode(),
is_premium=False,
domain=EMAIL_DOMAIN,
)
# create with a single mailbox
r = flask_client.post(
url_for("dashboard.custom_alias"),
data={
"prefix": "prefix",
"signed-alias-suffix": alias_suffix.signed_suffix,
"mailboxes": [user.default_mailbox_id],
},
follow_redirects=True,
)
assert r.status_code == 200
new_daily_metric = DailyMetric.get_or_create_today_metric()
assert new_daily_metric.nb_alias == nb_alias + 1
def test_add_alias_multiple_mailboxes(flask_client):
user = login(flask_client)
Session.commit()