summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsebdet <sebastien.determe@intl.att.com>2020-02-23 09:31:04 -0800
committersebdet <sebastien.determe@intl.att.com>2020-02-25 06:49:46 -0800
commit7658007d67c5c2bc1d81bff4bf972b315cb5bea6 (patch)
treee44324c6dd8a1d653a59d3458a5c38116f25b86a /src
parentaa486be66b1c29ad2e953cb44d105ca1bde40b1c (diff)
Simplify the user management
Simplify the user management and fix a bug in the server, crashing when no user are logged and an operation is requested, and also previous user still stored in the securitycontext when admin is logged (due to static variable) Issue-ID: CLAMP-651 Change-Id: I57523bc2c3afaf5ca5a3acf5c59823df06fd4cd9 Signed-off-by: sebdet <sebastien.determe@intl.att.com>
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/onap/clamp/authorization/AuthorizationController.java63
-rw-r--r--src/main/java/org/onap/clamp/authorization/CldsUser.java (renamed from src/main/java/org/onap/clamp/clds/service/CldsUser.java)2
-rw-r--r--src/main/java/org/onap/clamp/authorization/SecureServicePermission.java (renamed from src/main/java/org/onap/clamp/clds/service/SecureServicePermission.java)2
-rw-r--r--src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java (renamed from src/main/java/org/onap/clamp/clds/service/SecureServicePermissionDeserializer.java)3
-rw-r--r--src/main/java/org/onap/clamp/authorization/UserService.java (renamed from src/main/java/org/onap/clamp/clds/service/UserService.java)7
-rw-r--r--src/main/java/org/onap/clamp/clds/ClampServlet.java2
-rw-r--r--src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java2
-rw-r--r--src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java2
-rw-r--r--src/main/java/org/onap/clamp/clds/model/ClampInformation.java (renamed from src/main/java/org/onap/clamp/clds/service/DefaultUserNameHandler.java)105
-rw-r--r--src/main/java/org/onap/clamp/clds/model/CldsInfo.java110
-rw-r--r--src/main/java/org/onap/clamp/clds/service/CldsInfoProvider.java52
-rw-r--r--src/main/java/org/onap/clamp/clds/service/CldsService.java180
-rw-r--r--src/main/java/org/onap/clamp/clds/service/SecureServiceBase.java226
-rw-r--r--src/main/java/org/onap/clamp/clds/service/UserNameHandler.java31
-rw-r--r--src/main/java/org/onap/clamp/clds/util/JsonUtils.java4
-rw-r--r--src/main/java/org/onap/clamp/clds/util/LoggingUtils.java9
-rw-r--r--src/main/java/org/onap/clamp/tosca/DictionaryService.java3
-rw-r--r--src/main/java/org/onap/clamp/util/PrincipalUtils.java89
-rw-r--r--src/main/resources/clds/camel/rest/clamp-api-v2.xml5
-rw-r--r--src/main/resources/clds/camel/rest/clds-services.xml7
-rw-r--r--src/test/java/org/onap/clamp/clds/config/CldsUserJsonDecoderTest.java6
-rw-r--r--src/test/java/org/onap/clamp/clds/it/AuthorizationControllerItCase.java91
-rw-r--r--src/test/java/org/onap/clamp/clds/it/CldsServiceItCase.java240
-rw-r--r--src/test/java/org/onap/clamp/clds/it/PermissionTestDefaultHelper.java51
-rw-r--r--src/test/java/org/onap/clamp/clds/it/PermissionTestHelper.java79
-rw-r--r--src/test/java/org/onap/clamp/clds/service/CldsInfoProviderTest.java60
26 files changed, 198 insertions, 1233 deletions
diff --git a/src/main/java/org/onap/clamp/authorization/AuthorizationController.java b/src/main/java/org/onap/clamp/authorization/AuthorizationController.java
index b49be86bb..e4a03fd38 100644
--- a/src/main/java/org/onap/clamp/authorization/AuthorizationController.java
+++ b/src/main/java/org/onap/clamp/authorization/AuthorizationController.java
@@ -27,19 +27,18 @@ package org.onap.clamp.authorization;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
-
import java.util.Date;
-
import org.apache.camel.Exchange;
import org.onap.clamp.clds.config.ClampProperties;
import org.onap.clamp.clds.exception.NotAuthorizedException;
-import org.onap.clamp.clds.service.SecureServiceBase;
-import org.onap.clamp.clds.service.SecureServicePermission;
+import org.onap.clamp.clds.model.ClampInformation;
import org.onap.clamp.clds.util.LoggingUtils;
-import org.onap.clamp.util.PrincipalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
/**
@@ -48,7 +47,7 @@ import org.springframework.stereotype.Component;
@Component
public class AuthorizationController {
- protected static final EELFLogger logger = EELFManager.getInstance().getLogger(SecureServiceBase.class);
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(AuthorizationController.class);
protected static final EELFLogger auditLogger = EELFManager.getInstance().getMetricsLogger();
protected static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger();
@@ -56,9 +55,36 @@ public class AuthorizationController {
@Autowired
private ClampProperties refProp;
+ private SecurityContext securityContext = SecurityContextHolder.getContext();
+
public static final String PERM_PREFIX = "security.permission.type.";
private static final String PERM_INSTANCE = "security.permission.instance";
+ private static String retrieveUserName(SecurityContext securityContext) {
+ if (securityContext == null || securityContext.getAuthentication() == null) {
+ return null;
+ }
+ if ((securityContext.getAuthentication().getPrincipal()) instanceof String) {
+ // anonymous case
+ return ((String)securityContext.getAuthentication().getPrincipal());
+ } else {
+ return ((UserDetails) securityContext.getAuthentication().getPrincipal()).getUsername();
+ }
+ }
+ /**
+ * Get the principal name.
+ *
+ * @return The principal name
+ */
+ public static String getPrincipalName(SecurityContext securityContext) {
+ String principal = AuthorizationController.retrieveUserName(securityContext);
+ String name = "Not found";
+ if (principal != null) {
+ name = principal;
+ }
+ return name;
+ }
+
/**
* Insert authorize the api based on the permission.
*
@@ -78,7 +104,7 @@ public class AuthorizationController {
if (null != instanceVar && !instanceVar.isEmpty()) {
instance = instanceVar;
}
- String principalName = PrincipalUtils.getPrincipalName();
+ String principalName = AuthorizationController.getPrincipalName(this.securityContext);
SecureServicePermission perm = SecureServicePermission.create(type, instance, action);
Date startTime = new Date();
LoggingUtils.setTargetContext("Clamp", "authorize");
@@ -101,7 +127,7 @@ public class AuthorizationController {
*/
public boolean isUserPermitted(SecureServicePermission inPermission) {
- String principalName = PrincipalUtils.getPrincipalName();
+ String principalName = AuthorizationController.getPrincipalName(this.securityContext);
// check if the user has the permission key or the permission key with a
// combination of all instance and/or all action.
if (hasRole(inPermission.getKey()) || hasRole(inPermission.getKeyAllInstance())) {
@@ -124,7 +150,7 @@ public class AuthorizationController {
}
protected boolean hasRole(String role) {
- Authentication authentication = PrincipalUtils.getSecurityContext().getAuthentication();
+ Authentication authentication = securityContext.getAuthentication();
if (authentication == null) {
return false;
}
@@ -136,4 +162,23 @@ public class AuthorizationController {
return false;
}
+ /**
+ * Gets clds info. CLDS IFO service will return 3 things 1. User Name 2. CLDS
+ * code version that is currently installed from pom.xml file 3. User
+ * permissions
+ *
+ * @return the clds info
+ */
+ public ClampInformation getClampInformation() {
+ ClampInformation clampInfo = new ClampInformation();
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication == null) {
+ return new ClampInformation();
+ }
+ clampInfo.setUserName(AuthorizationController.getPrincipalName(this.securityContext));
+ for (GrantedAuthority auth : authentication.getAuthorities()) {
+ clampInfo.getAllPermissions().add(auth.getAuthority());
+ }
+ return clampInfo;
+ }
}
diff --git a/src/main/java/org/onap/clamp/clds/service/CldsUser.java b/src/main/java/org/onap/clamp/authorization/CldsUser.java
index 82b7727bd..b50f50cb2 100644
--- a/src/main/java/org/onap/clamp/clds/service/CldsUser.java
+++ b/src/main/java/org/onap/clamp/authorization/CldsUser.java
@@ -21,7 +21,7 @@
*
*/
-package org.onap.clamp.clds.service;
+package org.onap.clamp.authorization;
import java.util.Arrays;
diff --git a/src/main/java/org/onap/clamp/clds/service/SecureServicePermission.java b/src/main/java/org/onap/clamp/authorization/SecureServicePermission.java
index a93732c3b..374aab90c 100644
--- a/src/main/java/org/onap/clamp/clds/service/SecureServicePermission.java
+++ b/src/main/java/org/onap/clamp/authorization/SecureServicePermission.java
@@ -21,7 +21,7 @@
*
*/
-package org.onap.clamp.clds.service;
+package org.onap.clamp.authorization;
/**
* Permission class that can be instantiated easily using constructor or factory
diff --git a/src/main/java/org/onap/clamp/clds/service/SecureServicePermissionDeserializer.java b/src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java
index 9cbf711c9..026ee802c 100644
--- a/src/main/java/org/onap/clamp/clds/service/SecureServicePermissionDeserializer.java
+++ b/src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java
@@ -21,7 +21,8 @@
*
*/
-package org.onap.clamp.clds.service;
+package org.onap.clamp.authorization;
+
import com.google.gson.Gson;
import com.google.gson.JsonDeserializationContext;
diff --git a/src/main/java/org/onap/clamp/clds/service/UserService.java b/src/main/java/org/onap/clamp/authorization/UserService.java
index cf8f66309..b4f51c95b 100644
--- a/src/main/java/org/onap/clamp/clds/service/UserService.java
+++ b/src/main/java/org/onap/clamp/authorization/UserService.java
@@ -20,8 +20,7 @@
* ===================================================================
*/
-package org.onap.clamp.clds.service;
-
+package org.onap.clamp.authorization;
import org.springframework.security.core.context.SecurityContext;
@@ -35,7 +34,7 @@ import org.springframework.stereotype.Controller;
@Controller
public class UserService {
- private SecurityContext securityContext = SecurityContextHolder.getContext();
+ private SecurityContext securityContext = SecurityContextHolder.getContext();
/**
* REST service that returns the username.
@@ -43,6 +42,6 @@ public class UserService {
* @return the user name
*/
public String getUser() {
- return new DefaultUserNameHandler().retrieveUserName(securityContext);
+ return AuthorizationController.getPrincipalName(securityContext);
}
} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/ClampServlet.java b/src/main/java/org/onap/clamp/clds/ClampServlet.java
index 54aa95e5d..5908201fd 100644
--- a/src/main/java/org/onap/clamp/clds/ClampServlet.java
+++ b/src/main/java/org/onap/clamp/clds/ClampServlet.java
@@ -38,7 +38,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.camel.component.servlet.CamelHttpTransportServlet;
-import org.onap.clamp.clds.service.SecureServicePermission;
+import org.onap.clamp.authorization.SecureServicePermission;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
diff --git a/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java b/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java
index 876acc83f..626227e20 100644
--- a/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java
+++ b/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java
@@ -33,7 +33,7 @@ import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.onap.clamp.clds.exception.CldsUsersException;
-import org.onap.clamp.clds.service.CldsUser;
+import org.onap.clamp.authorization.CldsUser;
import org.onap.clamp.clds.util.JsonUtils;
public class CldsUserJsonDecoder {
diff --git a/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java b/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java
index 6a539c7ef..a4515860e 100644
--- a/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java
+++ b/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java
@@ -32,7 +32,7 @@ import java.io.IOException;
import org.onap.clamp.clds.exception.CldsConfigException;
import org.onap.clamp.clds.exception.CldsUsersException;
-import org.onap.clamp.clds.service.CldsUser;
+import org.onap.clamp.authorization.CldsUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
diff --git a/src/main/java/org/onap/clamp/clds/service/DefaultUserNameHandler.java b/src/main/java/org/onap/clamp/clds/model/ClampInformation.java
index 543dd4a92..d73e94204 100644
--- a/src/main/java/org/onap/clamp/clds/service/DefaultUserNameHandler.java
+++ b/src/main/java/org/onap/clamp/clds/model/ClampInformation.java
@@ -1,43 +1,62 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.service;
-
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.userdetails.UserDetails;
-
-
-
-public class DefaultUserNameHandler implements UserNameHandler {
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.onap.clamp.clds.service.PrincipalNameHandler#handleName(SecurityContext)
- */
- @Override
- public String retrieveUserName(SecurityContext securityContext) {
- return ((UserDetails)securityContext.getAuthentication().getPrincipal()).getUsername();
- }
-}
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.model;
+
+import com.google.gson.annotations.Expose;
+import java.util.ArrayList;
+import java.util.List;
+import org.onap.clamp.clds.util.ClampVersioning;
+
+public class ClampInformation {
+ @Expose
+ private String userName;
+ @Expose
+ private String cldsVersion = ClampVersioning.getCldsVersionFromProps();
+ @Expose
+ List<String> allPermissions = new ArrayList<>();
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getCldsVersion() {
+ return cldsVersion;
+ }
+
+ public void setCldsVersion(String cldsVersion) {
+ this.cldsVersion = cldsVersion;
+ }
+
+ public List<String> getAllPermissions() {
+ return allPermissions;
+ }
+
+ public void setAllPermissions(List<String> allPermissions) {
+ this.allPermissions = allPermissions;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/model/CldsInfo.java b/src/main/java/org/onap/clamp/clds/model/CldsInfo.java
deleted file mode 100644
index f3cf6ed19..000000000
--- a/src/main/java/org/onap/clamp/clds/model/CldsInfo.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.model;
-
-import com.google.gson.annotations.Expose;
-
-public class CldsInfo {
- @Expose
- private String userName;
- @Expose
- private String cldsVersion;
- @Expose
- private boolean permissionReadCl;
- @Expose
- private boolean permissionUpdateCl;
- @Expose
- private boolean permissionReadTemplate;
- @Expose
- private boolean permissionUpdateTemplate;
- @Expose
- private boolean permissionReadTosca;
- @Expose
- private boolean permissionUpdateTosca;
-
- public String getUserName() {
- return userName;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- public String getCldsVersion() {
- return cldsVersion;
- }
-
- public void setCldsVersion(String cldsVersion) {
- this.cldsVersion = cldsVersion;
- }
-
- public boolean isPermissionReadCl() {
- return permissionReadCl;
- }
-
- public void setPermissionReadCl(boolean permissionReadCl) {
- this.permissionReadCl = permissionReadCl;
- }
-
- public boolean isPermissionUpdateCl() {
- return permissionUpdateCl;
- }
-
- public void setPermissionUpdateCl(boolean permissionUpdateCl) {
- this.permissionUpdateCl = permissionUpdateCl;
- }
-
- public boolean isPermissionReadTemplate() {
- return permissionReadTemplate;
- }
-
- public void setPermissionReadTemplate(boolean permissionReadTemplate) {
- this.permissionReadTemplate = permissionReadTemplate;
- }
-
- public boolean isPermissionUpdateTemplate() {
- return permissionUpdateTemplate;
- }
-
- public void setPermissionUpdateTemplate(boolean permissionUpdateTemplate) {
- this.permissionUpdateTemplate = permissionUpdateTemplate;
- }
-
- public boolean isPermissionReadTosca() {
- return permissionReadTosca;
- }
-
- public void setPermissionReadTosca(boolean permissionReadTosca) {
- this.permissionReadTosca = permissionReadTosca;
- }
-
- public boolean isPermissionUpdateTosca() {
- return permissionUpdateTosca;
- }
-
- public void setPermissionUpdateTosca(boolean permissionUpdateTosca) {
- this.permissionUpdateTosca = permissionUpdateTosca;
- }
-
-}
diff --git a/src/main/java/org/onap/clamp/clds/service/CldsInfoProvider.java b/src/main/java/org/onap/clamp/clds/service/CldsInfoProvider.java
deleted file mode 100644
index 7027cf1b5..000000000
--- a/src/main/java/org/onap/clamp/clds/service/CldsInfoProvider.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * Modifications copyright (c) 2018 Nokia
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.service;
-
-import org.onap.clamp.clds.model.CldsInfo;
-import org.onap.clamp.clds.util.ClampVersioning;
-
-class CldsInfoProvider {
-
-
- private final CldsService cldsService;
-
- public CldsInfoProvider(CldsService cldsService) {
- this.cldsService = cldsService;
- }
-
- public CldsInfo getCldsInfo() {
- CldsInfo cldsInfo = new CldsInfo();
- cldsInfo.setUserName(cldsService.getUserName());
- cldsInfo.setCldsVersion(ClampVersioning.getCldsVersionFromProps());
-
- cldsInfo.setPermissionReadCl(cldsService.isAuthorizedNoException(cldsService.permissionReadCl));
- cldsInfo.setPermissionUpdateCl(cldsService.isAuthorizedNoException(cldsService.permissionUpdateCl));
- cldsInfo.setPermissionReadTemplate(cldsService.isAuthorizedNoException(cldsService.permissionReadTemplate));
- cldsInfo.setPermissionUpdateTemplate(cldsService.isAuthorizedNoException(cldsService.permissionUpdateTemplate));
- cldsInfo.setPermissionReadTosca(cldsService.isAuthorizedNoException(cldsService.permissionReadTosca));
- cldsInfo.setPermissionUpdateTosca(cldsService.isAuthorizedNoException(cldsService.permissionUpdateTosca));
- return cldsInfo;
- }
-}
diff --git a/src/main/java/org/onap/clamp/clds/service/CldsService.java b/src/main/java/org/onap/clamp/clds/service/CldsService.java
deleted file mode 100644
index 3b84e360c..000000000
--- a/src/main/java/org/onap/clamp/clds/service/CldsService.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Modifications Copyright (c) 2019 Samsung
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * Modifications copyright (c) 2018 Nokia
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.service;
-
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
-
-import java.util.Date;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.onap.clamp.clds.model.CldsInfo;
-import org.onap.clamp.clds.util.LoggingUtils;
-import org.onap.clamp.clds.util.OnapLogConstants;
-import org.slf4j.event.Level;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-/**
- * Service to save and retrieve the CLDS model attributes.
- */
-@Component
-public class CldsService extends SecureServiceBase {
-
- /**
- * The constant securityLogger.
- */
- protected static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger();
- /**
- * The constant logger.
- */
- protected static final EELFLogger logger = EELFManager.getInstance().getLogger(CldsService.class);
-
- private final String cldsPermissionTypeFilterVf;
- private final String cldsPermissionInstance;
- /**
- * The Permission read cl.
- */
- final SecureServicePermission permissionReadCl;
- /**
- * The Permission update cl.
- */
- final SecureServicePermission permissionUpdateCl;
- /**
- * The Permission read template.
- */
- final SecureServicePermission permissionReadTemplate;
- /**
- * The Permission update template.
- */
- final SecureServicePermission permissionUpdateTemplate;
- /**
- * The Permission read tosca.
- */
- final SecureServicePermission permissionReadTosca;
- /**
- * The Permission update tosca.
- */
- final SecureServicePermission permissionUpdateTosca;
-
- private LoggingUtils util = new LoggingUtils(logger);
-
- @Autowired
- private HttpServletRequest request;
-
- /**
- * Instantiates a new Clds service.
- *
- * @param cldsPersmissionTypeCl the clds persmission type cl
- * @param cldsPermissionTypeClManage the clds permission type cl manage
- * @param cldsPermissionTypeClEvent the clds permission type cl event
- * @param cldsPermissionTypeFilterVf the clds permission type filter vf
- * @param cldsPermissionTypeTemplate the clds permission type template
- * @param cldsPermissionTypeTosca the clds permission type tosca
- * @param cldsPermissionInstance the clds permission instance
- */
- @Autowired
- public CldsService(
- @Value("${clamp.config.security.permission.type.cl:permission-type-cl}") String cldsPersmissionTypeCl,
- @Value("${clamp.config.security.permission.type.cl.manage:permission-type-cl-manage}")
- String cldsPermissionTypeClManage,
- @Value("${clamp.config.security.permission.type.cl.event:permission-type-cl-event}")
- String cldsPermissionTypeClEvent,
- @Value("${clamp.config.security.permission.type.filter.vf:permission-type-filter-vf}")
- String cldsPermissionTypeFilterVf,
- @Value("${clamp.config.security.permission.type.template:permission-type-template}")
- String cldsPermissionTypeTemplate,
- @Value("${clamp.config.security.permission.type.tosca:permission-type-tosca}")
- String cldsPermissionTypeTosca,
- @Value("${clamp.config.security.permission.instance:dev}") String cldsPermissionInstance) {
- this.cldsPermissionTypeFilterVf = cldsPermissionTypeFilterVf;
- this.cldsPermissionInstance = cldsPermissionInstance;
- permissionReadCl = SecureServicePermission.create(cldsPersmissionTypeCl, cldsPermissionInstance, "read");
- permissionUpdateCl = SecureServicePermission.create(cldsPersmissionTypeCl, cldsPermissionInstance, "update");
- permissionReadTemplate = SecureServicePermission.create(cldsPermissionTypeTemplate, cldsPermissionInstance,
- "read");
- permissionUpdateTemplate = SecureServicePermission.create(cldsPermissionTypeTemplate, cldsPermissionInstance,
- "update");
- permissionReadTosca = SecureServicePermission.create(cldsPermissionTypeTosca, cldsPermissionInstance, "read");
- permissionUpdateTosca = SecureServicePermission.create(cldsPermissionTypeTosca, cldsPermissionInstance,
- "update");
- }
-
- /**
- * Gets clds info. CLDS IFO service will return 3 things 1. User Name 2. CLDS
- * code version that is currently installed from pom.xml file 3. User
- * permissions
- *
- * @return the clds info
- */
- public CldsInfo getCldsInfo() {
- util.entering(request, "CldsService: GET cldsInfo");
- final Date startTime = new Date();
- LoggingUtils.setTimeContext(startTime, new Date());
-
- CldsInfoProvider cldsInfoProvider = new CldsInfoProvider(this);
- final CldsInfo cldsInfo = cldsInfoProvider.getCldsInfo();
-
- // audit log
- LoggingUtils.setTimeContext(startTime, new Date());
- securityLogger.info("GET cldsInfo completed");
- util.exiting("200", "Get cldsInfo success", Level.INFO, OnapLogConstants.ResponseStatus.COMPLETED);
- return cldsInfo;
- }
-
- /**
- * Determine if the user is authorized for a particular VF by its invariant
- * UUID.
- *
- * @param vfInvariantUuid the vf invariant uuid
- * @return boolean or throws NotAuthorizedException
- */
- public boolean isAuthorizedForVf(String vfInvariantUuid) {
- if (cldsPermissionTypeFilterVf != null && !cldsPermissionTypeFilterVf.isEmpty()) {
- SecureServicePermission permission = SecureServicePermission.create(cldsPermissionTypeFilterVf,
- cldsPermissionInstance, vfInvariantUuid);
- return isAuthorized(permission);
- } else {
- // if CLDS_PERMISSION_TYPE_FILTER_VF property is not provided, then
- // VF filtering is turned off
- logger.warn("VF filtering turned off");
- return true;
- }
- }
-
- /**
- * Sets logging util.
- *
- * @param utilP the util p
- */
- // Created for the integration test
- public void setLoggingUtil(LoggingUtils utilP) {
- util = utilP;
- }
-}
diff --git a/src/main/java/org/onap/clamp/clds/service/SecureServiceBase.java b/src/main/java/org/onap/clamp/clds/service/SecureServiceBase.java
deleted file mode 100644
index debd687c5..000000000
--- a/src/main/java/org/onap/clamp/clds/service/SecureServiceBase.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.service;
-
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
-
-import java.util.Date;
-import javax.ws.rs.NotAuthorizedException;
-
-import org.onap.clamp.clds.util.LoggingUtils;
-import org.onap.clamp.clds.util.OnapLogConstants;
-import org.slf4j.event.Level;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-
-/**
- * Base/abstract Service class. Implements shared security methods.
- */
-public abstract class SecureServiceBase {
- protected static final EELFLogger logger = EELFManager.getInstance().getLogger(SecureServiceBase.class);
- protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
- protected static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger();
-
- // By default we'll set it to a default handler
- private static UserNameHandler userNameHandler = new DefaultUserNameHandler();
-
-
- private SecurityContext securityContext = SecurityContextHolder.getContext();
-
- /**
- * Get the userId from AAF/CSP.
- *
- * @return user ID
- */
- public String getUserId() {
- return getUserName();
- }
-
- /**
- * Get the Full name.
- *
- * @return user name
- */
- public String getUserName() {
- String name = userNameHandler.retrieveUserName(securityContext);
- Date startTime = new Date();
- LoggingUtils.setTargetContext("CLDS", "getUserName");
- LoggingUtils.setTimeContext(startTime, new Date());
- securityLogger.debug("User logged into the CLDS system={}", name);
- return name;
- }
-
- /**
- * Get the principal name.
- *
- * @return the principal name
- */
- public String getPrincipalName() {
- String principal = ((UserDetails)securityContext.getAuthentication().getPrincipal()).getUsername();
- String name = "Not found";
- if (principal != null) {
- name = principal;
- }
- logger.debug("userPrincipal.getName()={}", name);
- return name;
- }
-
- /**
- * Check if user is authorized for the given the permission. Allow matches
- * if user has a permission with an "*" in permission instance or permission
- * action even if the permission to check has a specific value in those
- * fields. For example: if the user has this permission: app-perm-type|*|*
- * it will be authorized if the inPermission to check is:
- * app-perm-type|dev|read
- *
- * @param inPermission
- * The permission to validate
- * @return A boolean to indicate if the user has the permission to do
- * execute the inPermission
- * @throws NotAuthorizedException
- * In case of issues with the permission test, error is returned
- * in this exception
- */
- public boolean isAuthorized(SecureServicePermission inPermission) throws NotAuthorizedException {
- Date startTime = new Date();
- LoggingUtils.setTargetContext("CLDS", "isAuthorized");
- LoggingUtils.setTimeContext(startTime, new Date());
- securityLogger.debug("checking if {} has permission: {}", getPrincipalName(), inPermission);
- try {
- return isUserPermitted(inPermission);
- } catch (NotAuthorizedException nae) {
- String msg = getPrincipalName() + " does not have permission: " + inPermission;
- LoggingUtils.setErrorContext("100", "Authorization Error");
- securityLogger.warn(msg);
- throw new NotAuthorizedException(msg);
- }
- }
-
- /**
- * Check if user is authorized for the given aaf permission. Allow matches
- * if user has a permission with an "*" in permission instance or permission
- * action even if the permission to check has a specific value in those
- * fields. For example: if the user has this permission: app-perm-type|*|*
- * it will be authorized if the inPermission to check is:
- * app-perm-type|dev|read
- *
- * @param inPermission
- * The permission to validate
- * @return A boolean to indicate if the user has the permission to do
- * execute the inPermission
- */
- public boolean isAuthorizedNoException(SecureServicePermission inPermission) {
- securityLogger.debug("checking if {} has permission: {}", getPrincipalName(), inPermission);
- Date startTime = new Date();
- LoggingUtils.setTargetContext("CLDS", "isAuthorizedNoException");
- LoggingUtils.setTimeContext(startTime, new Date());
- try {
- return isUserPermitted(inPermission);
- } catch (NotAuthorizedException nae) {
- String msg = getPrincipalName() + " does not have permission: " + inPermission;
- LoggingUtils.setErrorContext("100", "Authorization Error");
- securityLogger.warn(msg);
- }
- return false;
- }
-
- /**
- * This method can be used by the Application.class to set the
- * UserNameHandler that must be used in this class. The UserNameHandler
- * where to get the User name
- *
- * @param handler
- * The Handler impl to use
- */
- public static final void setUserNameHandler(UserNameHandler handler) {
- if (handler != null) {
- userNameHandler = handler;
- }
- }
-
- public void setSecurityContext(SecurityContext securityContext) {
- this.securityContext = securityContext;
- }
-
- private boolean isUserPermitted(SecureServicePermission inPermission) {
- boolean authorized = false;
- // check if the user has the permission key or the permission key with a
- // combination of all instance and/or all action.
- if (hasRole(inPermission.getKey())) {
- securityLogger.info("{} authorized for permission: {}", getPrincipalName(), inPermission.getKey());
- authorized = true;
- // the rest of these don't seem to be required - isUserInRole method
- // appears to take * as a wildcard
- } else if (hasRole(inPermission.getKeyAllInstance())) {
- securityLogger.info("{} authorized because user has permission with * for instance: {}",
- getPrincipalName(), inPermission.getKey());
- authorized = true;
- } else if (hasRole(inPermission.getKeyAllInstanceAction())) {
- securityLogger.info("{} authorized because user has permission with * for instance and * for action: {}",
- getPrincipalName(), inPermission.getKey());
- authorized = true;
- } else if (hasRole(inPermission.getKeyAllAction())) {
- securityLogger.info("{} authorized because user has permission with * for action: {}",
- getPrincipalName(), inPermission.getKey());
- authorized = true;
- } else {
- throw new NotAuthorizedException("");
- }
- return authorized;
- }
-
- protected boolean hasRole(String role) {
- Authentication authentication = securityContext.getAuthentication();
- if (authentication == null) {
- return false;
- }
-
- for (GrantedAuthority auth : authentication.getAuthorities()) {
- if (role.equals(auth.getAuthority())) {
- return true;
- }
- }
-
- return false;
- }
-
- protected void auditLogInfo(LoggingUtils util, String actionDescription, Date startTime) {
- LoggingUtils.setTimeContext(startTime, new Date());
- auditLogger.info(actionDescription + " completed");
- util.exiting("200", actionDescription + " success", Level.INFO,
- OnapLogConstants.ResponseStatus.COMPLETED);
- }
-
- protected void auditLogInfo(String actionDescription, Date startTime) {
-
- LoggingUtils.setTimeContext(startTime, new Date());
- LoggingUtils.setResponseContext("0", actionDescription + " success",
- this.getClass().getName());
- auditLogger.info(actionDescription + " completed");
- }
-} \ No newline at end of file
diff --git a/src/main/java/org/onap/clamp/clds/service/UserNameHandler.java b/src/main/java/org/onap/clamp/clds/service/UserNameHandler.java
deleted file mode 100644
index d48700f6a..000000000
--- a/src/main/java/org/onap/clamp/clds/service/UserNameHandler.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.service;
-
-import org.springframework.security.core.context.SecurityContext;
-
-public interface UserNameHandler {
-
- public String retrieveUserName(SecurityContext securityContext);
-}
diff --git a/src/main/java/org/onap/clamp/clds/util/JsonUtils.java b/src/main/java/org/onap/clamp/clds/util/JsonUtils.java
index 704d3ac37..8024331f2 100644
--- a/src/main/java/org/onap/clamp/clds/util/JsonUtils.java
+++ b/src/main/java/org/onap/clamp/clds/util/JsonUtils.java
@@ -30,8 +30,8 @@ import com.google.gson.GsonBuilder;
import java.time.Instant;
-import org.onap.clamp.clds.service.SecureServicePermission;
-import org.onap.clamp.clds.service.SecureServicePermissionDeserializer;
+import org.onap.clamp.authorization.SecureServicePermission;
+import org.onap.clamp.authorization.SecureServicePermissionDeserializer;
import org.onap.clamp.dao.model.gson.converter.InstantDeserializer;
import org.onap.clamp.dao.model.gson.converter.InstantSerializer;
diff --git a/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java
index 1a6cca6b8..a471b411b 100644
--- a/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java
+++ b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java
@@ -25,7 +25,6 @@ package org.onap.clamp.clds.util;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
-
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URLConnection;
@@ -39,12 +38,10 @@ import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.TimeZone;
import java.util.UUID;
-
import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
-
-import org.onap.clamp.clds.service.DefaultUserNameHandler;
+import org.onap.clamp.authorization.AuthorizationController;
import org.slf4j.MDC;
import org.slf4j.event.Level;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -188,8 +185,8 @@ public class LoggingUtils {
// Default the partner name to the user name used to login to clamp
if (partnerName.equalsIgnoreCase(EMPTY_MESSAGE)) {
- MDC.put(OnapLogConstants.Mdcs.PARTNER_NAME, new DefaultUserNameHandler()
- .retrieveUserName(SecurityContextHolder.getContext()));
+ MDC.put(OnapLogConstants.Mdcs.PARTNER_NAME,
+ AuthorizationController.getPrincipalName(SecurityContextHolder.getContext()));
}
// Set standard MDCs. Override this entire method if you want to set
diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryService.java b/src/main/java/org/onap/clamp/tosca/DictionaryService.java
index 21ca1f7f7..5b24def98 100644
--- a/src/main/java/org/onap/clamp/tosca/DictionaryService.java
+++ b/src/main/java/org/onap/clamp/tosca/DictionaryService.java
@@ -27,12 +27,11 @@ import com.google.common.collect.Sets;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityNotFoundException;
-import org.onap.clamp.clds.service.SecureServiceBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
-public class DictionaryService extends SecureServiceBase {
+public class DictionaryService {
private final DictionaryRepository dictionaryRepository;
private final DictionaryElementsRepository dictionaryElementsRepository;
diff --git a/src/main/java/org/onap/clamp/util/PrincipalUtils.java b/src/main/java/org/onap/clamp/util/PrincipalUtils.java
deleted file mode 100644
index d6dfacbdb..000000000
--- a/src/main/java/org/onap/clamp/util/PrincipalUtils.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * Modifications copyright (c) 2018 Nokia
- * ===================================================================
- *
- */
-
-package org.onap.clamp.util;
-
-import java.util.Date;
-
-import org.onap.clamp.clds.service.DefaultUserNameHandler;
-import org.onap.clamp.clds.service.UserNameHandler;
-import org.onap.clamp.clds.util.LoggingUtils;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-
-public class PrincipalUtils {
- private static UserNameHandler userNameHandler = new DefaultUserNameHandler();
- private static SecurityContext securityContext = SecurityContextHolder.getContext();
-
- /**
- * Private constructor to avoid creating instances of util class.
- */
- private PrincipalUtils(){
- }
-
- /**
- * Get the Full name.
- *
- * @return The user name
- */
- public static String getUserName() {
- String name = userNameHandler.retrieveUserName(securityContext);
- Date startTime = new Date();
- LoggingUtils.setTargetContext("CLDS", "getUserName");
- LoggingUtils.setTimeContext(startTime, new Date());
- return name;
- }
-
- /**
- * Get the userId from AAF/CSP.
- *
- * @return The user ID
- */
- public static String getUserId() {
- return getUserName();
- }
-
- /**
- * Get the principal name.
- *
- * @return The principal name
- */
- public static String getPrincipalName() {
- String principal = ((UserDetails)securityContext.getAuthentication().getPrincipal()).getUsername();
- String name = "Not found";
- if (principal != null) {
- name = principal;
- }
- return name;
- }
-
- public static void setSecurityContext(SecurityContext securityContext) {
- PrincipalUtils.securityContext = securityContext;
- }
-
- public static SecurityContext getSecurityContext() {
- return securityContext;
- }
-}
diff --git a/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/src/main/resources/clds/camel/rest/clamp-api-v2.xml
index d62a0c289..1f927267c 100644
--- a/src/main/resources/clds/camel/rest/clamp-api-v2.xml
+++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml
@@ -1050,5 +1050,10 @@
</doTry>
</route>
</get>
+ <get uri="/v2/clampInformation" outType="org.onap.clamp.clds.model.ClampInformation"
+ produces="application/json">
+ <to
+ uri="bean:org.onap.clamp.authorization.AuthorizationController?method=getClampInformation()" />
+ </get>
</rest>
</rests>
diff --git a/src/main/resources/clds/camel/rest/clds-services.xml b/src/main/resources/clds/camel/rest/clds-services.xml
index dd3a4bfdc..ce52f31d6 100644
--- a/src/main/resources/clds/camel/rest/clds-services.xml
+++ b/src/main/resources/clds/camel/rest/clds-services.xml
@@ -1,10 +1,5 @@
<rests xmlns="http://camel.apache.org/schema/spring">
<rest>
- <get uri="/v1/clds/cldsInfo" outType="org.onap.clamp.clds.model.CldsInfo"
- produces="application/json">
- <to
- uri="bean:org.onap.clamp.clds.service.CldsService?method=getCldsInfo()" />
- </get>
<get uri="/v1/healthcheck" produces="application/json"
outType="org.onap.clamp.clds.model.CldsHealthCheck">
<route>
@@ -23,7 +18,7 @@
</get>
<get uri="/v1/user/getUser" produces="text/plain">
- <to uri="bean:org.onap.clamp.clds.service.UserService?method=getUser()" />
+ <to uri="bean:org.onap.clamp.authorization.UserService?method=getUser()" />
</get>
</rest>
</rests>
diff --git a/src/test/java/org/onap/clamp/clds/config/CldsUserJsonDecoderTest.java b/src/test/java/org/onap/clamp/clds/config/CldsUserJsonDecoderTest.java
index a94804212..5a1292210 100644
--- a/src/test/java/org/onap/clamp/clds/config/CldsUserJsonDecoderTest.java
+++ b/src/test/java/org/onap/clamp/clds/config/CldsUserJsonDecoderTest.java
@@ -26,11 +26,11 @@
package org.onap.clamp.clds.config;
-import static org.assertj.core.api.Assertions.assertThat;
-
import org.junit.Test;
+import org.onap.clamp.authorization.CldsUser;
import org.onap.clamp.clds.exception.CldsUsersException;
-import org.onap.clamp.clds.service.CldsUser;
+
+import static org.assertj.core.api.Assertions.assertThat;
public class CldsUserJsonDecoderTest {
diff --git a/src/test/java/org/onap/clamp/clds/it/AuthorizationControllerItCase.java b/src/test/java/org/onap/clamp/clds/it/AuthorizationControllerItCase.java
index 49f173644..3406042c1 100644
--- a/src/test/java/org/onap/clamp/clds/it/AuthorizationControllerItCase.java
+++ b/src/test/java/org/onap/clamp/clds/it/AuthorizationControllerItCase.java
@@ -25,27 +25,27 @@
package org.onap.clamp.clds.it;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.List;
+import java.util.Arrays;
+import java.util.Collection;
import org.apache.camel.Exchange;
-import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.onap.clamp.authorization.AuthorizationController;
+import org.onap.clamp.authorization.SecureServicePermission;
import org.onap.clamp.clds.exception.NotAuthorizedException;
-import org.onap.clamp.clds.service.SecureServicePermission;
-import org.onap.clamp.util.PrincipalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.junit4.SpringRunner;
/**
@@ -53,33 +53,67 @@ import org.springframework.test.context.junit4.SpringRunner;
* and stored procedures.
*/
@RunWith(SpringRunner.class)
-@SpringBootTest
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AuthorizationControllerItCase {
- private PermissionTestDefaultHelper permissionTestHelper = new PermissionTestDefaultHelper();
-
- // @Spy
- // MockEnvironment env;
-
@Autowired
private AuthorizationController auth;
+ private static SecurityContext sc = SecurityContextHolder.getContext();
+
/**
* Setup the variable before the tests execution.
*/
- @Before
- public void setupBefore() {
- // permissionTestHelper.setupMockEnv(env);
- List<GrantedAuthority> authList = permissionTestHelper.getAuthList();
-
- SecurityContext securityContext = Mockito.mock(SecurityContext.class);
- Mockito.when(securityContext.getAuthentication())
- .thenReturn(new UsernamePasswordAuthenticationToken(new User("admin", "", authList), "", authList));
- PrincipalUtils.setSecurityContext(securityContext);
+ @BeforeClass
+ public static void setupBefore() {
+
+ sc.setAuthentication(new Authentication() {
+ @Override
+ public Collection<? extends GrantedAuthority> getAuthorities() {
+ return Arrays.asList(new SimpleGrantedAuthority(
+ new SecureServicePermission("permission-type-cl", "dev", "read").getKey()),
+ new SimpleGrantedAuthority(new SecureServicePermission("permission-type-cl-manage", "dev",
+ "DEPLOY").getKey()),
+ new SimpleGrantedAuthority(new SecureServicePermission("permission-type-filter-vf", "dev",
+ "12345-55555-55555-5555").getKey()));
+ }
+
+ @Override
+ public Object getCredentials() {
+ return null;
+ }
+
+ @Override
+ public Object getDetails() {
+ return null;
+ }
+
+ @Override
+ public Object getPrincipal() {
+ return "admin";
+ }
+
+ @Override
+ public boolean isAuthenticated() {
+ return true;
+ }
+
+ @Override
+ public void setAuthenticated(boolean authenticatedFlag) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public String getName() {
+ return "admin";
+ }
+ });
+
}
@Test
public void testIsUserPermitted() {
+ assertEquals(AuthorizationController.getPrincipalName(sc),"admin");
assertTrue(auth.isUserPermitted(new SecureServicePermission("permission-type-cl", "dev", "read")));
assertTrue(auth.isUserPermitted(new SecureServicePermission("permission-type-cl-manage", "dev", "DEPLOY")));
assertTrue(auth.isUserPermitted(
@@ -87,17 +121,6 @@ public class AuthorizationControllerItCase {
assertFalse(auth.isUserPermitted(new SecureServicePermission("permission-type-cl", "test", "read")));
}
- @Test
- public void testIfUserAuthorize() {
- Exchange ex = Mockito.mock(Exchange.class);
- try {
- permissionTestHelper
- .doActionOnAllPermissions(((type, instance, action) -> auth.authorize(ex, type, instance, action)));
- } catch (NotAuthorizedException e) {
- fail(e.getMessage());
- }
- }
-
@Test(expected = NotAuthorizedException.class)
public void testIfAuthorizeThrowException() {
Exchange ex = Mockito.mock(Exchange.class);
diff --git a/src/test/java/org/onap/clamp/clds/it/CldsServiceItCase.java b/src/test/java/org/onap/clamp/clds/it/CldsServiceItCase.java
deleted file mode 100644
index 40cc0650e..000000000
--- a/src/test/java/org/onap/clamp/clds/it/CldsServiceItCase.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.it;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Properties;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.NotAuthorizedException;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Matchers;
-import org.mockito.Mockito;
-import org.onap.clamp.clds.model.CldsInfo;
-import org.onap.clamp.clds.service.CldsService;
-import org.onap.clamp.clds.util.LoggingUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-/**
- * Test HTTP and HTTPS settings + redirection of HTTP to HTTPS.
- */
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-public class CldsServiceItCase {
-
- @Autowired
- private CldsService cldsService;
-
- private LoggingUtils util;
- private SecurityContext securityContext = mock(SecurityContext.class);
- private Authentication auth = Mockito.mock(Authentication.class);
- private UserDetails userDetails = Mockito.mock(UserDetails.class);
- private List<GrantedAuthority> authorityList = new LinkedList<GrantedAuthority>();
- /**
- * Setup the variable before the tests execution.
- *
- * @throws IOException In case of issues when opening the files
- */
- @Before
- public void setupBefore() throws IOException {
- util = Mockito.mock(LoggingUtils.class);
- Mockito.doNothing().when(util).entering(Matchers.any(HttpServletRequest.class), Matchers.any(String.class));
- cldsService.setLoggingUtil(util);
-
- }
-
- @Test
- public void testCldsInfoNotAuthorized() {
- Mockito.when(userDetails.getUsername()).thenReturn("admin");
- Mockito.when(securityContext.getAuthentication()).thenReturn(auth);
- Mockito.when(auth.getPrincipal()).thenReturn(userDetails);
-
- cldsService.setSecurityContext(securityContext);
- CldsInfo cldsInfo = cldsService.getCldsInfo();
- assertFalse(cldsInfo.isPermissionReadCl());
- assertFalse(cldsInfo.isPermissionReadTemplate());
- assertFalse(cldsInfo.isPermissionUpdateCl());
- assertFalse(cldsInfo.isPermissionUpdateTemplate());
- }
-
- @Test
- public void testCldsInfoAuthorized() throws Exception {
- List<GrantedAuthority> authList = new LinkedList<GrantedAuthority>();
- authList.add(new SimpleGrantedAuthority("permission-type-cl-manage|dev|*"));
- authList.add(new SimpleGrantedAuthority("permission-type-cl|dev|read"));
- authList.add(new SimpleGrantedAuthority("permission-type-cl|dev|update"));
- authList.add(new SimpleGrantedAuthority("permission-type-template|dev|read"));
- authList.add(new SimpleGrantedAuthority("permission-type-template|dev|update"));
- authList.add(new SimpleGrantedAuthority("permission-type-filter-vf|dev|*"));
- authList.add(new SimpleGrantedAuthority("permission-type-cl-event|dev|*"));
- Authentication authentication;
- authentication = new UsernamePasswordAuthenticationToken(new User("admin", "", authList), "", authList);
-
- Mockito.when(securityContext.getAuthentication()).thenReturn(authentication);
-
- cldsService.setSecurityContext(securityContext);
- CldsInfo cldsInfo = cldsService.getCldsInfo();
- assertTrue(cldsInfo.isPermissionReadCl());
- assertTrue(cldsInfo.isPermissionReadTemplate());
- assertTrue(cldsInfo.isPermissionUpdateCl());
- assertTrue(cldsInfo.isPermissionUpdateTemplate());
- Properties prop = new Properties();
- InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("clds-version.properties");
- prop.load(in);
- assertNotNull(in);
- in.close();
- assertEquals(cldsInfo.getCldsVersion(), prop.getProperty("clds.version"));
- assertEquals(cldsInfo.getUserName(), "admin");
- }
-
- @Test(expected = NotAuthorizedException.class)
- public void isAuthorizedForVfTestNotAuthorized1() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- when(securityContext.getAuthentication()).thenReturn(auth);
- cldsService.setSecurityContext(securityContext);
- boolean res = cldsService.isAuthorizedForVf("testId");
- assertThat(res).isTrue();
- }
-
- @Test(expected = NotAuthorizedException.class)
- public void isAuthorizedForVfTestNotAuthorized2() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- authorityList.add(new SimpleGrantedAuthority("permission-type-filter-vf|prod|*"));
- when((List<GrantedAuthority>)auth.getAuthorities()).thenReturn(authorityList);
- when(securityContext.getAuthentication()).thenReturn(auth);
- cldsService.setSecurityContext(securityContext);
- boolean res = cldsService.isAuthorizedForVf("testId");
- assertThat(res).isTrue();
- }
-
- @Test(expected = NotAuthorizedException.class)
- public void isAuthorizedForVfTestNotAuthorized3() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- authorityList.add(new SimpleGrantedAuthority("permission-type-filter-vf|dev|testId2"));
- when((List<GrantedAuthority>)auth.getAuthorities()).thenReturn(authorityList);
- when(securityContext.getAuthentication()).thenReturn(auth);
- cldsService.setSecurityContext(securityContext);
- boolean res = cldsService.isAuthorizedForVf("testId");
- assertThat(res).isTrue();
- }
-
- @Test(expected = NullPointerException.class)
- public void isAuthorizedForVfTestNotAuthorized4() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- when(securityContext.getAuthentication()).thenReturn(null);
- cldsService.setSecurityContext(securityContext);
- boolean res = cldsService.isAuthorizedForVf("testId");
- assertThat(res).isTrue();
- }
-
- @Test
- public void isAuthorizedForVfTest1() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- authorityList.add(new SimpleGrantedAuthority("permission-type-filter-vf|*|*"));
- when((List<GrantedAuthority>)auth.getAuthorities()).thenReturn(authorityList);
- when(securityContext.getAuthentication()).thenReturn(auth);
-
- cldsService.setSecurityContext(securityContext);
- boolean res = cldsService.isAuthorizedForVf("testId");
- assertThat(res).isTrue();
- }
-
- @Test
- public void isAuthorizedForVfTest2() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- authorityList.add(new SimpleGrantedAuthority("permission-type-filter-vf|dev|*"));
- when((List<GrantedAuthority>)auth.getAuthorities()).thenReturn(authorityList);
- when(securityContext.getAuthentication()).thenReturn(auth);
-
- cldsService.setSecurityContext(securityContext);
- boolean res = cldsService.isAuthorizedForVf("testId");
- assertThat(res).isTrue();
- }
-
- @Test
- public void isAuthorizedForVfTest3() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- authorityList.add(new SimpleGrantedAuthority("permission-type-filter-vf|dev|testId"));
- when((List<GrantedAuthority>)auth.getAuthorities()).thenReturn(authorityList);
- when(securityContext.getAuthentication()).thenReturn(auth);
-
- cldsService.setSecurityContext(securityContext);
- boolean res = cldsService.isAuthorizedForVf("testId");
- assertThat(res).isTrue();
- }
-
- @Test
- public void isAuthorizedForVfTest4() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- authorityList.add(new SimpleGrantedAuthority("permission-type-filter-vf|*|testId"));
- when((List<GrantedAuthority>)auth.getAuthorities()).thenReturn(authorityList);
- when(securityContext.getAuthentication()).thenReturn(auth);
-
- cldsService.setSecurityContext(securityContext);
- boolean res = cldsService.isAuthorizedForVf("testId");
- assertThat(res).isTrue();
- }
-
- @Test
- public void getUserIdTest() throws Exception {
- when(userDetails.getUsername()).thenReturn("testName");
- when(auth.getPrincipal()).thenReturn(userDetails);
- when(securityContext.getAuthentication()).thenReturn(auth);
-
- cldsService.setSecurityContext(securityContext);
- assertThat(cldsService.getUserId()).isEqualTo("testName");
- }
-}
diff --git a/src/test/java/org/onap/clamp/clds/it/PermissionTestDefaultHelper.java b/src/test/java/org/onap/clamp/clds/it/PermissionTestDefaultHelper.java
deleted file mode 100644
index 1830115f8..000000000
--- a/src/test/java/org/onap/clamp/clds/it/PermissionTestDefaultHelper.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2019 Samsung. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.it;
-
-import com.google.common.collect.ImmutableMap;
-
-import java.util.Map;
-
-public class PermissionTestDefaultHelper extends PermissionTestHelper {
-
- private static final String[] ALL_ACTION = new String[] { "*" };
- private static final String[] READ_UPDATE_ACTION = new String[] { "read", "update" };
-
- private static final String DEV_INSTANCE = "dev";
- private static final String TEST_INSTANCE = "test";
-
- private static final Map<String, Map<?, ?>> defaultPermission = ImmutableMap.of("permission-type-cl",
- ImmutableMap.of(DEV_INSTANCE, ALL_ACTION), "permission-type-cl-event",
- ImmutableMap.of(DEV_INSTANCE, ALL_ACTION, TEST_INSTANCE, READ_UPDATE_ACTION), "permission-type-cl-manage",
- ImmutableMap.of(DEV_INSTANCE, ALL_ACTION, TEST_INSTANCE, READ_UPDATE_ACTION), "permission-type-filter-vf",
- ImmutableMap.of(DEV_INSTANCE, ALL_ACTION, TEST_INSTANCE, READ_UPDATE_ACTION), "permission-type-template",
- ImmutableMap.of(DEV_INSTANCE, ALL_ACTION, TEST_INSTANCE, READ_UPDATE_ACTION));
-
- /**
- * Permission test default helper constructor. This class setup the default
- * permission in the parent PermissionTestHelper class.
- */
- public PermissionTestDefaultHelper() {
- super(defaultPermission);
- }
-}
diff --git a/src/test/java/org/onap/clamp/clds/it/PermissionTestHelper.java b/src/test/java/org/onap/clamp/clds/it/PermissionTestHelper.java
deleted file mode 100644
index 905b7f702..000000000
--- a/src/test/java/org/onap/clamp/clds/it/PermissionTestHelper.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2019 Samsung. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.it;
-
-import static org.onap.clamp.authorization.AuthorizationController.PERM_PREFIX;
-import static org.onap.clamp.clds.config.ClampProperties.CONFIG_PREFIX;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.springframework.mock.env.MockEnvironment;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
-
-public class PermissionTestHelper {
-
- private static final String securityPrefix = CONFIG_PREFIX + PERM_PREFIX;
- private final Map<String, Map<?, ?>> permission;
- private static final List<GrantedAuthority> authList = new LinkedList<>();
-
- /**
- * Permission Test Helper constructor. Generate authList base on general
- * permission collection.
- */
- public PermissionTestHelper(Map<String, Map<?, ?>> permission) {
- this.permission = permission;
- this.createAuthList();
- }
-
- private void createAuthList() {
- permission.forEach((type, instanceMap) -> instanceMap.forEach((instance, actionList) -> {
- for (String action : (String[]) actionList) {
- authList.add(new SimpleGrantedAuthority(type + "|" + instance + "|" + action));
- }
- }));
- }
-
- List<GrantedAuthority> getAuthList() {
- return authList;
- }
-
- void setupMockEnv(MockEnvironment env) {
- permission.forEach((type, instanceMap) -> env.withProperty(securityPrefix + type, type));
- }
-
- void doActionOnAllPermissions(PermissionAction action) {
- permission.forEach((type, instanceMap) -> instanceMap.forEach((instance, actionList) -> {
- for (String actionName : (String[]) actionList) {
- action.doAction(type, (String) instance, actionName);
- }
- }));
- }
-
- @FunctionalInterface
- public interface PermissionAction {
- void doAction(String type, String instance, String action);
- }
-}
diff --git a/src/test/java/org/onap/clamp/clds/service/CldsInfoProviderTest.java b/src/test/java/org/onap/clamp/clds/service/CldsInfoProviderTest.java
deleted file mode 100644
index fa898c7a2..000000000
--- a/src/test/java/org/onap/clamp/clds/service/CldsInfoProviderTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2018 Nokia Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.clds.service;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Test;
-import org.onap.clamp.clds.model.CldsInfo;
-
-
-public class CldsInfoProviderTest {
-
- private static final String TEST_USERNAME = "TEST_USERNAME";
-
- @Test
- public void shouldProvideCldsInfoFromContext() throws Exception {
-
- // given
- CldsService serviceBase = mock(CldsService.class);
- when(serviceBase.getUserName()).thenReturn(TEST_USERNAME);
- when(serviceBase.isAuthorizedNoException(any())).thenReturn(true);
- CldsInfoProvider cldsInfoProvider = new CldsInfoProvider(serviceBase);
-
- // when
- CldsInfo cldsInfo = cldsInfoProvider.getCldsInfo();
-
- // then
- assertThat(cldsInfo.getUserName()).isEqualTo(TEST_USERNAME);
- assertThat(cldsInfo.isPermissionReadCl()).isTrue();
- assertThat(cldsInfo.isPermissionReadTemplate()).isTrue();
- assertThat(cldsInfo.isPermissionUpdateCl()).isTrue();
- assertThat(cldsInfo.isPermissionUpdateTemplate()).isTrue();
- assertThat(cldsInfo.isPermissionReadTosca()).isTrue();
- assertThat(cldsInfo.isPermissionUpdateTosca()).isTrue();
- }
-} \ No newline at end of file