content: /*
   * Copyright 1999-2018 Alibaba Group Holding Ltd.
   *
   * 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.
   */
  
  package com.alibaba.nacos.test.core.auth;
  
  import com.alibaba.nacos.api.PropertyKeyConst;
  import com.alibaba.nacos.plugin.auth.impl.configuration.AuthConfigs;
  import com.alibaba.nacos.common.utils.JacksonUtils;
  import com.alibaba.nacos.test.base.HttpClient4Test;
  import com.alibaba.nacos.test.base.Params;
  import com.fasterxml.jackson.databind.JsonNode;
  import org.springframework.http.HttpMethod;
  import org.springframework.http.ResponseEntity;
  
  import java.net.URL;
  import java.util.Properties;
  import java.util.concurrent.TimeUnit;
  
  import static org.junit.jupiter.api.Assertions.assertTrue;
  
  /**
   * Base class for authentication tests in Nacos.`
   *
   * @author nkorange
   * @since 1.2.0
   */
  public class AuthBase extends HttpClient4Test {
      
      protected String accessToken;
      
      protected String username1 = "username1";
      
      protected String password1 = "password1";
      
      protected String username2 = "username2";
      
      protected String password2 = "password2";
      
      protected String username3 = "username3";
      
      protected String password3 = "password3";
      
      protected String role1 = "role1";
      
      protected String role2 = "role2";
      
      protected String role3 = "role3";
      
      protected Properties properties;
      
      protected String namespace1 = "namespace1";
      
      /**
       * Logs in a user with the provided username and password, then returns the access token.
       *
       * @param username the username of the user
       * @param password the password of the user
       * @return the access token (accessToken) as a String
       * @throws AssertionError if the response status is not 2xx or the accessToken is missing
       */
      public String login(String username, String password) {
          ResponseEntity<String> response = request("/nacos/v1/auth/users/login",
                  Params.newParams().appendParam("username", username).appendParam("password", password).done(),
                  String.class, HttpMethod.POST);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          JsonNode json = JacksonUtils.toObj(response.getBody());
          assertTrue(json.has("accessToken"));
          return json.get("accessToken").textValue();
      }
      
      public String login() {
          return login("nacos", "nacos");
      }
      
      protected void init(int port) throws Exception {
          AuthConfigs.setCachingEnabled(false);
          TimeUnit.SECONDS.sleep(5L);
          String url = String.format("http://localhost:%d/", port);
          System.setProperty("nacos.core.auth.enabled", "true");
          this.base = new URL(url);
          accessToken = login();
          
          // Create a user:
          ResponseEntity<String> response = request("/nacos/v1/auth/users",
                  Params.newParams().appendParam("username", username1).appendParam("password", password1)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.POST);
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Create a user:
          response = request("/nacos/v1/auth/users",
                  Params.newParams().appendParam("username", username2).appendParam("password", password2)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.POST);
          
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Create a user:
          response = request("/nacos/v1/auth/users",
                  Params.newParams().appendParam("username", username3).appendParam("password", password3)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.POST);
          
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Create a role:
          response = request("/nacos/v1/auth/roles",
                  Params.newParams().appendParam("role", role1).appendParam("username", username1)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.POST);
          
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Create a role:
          response = request("/nacos/v1/auth/roles",
                  Params.newParams().appendParam("role", role2).appendParam("username", username2)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.POST);
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Create a role:
          response = request("/nacos/v1/auth/roles",
                  Params.newParams().appendParam("role", role3).appendParam("username", username3)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.POST);
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Add read permission of namespace1 to role1:
          response = request("/nacos/v1/auth/permissions",
                  Params.newParams().appendParam("role", role1).appendParam("resource", namespace1 + ":*:*")
                          .appendParam("action", "r").appendParam("accessToken", accessToken).done(), String.class,
                  HttpMethod.POST);
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Add write permission of namespace1 to role2:
          response = request("/nacos/v1/auth/permissions",
                  Params.newParams().appendParam("role", role2).appendParam("resource", namespace1 + ":*:*")
                          .appendParam("action", "w").appendParam("accessToken", accessToken).done(), String.class,
                  HttpMethod.POST);
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Add read/write permission of namespace1 to role3:
          response = request("/nacos/v1/auth/permissions",
                  Params.newParams().appendParam("role", role3).appendParam("resource", namespace1 + ":*:*")
                          .appendParam("action", "rw").appendParam("accessToken", accessToken).done(), String.class,
                  HttpMethod.POST);
          System.out.println(response);
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Init properties:
          properties = new Properties();
          properties.put(PropertyKeyConst.NAMESPACE, namespace1);
          properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1" + ":" + port);
      }
      
      protected void destroy() {
          
          // Delete permission:
          ResponseEntity<String> response = request("/nacos/v1/auth/permissions",
                  Params.newParams().appendParam("role", role1).appendParam("resource", namespace1 + ":*:*")
                          .appendParam("action", "r").appendParam("accessToken", accessToken).done(), String.class,
                  HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Delete permission:
          response = request("/nacos/v1/auth/permissions",
                  Params.newParams().appendParam("role", role2).appendParam("resource", namespace1 + ":*:*")
                          .appendParam("action", "w").appendParam("accessToken", accessToken).done(), String.class,
                  HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Delete permission:
          response = request("/nacos/v1/auth/permissions",
                  Params.newParams().appendParam("role", role3).appendParam("resource", namespace1 + ":*:*")
                          .appendParam("action", "rw").appendParam("accessToken", accessToken).done(), String.class,
                  HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Delete a role:
          response = request("/nacos/v1/auth/roles",
                  Params.newParams().appendParam("role", role1).appendParam("username", username1)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Delete a role:
          response = request("/nacos/v1/auth/roles",
                  Params.newParams().appendParam("role", role2).appendParam("username", username2)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Delete a role:
          response = request("/nacos/v1/auth/roles",
                  Params.newParams().appendParam("role", role3).appendParam("username", username3)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Delete a user:
          response = request("/nacos/v1/auth/users",
                  Params.newParams().appendParam("username", username1).appendParam("password", password1)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Delete a user:
          response = request("/nacos/v1/auth/users",
                  Params.newParams().appendParam("username", username2).appendParam("password", password2)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          // Delete a user:
          response = request("/nacos/v1/auth/users",
                  Params.newParams().appendParam("username", username3).appendParam("password", password3)
                          .appendParam("accessToken", accessToken).done(), String.class, HttpMethod.DELETE);
          
          assertTrue(response.getStatusCode().is2xxSuccessful());
          
          System.setProperty("nacos.core.auth.enabled", "false");
      }
  }
  