Skip to content

Commit

Permalink
Merge branch 'main' into twilio-update
Browse files Browse the repository at this point in the history
  • Loading branch information
norkans7 authored Feb 17, 2023
2 parents d38c66f + f3bb617 commit eb0723d
Show file tree
Hide file tree
Showing 82 changed files with 1,953 additions and 1,410 deletions.
58 changes: 58 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,61 @@
v8.1.34 (2023-02-16)
-------------------------
* Drop raw_urns field on Broadcast
* Pass group id instead of uuid to contact_search mailroom endpoint
* Remove unused expression_migrate from mailroom client

v8.1.33 (2023-02-15)
-------------------------
* Fix routing of current workspace to settings
* Add Broadcast.urns which matches the JSON and FlowStart.urns

v8.1.32 (2023-02-14)
-------------------------
* Drop Broadcast.urns and .send_all

v8.1.30 (2023-02-13)
-------------------------
* Fix keyword triggers match type

v8.1.29 (2023-02-13)
-------------------------
* Fix omnibox search for anon org to allow search by contact name
* Prepare to drop Broadcast.send_all and .urns

v8.1.27 (2023-02-10)
-------------------------
* Move all form text from Trigger model to forms
* Add migration to convert URNs to contacts on scheduled broadcasts

v8.1.26 (2023-02-10)
-------------------------
* Remove returning specific URNs from omniboxes and instead match contacts by URN
* Rework spa menu eliminate mapping

v8.1.25 (2023-02-09)
-------------------------
* Remove support for unused v1 omnibox format
* Update broadcasts API endpoint to support attachments

v8.1.24 (2023-02-08)
-------------------------
* Update to latest cryptography library
* Add task to interrupt flow sessions after 90 days

v8.1.23 (2023-02-06)
-------------------------
* Fix flow results redirecting to it's own page
* Make sure WA numbers can only be claimed once

v8.1.22 (2023-02-06)
-------------------------
* Update to latest django to get security fix

v8.1.21 (2023-02-06)
-------------------------
* Fix export > import path on new ui
* Fix login redirects from pjax calls

v8.1.20 (2023-02-02)
-------------------------
* Add servicing menu on org read
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
]
},
"dependencies": {
"@nyaruka/flow-editor": "1.19.1",
"@nyaruka/temba-components": "0.39.1",
"@nyaruka/flow-editor": "1.19.2",
"@nyaruka/temba-components": "0.41.0",
"codemirror": "5.18.2",
"colorette": "1.2.2",
"fa-icons": "0.2.0",
"highcharts": "5.0.6",
"intercooler": "1.1.2",
"intercooler": "1.2.3",
"is-core-module": "2.4.0",
"jquery": "2.1.0",
"jquery-migrate": "1.4.1",
Expand Down
35 changes: 11 additions & 24 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "temba"
version = "8.1.20"
version = "8.1.34"
description = "Hosted service for visually building interactive messaging applications"
authors = ["Nyaruka <code@nyaruka.com>"]
license = "AGPL-3"
Expand All @@ -10,7 +10,7 @@ repository = "http://github.com/rapidpro/rapidpro"

[tool.poetry.dependencies]
python = "^3.10"
Django = "^4.0.7"
Django = "4.0.9"
django-compressor = "^3.1"
django-countries = "^7.0"
django-hamlpy = "^1.4.4"
Expand All @@ -26,7 +26,7 @@ redis = "^3.5.3"
elasticsearch = "^7.11.0"
elasticsearch-dsl = "^7.3.0"
boto3 = "^1.17.21"
cryptography = "3.4.7"
cryptography = "^39.0.1"
vonage = "2.5.2"
pyfcm = "^1.5.1"
pyotp = "2.4.1"
Expand All @@ -46,7 +46,7 @@ gunicorn = "^20.0.4"
iptools = "^0.7.0"
iso-639 = "^0.4.5"
iso8601 = "^0.1.14"
phonenumbers = "*"
phonenumbers = "^8.13.6"
pycountry = "^20.7.3"
python-dateutil = "^2.8.2"
psycopg2-binary = "^2.9.1"
Expand Down
69 changes: 0 additions & 69 deletions static/js/urls.js

This file was deleted.

98 changes: 69 additions & 29 deletions temba/api/v2/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,52 @@
from temba.flows.models import Flow
from temba.msgs.models import Label, Msg
from temba.tickets.models import Ticket, Ticketer, Topic
from temba.utils import languages
from temba.utils.uuid import is_uuid

# default maximum number of items in a posted list or dict
DEFAULT_MAX_LIST_ITEMS = 100
DEFAULT_MAX_DICT_ITEMS = 100


def validate_size(value, max_size):
def validate_size(value, max_size: int):
if hasattr(value, "__len__") and len(value) > max_size:
raise serializers.ValidationError("This field can only contain up to %d items." % max_size)
raise serializers.ValidationError(f"This field can only contain up to {max_size} items.")


def validate_translations(value, base_language, max_length):
if len(value) == 0:
def validate_language(value):
if not isinstance(value, str) or len(value) != 3 or not languages.get_name(value):
raise serializers.ValidationError("Not an allowed ISO 639-3 language code.")


def validate_translations(value, *, max_length: int, lists: bool, max_items: int = 0):
if not isinstance(value, dict):
raise serializers.ValidationError("Must be a dictionary of languages to translated values.")
elif len(value) == 0:
raise serializers.ValidationError("Must include at least one translation.")
if base_language not in value:
raise serializers.ValidationError("Must include translation for base language '%s'" % base_language)

for lang, trans in value.items():
if not isinstance(lang, str) or len(lang) != 3:
raise serializers.ValidationError("Language code %s is not valid." % str(lang))
if not isinstance(trans, str):
raise serializers.ValidationError("Translations must be strings.")
if len(trans) > max_length:
raise serializers.ValidationError("Ensure translations have no more than %d characters." % max_length)
validate_language(lang)

if lists:
if not isinstance(trans, list) or not all([isinstance(t, str) for t in trans]):
raise serializers.ValidationError("Translations must be lists of strings.")

if len(trans) > max_items:
raise serializers.ValidationError(f"Translations can only contain up to {max_items} items.")

as_list = trans
else:
if not isinstance(trans, str):
raise serializers.ValidationError("Translations must be strings.")

as_list = [trans]

for t in as_list:
if not t.strip():
raise serializers.ValidationError("Translations cannot be empty or blank.")
if len(t) > max_length:
raise serializers.ValidationError("Translations must have no more than %d characters." % max_length)


def validate_urn(value, strict=True, country_code=None):
Expand All @@ -47,33 +68,52 @@ def validate_urn(value, strict=True, country_code=None):
return normalized


class TranslatableField(serializers.Field):
class LanguageField(serializers.CharField):
max_length = 3

def to_internal_value(self, data):
validate_language(data)

return super().to_internal_value(data)


class TranslationsField(serializers.Field):
"""
A field which is either a simple string or a translations dict
A field which is either a string or a language -> string translations dict
"""

def __init__(self, **kwargs):
self.max_length = kwargs.pop("max_length", None)
def __init__(self, max_length, **kwargs):
self.max_length = max_length

super().__init__(**kwargs)

def to_internal_value(self, data):
org = self.context["org"]
base_language = org.flow_languages[0]

if isinstance(data, str):
if len(data) > self.max_length:
raise serializers.ValidationError(
"Ensure this field has no more than %d characters." % self.max_length
)
data = {self.context["org"].flow_languages[0]: data}

data = {base_language: data}
validate_translations(data, max_length=self.max_length, lists=False)

elif isinstance(data, dict):
validate_translations(data, base_language, self.max_length)
else:
raise serializers.ValidationError("Value must be a string or dict of strings.")
return data


class TranslationsListField(serializers.Field):
"""
A field which is either a list of strings or a language -> list of strings translations dict
"""

def __init__(self, max_items, max_length, **kwargs):
self.max_items = max_items
self.max_length = max_length

super().__init__(**kwargs)

def to_internal_value(self, data):
if isinstance(data, list):
data = {self.context["org"].flow_languages[0]: data}

validate_translations(data, max_length=self.max_length, lists=True, max_items=self.max_items)

return data, base_language
return data


class LimitedListField(serializers.ListField):
Expand Down
Loading

0 comments on commit eb0723d

Please sign in to comment.