Skip to content

Commit

Permalink
merge base
Browse files Browse the repository at this point in the history
  • Loading branch information
ricwo committed Sep 23, 2019
2 parents 8dba0de + 73e9c97 commit 46531c1
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 24 deletions.
32 changes: 29 additions & 3 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,23 @@ Rasa Change Log
All notable changes to this project will be documented in this file.
This project adheres to `Semantic Versioning`_ starting with version 1.0.

[1.3.4] - 2019-09-19

[1.3.6] - 2019-09-21
^^^^^^^^^^^^^^^^^^^^

Added
-----
- Added the ability for users to specify a conversation id to send a message to when
using the ``RasaChat`` input channel.

[1.3.5] - 2019-09-20
^^^^^^^^^^^^^^^^^^^^

Fixed
-----
- Fixed issue where ``rasa init`` would fail without spaCy being installed

[1.3.4] - 2019-09-20
^^^^^^^^^^^^^^^^^^^^

Added
Expand All @@ -27,6 +43,14 @@ Fixed
``Doc``-objects. The resulting lists are merged with their preserved order and
properly returned.

Changed
-------
- The endpoint ``POST /model/train`` no longer supports specifying an output directory
for the trained model using the field ``out``. Instead you can choose whether you
want to save the trained model in the default model directory (``models``)
(default behavior) or in a temporary directory by specifying the
``save_to_default_model_directory`` field in the training request.

[1.3.3] - 2019-09-13
^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -57,6 +81,7 @@ Changed
-------
- Pin gast to == 0.2.2


[1.3.0] - 2019-09-05
^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -150,7 +175,7 @@ Removed

Fixed
-----
- Correctly pass SSL flag values to x CLI command
- Correctly pass SSL flag values to x CLI command (backport of


[1.2.8] - 2019-09-10
Expand All @@ -159,7 +184,8 @@ Fixed
Fixed
-----
- SQL tracker events are retrieved ordered by timestamps. This fixes interactive
learning events being shown in the wrong order.
learning events being shown in the wrong order. Backport of ``1.3.2`` patch
(PR #4427).


[1.2.7] - 2019-09-02
Expand Down
9 changes: 5 additions & 4 deletions docs/_static/spec/rasa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1228,15 +1228,16 @@ components:
$ref: '#/components/schemas/NLUTrainingData'
stories:
$ref: '#/components/schemas/StoriesTrainingData'
out:
type: string
description: Output directory
example: models
force:
type: boolean
description: >-
Force a model training even if the data has not changed
example: false
save_to_default_model_directory:
type: boolean
description: >-
If `true` (default) the trained model will be saved in the default model
directory, if `false` it will be saved in a temporary directory
required: ["config"]

NLUTrainingData:
Expand Down
48 changes: 38 additions & 10 deletions rasa/core/channels/rasa_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

logger = logging.getLogger(__name__)

CONVERSATION_ID_KEY = "conversation_id"
JWT_USERNAME_KEY = "username"
INTERACTIVE_LEARNING_PERMISSION = "clientEvents:create"


class RasaChatInput(RestInput):
"""Chat input channel for Rasa X"""
Expand Down Expand Up @@ -88,15 +92,39 @@ async def _decode_bearer_token(self, bearer_token: Text) -> Optional[Dict]:
logger.exception("Failed to decode bearer token.")

async def _extract_sender(self, req: Request) -> Optional[Text]:
"""Fetch user from the Rasa X Admin API"""
"""Fetch user from the Rasa X Admin API."""

jwt_payload = None
if req.headers.get("Authorization"):
user = await self._decode_bearer_token(req.headers["Authorization"])
if user:
return user["username"]

user = await self._decode_bearer_token(req.args.get("token", default=None))
if user:
return user["username"]

abort(401)
jwt_payload = await self._decode_bearer_token(req.headers["Authorization"])

if not jwt_payload:
jwt_payload = await self._decode_bearer_token(req.args.get("token"))

if not jwt_payload:
abort(401)

if CONVERSATION_ID_KEY in req.json:
if self._has_user_permission_to_send_messages_to_conversation(
jwt_payload, req.json
):
return req.json[CONVERSATION_ID_KEY]
else:
logger.error(
"User '{}' does not have permissions to send messages to "
"conversation '{}'.".format(
jwt_payload[JWT_USERNAME_KEY], req.json[CONVERSATION_ID_KEY]
)
)
abort(401)

return jwt_payload[JWT_USERNAME_KEY]

@staticmethod
def _has_user_permission_to_send_messages_to_conversation(
jwt_payload: Dict, message: Dict
) -> bool:
user_scopes = jwt_payload.get("scopes", [])
return INTERACTIVE_LEARNING_PERMISSION in user_scopes or message[
CONVERSATION_ID_KEY
] == jwt_payload.get(JWT_USERNAME_KEY)
3 changes: 2 additions & 1 deletion rasa/nlu/utils/spacy_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import typing
from typing import Any, Dict, List, Optional, Text, Tuple

from spacy.tokens import Doc
from rasa.nlu.components import Component
from rasa.nlu.config import RasaNLUModelConfig, override_defaults
from rasa.nlu.training_data import Message, TrainingData
Expand Down Expand Up @@ -185,6 +184,8 @@ def process_non_content_bearing_samples(
) -> List[Tuple[int, "Doc"]]:
"""Creates empty Doc-objects from zero-lengthed training samples strings."""

from spacy.tokens import Doc

n_docs = [
(empty_sample[0], doc)
for empty_sample, doc in zip(
Expand Down
7 changes: 6 additions & 1 deletion rasa/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,11 @@ async def train(request: Request):
domain_path = os.path.join(temp_dir, "domain.yml")
dump_obj_as_str_to_file(domain_path, rjs["domain"])

if rjs.get("save_to_default_model_directory", True) is True:
model_output_directory = DEFAULT_MODELS_PATH
else:
model_output_directory = tempfile.gettempdir()

try:
with app.active_training_processes.get_lock():
app.active_training_processes.value += 1
Expand All @@ -678,7 +683,7 @@ async def train(request: Request):
domain=domain_path,
config=config_path,
training_files=temp_dir,
output_path=rjs.get("out", DEFAULT_MODELS_PATH),
output_path=model_output_directory,
force_training=rjs.get("force", False),
)

Expand Down
7 changes: 3 additions & 4 deletions rasa/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ async def train_async(
output_path: Output path.
force_training: If `True` retrain model even if data has not changed.
fixed_model_name: Name of model to be stored.
persist_nlu_training_data: `True` if the NLU training data should be persisted
with the model.
kwargs: Additional training parameters.
Returns:
Expand Down Expand Up @@ -115,11 +117,8 @@ async def _train_async_internal(
"""Trains a Rasa model (Core and NLU). Use only from `train_async`.
Args:
domain: Path to the domain file.
config: Path to the config for Core and NLU.
file_importer: `TrainingDataImporter` which supplies the training data.
train_path: Directory in which to train the model.
nlu_data_directory: Path to NLU training files.
story_directory: Path to Core training files.
output_path: Output path.
force_training: If `True` retrain model even if data has not changed.
fixed_model_name: Name of model to be stored.
Expand Down
2 changes: 1 addition & 1 deletion rasa/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.3.4"
__version__ = "1.3.6"
44 changes: 44 additions & 0 deletions tests/core/test_channels.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import logging
from typing import Dict
from unittest.mock import patch, MagicMock

import pytest
Expand All @@ -9,7 +10,13 @@

import rasa.core.run
from rasa.core import utils
from rasa.core.channels import RasaChatInput
from rasa.core.channels.channel import UserMessage
from rasa.core.channels.rasa_chat import (
JWT_USERNAME_KEY,
CONVERSATION_ID_KEY,
INTERACTIVE_LEARNING_PERMISSION,
)
from rasa.core.channels.telegram import TelegramOutput
from rasa.utils.endpoints import EndpointConfig
from tests.core import utilities
Expand Down Expand Up @@ -822,3 +829,40 @@ async def test_rasa_chat_input():
await rasa_chat_input._fetch_public_key()
assert rasa_chat_input.jwt_key == public_key
assert rasa_chat_input.jwt_algorithm == jwt_algorithm


@pytest.mark.parametrize(
"jwt, message",
[
({JWT_USERNAME_KEY: "abc"}, {CONVERSATION_ID_KEY: "abc"}),
(
{
JWT_USERNAME_KEY: "abc",
"scopes": ["a", "b", INTERACTIVE_LEARNING_PERMISSION],
},
{CONVERSATION_ID_KEY: "test"},
),
],
)
def test_has_user_permission_to_send_messages_to_conversation(jwt: Dict, message: Dict):
assert RasaChatInput._has_user_permission_to_send_messages_to_conversation(
jwt, message
)


@pytest.mark.parametrize(
"jwt, message",
[
({JWT_USERNAME_KEY: "abc"}, {CONVERSATION_ID_KEY: "xyz"}),
(
{JWT_USERNAME_KEY: "abc", "scopes": ["a", "b"]},
{CONVERSATION_ID_KEY: "test"},
),
],
)
def test_has_user_permission_to_send_messages_to_conversation_without_permission(
jwt: Dict, message: Dict
):
assert not RasaChatInput._has_user_permission_to_send_messages_to_conversation(
jwt, message
)

0 comments on commit 46531c1

Please sign in to comment.