Source code for hawat.blueprints.groups.forms
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# This file is part of Mentat system (https://mentat.cesnet.cz/).
#
# Copyright (C) since 2011 CESNET, z.s.p.o (http://www.ces.net/)
# Use of this source is governed by the MIT license, see LICENSE file.
# -------------------------------------------------------------------------------
"""
This module contains custom group management forms for Hawat.
"""
__author__ = "Jan Mach <jan.mach@cesnet.cz>"
__credits__ = "Pavel Kácha <pavel.kacha@cesnet.cz>, Andrea Kropáčová <andrea.kropacova@cesnet.cz>"
import sqlalchemy
import wtforms
from wtforms_sqlalchemy.fields import QuerySelectField, QuerySelectMultipleField
#
# Flask related modules.
#
from flask_babel import gettext, lazy_gettext
#
# Custom modules.
#
import hawat.db
import hawat.forms
from hawat.forms import get_available_users, get_available_group_sources
from mentat.datatype.sqldb import GroupModel
[docs]def check_name_existence(_form, field): # pylint: disable=locally-disabled,unused-argument
"""
Callback for validating user logins during account create action.
"""
try:
hawat.db.db_get().session.query(GroupModel). \
filter(GroupModel.name == field.data). \
one()
except sqlalchemy.orm.exc.NoResultFound:
return
except: # pylint: disable=locally-disabled,bare-except
pass
raise wtforms.validators.ValidationError(gettext('Group with this name already exists.'))
[docs]def check_name_uniqueness(form, field):
"""
Callback for validating user logins during account update action.
"""
item = hawat.db.db_get().session.query(GroupModel). \
filter(GroupModel.name == field.data). \
filter(GroupModel.id != form.db_item_id). \
all()
if not item:
return
raise wtforms.validators.ValidationError(gettext('Group with this name already exists.'))
[docs]def check_parent_not_self(form, field):
"""
Callback for validating that parent group is not self.
"""
if field.data and form.db_item_id == field.data.id:
raise wtforms.validators.ValidationError(
gettext('You must not select a group as its own parent! Naughty, naughty you!'))
[docs]def format_select_option_label_user(item):
"""
Format option for selection of user accounts.
"""
return "{} ({})".format(item.fullname, item.login)
[docs]def get_available_groups():
"""
Query the database for list of all available groups.
"""
return hawat.db.db_query(GroupModel).order_by(GroupModel.name).all()
[docs]class BaseGroupForm(hawat.forms.BaseItemForm):
"""
Class representing base group form.
"""
description = wtforms.StringField(
lazy_gettext('Description:'),
validators=[
wtforms.validators.DataRequired(),
hawat.forms.check_null_character
],
description=lazy_gettext('Additional and more extensive group description.')
)
source = wtforms.HiddenField(
default='manual',
validators=[
wtforms.validators.DataRequired(),
wtforms.validators.Length(min=3, max=50)
],
description=lazy_gettext(
'Origin of the group record, whether it was added manually, or via some automated mechanism from data from some third party system.')
)
members = QuerySelectMultipleField(
lazy_gettext('Members:'),
query_factory=hawat.forms.get_available_users,
get_label=format_select_option_label_user,
blank_text=lazy_gettext('<< no selection >>'),
description=lazy_gettext('List of group members.')
)
submit = wtforms.SubmitField(
lazy_gettext('Submit')
)
cancel = wtforms.SubmitField(
lazy_gettext('Cancel')
)
[docs]class UpdateGroupForm(BaseGroupForm):
"""
Class representing group update form for regular users.
"""
[docs]class AdminBaseGroupForm(BaseGroupForm):
"""
Class representing group create form.
"""
enabled = wtforms.RadioField(
lazy_gettext('State:'),
validators=[
wtforms.validators.InputRequired(),
],
choices=[
(True, lazy_gettext('Enabled')),
(False, lazy_gettext('Disabled'))
],
filters=[hawat.forms.str_to_bool],
coerce=hawat.forms.str_to_bool,
description=lazy_gettext(
'Boolean flag whether the group is enabled or disabled. Disabled groups are hidden to the most of the system features.')
)
managers = QuerySelectMultipleField(
lazy_gettext('Managers:'),
query_factory=hawat.forms.get_available_users,
get_label=format_select_option_label_user,
blank_text=lazy_gettext('<< no selection >>'),
description=lazy_gettext(
'List of users acting as group managers. These users may change various group settings.')
)
parent = QuerySelectField(
lazy_gettext('Parent group:'),
validators=[
wtforms.validators.Optional(),
check_parent_not_self
],
query_factory=hawat.forms.get_available_groups,
allow_blank=True,
blank_text=lazy_gettext('<< no selection >>'),
description=lazy_gettext(
'Parent group for this group. This feature enables the posibility to create structured group hierarchy.')
)
[docs]class AdminCreateGroupForm(AdminBaseGroupForm):
"""
Class representing group create form for administrators.
"""
name = wtforms.StringField(
lazy_gettext('Name:'),
validators=[
wtforms.validators.DataRequired(),
wtforms.validators.Length(min=3, max=100),
hawat.forms.check_unique_group
],
description=lazy_gettext('System-wide unique name for the group.')
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.db_item_id = None
[docs]class AdminUpdateGroupForm(AdminBaseGroupForm):
"""
Class representing group update form for administrators.
"""
name = wtforms.StringField(
lazy_gettext('Name:'),
validators=[
wtforms.validators.DataRequired(),
wtforms.validators.Length(min=3, max=100),
check_name_uniqueness,
hawat.forms.check_null_character
],
description=lazy_gettext('System-wide unique name for the group.')
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Store the ID of original item in database to enable the ID uniqueness
# check with check_name_uniqueness() validator.
self.db_item_id = kwargs['db_item_id']
[docs]class GroupSearchForm(hawat.forms.BaseSearchForm):
"""
Class representing simple user search form.
"""
search = wtforms.StringField(
lazy_gettext('Name, description:'),
validators=[
wtforms.validators.Optional(),
wtforms.validators.Length(min=3, max=100),
hawat.forms.check_null_character
],
description=lazy_gettext(
'Group`s full name or description. Search is performed even in the middle of the strings.')
)
dt_from = hawat.forms.SmartDateTimeField(
lazy_gettext('Creation time from:'),
validators=[
wtforms.validators.Optional()
],
description=lazy_gettext(
'Lower time boundary for item creation time. Timestamp is expected to be in the format <code>YYYY-MM-DD hh:mm:ss</code> and in the timezone according to the user`s preferences.')
)
dt_to = hawat.forms.SmartDateTimeField(
lazy_gettext('Creation time to:'),
validators=[
wtforms.validators.Optional()
],
description=lazy_gettext(
'Upper time boundary for item creation time. Timestamp is expected to be in the format <code>YYYY-MM-DD hh:mm:ss</code> and in the timezone according to the user`s preferences.')
)
state = wtforms.SelectField(
lazy_gettext('State:'),
validators=[
wtforms.validators.Optional(),
],
choices=[
('', lazy_gettext('Nothing selected')),
('enabled', lazy_gettext('Enabled')),
('disabled', lazy_gettext('Disabled'))
],
default='',
description=lazy_gettext('Search for groups with particular state.')
)
source = wtforms.SelectField(
lazy_gettext('Record source:'),
validators=[
wtforms.validators.Optional()
],
default='',
description=lazy_gettext('Search for groups coming from particular sources/feeds.')
)
members = QuerySelectField(
lazy_gettext('Group members:'),
query_factory=get_available_users,
allow_blank=True,
description=lazy_gettext('Search for groups with particular members.')
)
managers = QuerySelectField(
lazy_gettext('Group managers:'),
query_factory=get_available_users,
allow_blank=True,
description=lazy_gettext('Search for groups with particular managers.')
)
sortby = wtforms.SelectField(
lazy_gettext('Sort by:'),
validators=[
wtforms.validators.Optional()
],
choices=[
('createtime.desc', lazy_gettext('by creation time descending')),
('createtime.asc', lazy_gettext('by creation time ascending')),
('name.desc', lazy_gettext('by name descending')),
('name.asc', lazy_gettext('by name ascending'))
],
default='name.asc'
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
#
# Handle additional custom keywords.
#
# The list of choices for 'roles' attribute comes from outside of the
# form to provide as loose tie as possible to the outer application.
# Another approach would be to load available choices here with:
#
# roles = flask.current_app.config['ROLES']
#
# That would mean direct dependency on flask.Flask application.
source_list = get_available_group_sources()
self.source.choices = [('', lazy_gettext('Nothing selected'))] + list(zip(source_list, source_list))
[docs] @staticmethod
def is_multivalue(field_name):
"""
Check, if given form field is a multivalue field.
:param str field_name: Name of the form field.
:return: ``True``, if the field can contain multiple values, ``False`` otherwise.
:rtype: bool
"""
return False