Skip to content

Commit

Permalink
Merge commit for 4.0.4
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaian committed Apr 12, 2024
2 parents 8f0bb92 + 8e1b810 commit 35312bc
Show file tree
Hide file tree
Showing 73 changed files with 1,076 additions and 121 deletions.
24 changes: 24 additions & 0 deletions ChangeLog
@@ -1,3 +1,27 @@
Fri, 12 Apr 2024 08:37:49 +0200 IvozProvider Team <vozip+ivozprovider@irontec.com>

* IvozProvider 4.0.4 released

* Portals
- Fixed a bug displaying Routing Tags for brands without Retail or Wholesale features
- Fixed a bug displaying Balance fields for brands without Billing feature
- Fixed a bug displaying Holiday range actions for Administrators without permission on Holiday dates
- Fixed a bug displaying Terminal provisioning templates preview dialogs
- Fixed a crash on Call ACL permissions screens
- Added missing action to resend failed outgoing faxes
- Added new section Voicemails in user portal
- DDI numbers are now displayed in E.164 format
- Imported destination rates files can now be downloaded

* Proxies
- Added support to DDIs without client assigned
- Fixed a bug while routing SUBSCRIBE and PUBLISH messages to wrong application server
- Subscribed extensions are now validated before relaying to application servers
- Increased min subscribe expire to 1800 seconds

* Application Server
- Disable initial MWI notification during asterisk startup

Thu, 21 Mar 2024 08:50:54 +0100 IvozProvider Team <vozip+ivozprovider@irontec.com>

* IvozProvider 4.0.3 released
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -51,7 +51,7 @@ If you want to test an [standalone](https://irontec.github.io/ivozprovider/en/ar
| oldoldstable (oasis 1.7) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-1.7.1-oasis-amd64.iso) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-1.7.1-oasis-i386.iso)|
| oldstable (artemis 2.23.0) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-2.23~2.23.0-artemis-amd64.iso) | |
| stable (halliday 3.4.1) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-3.4~3.4.1-halliday-amd64.iso) | |
| testing (tempest 4.0.3) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-4.0~4.0.0-tempest-amd64.iso) | |
| testing (tempest 4.0.4) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-4.0~4.0.0-tempest-amd64.iso) | |


You can read about differences between releases [here](https://github.com/irontec/ivozprovider/blob/bleeding/FAQ.md#what-release-should-i-use).
Expand Down
2 changes: 2 additions & 0 deletions asterisk/config/dialplan/default.conf
Expand Up @@ -6,6 +6,8 @@
[trunks]
exten => _[+*0-9]!,1,NoOp(Incoming external call from ${CALLERID(all)} to ${EXTEN})
same => n,AGI(agi://${FASTAGI_SERVER}/fastagi-runner.php?command=Dialplan/Trunks)
; Playback specific sounds and leave
include => sounds

;; Context for user calls (from proxyUsers)
;; ${EXTEN} may match a Company Extension, Company Service or External number
Expand Down
1 change: 1 addition & 0 deletions asterisk/config/dialplan/sounds.conf
Expand Up @@ -2,6 +2,7 @@
;; ${EXTEN} MUST match a predefined ivozprovider locution
[sounds]
exten => ipnotallowed,1,Goto(playsound,${EXTEN},1)
exten => noclient,1,Goto(playsound,${EXTEN},1)

[playsound]
exten => _[a-zA-Z].,1,NoOp(Playing requested sound ${EXTEN})
Expand Down
1 change: 1 addition & 0 deletions asterisk/config/pjsip.conf
Expand Up @@ -5,6 +5,7 @@
type=global
user_agent=Irontec IvozProvider v4.0
endpoint_identifier_order=ip,header,username,anonymous
mwi_disable_initial_unsolicited=yes

;;
;; Enabled SIP Transports
Expand Down
8 changes: 7 additions & 1 deletion debian/changelog
@@ -1,4 +1,10 @@
ivozprovider (4.0~4.0.3) UNRELEASED; urgency=medium
ivozprovider (4.0~4.0.4) UNRELEASED; urgency=medium

* Version bump to 4.0.4

-- Irontec IvozProvider Team <ivozprovider@irontec.com> Thu, 11 Apr 2024 12:26:05 +0200

ivozprovider (4.0~4.0.3) unstable; urgency=medium

* Version bump to 4.0.3

Expand Down
5 changes: 3 additions & 2 deletions doc/dev/AcceptedCommitTagsList.txt
@@ -1,6 +1,7 @@
agi
as
asterisk
build(deps)
ci
core
data
Expand All @@ -21,12 +22,12 @@ portal
portal/brand
portal/client
portal/platform
portal/users
portal/user
proxy
rest/brand
rest/client
rest/platform
rest/users
rest/user
schema
systemd
tests
Expand Down
15 changes: 14 additions & 1 deletion kamailio/trunks/config/kamailio.cfg
Expand Up @@ -1476,6 +1476,8 @@ route[APPLY_TRANSFORMATION] {
}

route[GET_INFO_FROM_MATCHED_DDI] {
if ($dlg_var(type) == 'unassigned') return;

sql_xquery("cb", "SELECT c.mediaRelaySetsId, c.maxCalls AS maxCallsCompany, b.maxCalls AS maxCallsBrand, d.recordCalls, c.distributeMethod, AppS.ip AS asAddress, d.routeType, d.residentialDeviceId, d.retailAccountId, d.faxId FROM DDIs d JOIN Companies c ON d.companyId=c.id LEFT JOIN ApplicationServers AppS ON AppS.id=c.applicationServerId JOIN Brands b ON c.brandId=b.id WHERE d.DDIE164='$rU'", "ra");

# Matched DDI
Expand Down Expand Up @@ -1741,9 +1743,18 @@ route[CLASSIFY] {
set_dlg_profile("outboundCallsCompany", "$dlg_var(companyId)");
set_dlg_profile("outboundCallsBrand", "$dlg_var(brandId)");
} else {
sql_xquery("cb", "SELECT C.brandId, C.id AS companyId, C.type FROM DDIs D JOIN Companies C ON D.companyId=C.id WHERE DDIE164='$rU'", "rp");
sql_xquery("cb", "SELECT B.id AS brandId, C.id AS companyId, C.type FROM DDIs D JOIN Brands B ON B.id=D.brandId LEFT JOIN Companies C ON D.companyId=C.id WHERE DDIE164='$rU'", "rp");
$dlg_var(brandId) = $xavp(rp=>brandId);
$dlg_var(companyId) = $xavp(rp=>companyId);

if ($dlg_var(brandId) != $null && $dlg_var(companyId) == $null) {
xnotice("[$dlg_var(cidhash)] CLASSIFY: inbound call to unassigned DDI $rU (b$dlg_var(brandId))");
$dlg_var(skipRealtime) = 'yes'; # Skip this call in realtime
$dlg_var(type) = 'unassigned';
$rU = 'noclient';
return;
}

$dlg_var(type) = $xavp(rp=>type);

if ($dlg_var(type) == 'wholesale') {
Expand Down Expand Up @@ -2340,6 +2351,8 @@ route[RECORD] {
}

route[CONTROL_MAXCALLS] {
if ($dlg_var(type) == 'unassigned') return;

if (!get_profile_size("activeCallsCompany", "$dlg_var(companyId)", "$avp(activeCallsCompany)")) {
xerr("[$dlg_var(cidhash)] CONTROL-MAXCALLS: company$dlg_var(companyId) $avp(activeCallsCompany)/$dlg_var(maxCallsCompany) calls (error obtaining value)\n");
if ($dlg_var(maxCallsCompany) > 0) {
Expand Down
48 changes: 44 additions & 4 deletions kamailio/users/config/kamailio.cfg
Expand Up @@ -1193,19 +1193,21 @@ route[DISPATCH_TO_AS] {
}
$var(sorcery) = $var(sorcery) + "_" + $avp(endpointName);
append_hf("X-Info-Endpoint: $var(sorcery)\r\n");
xinfo("[$dlg_var(cidhash)] DISPATCH-TO-AS: Sorcery $var(sorcery)\n");

# Static routing to specific AS?
if ($avp(distributeMethod) == 'static') {
$du = "sip:" + $avp(asAddress) + ":6060";
xinfo("[$dlg_var(cidhash)] DISPATCH-TO-AS: Company has static routing enabled\n");
xnotice("[$dlg_var(cidhash)] DISPATCH-TO-AS: Company '$dlg_var(companyId)' has static routing enabled through AS '$avp(asAddress)'\n");
} else {
if ($avp(distributeMethod) == 'hash') {
$avp(hash) = $dlg_var(companyId);
# hash over $avp(hash)
$var(alg) = 7;
xinfo("[$dlg_var(cidhash)] DISPATCH-TO-AS: Company '$dlg_var(companyId)' has hash routing enabled\n");
} else {
# round robin dispatching on ASs (distributeMethod == 'rr')
xinfo("[$dlg_var(cidhash)] DISPATCH-TO-AS: dispatch to any AS (round robin)\n");
xnotice("[$dlg_var(cidhash)] DISPATCH-TO-AS: Company '$dlg_var(companyId)' dispatches to any AS (round robin)\n");
$var(alg) = 4;
}

Expand Down Expand Up @@ -1342,6 +1344,16 @@ route[STATIC_LOCATION] {
return;
}

route[GET_DISTRIBUTE_METHOD] {
sql_xquery("cb", "SELECT C.distributeMethod, AppS.ip AS asAddress FROM Companies C LEFT JOIN ApplicationServers AppS ON AppS.id=C.applicationServerId WHERE C.id='$dlg_var(companyId)'", "gdm");

$avp(distributeMethod) = $xavp(gdm=>distributeMethod);
$avp(asAddress) = $xavp(dgm=>asAddress);

xinfo("[$dlg_var(cidhash)] GET-DISTRIBUTE-METHOD: distributeMethod '$avp(distributeMethod)' - asAddress '$avp(asAddress)' (companyId $dlg_var(companyId))\n");
return;
}

route[GET_CALL_INFO] {
sql_xquery("cb", "SELECT C.mediaRelaySetsId, C.distributeMethod, AppS.ip AS asAddress, C.onDemandRecord, CONCAT(C.transformationRuleSetId,0) AS caller_in, CONCAT(C.transformationRuleSetId,1) AS callee_in, CONCAT(C.transformationRuleSetId,2) AS caller_out, CONCAT(C.transformationRuleSetId,3) AS callee_out FROM Companies C LEFT JOIN ApplicationServers AppS ON AppS.id=C.applicationServerId WHERE C.id='$dlg_var(companyId)'", "ra");

Expand Down Expand Up @@ -3047,18 +3059,26 @@ route[PRESENCE] {
exit;
}

if(is_method("SUBSCRIBE") && $hdr(Expires) < 1800) {
append_to_reply("Min-Expires: 1800\r\n");
send_reply("423", "Interval Too Brief");
exit;
}

if(is_method("PUBLISH|SUBSCRIBE")) {
if ($var(is_from_inside)) {
xwarn("[$dlg_var(cidhash)] NOTIFY: Received $rm from AS, 405 Method Not Allowed\n");
xwarn("[$dlg_var(cidhash)] PRESENCE: Received $rm from AS, 405 Method Not Allowed\n");
send_reply("405", "Method Not Allowed");
exit;
}

route(DISCARD_NONEXISTING_SUBS);
route(GET_DISTRIBUTE_METHOD);
route(DISPATCH_TO_AS);
} else if(is_method("NOTIFY")) {
# Handle unsolicited NOTIFY messages (non-related to previous SUBSCRIBE)
if (!$var(is_from_inside)) {
xwarn("[$dlg_var(cidhash)] NOTIFY: Received $rm from not AS, 405 Method Not Allowed\n");
xwarn("[$dlg_var(cidhash)] PRESENCE: Received $rm from not AS, 405 Method Not Allowed\n");
send_reply("405", "Method Not Allowed");
exit;
}
Expand All @@ -3073,6 +3093,26 @@ route[PRESENCE] {
exit;
}

route[DISCARD_NONEXISTING_SUBS] {
if (!is_method("SUBSCRIBE")) return;

sql_query("cb", "SELECT CONCAT('*', CS.code, RL.id) AS extension FROM RouteLocks RL INNER JOIN Companies C ON C.id = RL.companyId INNER JOIN CompanyServices CS ON CS.companyId = C.id WHERE C.id = '$dlg_var(companyId)' AND serviceId = 7 UNION SELECT number FROM Extensions E INNER JOIN Users U ON U.extensionId = E.id INNER JOIN Terminals T ON T.id = U.terminalId WHERE E.companyId = '$dlg_var(companyId)'", "hints");

if ($dbr(hints=>rows) > 0) {
$var(i) = 0;
while($var(i) < $dbr(hints=>rows)) {
if ($rU == $dbr(hints=>[$var(i),0])) {
return; # Hint exists, return
}
$var(i) = $var(i) + 1;
}
}

xinfo("[$dlg_var(cidhash)] DISCARD-NONEXISTING-SUBS: '$rU' is not valid subscription for company '$dlg_var(companyId)', discard\n");
send_reply("404", "Not Here [NES]");
exit;
}

route[EXIT_NOW] {
if ($sel(cfg_get.config.maintenance_mode) != 3) {
# Only when maintenance mode 3 is enabled
Expand Down
37 changes: 37 additions & 0 deletions library/DataFixtures/ORM/ProviderFaxesInOut.php
Expand Up @@ -40,6 +40,43 @@ public function load(ObjectManager $manager)
$this->sanitizeEntityValues($item1);
$manager->persist($item1);

/** @var FaxesInOut $item2 */
$item2 = $this->createEntityInstance(FaxesInOut::class);
(function () use ($fixture) {
$this->calldate = new \DateTime('2018-01-02', new \DateTimeZone('UTC'));
$this->setSrc('34688888888');
$this->setDst('34688888881');
$this->setType('In');
$this->setStatus('completed');
$this->setFax(
$fixture->getReference('_reference_ProviderFax1')
);
$this->file = new File(null, null, null);
})->call($item2);

$this->addReference('_reference_ProviderFaxesInOut2', $item2);
$this->sanitizeEntityValues($item2);
$manager->persist($item2);

/** @var FaxesInOut $item3 */
$item3 = $this->createEntityInstance(FaxesInOut::class);
(function () use ($fixture) {
$this->calldate = new \DateTime('2018-01-02', new \DateTimeZone('UTC'));
$this->setSrc('34688888888');
$this->setDst('34688888881');
$this->setType('Out');
$this->setStatus('error');
$this->setFax(
$fixture->getReference('_reference_ProviderFax1')
);
$this->file = new File(null, null, null);
})->call($item3);

$this->addReference('_reference_ProviderFaxesInOut3', $item3);
$this->sanitizeEntityValues($item3);
$manager->persist($item3);


$manager->flush();
}

Expand Down
4 changes: 2 additions & 2 deletions library/bin/test-commit-tags
Expand Up @@ -7,7 +7,7 @@ cd $(dirname $(realpath $0))/../../
BASE_BRANCH=${1:-origin/bleeding}

# Get the list of commits
COMMITS=$(git --no-pager log --format=%B ${BASE_BRANCH}..HEAD | grep -v ^$)
COMMITS=$(git --no-pager log --format=%s ${BASE_BRANCH}..HEAD | grep -v ^$)

# Check we have at least some commits
if [ -z "$COMMITS" ]; then
Expand All @@ -25,7 +25,7 @@ for COMMIT in $COMMITS; do
ERROR=1
continue
fi
grep -E -q "${TAG}$" doc/dev/AcceptedCommitTagsList.txt
grep -q "${TAG}$" doc/dev/AcceptedCommitTagsList.txt
if [ $? -ne 0 ]; then
echo "ERROR: $TAG is not a valid commit tag"
ERROR=1
Expand Down
2 changes: 1 addition & 1 deletion library/composer.json
Expand Up @@ -85,7 +85,7 @@
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.8",
"doctrine/persistence": "^2.1",
"irontec/ivoz-api-bundle": "^4.8.3",
"irontec/ivoz-api-bundle": "^4.8.4",
"irontec/ivoz-core": "^4.18.0",
"irontec/ivoz-dev-tools": "^5.12.1",
"irontec/ivoz-provider-bundle": "^2.6.7",
Expand Down
28 changes: 14 additions & 14 deletions library/composer.lock

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

0 comments on commit 35312bc

Please sign in to comment.