mirror of
https://github.com/simple-login/app.git
synced 2024-09-20 15:05:59 +08:00
reduce subdomain/directory quota when user create/delete subdomain/directory
This commit is contained in:
parent
85c6e791bc
commit
38ecb227b0
|
@ -114,7 +114,7 @@ def directory():
|
|||
flash("Only premium plan can add directory", "warning")
|
||||
return redirect(url_for("dashboard.directory"))
|
||||
|
||||
if current_user.nb_directory() >= MAX_NB_DIRECTORY:
|
||||
if current_user.directory_quota <= 0:
|
||||
flash(
|
||||
f"You cannot have more than {MAX_NB_DIRECTORY} directories",
|
||||
"warning",
|
||||
|
|
|
@ -28,7 +28,7 @@ def subdomain_route():
|
|||
flash("Only premium plan can add subdomain", "warning")
|
||||
return redirect(request.url)
|
||||
|
||||
if len(subdomains) >= MAX_NB_SUBDOMAIN:
|
||||
if current_user.subdomain_quota <= 0:
|
||||
flash(
|
||||
f"You can't create more than {MAX_NB_SUBDOMAIN} subdomains", "error"
|
||||
)
|
||||
|
@ -88,5 +88,4 @@ def subdomain_route():
|
|||
sl_domains=sl_domains,
|
||||
errors=errors,
|
||||
subdomains=subdomains,
|
||||
can_create=len(subdomains) < MAX_NB_SUBDOMAIN,
|
||||
)
|
||||
|
|
|
@ -2016,6 +2016,11 @@ class CustomDomain(Base, ModelMixin):
|
|||
domain.ownership_txt_token = random_string(30)
|
||||
Session.commit()
|
||||
|
||||
if domain.is_sl_subdomain:
|
||||
user = domain.user
|
||||
user._subdomain_quota -= 1
|
||||
Session.flush()
|
||||
|
||||
return domain
|
||||
|
||||
@classmethod
|
||||
|
@ -2024,6 +2029,10 @@ class CustomDomain(Base, ModelMixin):
|
|||
if obj.is_sl_subdomain:
|
||||
DeletedSubdomain.create(domain=obj.domain)
|
||||
|
||||
user = obj.user
|
||||
user._subdomain_quota -= 1
|
||||
Session.flush()
|
||||
|
||||
return super(CustomDomain, cls).delete(obj_id)
|
||||
|
||||
@property
|
||||
|
@ -2166,7 +2175,14 @@ class Directory(Base, ModelMixin):
|
|||
if DeletedDirectory.get_by(name=name):
|
||||
raise DirectoryInTrashError
|
||||
|
||||
return super(Directory, cls).create(*args, **kwargs)
|
||||
directory = super(Directory, cls).create(*args, **kwargs)
|
||||
Session.flush()
|
||||
|
||||
user = directory.user
|
||||
user._directory_quota -= 1
|
||||
|
||||
Session.flush()
|
||||
return directory
|
||||
|
||||
@classmethod
|
||||
def delete(cls, obj_id):
|
||||
|
@ -2180,6 +2196,10 @@ class Directory(Base, ModelMixin):
|
|||
|
||||
DeletedDirectory.create(name=obj.name)
|
||||
cls.filter(cls.id == obj_id).delete()
|
||||
|
||||
user = obj.user
|
||||
user._directory_quota -= 1
|
||||
|
||||
Session.commit()
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="row {% if current_user.directory_quota <= 0 %} disabled-content {% endif %}">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
|
@ -148,7 +148,10 @@
|
|||
{{ new_dir_form.csrf_token }}
|
||||
<input type="hidden" name="form-name" value="create">
|
||||
|
||||
<h2 class="h4">New Directory</h2>
|
||||
<h2 class="h4 mb-1">New Directory</h2>
|
||||
<div class="small-text mb-4">
|
||||
You can create up to {{ current_user.directory_quota }} directories.
|
||||
</div>
|
||||
|
||||
{{ new_dir_form.name(class="form-control", placeholder="my-directory",
|
||||
pattern="[0-9a-z-_]{3,}",
|
||||
|
@ -195,7 +198,8 @@
|
|||
let directory = $(this).parent().find(".dir-name").val();
|
||||
|
||||
let that = $(this);
|
||||
let message = `All aliases associated with <b>${directory}</b> directory will also be deleted, ` +
|
||||
let message = `All aliases associated with <b>${directory}</b> directory will also be deleted. ` +
|
||||
`Your directory quota will be {{ current_user.directory_quota - 1 }} after the deletion, ` +
|
||||
" please confirm.";
|
||||
|
||||
bootbox.confirm({
|
||||
|
|
|
@ -128,11 +128,24 @@
|
|||
</div>
|
||||
|
||||
<hr>
|
||||
<h3 class="mb-1">Delete Domain</h3>
|
||||
<h3 class="mb-1">
|
||||
{% if custom_domain.is_sl_subdomain %}
|
||||
Delete Subdomain
|
||||
{% else %}
|
||||
Delete Domain
|
||||
{% endif %}
|
||||
</h3>
|
||||
|
||||
<div class="mb-3">This operation is <b>irreversible</b>.
|
||||
All aliases associated with this domain will be deleted.
|
||||
{% if custom_domain.is_sl_subdomain %}
|
||||
<br>
|
||||
After deletion, your subdomain quota will be {{ current_user.subdomain_quota - 1 }}.
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden" name="form-name" value="delete">
|
||||
<span class="delete-custom-domain btn btn-danger">Delete domain</span>
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
|
||||
<div class="alert alert-primary collapse {% if not subdomains %} show {% endif %}" id="howtouse" role="alert">
|
||||
You can use subdomain to quickly create email aliases without opening SimpleLogin app. <br>
|
||||
Handy when you need to quickly give out an email address, for example on a phone call, in a meeting or just anywhere you want. <br>
|
||||
Handy when you need to quickly give out an email address, for example on a phone call, in a meeting or just
|
||||
anywhere you want. <br>
|
||||
After choosing a subdomain, simply use <b>anything@my-subdomain.simplelogin.co</b>
|
||||
next time you need an alias:
|
||||
it'll be <b>automatically created</b> the first time it receives an email. <br>
|
||||
|
@ -61,12 +62,15 @@
|
|||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="row {% if not can_create %} disabled-content {% endif %}" id="new-subdomain" >
|
||||
<div class="row {% if current_user.subdomain_quota <= 0 %} disabled-content {% endif %}" id="new-subdomain">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
|
||||
<h2 class="h4">New Subdomain</h2>
|
||||
<h2 class="h4 mb-1">New Subdomain</h2>
|
||||
<div class="small-text mb-4">
|
||||
You can create up to {{ current_user.subdomain_quota }} subdomains.
|
||||
</div>
|
||||
|
||||
<form method="post" class="mt-2" data-parsley-validate>
|
||||
<input type="hidden" name="form-name" value="create">
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.config import MAX_NB_DIRECTORY
|
||||
from app.models import Directory
|
||||
from tests.utils import login
|
||||
|
||||
|
@ -56,3 +57,21 @@ def test_create_directory_in_trash(flask_client):
|
|||
|
||||
assert r.status_code == 200
|
||||
assert "test has been used before and cannot be reused" in r.data.decode()
|
||||
|
||||
|
||||
def test_create_directory_out_of_quota(flask_client):
|
||||
user = login(flask_client)
|
||||
|
||||
for i in range(MAX_NB_DIRECTORY):
|
||||
Directory.create(name=f"test{i}", user_id=user.id, commit=True)
|
||||
|
||||
assert Directory.count() == MAX_NB_DIRECTORY
|
||||
|
||||
flask_client.post(
|
||||
url_for("dashboard.directory"),
|
||||
data={"form-name": "create", "name": "test"},
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
# no new directory is created
|
||||
assert Directory.count() == MAX_NB_DIRECTORY
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.config import MAX_NB_SUBDOMAIN
|
||||
from app.db import Session
|
||||
from app.models import SLDomain, CustomDomain, Job
|
||||
from tests.utils import login
|
||||
|
@ -81,3 +82,27 @@ def test_create_subdomain_in_trash(flask_client):
|
|||
f"test.{sl_domain.domain} has been used before and cannot be reused"
|
||||
in r.data.decode()
|
||||
)
|
||||
|
||||
|
||||
def test_create_subdomain_out_of_quota(flask_client):
|
||||
user = login(flask_client)
|
||||
sl_domain = setup_sl_domain()
|
||||
|
||||
for i in range(MAX_NB_SUBDOMAIN):
|
||||
CustomDomain.create(
|
||||
domain=f"test{i}.{sl_domain.domain}",
|
||||
user_id=user.id,
|
||||
is_sl_subdomain=True,
|
||||
commit=True,
|
||||
)
|
||||
|
||||
assert CustomDomain.count() == MAX_NB_SUBDOMAIN
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("dashboard.subdomain_route"),
|
||||
data={"form-name": "create", "subdomain": "test", "domain": sl_domain.domain},
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
# no new subdomain is created
|
||||
assert CustomDomain.count() == MAX_NB_SUBDOMAIN
|
||||
|
|
Loading…
Reference in a new issue