Skip to content

Commit 5fb71e9

Browse files
authored
Allow disabling registration, treat admins like owners in single-tree setup (#484)
* Allow disabling registration; Do not disable registration in single-tree setup if only admin exists * Send new user e-mail also to admins for single-tree
1 parent 1b058f9 commit 5fb71e9

File tree

4 files changed

+38
-9
lines changed

4 files changed

+38
-9
lines changed

gramps_webapi/api/resources/user.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import datetime
2323
from gettext import gettext as _
24-
from typing import Tuple
24+
from typing import Optional, Tuple
2525

2626
from flask import abort, current_app, jsonify, render_template, request
2727
from flask_jwt_extended import create_access_token, get_jwt, get_jwt_identity
@@ -296,6 +296,22 @@ def delete(self, user_name: str):
296296
class UserRegisterResource(Resource):
297297
"""Resource for registering a new user."""
298298

299+
def _is_disabled(self, tree: Optional[str]) -> bool:
300+
"""Check if the registration is disabled."""
301+
if current_app.config["REGISTRATION_DISABLED"]:
302+
return True
303+
# check if there are tree owners or, in a single-tree setup,
304+
# tree admins
305+
if current_app.config["TREE"] == TREE_MULTI:
306+
roles = (ROLE_OWNER,)
307+
else:
308+
roles = (ROLE_OWNER, ROLE_ADMIN)
309+
if get_number_users(tree=tree, roles=roles) == 0:
310+
# no users authorized to enable new accounts:
311+
# registration disabled
312+
return True
313+
return False
314+
299315
@limiter.limit("1/second")
300316
@use_args(
301317
{
@@ -315,7 +331,7 @@ def post(self, args, user_name: str):
315331
# if multi-tree is enabled, tree is required
316332
abort_with_message(422, "tree is required")
317333
# do not allow registration if no tree owner account exists!
318-
if get_number_users(tree=args.get("tree"), roles=(ROLE_OWNER,)) == 0:
334+
if self._is_disabled(tree=args.get("tree")):
319335
abort_with_message(405, "Registration is disabled")
320336
if (
321337
"tree" in args
@@ -542,12 +558,15 @@ def get(self):
542558
# otherwise it has been confirmed already
543559
modify_user(name=username, role=ROLE_DISABLED)
544560
tree = get_tree_from_jwt()
561+
is_multi = current_app.config["TREE"] == TREE_MULTI
545562
run_task(
546563
send_email_new_user,
547564
username=username,
548565
fullname=current_details.get("full_name", ""),
549566
email=claims["email"],
550567
tree=tree,
568+
# for single-tree setups, send e-mail also to admins
569+
include_admins=not is_multi,
551570
)
552571
title = _("E-mail address confirmation")
553572
message = _("Thank you for confirming your e-mail address.")

gramps_webapi/api/tasks.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,16 @@ def send_email_confirm_email(email: str, token: str):
8080

8181

8282
@shared_task()
83-
def send_email_new_user(username: str, fullname: str, email: str, tree: str):
83+
def send_email_new_user(
84+
username: str, fullname: str, email: str, tree: str, include_admins: bool
85+
):
8486
"""Send an email to owners to notify of a new registered user."""
8587
base_url = get_config("BASE_URL").rstrip("/")
8688
body = email_new_user(
8789
base_url=base_url, username=username, fullname=fullname, email=email
8890
)
8991
subject = _("New registered user")
90-
emails = get_owner_emails(tree=tree)
92+
emails = get_owner_emails(tree=tree, include_admins=include_admins)
9193
if emails:
9294
send_email(subject=subject, body=body, to=emails)
9395

gramps_webapi/auth/__init__.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from sqlalchemy.sql.functions import coalesce
3232

3333
from ..const import DB_CONFIG_ALLOWED_KEYS
34-
from .const import PERMISSIONS, ROLE_OWNER
34+
from .const import PERMISSIONS, ROLE_ADMIN, ROLE_OWNER
3535
from .passwords import hash_password, verify_password
3636
from .sql_guid import GUID
3737

@@ -239,11 +239,18 @@ def get_permissions(username: str) -> Set[str]:
239239
return PERMISSIONS[user.role]
240240

241241

242-
def get_owner_emails(tree: str) -> List[str]:
243-
"""Get e-mail addresses of all tree owners."""
242+
def get_owner_emails(tree: str, include_admins: bool = False) -> List[str]:
243+
"""Get e-mail addresses of all tree owners (and optionally include site admins)."""
244244
query = user_db.session.query(User) # pylint: disable=no-member
245-
owners = query.filter_by(tree=tree, role=ROLE_OWNER).all()
246-
return [user.email for user in owners if user.email]
245+
if include_admins:
246+
users = (
247+
query.filter_by(tree=tree)
248+
.filter(sa.or_(User.role == ROLE_OWNER, User.role == ROLE_ADMIN))
249+
.all()
250+
)
251+
else:
252+
users = query.filter_by(tree=tree, role=ROLE_OWNER).all()
253+
return [user.email for user in users if user.email]
247254

248255

249256
def get_number_users(

gramps_webapi/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class DefaultConfig(object):
5656
EXPORT_DIR = str(Path.cwd() / "export_cache")
5757
NEW_DB_BACKEND = "sqlite"
5858
RATE_LIMIT_MEDIA_ARCHIVE = "1 per day"
59+
REGISTRATION_DISABLED = False
5960

6061

6162
class DefaultConfigJWT(object):

0 commit comments

Comments
 (0)