user-groups: Add create API endpoint.

Significantly modified by tabbott for better security structure.
This commit is contained in:
Umair Khan
2017-11-01 14:04:16 +05:00
committed by Tim Abbott
parent 39ca38837e
commit 1bbe84af49
7 changed files with 116 additions and 2 deletions

View File

@@ -4,6 +4,7 @@ from typing import (
)
from mypy_extensions import TypedDict
import django.db.utils
from django.contrib.contenttypes.models import ContentType
from django.utils.html import escape
from django.utils.translation import ugettext as _
@@ -48,6 +49,7 @@ from zerver.lib.topic_mutes import (
add_topic_mute,
remove_topic_mute,
)
from zerver.lib.user_groups import create_user_group
from zerver.models import Realm, RealmEmoji, Stream, UserProfile, UserActivity, \
RealmDomain, \
Subscription, Recipient, Message, Attachment, UserMessage, RealmAuditLog, \
@@ -4183,3 +4185,10 @@ def do_update_user_custom_profile_data(user_profile, data):
update_or_create(user_profile=user_profile,
field_id=field['id'],
defaults={'value': field['value']})
def check_add_user_group(realm, name, initial_members, description):
# type: (Realm, Text, List[UserProfile], Text) -> None
try:
create_user_group(name, initial_members, realm, description=description)
except django.db.utils.IntegrityError:
raise JsonableError(_("User group '%s' already exists." % (name,)))

View File

@@ -1,9 +1,18 @@
from __future__ import absolute_import
from django.db import transaction
from django.utils.translation import ugettext as _
from zerver.lib.exceptions import JsonableError
from zerver.models import UserProfile, Realm, UserGroupMembership, UserGroup
from typing import Dict, Iterable, List, Text
def access_user_group_by_id(user_group_id: int, realm: Realm) -> UserGroup:
try:
user_group = UserGroup.objects.get(id=user_group_id, realm=realm)
except UserGroup.DoesNotExist:
raise JsonableError(_("Invalid user group"))
return user_group
def user_groups_in_realm(realm):
# type: (Realm) -> List[UserGroup]
user_groups = UserGroup.objects.filter(realm=realm)

View File

@@ -1,10 +1,11 @@
from typing import Text
from typing import List, Text
from django.utils.translation import ugettext as _
from zerver.lib.actions import do_change_full_name
from zerver.lib.request import JsonableError
from zerver.models import UserProfile, Service
from zerver.models import UserProfile, Service, Realm, \
get_user_profile_by_id
def check_full_name(full_name_raw):
# type: (Text) -> Text
@@ -43,3 +44,20 @@ def check_valid_interface_type(interface_type):
# type: (int) -> None
if interface_type not in Service.ALLOWED_INTERFACE_TYPES:
raise JsonableError(_('Invalid interface type'))
def user_ids_to_users(user_ids: List[int], realm: Realm) -> List[UserProfile]:
# TODO: Change this to do a single bulk query with
# generic_bulk_cached_fetch; it'll be faster.
#
# TODO: Consider adding a flag to control whether deactivated
# users should be included.
user_profiles = []
for user_id in user_ids:
try:
user_profile = get_user_profile_by_id(user_id)
except UserProfile.DoesNotExist:
raise JsonableError(_("Invalid user ID: %s" % (user_id,)))
if user_profile.realm != realm:
raise JsonableError(_("Invalid user ID: %s" % (user_id,)))
user_profiles.append(user_profile)
return user_profiles

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from typing import Any, List, Optional, Text
import ujson
import django
import mock
@@ -55,3 +56,39 @@ class UserGroupTestCase(ZulipTestCase):
with mock.patch('zerver.lib.user_groups.remove_user_from_user_group',
side_effect=Exception):
self.assertFalse(check_remove_user_from_user_group(othello, user_group))
class UserGroupAPITestCase(ZulipTestCase):
def test_user_group_create(self):
# type: () -> None
hamlet = self.example_user('hamlet')
# Test success
self.login(self.example_email("hamlet"))
params = {
'name': 'support',
'members': ujson.dumps([hamlet.id]),
'description': 'Support team',
}
result = self.client_post('/json/user_groups/create', info=params)
self.assert_json_success(result)
self.assert_length(UserGroup.objects.all(), 1)
# Test invalid member error
params = {
'name': 'backend',
'members': ujson.dumps([1111]),
'description': 'Backend team',
}
result = self.client_post('/json/user_groups/create', info=params)
self.assert_json_error(result, "Invalid user ID: 1111")
self.assert_length(UserGroup.objects.all(), 1)
# Test we cannot add hamlet again
params = {
'name': 'support',
'members': ujson.dumps([hamlet.id]),
'description': 'Support team',
}
result = self.client_post('/json/user_groups/create', info=params)
self.assert_json_error(result, "User group 'support' already exists.")
self.assert_length(UserGroup.objects.all(), 1)

View File

@@ -24,6 +24,7 @@ from zerver.models import UserProfile, Recipient, \
from zerver.lib.avatar import avatar_url
from zerver.lib.email_mirror import create_missed_message_address
from zerver.lib.exceptions import JsonableError
from zerver.lib.send_email import send_future_email
from zerver.lib.actions import (
get_emails_from_user_ids,
@@ -35,6 +36,7 @@ from zerver.lib.actions import (
)
from zerver.lib.topic_mutes import add_topic_mute
from zerver.lib.stream_topic import StreamTopicTarget
from zerver.lib.users import user_ids_to_users
from django.conf import settings
@@ -265,6 +267,18 @@ class UserProfileTest(ZulipTestCase):
self.assertFalse(m.called)
def test_user_ids_to_users(self) -> None:
real_user_ids = [
self.example_user('hamlet').id,
self.example_user('cordelia').id,
]
user_ids_to_users(real_user_ids, get_realm("zulip"))
with self.assertRaises(JsonableError):
user_ids_to_users([1234], get_realm("zephyr"))
with self.assertRaises(JsonableError):
user_ids_to_users(real_user_ids, get_realm("zephyr"))
class ActivateTest(ZulipTestCase):
def test_basics(self) -> None:
user = self.example_user('hamlet')

View File

@@ -0,0 +1,22 @@
from django.http import HttpResponse, HttpRequest
from typing import List, Text
from zerver.context_processors import get_realm_from_request
from zerver.lib.actions import check_add_user_group
from zerver.lib.request import has_request_variables, REQ
from zerver.lib.response import json_success, json_error
from zerver.lib.users import user_ids_to_users
from zerver.lib.validator import check_list, check_string, check_int, \
check_short_string
from zerver.models import UserProfile
@has_request_variables
def add_user_group(request, user_profile,
name=REQ(),
members=REQ(validator=check_list(check_int), default=[]),
description=REQ()):
# type: (HttpRequest, UserProfile, Text, List[int], Text) -> HttpResponse
user_profiles = user_ids_to_users(members, user_profile.realm)
check_add_user_group(user_profile.realm, name, user_profiles, description)
return json_success()

View File

@@ -27,6 +27,7 @@ import zerver.views.zephyr
import zerver.views.users
import zerver.views.unsubscribe
import zerver.views.integrations
import zerver.views.user_groups
import zerver.views.user_settings
import zerver.views.muting
import zerver.views.streams
@@ -214,6 +215,10 @@ v1_api_and_json_patterns = [
{'POST': 'zerver.views.push_notifications.add_android_reg_id',
'DELETE': 'zerver.views.push_notifications.remove_android_reg_id'}),
# user_groups -> zerver.views.user_groups
url(r'^user_groups/create$', rest_dispatch,
{'POST': 'zerver.views.user_groups.add_user_group'}),
# users/me -> zerver.views.user_settings
url(r'^users/me/api_key/regenerate$', rest_dispatch,
{'POST': 'zerver.views.user_settings.regenerate_api_key'}),