FitTrackee/fittrackee/users/commands.py

153 lines
4.7 KiB
Python
Raw Permalink Normal View History

import logging
from typing import Optional
2022-04-23 11:20:43 +02:00
import click
from humanize import naturalsize
2022-04-23 11:20:43 +02:00
2023-04-12 09:57:41 +02:00
from fittrackee import db
2022-04-23 11:20:43 +02:00
from fittrackee.cli.app import app
from fittrackee.users.exceptions import UserNotFoundException
from fittrackee.users.export_data import (
clean_user_data_export,
generate_user_data_archives,
)
from fittrackee.users.utils.admin import UserManagerService
from fittrackee.users.utils.token import clean_blacklisted_tokens
handler = logging.StreamHandler()
logger = logging.getLogger('fittrackee_users_cli')
logger.setLevel(logging.INFO)
logger.addHandler(handler)
2022-04-23 11:20:43 +02:00
@click.group(name='users')
def users_cli() -> None:
"""Manage users."""
pass
2023-04-12 09:57:41 +02:00
@users_cli.command('create')
@click.argument('username')
@click.option('--email', type=str, required=True, help='User email.')
@click.option(
'--password',
type=str,
help='User password. If not provided, a random password is generated.',
)
def create_user(username: str, email: str, password: Optional[str]) -> None:
"""Create an active user account."""
with app.app_context():
try:
user_manager_service = UserManagerService(username)
user, user_password = user_manager_service.create_user(
email=email, password=password, check_email=True
2023-04-12 09:57:41 +02:00
)
db.session.add(user)
db.session.commit()
user_manager_service.update(activate=True)
click.echo(f"User '{username}' created.")
if not password:
click.echo(f"The user password is: {user_password}")
except Exception as e:
click.echo(f'Error(s) occurred:\n{e}', err=True)
@users_cli.command('update')
2022-04-23 11:20:43 +02:00
@click.argument('username')
@click.option(
'--set-admin',
type=bool,
help='Add/remove admin rights (when adding admin rights, '
'it also activates user account if not active).',
)
@click.option('--activate', is_flag=True, help='Activate user account.')
@click.option(
'--reset-password',
is_flag=True,
help='Reset user password (a new password will be displayed).',
)
@click.option('--update-email', type=str, help='Update user email.')
def manage_user(
username: str,
set_admin: Optional[bool],
activate: bool,
reset_password: bool,
update_email: Optional[str],
) -> None:
"""Manage given user account."""
2022-04-23 11:20:43 +02:00
with app.app_context():
try:
user_manager_service = UserManagerService(username)
_, is_user_updated, password = user_manager_service.update(
is_admin=set_admin,
with_confirmation=False,
activate=activate,
reset_password=reset_password,
new_email=update_email,
)
if is_user_updated:
click.echo(f"User '{username}' updated.")
if password:
click.echo(f"The new password is: {password}")
else:
click.echo("No updates.")
2022-04-23 11:20:43 +02:00
except UserNotFoundException:
click.echo(
f"User '{username}' not found.\n"
"Check the provided user name (case sensitive).",
err=True,
)
except Exception as e:
click.echo(f'An error occurred: {e}', err=True)
@users_cli.command('clean_tokens')
@click.option('--days', type=int, required=True, help='Number of days.')
def clean(
days: int,
) -> None:
"""
Clean blacklisted tokens expired for more than provided number of days.
"""
with app.app_context():
deleted_rows = clean_blacklisted_tokens(days)
logger.info(f'Blacklisted tokens deleted: {deleted_rows}.')
@users_cli.command('clean_archives')
@click.option('--days', type=int, required=True, help='Number of days.')
def clean_export_archives(
days: int,
) -> None:
"""
Clean user export archives created for more than provided number of days.
"""
with app.app_context():
counts = clean_user_data_export(days)
logger.info(
f'Deleted data export requests: {counts["deleted_requests"]}.'
)
logger.info(
f'Deleted data export archives: {counts["deleted_archives"]}.'
)
logger.info(f'Freed space: {naturalsize(counts["freed_space"])}.')
@users_cli.command('export_archives')
@click.option(
'--max',
type=int,
required=True,
2023-03-04 17:49:02 +01:00
help='Maximum number of export requests to process.',
)
def export_archives(
max: int,
) -> None:
"""
Export user data in zip archive if incomplete requests exist.
To use in case redis is not set.
"""
with app.app_context():
count = generate_user_data_archives(max)
logger.info(f'Generated data export archives: {count}.')