<commit_before># -*- coding: utf-8 -*-
#
# http://www.privacyidea.org
# (c) <NAME>, privacyidea.org
#
# 2019-09-04 <NAME> <<EMAIL>>
#            Add decorators for event handling
# 2016-07-12 <NAME> <<EMAIL>>
#            Add decorator for checking realmadmin realms during userlist
# 2014-12-08 <NAME>, <<EMAIL>>
#            Complete rewrite during flask migration
#            Try to provide REST API
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
# License as published by the Free Software Foundation; either
# version 3 of the License, or any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU AFFERO GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

from flask import (Blueprint,
                   request)
from .lib.utils import (getParam,
                        send_result)
from ..api.lib.prepolicy import (prepolicy, check_base_action, realmadmin,
                                 check_custom_user_attributes)
from ..lib.policy import ACTION, get_allowed_custom_attributes
from privacyidea.api.auth import admin_required, user_required
from privacyidea.lib.user import create_user, User, is_attribute_at_all
from privacyidea.lib.event import event


from flask import (g)
from ..lib.user import get_user_list
import logging


log = logging.getLogger(__name__)


user_blueprint = Blueprint('user_blueprint', __name__)


@user_blueprint.route('/', methods=['GET'])
@prepolicy(realmadmin, request, ACTION.USERLIST)
@prepolicy(check_base_action, request, ACTION.USERLIST)
@user_required
@event("user_list", request, g)
def get_users():
    """
    list the users in a realm

    A normal user can call this endpoint and will get information about his
    own account.

    :param realm: a realm that contains several resolvers. Only show users
                  from this realm
    :param resolver: a distinct resolvername
    :param <searchexpr>: a search expression, that depends on the ResolverClass
    
    :return: json result with "result": true and the userlist in "value".

    **Example request**:

    .. sourcecode:: http

       GET /user?realm=realm1 HTTP/1.1
       Host: example.com
       Accept: application/json

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

        {
          "id": 1,
          "jsonrpc": "2.0",
          "result": {
            "status": true,
            "value": [
              {
                "description": "<NAME>\u00f6lbel,,+49 151 2960 1417,+49 561 3166797,<EMAIL>",
                "email": "<EMAIL>",
                "givenname": "Cornelius",
                "mobile": "+49 151 2960 1417",
                "phone": "+49 561 3166797",
                "surname": "K\u00f6lbel",
                "userid": "1009",
                "username": "cornelius",
                "resolver": "name-of-resolver"
              }
            ]
          },
          "version": "privacyIDEA unknown"
        }
    """
    realm = getParam(request.all_data, "realm")
    attr = is_attribute_at_all()
    users = get_user_list(request.all_data, custom_attributes=attr)

    g.audit_object.log({'success': True,
                        'info': "realm: {0!s}".format(realm)})
    
    return send_result(users)


@user_blueprint.route('/attribute', methods=['POST'])
@prepolicy(check_custom_user_attributes, request, "set")
@user_required
@event("set_custom_user_attribute", request, g)
def set_user_attribute():
    """
    Set a custom attribute for a user.
    The user is specified by the usual parameters user, resolver and realm.

    :httpparam key: The name of the attributes
    :httpparam value: The value of the attribute
    :httpparam type: an optional type of the attribute

    The database id of the attribute is returned. The return
    value thus should be >=0.
    """
    # We basically need a user, otherwise we will fail, but the
    # user object is later simply used from request.User. We only
    # need to avoid an empty User object.
    _user = getParam(request.all_data, "user", optional=False)
    attrkey = getParam(request.all_data, "key", optional=False)
    attrvalue = getParam(request.all_data, "value", optional=False)<commit_msg>Add the user parameter to the docstring to be more clear<commit_after># -*- coding: utf-8 -*-
#
# http://www.privacyidea.org
# (c) <NAME>, privacyidea.org
#
# 2019-09-04 <NAME> <<EMAIL>>
#            Add decorators for event handling
# 2016-07-12 <NAME> <<EMAIL>>
#            Add decorator for checking realmadmin realms during userlist
# 2014-12-08 <NAME>, <<EMAIL>>
#            Complete rewrite during flask migration
#            Try to provide REST API
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
# License as published by the Free Software Foundation; either
# version 3 of the License, or any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU AFFERO GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

from flask import (Blueprint,
                   request)
from .lib.utils import (getParam,
                        send_result)
from ..api.lib.prepolicy import (prepolicy, check_base_action, realmadmin,
                                 check_custom_user_attributes)
from ..lib.policy import ACTION, get_allowed_custom_attributes
from privacyidea.api.auth import admin_required, user_required
from privacyidea.lib.user import create_user, User, is_attribute_at_all
from privacyidea.lib.event import event


from flask import (g)
from ..lib.user import get_user_list
import logging


log = logging.getLogger(__name__)


user_blueprint = Blueprint('user_blueprint', __name__)


@user_blueprint.route('/', methods=['GET'])
@prepolicy(realmadmin, request, ACTION.USERLIST)
@prepolicy(check_base_action, request, ACTION.USERLIST)
@user_required
@event("user_list", request, g)
def get_users():
    """
    list the users in a realm

    A normal user can call this endpoint and will get information about his
    own account.

    :param realm: a realm that contains several resolvers. Only show users
                  from this realm
    :param resolver: a distinct resolvername
    :param <searchexpr>: a search expression, that depends on the ResolverClass
    
    :return: json result with "result": true and the userlist in "value".

    **Example request**:

    .. sourcecode:: http

       GET /user?realm=realm1 HTTP/1.1
       Host: example.com
       Accept: application/json

    **Example response**:

    .. sourcecode:: http

       HTTP/1.1 200 OK
       Content-Type: application/json

        {
          "id": 1,
          "jsonrpc": "2.0",
          "result": {
            "status": true,
            "value": [
              {
                "description": "Cornelius K\u00f6lbel,,+49 151 2960 1417,+49 561 3166797,<EMAIL>",
                "email": "<EMAIL>",
                "givenname": "Cornelius",
                "mobile": "+49 151 2960 1417",
                "phone": "+49 561 3166797",
                "surname": "K\u00f6lbel",
                "userid": "1009",
                "username": "cornelius",
                "resolver": "name-of-resolver"
              }
            ]
          },
          "version": "privacyIDEA unknown"
        }
    """
    realm = getParam(request.all_data, "realm")
    attr = is_attribute_at_all()
    users = get_user_list(request.all_data, custom_attributes=attr)

    g.audit_object.log({'success': True,
                        'info': "realm: {0!s}".format(realm)})
    
    return send_result(users)


@user_blueprint.route('/attribute', methods=['POST'])
@prepolicy(check_custom_user_attributes, request, "set")
@user_required
@event("set_custom_user_attribute", request, g)
def set_user_attribute():
    """
    Set a custom attribute for a user.
    The user is specified by the usual parameters user, resolver and realm.
    When a user is calling the endpoint the parameters will be implicitly set.

    :httpparam user: The username of the user, for whom the attribute should be set
    :httpparam resolver: The resolver of the user (optional)
    :httpparam realm: The realm of the user (optional)
    :httpparam key: The name of the attributes
    :httpparam value: The value of the attribute
    :httpparam type: an optional type of the attribute

    The database id of the attribute is returned. The return
    value thus should be >=0.
    """
    # We basically need a user, otherwise we will fail, but the
    # user object is later simply used from request.User. We only
    # need to avoid an empty User object.
    _user = getParam(request.all_data, "user", optional=False)
    attrkey = getParam(request.all_data, "key", optional=False)
    attrvalue = getParam(request.all_data, "value", optional=False)
{'fraction_non_alphanumeric': 0.09886975810710891, 'fraction_numerical': 0.020914756522657653, 'mean_word_length': 2.754163362410785, 'pattern_counts': {'":': 32, '<': 32, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '777101', 'n_tokens_mistral': 2880, 'n_tokens_neox': 2650, 'n_words': 947}