any one of the composed methods. TODO: Move this a utils-like module if we end up using it more widely. ''' json_dict: Dict[str, Any] = {} with transaction.atomic(): for method, kwargs in method_kwarg_pairs: response = method(request, user_profile, **kwargs) if response.status_code != 200: raise JsonableError(response.content) json_dict.update(orjson.loads(response.content)) return json_success(json_dict) check_principals: Validator[Union[List[str], List[int]]] = check_union( [check_list(check_string), check_list(check_int)], ) @has_request_variables def remove_subscriptions_backend( request: HttpRequest, user_profile: UserProfile, streams_raw: Iterable[str] = REQ("subscriptions", validator=remove_subscriptions_schema), principals: Optional[Union[List[str], List[int]]] = REQ(validator=check_principals, default=None), ) -> HttpResponse: removing_someone_else = check_if_removing_someone_else( user_profile, principals)
def update_subscription_properties_backend( request: HttpRequest, user_profile: UserProfile, subscription_data: List[Dict[str, Any]] = REQ(validator=check_list( check_dict([("stream_id", check_int), ("property", check_string), ("value", check_union([check_string, check_bool]))]), ), ), ) -> HttpResponse: """ This is the entry point to changing subscription properties. This is a bulk endpoint: requestors always provide a subscription_data list containing dictionaries for each stream of interest. Requests are of the form: [{"stream_id": "1", "property": "is_muted", "value": False}, {"stream_id": "1", "property": "color", "value": "#c2c2c2"}] """ property_converters = { "color": check_color, "in_home_view": check_bool, "is_muted": check_bool, "desktop_notifications": check_bool, "audible_notifications": check_bool, "push_notifications": check_bool, "email_notifications": check_bool, "pin_to_top": check_bool, "wildcard_mentions_notify": check_bool } response_data = [] for change in subscription_data: stream_id = change["stream_id"] property = change["property"] value = change["value"] if property not in property_converters: return json_error( _("Unknown subscription property: {}").format(property)) (stream, recipient, sub) = access_stream_by_id(user_profile, stream_id) if sub is None: return json_error( _("Not subscribed to stream id {}").format(stream_id)) try: value = property_converters[property](property, value) except ValidationError as error: return json_error(error.message) do_change_subscription_property(user_profile, sub, stream, property, value, acting_user=user_profile) response_data.append({ 'stream_id': stream_id, 'property': property, 'value': value }) return json_success({"subscription_data": response_data})
allow_bots=True) if target.is_bot: assert target.bot_type is not None check_bot_creation_policy(user_profile, target.bot_type) do_reactivate_user(target, acting_user=user_profile) return json_success() check_profile_data: Validator[List[Dict[str, Optional[Union[ int, str, List[int]]]]]] = check_list( check_dict( [('id', check_int)], value_validator=check_none_or( check_union([ check_int, check_string, check_list(check_int), ])), ), ) @has_request_variables def update_user_backend( request: HttpRequest, user_profile: UserProfile, user_id: int, full_name: Optional[str] = REQ(default=None, validator=check_string), role: Optional[int] = REQ(default=None, validator=check_int_in( UserProfile.ROLE_TYPES, )), profile_data: Optional[List[Dict[str, Optional[Union[
VALID_DRAFT_TYPES: Set[str] = {"", "private", "stream"} # A validator to verify if the structure (syntax) of a dictionary # meets the requirements to be a draft dictionary: draft_dict_validator = check_dict_only( required_keys=[ ("type", check_string_in(VALID_DRAFT_TYPES)), ("to", check_list(check_int) ), # The ID of the stream to send to, or a list of user IDs. ("topic", check_string ), # This string can simply be empty for private type messages. ("content", check_required_string), ], optional_keys=[ ("timestamp", check_union([check_int, check_float])), # A Unix timestamp. ], ) def further_validated_draft_dict(draft_dict: Dict[str, Any], user_profile: UserProfile) -> Dict[str, Any]: """Take a draft_dict that was already validated by draft_dict_validator then further sanitize, validate, and transform it. Ultimately return this "further validated" draft dict. It will have a slightly different set of keys the values for which can be used to directly create a Draft object.""" content = normalize_body(draft_dict["content"]) timestamp = draft_dict.get("timestamp", time.time()) timestamp = round(timestamp, 6)
""" rkeys = [key[0] for key in required_keys] okeys = [key[0] for key in optional_keys] keys = rkeys + okeys assert len(keys) == len(set(keys)) assert "type" in rkeys assert "id" not in keys return check_dict_only( required_keys=list(required_keys) + [("id", check_int)], optional_keys=optional_keys, ) check_add_or_remove = check_union([ # force vertical equals("add"), equals("remove"), ]) check_value = check_union([ # force vertical formatting check_bool, check_int, check_string, ]) check_optional_value = check_union([ # force vertical formatting check_bool, check_int, check_string,
def update_subscription_properties_backend( request: HttpRequest, user_profile: UserProfile, subscription_data: List[Dict[str, Any]] = REQ(json_validator=check_list( check_dict([ ("stream_id", check_int), ("property", check_string), ("value", check_union([check_string, check_bool])), ]), ), ), ) -> HttpResponse: """ This is the entry point to changing subscription properties. This is a bulk endpoint: requestors always provide a subscription_data list containing dictionaries for each stream of interest. Requests are of the form: [{"stream_id": "1", "property": "is_muted", "value": False}, {"stream_id": "1", "property": "color", "value": "#c2c2c2"}] """ property_converters = { "color": check_color, "in_home_view": check_bool, "is_muted": check_bool, "desktop_notifications": check_bool, "audible_notifications": check_bool, "push_notifications": check_bool, "email_notifications": check_bool, "pin_to_top": check_bool, "wildcard_mentions_notify": check_bool, } for change in subscription_data: stream_id = change["stream_id"] property = change["property"] value = change["value"] if property not in property_converters: raise JsonableError( _("Unknown subscription property: {}").format(property)) (stream, sub) = access_stream_by_id(user_profile, stream_id) if sub is None: raise JsonableError( _("Not subscribed to stream id {}").format(stream_id)) try: value = property_converters[property](property, value) except ValidationError as error: raise JsonableError(error.message) do_change_subscription_property(user_profile, sub, stream, property, value, acting_user=user_profile) # TODO: Do this more generally, see update_realm_user_settings_defaults.realm.py from zerver.lib.request import RequestNotes request_notes = RequestNotes.get_notes(request) for req_var in request.POST: if req_var not in request_notes.processed_parameters: request_notes.ignored_parameters.add(req_var) result: Dict[str, Any] = {} if len(request_notes.ignored_parameters) > 0: result["ignored_parameters_unsupported"] = list( request_notes.ignored_parameters) return json_success(request, data=result)
for_admin=True) if target.is_bot: assert target.bot_type is not None check_bot_creation_policy(user_profile, target.bot_type) do_reactivate_user(target, acting_user=user_profile) return json_success() check_profile_data: Validator[List[Dict[str, Optional[Union[ int, ProfileDataElementValue]]]]] = check_list( check_dict_only([ ("id", check_int), ( "value", check_none_or( check_union([check_string, check_list(check_int)]), ), ), ]), ) @has_request_variables def update_user_backend( request: HttpRequest, user_profile: UserProfile, user_id: int, full_name: Optional[str] = REQ(default=None), role: Optional[int] = REQ( default=None, json_validator=check_int_in(UserProfile.ROLE_TYPES, ), ), profile_data: Optional[List[Dict[str, Optional[Union[