// Copyright (C) 2020 The Android Open Source Project
//
// 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.google.gerrit.acceptance.server.mail;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.io.BaseEncoding;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.server.mail.EmailTokenVerifier;
import com.google.gerrit.server.mail.EmailTokenVerifier.InvalidTokenException;
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gwtjsonrpc.server.SignedToken;
import java.nio.charset.StandardCharsets;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
import org.junit.Test;

public class SignedTokenEmailTokenVerifierIT extends AbstractDaemonTest {
  @ConfigSuite.Default
  public static Config defaultConfig() {
    Config cfg = new Config();
    cfg.setString("auth", null, "registerEmailPrivateKey", SignedToken.generateRandomKey());
    return cfg;
  }

  private SignedTokenEmailTokenVerifier signedTokenEmailTokenVerifier;

  @Before
  public void setUp() throws Exception {
    signedTokenEmailTokenVerifier =
        server
            .getTestInjector()
            .getBinding(SignedTokenEmailTokenVerifier.class)
            .getProvider()
            .get();
  }

  /** Test encode */
  @Test
  public void encode() throws Exception {
    String tokenString = signedTokenEmailTokenVerifier.encode(user.id, user.email);
    int index = tokenString.indexOf("$");
    String text = tokenString.substring(index + 1);
    String textDecoded = new String(BaseEncoding.base64Url().decode(text), StandardCharsets.UTF_8);
    int pos = textDecoded.indexOf(":");
    assertThat(textDecoded.substring(0, pos)).isEqualTo(user.id.toString());
    assertThat(textDecoded.substring(pos + 1)).isEqualTo(user.email);
  }

  /** Test decode */
  @Test
  public void decode() throws Exception {
    String tokenString = signedTokenEmailTokenVerifier.encode(user.id, user.email);
    String tokenKey = tokenString.substring(0, tokenString.indexOf("$"));
    String text = user.id + ":" + user.email;
    String invalidTokenString =
        tokenKey + "$" + BaseEncoding.base64Url().encode(text.getBytes(StandardCharsets.UTF_8));
    EmailTokenVerifier.ParsedToken parsedToken =
        signedTokenEmailTokenVerifier.decode(invalidTokenString);
    assertThat(parsedToken.getAccountId()).isEqualTo(user.id);
    assertThat(parsedToken.getEmailAddress()).isEqualTo(user.email);
  }

  /** Test token format is wrong(without '$' to split key and text) */
  @Test
  public void invalidFormat() throws Exception {
    InvalidTokenException thrown =
        assertThrows(
            InvalidTokenException.class,
            () -> signedTokenEmailTokenVerifier.decode("Invalid token"));
    assertThat(thrown)
        .hasCauseThat()
        .hasMessageThat()
        .isEqualTo("Token does not contain character '$'");
  }

  /** Test input token string is empty or null */
  @Test
  public void emptyInput() throws Exception {
    InvalidTokenException thrownWithNull =
        assertThrows(InvalidTokenException.class, () -> signedTokenEmailTokenVerifier.decode(null));
    InvalidTokenException thrownWithEmpty =
        assertThrows(InvalidTokenException.class, () -> signedTokenEmailTokenVerifier.decode(""));
    assertThat(thrownWithNull).hasCauseThat().hasMessageThat().isEqualTo("Empty token");
    assertThat(thrownWithEmpty).hasCauseThat().hasMessageThat().isEqualTo("Empty token");
  }

  /** Test token format is right but key is an illegal BASE64 string */
  @Test
  public void illegalTokenKey() throws Exception {
    InvalidTokenException thrown =
        assertThrows(
            InvalidTokenException.class,
            () -> signedTokenEmailTokenVerifier.decode("Illegal token key$...."));
    assertThat(thrown).hasCauseThat().hasMessageThat().isEqualTo("Token length mismatch");
  }

  /** Test token text not match the required pattern */
  @Test
  public void tokenTextPatternMismatch() throws Exception {
    String tokenString = signedTokenEmailTokenVerifier.encode(user.id, user.email);
    String tokenKey = tokenString.substring(0, tokenString.indexOf("$"));
    String pattern = user.id + ":" + user.email;
    String invalidTokenTextPattern = tokenKey + "$" + pattern.replace(":", "");
    InvalidTokenException thrown =
        assertThrows(
            InvalidTokenException.class,
            () -> signedTokenEmailTokenVerifier.decode(invalidTokenTextPattern));
    assertThat(thrown).hasCauseThat().hasMessageThat().isEqualTo("Token text mismatch");
  }
}
