Skip to content

Commit 5f5d948

Browse files
committed
Merge branch 'restcomm-1512'
2 parents bf54e86 + 666e1f6 commit 5f5d948

15 files changed

Lines changed: 766 additions & 315 deletions

File tree

restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ApiRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*/
2727
public class ApiRequest {
2828
public static enum Type {
29-
INCOMINGPHONENUMBER, CREATE_CALL, CREATE_SMS, CREATE_USSD
29+
INCOMINGPHONENUMBER, CREATE_CALL, CREATE_SMS, CREATE_USSD, CREATE_SUBACCOUNT
3030
};
3131

3232
final String requestedAccountSid;

restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@
2525
*
2626
*/
2727
public enum ExtensionType {
28-
CallManager, SmsService, UssdCallManager,RestApi
28+
CallManager, SmsService, UssdCallManager,RestApi, FeatureAccessControl
2929
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.restcomm.connect.extension.api;
2+
3+
import org.restcomm.connect.commons.dao.Sid;
4+
5+
public interface IExtensionFeatureAccessRequest extends IExtensionRequest{
6+
7+
void setAccountSid (Sid accountSid);
8+
9+
String getDestinationNumber();
10+
11+
void setDestinationNumber(String destinationNumber);
12+
13+
14+
}

restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
package org.restcomm.connect.extension.api;
2222

2323
import javax.servlet.ServletContext;
24-
import javax.servlet.sip.SipServletRequest;
2524

2625
/**
2726
* @author <a href="mailto:gvagenas@gmail.com">gvagenas</a>
@@ -43,14 +42,14 @@ public interface RestcommExtensionGeneric {
4342
* and either block/allow or modify the session before Restcomm process it
4443
* @return ExtensionResponse see ExtensionResponse
4544
*/
46-
ExtensionResponse preInboundAction(SipServletRequest request);
45+
ExtensionResponse preInboundAction(IExtensionRequest extensionRequest);
4746
/**
4847
* Method that will be executed AFTER the process of an Incoming session
4948
* Implement this method so you will be able to check the Incoming session
5049
* and either block or allow or modify the session after Restcomm process it
5150
* @return ExtensionResponse see ExtensionResponse
5251
*/
53-
ExtensionResponse postInboundAction(SipServletRequest request);
52+
ExtensionResponse postInboundAction(IExtensionRequest extensionRequest);
5453
/**
5554
* Method that will be executed before the process of an Outbound session
5655
* Implement this method so you will be able to check the Outbound session

restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.restcomm.connect.extension.controller;
22

3+
import org.restcomm.connect.extension.api.ApiRequest;
34
import org.restcomm.connect.extension.api.ExtensionResponse;
45
import org.restcomm.connect.extension.api.ExtensionType;
56
import org.restcomm.connect.extension.api.IExtensionRequest;
@@ -116,4 +117,55 @@ public ExtensionResponse executePostOutboundAction(final IExtensionRequest er, L
116117
//TODO: implement actual calls
117118
return response;
118119
}
120+
121+
public ExtensionResponse executePreInboundAction(final IExtensionRequest er, List<RestcommExtensionGeneric> extensions) {
122+
ExtensionResponse response = new ExtensionResponse();
123+
// response.setAllowed(true);
124+
if (extensions != null && extensions.size() > 0) {
125+
for (RestcommExtensionGeneric extension : extensions) {
126+
if(logger.isInfoEnabled()) {
127+
logger.info( extension.getName()+" is enabled="+extension.isEnabled());
128+
}
129+
if (extension.isEnabled()) {
130+
response = extension.preInboundAction(er);
131+
//fail fast
132+
if (!response.isAllowed()){
133+
break;
134+
}
135+
}
136+
}
137+
}
138+
return response;
139+
}
140+
141+
public ExtensionResponse executePostInboundAction(final IExtensionRequest er, List<RestcommExtensionGeneric> extensions) {
142+
ExtensionResponse response = new ExtensionResponse();
143+
//TODO: implement actual calls
144+
return response;
145+
}
146+
147+
public ExtensionResponse executePreApiAction(final ApiRequest apiRequest, List<RestcommExtensionGeneric> extensions) {
148+
ExtensionResponse response = new ExtensionResponse();
149+
150+
if (extensions != null && extensions.size() > 0) {
151+
for (RestcommExtensionGeneric extension : extensions) {
152+
if(logger.isInfoEnabled()) {
153+
logger.info( extension.getName()+" is enabled="+extension.isEnabled());
154+
}
155+
if (extension.isEnabled()) {
156+
response = extension.preApiAction(apiRequest);
157+
//fail fast
158+
if (!response.isAllowed())
159+
break;
160+
}
161+
}
162+
}
163+
return response;
164+
}
165+
166+
public ExtensionResponse executePostApiAction(final ApiRequest apiRequest, List<RestcommExtensionGeneric> extensions) {
167+
ExtensionResponse response = new ExtensionResponse();
168+
//TODO: implement actual calls
169+
return response;
170+
}
119171
}

restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/AccountsEndpoint.java

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import org.restcomm.connect.dao.entities.IncomingPhoneNumber;
3939
import org.restcomm.connect.dao.entities.Organization;
4040
import org.restcomm.connect.dao.entities.RestCommResponse;
41+
import org.restcomm.connect.extension.api.ApiRequest;
42+
import org.restcomm.connect.extension.controller.ExtensionController;
4143
import org.restcomm.connect.http.client.rcmlserver.RcmlserverApi;
4244
import org.restcomm.connect.http.client.rcmlserver.RcmlserverNotifications;
4345
import org.restcomm.connect.http.converter.AccountConverter;
@@ -376,57 +378,73 @@ protected Response putAccount(final MultivaluedMap<String, String> data, final M
376378

377379
// what if effectiveAccount is null ?? - no need to check since we checkAuthenticatedAccount() in AccountsEndoint.init()
378380
final Sid sid = userIdentityContext.getEffectiveAccount().getSid();
379-
final Account parent = accountsDao.getAccount(sid);
380-
Account account = null;
381-
try {
382-
account = createFrom(sid, data, parent);
383-
} catch (IllegalArgumentException illegalArgumentException) {
384-
return status(BAD_REQUEST).entity(illegalArgumentException.getMessage()).build();
385-
}catch (final NullPointerException exception) {
386-
return status(BAD_REQUEST).entity(exception.getMessage()).build();
387-
} catch (PasswordTooWeak passwordTooWeak) {
388-
return status(BAD_REQUEST).entity(buildErrorResponseBody("Password too weak",responseType)).type(responseType).build();
389-
}
390381

391-
// If Account already exists don't add it again
382+
ExtensionController ec = ExtensionController.getInstance();
383+
ApiRequest apiRequest = new ApiRequest(sid.toString(), data, ApiRequest.Type.CREATE_SUBACCOUNT);
384+
385+
if (executePreApiAction(apiRequest)) {
386+
final Account parent = accountsDao.getAccount(sid);
387+
Account account = null;
388+
try {
389+
account = createFrom(sid, data, parent);
390+
} catch (IllegalArgumentException illegalArgumentException) {
391+
return status(BAD_REQUEST).entity(illegalArgumentException.getMessage()).build();
392+
}catch (final NullPointerException exception) {
393+
return status(BAD_REQUEST).entity(exception.getMessage()).build();
394+
} catch (PasswordTooWeak passwordTooWeak) {
395+
return status(BAD_REQUEST).entity(buildErrorResponseBody("Password too weak",responseType)).type(responseType).build();
396+
}
397+
398+
// If Account already exists don't add it again
392399
/*
393400
Account creation rules:
394401
- either be Administrator or have the following permission: RestComm:Create:Accounts
395402
- only Administrators can choose a role for newly created accounts. Normal users will create accounts with the same role as their own.
396403
*/
397-
if (accountsDao.getAccount(account.getSid()) == null && !account.getEmailAddress().equalsIgnoreCase("administrator@company.com")) {
398-
if (parent.getStatus().equals(Account.Status.ACTIVE) && isSecuredByPermission("RestComm:Create:Accounts")) {
399-
if (!hasAccountRole(getAdministratorRole()) || !data.containsKey("Role")) {
400-
account = account.setRole(parent.getRole());
401-
}
402-
accountsDao.addAccount(account);
403-
404-
// Create default SIP client data
405-
MultivaluedMap<String, String> clientData = new MultivaluedMapImpl();
406-
String username = data.getFirst("EmailAddress").split("@")[0];
407-
clientData.add("Login", username);
408-
clientData.add("Password", data.getFirst("Password"));
409-
clientData.add("FriendlyName", account.getFriendlyName());
410-
clientData.add("AccountSid", account.getSid().toString());
411-
Client client = clientDao.getClient(clientData.getFirst("Login"), account.getOrganizationSid());
412-
if (client == null) {
413-
client = createClientFrom(account.getSid(), clientData);
414-
clientDao.addClient(client);
404+
if (accountsDao.getAccount(account.getSid()) == null && !account.getEmailAddress().equalsIgnoreCase("administrator@company.com")) {
405+
if (parent.getStatus().equals(Account.Status.ACTIVE) && isSecuredByPermission("RestComm:Create:Accounts")) {
406+
if (!hasAccountRole(getAdministratorRole()) || !data.containsKey("Role")) {
407+
account = account.setRole(parent.getRole());
408+
}
409+
accountsDao.addAccount(account);
410+
411+
// Create default SIP client data
412+
MultivaluedMap<String, String> clientData = new MultivaluedMapImpl();
413+
String username = data.getFirst("EmailAddress").split("@")[0];
414+
clientData.add("Login", username);
415+
clientData.add("Password", data.getFirst("Password"));
416+
clientData.add("FriendlyName", account.getFriendlyName());
417+
clientData.add("AccountSid", account.getSid().toString());
418+
Client client = clientDao.getClient(clientData.getFirst("Login"), account.getOrganizationSid());
419+
if (client == null) {
420+
client = createClientFrom(account.getSid(), clientData);
421+
clientDao.addClient(client);
422+
}
423+
} else {
424+
throw new InsufficientPermission();
415425
}
416426
} else {
417-
throw new InsufficientPermission();
427+
return status(CONFLICT).entity("The email address used for the new account is already in use.").build();
418428
}
419-
} else {
420-
return status(CONFLICT).entity("The email address used for the new account is already in use.").build();
421-
}
422429

423-
if (APPLICATION_JSON_TYPE == responseType) {
424-
return ok(gson.toJson(account), APPLICATION_JSON).build();
425-
} else if (APPLICATION_XML_TYPE == responseType) {
426-
final RestCommResponse response = new RestCommResponse(account);
427-
return ok(xstream.toXML(response), APPLICATION_XML).build();
430+
executePostApiAction(apiRequest);
431+
432+
if (APPLICATION_JSON_TYPE == responseType) {
433+
return ok(gson.toJson(account), APPLICATION_JSON).build();
434+
} else if (APPLICATION_XML_TYPE == responseType) {
435+
final RestCommResponse response = new RestCommResponse(account);
436+
return ok(xstream.toXML(response), APPLICATION_XML).build();
437+
} else {
438+
return null;
439+
}
428440
} else {
429-
return null;
441+
if (logger.isDebugEnabled()) {
442+
final String errMsg = "Creation of sub-accounts is not Allowed";
443+
logger.debug(errMsg);
444+
}
445+
executePostApiAction(apiRequest);
446+
String errMsg = "Creation of sub-accounts is not Allowed";
447+
return status(Response.Status.FORBIDDEN).entity(errMsg).build();
430448
}
431449
}
432450

restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/SecuredEndpoint.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,14 @@
2525
import org.apache.shiro.authz.Permission;
2626
import org.apache.shiro.authz.SimpleRole;
2727
import org.apache.shiro.authz.permission.WildcardPermissionResolver;
28-
import org.restcomm.connect.dao.exceptions.AccountHierarchyDepthCrossed;
28+
import org.restcomm.connect.commons.dao.Sid;
2929
import org.restcomm.connect.dao.AccountsDao;
3030
import org.restcomm.connect.dao.DaoManager;
3131
import org.restcomm.connect.dao.OrganizationsDao;
3232
import org.restcomm.connect.dao.entities.Account;
3333
import org.restcomm.connect.dao.entities.Organization;
34-
import org.restcomm.connect.commons.dao.Sid;
34+
import org.restcomm.connect.dao.exceptions.AccountHierarchyDepthCrossed;
3535
import org.restcomm.connect.extension.api.ApiRequest;
36-
import org.restcomm.connect.extension.api.ExtensionResponse;
3736
import org.restcomm.connect.extension.api.ExtensionType;
3837
import org.restcomm.connect.extension.api.RestcommExtensionGeneric;
3938
import org.restcomm.connect.extension.controller.ExtensionController;
@@ -439,20 +438,13 @@ protected String getAdministratorRole() {
439438
}
440439

441440
protected boolean executePreApiAction(final ApiRequest apiRequest) {
442-
if (extensions != null && extensions.size() > 0) {
443-
for (RestcommExtensionGeneric extension : extensions) {
444-
if (extension.isEnabled()) {
445-
ExtensionResponse response = extension.preApiAction(apiRequest);
446-
if (!response.isAllowed())
447-
return false;
448-
}
449-
}
450-
}
451-
return true;
441+
ExtensionController ec = ExtensionController.getInstance();
442+
return ec.executePreApiAction(apiRequest, extensions).isAllowed();
452443
}
453444

454445
protected boolean executePostApiAction(final ApiRequest apiRequest) {
455-
return false;
446+
ExtensionController ec = ExtensionController.getInstance();
447+
return ec.executePostApiAction(apiRequest, extensions).isAllowed();
456448
}
457449

458450
}

restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/BaseVoiceInterpreter.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@
7474
import org.restcomm.connect.email.api.EmailRequest;
7575
import org.restcomm.connect.email.api.EmailResponse;
7676
import org.restcomm.connect.email.api.Mail;
77+
import org.restcomm.connect.extension.api.ExtensionResponse;
78+
import org.restcomm.connect.extension.api.ExtensionType;
79+
import org.restcomm.connect.extension.api.IExtensionFeatureAccessRequest;
80+
import org.restcomm.connect.extension.api.RestcommExtensionGeneric;
81+
import org.restcomm.connect.extension.controller.ExtensionController;
7782
import org.restcomm.connect.fax.FaxRequest;
7883
import org.restcomm.connect.fax.InterfaxService;
7984
import org.restcomm.connect.http.client.Downloader;
@@ -102,6 +107,7 @@
102107
import org.restcomm.connect.telephony.api.CallInfo;
103108
import org.restcomm.connect.telephony.api.CallManagerResponse;
104109
import org.restcomm.connect.telephony.api.CallStateChanged;
110+
import org.restcomm.connect.telephony.api.FeatureAccessRequest;
105111
import org.restcomm.connect.telephony.api.GetCallInfo;
106112
import org.restcomm.connect.telephony.api.Hangup;
107113
import org.restcomm.connect.telephony.api.Reject;
@@ -269,6 +275,9 @@ public abstract class BaseVoiceInterpreter extends RestcommUntypedActor {
269275

270276
protected RestcommConfiguration restcommConfiguration;
271277

278+
//List of extensions for VoiceInterpreter
279+
List<RestcommExtensionGeneric> extensions;
280+
272281
public BaseVoiceInterpreter() {
273282
super();
274283
restcommConfiguration = RestcommConfiguration.getInstance();
@@ -406,6 +415,8 @@ public BaseVoiceInterpreter() {
406415
transitions.add(new Transition(sendingSms, creatingRecording));
407416
transitions.add(new Transition(sendingSms, creatingSmsSession));
408417
transitions.add(new Transition(sendingSms, hangingUp));
418+
419+
extensions = ExtensionController.getInstance().getExtensions(ExtensionType.FeatureAccessControl);
409420
}
410421

411422
@Override
@@ -1564,6 +1575,23 @@ public void execute(final Object message) throws Exception {
15641575
inputType = Collect.Type.parseOrDefault(typeAttr.value(), Collect.Type.DTMF);
15651576
}
15661577

1578+
if (inputType.equals(Collect.Type.SPEECH) || inputType.equals(Collect.Type.DTMF_SPEECH)) {
1579+
ExtensionController ec = ExtensionController.getInstance();
1580+
final IExtensionFeatureAccessRequest far = new FeatureAccessRequest(FeatureAccessRequest.Feature.ASR, accountId);
1581+
ExtensionResponse er = ec.executePreInboundAction(far, extensions);
1582+
if (!er.isAllowed()) {
1583+
if (logger.isDebugEnabled()) {
1584+
final String errMsg = "ASR feature is not allowed";
1585+
logger.debug(errMsg);
1586+
}
1587+
String errMsg = "ASR feature is not allowed";
1588+
notification(WARNING_NOTIFICATION, 11001, errMsg);
1589+
call.tell(new Hangup(errMsg), source);
1590+
return;
1591+
}
1592+
ec.executePostOutboundAction(er, extensions);
1593+
}
1594+
15671595
// parse attribute "language"
15681596
Attribute langAttr = verb.attribute(GatherAttributes.ATTRIBUTE_LANGUAGE);
15691597
String defaultLang = restcommConfiguration.getMgAsr().getDefaultLanguage();

0 commit comments

Comments
 (0)