Compare commits
2 Commits
7f1724bfa8
...
f5b082cc99
Author | SHA1 | Date |
---|---|---|
Adrià Casajús | f5b082cc99 | |
Son Nguyen Kim | d5df91aab6 |
|
@ -68,6 +68,12 @@ For most tests, you will need to have ``redis`` installed and started on your ma
|
||||||
sh scripts/run-test.sh
|
sh scripts/run-test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can also run tests using a local Postgres DB to speed things up. This can be done by
|
||||||
|
|
||||||
|
- creating an empty test DB and running the database migration by `dropdb test && createdb test && DB_URI=postgresql://localhost:5432/test alembic upgrade head`
|
||||||
|
|
||||||
|
- replacing the `DB_URI` in `test.env` file by `DB_URI=postgresql://localhost:5432/test`
|
||||||
|
|
||||||
## Run the code locally
|
## Run the code locally
|
||||||
|
|
||||||
Install npm packages
|
Install npm packages
|
||||||
|
|
|
@ -227,6 +227,21 @@ def setting():
|
||||||
Session.commit()
|
Session.commit()
|
||||||
flash("Your preference has been updated", "success")
|
flash("Your preference has been updated", "success")
|
||||||
return redirect(url_for("dashboard.setting"))
|
return redirect(url_for("dashboard.setting"))
|
||||||
|
elif request.form.get("form-name") == "enable_data_breach_check":
|
||||||
|
if not current_user.is_premium():
|
||||||
|
flash("Only premium plan can enable data breach monitoring", "warning")
|
||||||
|
return redirect(url_for("dashboard.setting"))
|
||||||
|
choose = request.form.get("enable_data_breach_check")
|
||||||
|
if choose == "on":
|
||||||
|
LOG.i("User {current_user} has enabled data breach monitoring")
|
||||||
|
current_user.enable_data_breach_check = True
|
||||||
|
flash("Data breach monitoring is enabled", "success")
|
||||||
|
else:
|
||||||
|
LOG.i("User {current_user} has disabled data breach monitoring")
|
||||||
|
current_user.enable_data_breach_check = False
|
||||||
|
flash("Data breach monitoring is disabled", "info")
|
||||||
|
Session.commit()
|
||||||
|
return redirect(url_for("dashboard.setting"))
|
||||||
elif request.form.get("form-name") == "sender-in-ra":
|
elif request.form.get("form-name") == "sender-in-ra":
|
||||||
choose = request.form.get("enable")
|
choose = request.form.get("enable")
|
||||||
if choose == "on":
|
if choose == "on":
|
||||||
|
|
|
@ -525,6 +525,11 @@ class User(Base, ModelMixin, UserMixin, PasswordOracle):
|
||||||
sa.Boolean, default=True, nullable=False, server_default="1"
|
sa.Boolean, default=True, nullable=False, server_default="1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# user opted in for data breach check
|
||||||
|
enable_data_breach_check = sa.Column(
|
||||||
|
sa.Boolean, default=False, nullable=False, server_default="0"
|
||||||
|
)
|
||||||
|
|
||||||
# bitwise flags. Allow for future expansion
|
# bitwise flags. Allow for future expansion
|
||||||
flags = sa.Column(
|
flags = sa.Column(
|
||||||
sa.BigInteger,
|
sa.BigInteger,
|
||||||
|
|
1
cron.py
1
cron.py
|
@ -1070,6 +1070,7 @@ def get_alias_to_check_hibp(
|
||||||
Alias.id >= min_alias_id,
|
Alias.id >= min_alias_id,
|
||||||
Alias.id < max_alias_id,
|
Alias.id < max_alias_id,
|
||||||
User.disabled == False, # noqa: E712
|
User.disabled == False, # noqa: E712
|
||||||
|
User.enable_data_breach_check,
|
||||||
or_(
|
or_(
|
||||||
User.lifetime,
|
User.lifetime,
|
||||||
ManualSubscription.end_at > now,
|
ManualSubscription.end_at > now,
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: fa2f19bb4e5a
|
||||||
|
Revises: 52510a633d6f
|
||||||
|
Create Date: 2024-04-09 13:12:26.305340
|
||||||
|
|
||||||
|
"""
|
||||||
|
import sqlalchemy_utils
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'fa2f19bb4e5a'
|
||||||
|
down_revision = '52510a633d6f'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('users', sa.Column('enable_data_breach_check', sa.Boolean(), server_default='0', nullable=False))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('users', 'enable_data_breach_check')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -249,6 +249,42 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- END Random alias -->
|
<!-- END Random alias -->
|
||||||
|
<!-- Data breach check -->
|
||||||
|
<div class="card" id="data-breach">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title">Data breach monitoring</div>
|
||||||
|
<div class="mt-1 mb-3">
|
||||||
|
{% if not current_user.is_premium() %}
|
||||||
|
|
||||||
|
<div class="alert alert-info" role="alert">
|
||||||
|
This feature is only available on Premium plan.
|
||||||
|
<a href="{{ url_for('dashboard.pricing') }}"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
|
Upgrade<i class="fe fe-external-link"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
If enabled, we will inform you via email if one of your aliases appears in a data breach.
|
||||||
|
<br>
|
||||||
|
SimpleLogin uses <a href="https://haveibeenpwned.com/">HaveIBeenPwned</a> API for checking for data breaches.
|
||||||
|
</div>
|
||||||
|
<form method="post" action="#data-breach">
|
||||||
|
{{ csrf_form.csrf_token }}
|
||||||
|
<input type="hidden" name="form-name" value="enable_data_breach_check">
|
||||||
|
<div class="form-check">
|
||||||
|
<input type="checkbox"
|
||||||
|
id="enable_data_breach_check"
|
||||||
|
name="enable_data_breach_check"
|
||||||
|
{% if current_user.enable_data_breach_check %} checked{% endif %}
|
||||||
|
class="form-check-input">
|
||||||
|
<label for="enable_data_breach_check">Enable data breach monitoring</label>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-outline-primary">Update</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- END Data breach check -->
|
||||||
<!-- Sender Format -->
|
<!-- Sender Format -->
|
||||||
<div class="card" id="sender-format">
|
<div class="card" id="sender-format">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@ -285,7 +321,9 @@
|
||||||
No Name (i.e. only reverse-alias)
|
No Name (i.e. only reverse-alias)
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="btn btn-outline-primary mt-3">Update</button>
|
<button class="btn btn-outline-primary mt-3">
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -295,7 +333,9 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-title">
|
<div class="card-title">
|
||||||
Reverse Alias Replacement
|
Reverse Alias Replacement
|
||||||
<div class="badge badge-warning">Experimental</div>
|
<div class="badge badge-warning">
|
||||||
|
Experimental
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
When replying to a forwarded email, the <b>reverse-alias</b> can be automatically included
|
When replying to a forwarded email, the <b>reverse-alias</b> can be automatically included
|
||||||
|
@ -312,9 +352,13 @@
|
||||||
name="replace-ra"
|
name="replace-ra"
|
||||||
{% if current_user.replace_reverse_alias %} checked{% endif %}
|
{% if current_user.replace_reverse_alias %} checked{% endif %}
|
||||||
class="form-check-input">
|
class="form-check-input">
|
||||||
<label for="replace-ra">Enable replacing reverse alias</label>
|
<label for="replace-ra">
|
||||||
|
Enable replacing reverse alias
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-outline-primary">Update</button>
|
<button type="submit" class="btn btn-outline-primary">
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,6 +31,7 @@ def test_get_alias_for_free_user_has_no_alias():
|
||||||
def test_get_alias_for_lifetime_with_null_hibp_date():
|
def test_get_alias_for_lifetime_with_null_hibp_date():
|
||||||
user = create_new_user()
|
user = create_new_user()
|
||||||
user.lifetime = True
|
user.lifetime = True
|
||||||
|
user.enable_data_breach_check = True
|
||||||
alias_id = Alias.create_new_random(user).id
|
alias_id = Alias.create_new_random(user).id
|
||||||
Session.commit()
|
Session.commit()
|
||||||
aliases = list(
|
aliases = list(
|
||||||
|
@ -42,6 +43,7 @@ def test_get_alias_for_lifetime_with_null_hibp_date():
|
||||||
def test_get_alias_for_lifetime_with_old_hibp_date():
|
def test_get_alias_for_lifetime_with_old_hibp_date():
|
||||||
user = create_new_user()
|
user = create_new_user()
|
||||||
user.lifetime = True
|
user.lifetime = True
|
||||||
|
user.enable_data_breach_check = True
|
||||||
alias = Alias.create_new_random(user)
|
alias = Alias.create_new_random(user)
|
||||||
alias.hibp_last_check = arrow.now().shift(days=-1)
|
alias.hibp_last_check = arrow.now().shift(days=-1)
|
||||||
alias_id = alias.id
|
alias_id = alias.id
|
||||||
|
@ -97,6 +99,7 @@ sub_generator_list = [
|
||||||
@pytest.mark.parametrize("sub_generator", sub_generator_list)
|
@pytest.mark.parametrize("sub_generator", sub_generator_list)
|
||||||
def test_get_alias_for_sub(sub_generator):
|
def test_get_alias_for_sub(sub_generator):
|
||||||
user = create_new_user()
|
user = create_new_user()
|
||||||
|
user.enable_data_breach_check = True
|
||||||
sub_generator(user)
|
sub_generator(user)
|
||||||
alias_id = Alias.create_new_random(user).id
|
alias_id = Alias.create_new_random(user).id
|
||||||
Session.commit()
|
Session.commit()
|
||||||
|
@ -140,3 +143,26 @@ def test_already_checked_is_not_checked():
|
||||||
cron.get_alias_to_check_hibp(arrow.now(), [user.id], alias_id, alias_id + 1)
|
cron.get_alias_to_check_hibp(arrow.now(), [user.id], alias_id, alias_id + 1)
|
||||||
)
|
)
|
||||||
assert len(aliases) == 0
|
assert len(aliases) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_outed_in_user_is_checked():
|
||||||
|
user = create_new_user()
|
||||||
|
user.lifetime = True
|
||||||
|
user.enable_data_breach_check = True
|
||||||
|
alias_id = Alias.create_new_random(user).id
|
||||||
|
Session.commit()
|
||||||
|
aliases = list(
|
||||||
|
cron.get_alias_to_check_hibp(arrow.now(), [], alias_id, alias_id + 1)
|
||||||
|
)
|
||||||
|
assert len(aliases) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_outed_out_user_is_not_checked():
|
||||||
|
user = create_new_user()
|
||||||
|
user.lifetime = True
|
||||||
|
alias_id = Alias.create_new_random(user).id
|
||||||
|
Session.commit()
|
||||||
|
aliases = list(
|
||||||
|
cron.get_alias_to_check_hibp(arrow.now(), [], alias_id, alias_id + 1)
|
||||||
|
)
|
||||||
|
assert len(aliases) == 0
|
||||||
|
|
Loading…
Reference in New Issue