; Ringnex SaaS tenant-aware internal/PSTN routing reference
; IMPORTANT: review and merge into the custom Ringnex Asterisk only:
; /opt/ringnex-webrtc/etc/asterisk/extensions.conf
; Do NOT apply this to the separate MagnusBilling/system Asterisk.
;
; Backend maintains these AstDB families automatically:
; ringnex_tenant/<sip-endpoint> = <tenant-uuid>
; ringnex_tenant_status/<tenant-uuid> = ACTIVE|TRIAL|INACTIVE|SUSPENDED|CANCELLED
; ringnex_ext/<tenant-uuid>/<extension> = <sip-endpoint>
; ringnex_did/<sip-endpoint> = <assigned-did>
;
; This context demonstrates the required isolation rule:
; 1) identify caller's tenant from endpoint
; 2) reject disabled tenants
; 3) resolve short/internal extensions ONLY inside the same tenant
; 4) never send an unknown short extension to Commio
; 5) send external numbers to Commio using the caller's assigned DID

[from-webrtc-saas]
exten => _X.,1,NoOp(Ringnex SaaS call from endpoint ${CHANNEL(endpoint)} to ${EXTEN})
 same => n,Set(RN_ENDPOINT=${CHANNEL(endpoint)})
 same => n,Set(RN_TENANT=${DB(ringnex_tenant/${RN_ENDPOINT})})
 same => n,GotoIf($["${RN_TENANT}"=""]?blocked)
 same => n,Set(RN_TENANT_STATUS=${DB(ringnex_tenant_status/${RN_TENANT})})
 same => n,GotoIf($["${RN_TENANT_STATUS}"="ACTIVE" | "${RN_TENANT_STATUS}"="TRIAL"]?tenant-ok:blocked)

 same => n(tenant-ok),Set(RN_INTERNAL_SIP=${DB(ringnex_ext/${RN_TENANT}/${EXTEN})})
 same => n,GotoIf($["${RN_INTERNAL_SIP}"!=""]?internal)
 ; Unknown short extensions are blocked instead of accidentally reaching the PSTN carrier.
 same => n,GotoIf($[${LEN(${EXTEN})} < 7]?unknown-extension:pstn)

 same => n(internal),NoOp(Same-tenant internal call ${EXTEN} -> ${RN_INTERNAL_SIP})
 same => n,Dial(PJSIP/${RN_INTERNAL_SIP},30)
 same => n,Hangup()

 same => n(pstn),Set(RN_CALLER_DID=${DB(ringnex_did/${RN_ENDPOINT})})
 same => n,GotoIf($["${RN_CALLER_DID}"=""]?no-did)
 same => n,Set(CALLERID(num)=${RN_CALLER_DID})
 same => n,Set(CALLERID(name)=Ringnex)
 same => n,Dial(PJSIP/${EXTEN}@commio,60,R)
 same => n,Hangup()

 same => n(unknown-extension),Playback(invalid)
 same => n,Hangup(1)
 same => n(no-did),Playback(cannot-complete-as-dialed)
 same => n,Hangup(21)
 same => n(blocked),Playback(access-denied)
 same => n,Hangup(21)
