package com.adaptris.core.http.jetty;

import javax.validation.constraints.NotNull;

import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.hibernate.validator.constraints.NotBlank;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adaptris.annotation.AdvancedConfig;
import com.adaptris.annotation.AutoPopulated;
import com.adaptris.annotation.Removal;
import com.adaptris.core.util.Args;
import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * Allows you to configure a {@code HashLoginService} for use with Jetty.
 * <p>
 * This simply exposes the Jetty HashLoginService as Interlok configuration. The documentation from
 * <a href="https://wiki.eclipse.org/Jetty/Tutorial/Realms">the eclipse jetty site</a> should always be considered canonical. The
 * HashLoginService is a realm whose authentication and authorization information is stored in a properties file. Each line in the
 * file contains a username, a password, and zero or more role assignments. The format is <pre>
 * {@code 
username: password[,rolename ...]
username: password[,rolename ...]
 * }
 * </pre> where:
 * <ul>
 * <li><strong>username</strong> is the user's unique identity</li>
 * <li><strong>password</strong> is the user's (possibly obfuscated or MD5 encrypted) password;</li>
 * <li><strong>rolename</strong> is the user's role.</li>
 * </ul>
 * <p>
 * If you need to secure the passwords in your properties file then you can follow
 * <a href= "https://www.eclipse.org/jetty/documentation/9.3.x/configuring-security-secure-passwords.html">the jetty
 * documentation</a> to obfuscate/hash the password. <pre>
 * {@code
$ java -cp ./lib/jetty-util.jar  org.eclipse.jetty.util.security.Password myusername MySuperSecretPassword
OBF:1o4o1zly1rhf1zst1y0s1vu91uvk1ldu1w1c1sot1y7z1sox1w261ldo1uum1vv11y0y1zsx1riz1zlk1o5y
MD5:d418c3e96fb98e73fd603a8b6134edda
CRYPT:my8hdCDBVkNU.
 * }
 * </pre>
 * 
 * @author lchan
 *
 */
@XStreamAlias("jetty-hash-login-service")
public class HashLoginServiceFactory implements JettyLoginServiceFactory {
  private transient Logger log = LoggerFactory.getLogger(this.getClass());

  @NotNull
  @NotBlank
  @AutoPopulated
  private String userRealm;
  @NotNull
  @NotBlank
  private String filename;
  @AdvancedConfig
  @Deprecated
  @Removal(version = "3.9.0")
  private Integer refreshInterval;

  public HashLoginServiceFactory() {
    setUserRealm("InterlokJetty");
  }

  public HashLoginServiceFactory(String realm, String filename) {
    this();
    setUserRealm(realm);
    setFilename(filename);
  }

  @Override
  public LoginService retrieveLoginService() {
    HashLoginService loginService = new HashLoginService(getUserRealm(), getFilename());
    if (refreshInterval != null) {
      log.warn("[refresh-interval] is deprecated, and has no effect");
    }
    loginService.setHotReload(true);
    return loginService;
  }

  public String getUserRealm() {
    return userRealm;
  }

  public void setUserRealm(String userRealm) {
    this.userRealm = Args.notNull(userRealm, "userRealm");
  }

  public String getFilename() {
    return filename;
  }

  /**
   * Set the filename containing the username/password/roles.
   * 
   * @param filename the filename.
   */
  public void setFilename(String filename) {
    this.filename = Args.notNull(filename, "filename");
  }


  /**
   * @return the refreshInterval
   * @deprecated since 3.6.0 refresh interval has no effect.
   */
  @Deprecated
  @Removal(version = "3.9.0")
  public Integer getRefreshInterval() {
    return refreshInterval;
  }


  /**
   * Specify the refresh interval (in seconds) for monitoring the password file.
   * 
   * @deprecated since 3.6.0 refresh interval has no effect.
   * @param i the refreshInterval to set
   */
  @Deprecated
  @Removal(version = "3.9.0")
  public void setRefreshInterval(Integer i) {
    this.refreshInterval = i;
  }
}

@@ -77,17 +77,16 @@
 otNull;%0A
-%0A
 import o
@@ -287,17 +287,16 @@
 actory;%0A
-%0A
 import c
@@ -800,16 +800,19 @@
 d always
+%0A *
  be cons
@@ -832,19 +832,16 @@
 cal. The
-%0A *
  HashLog
@@ -899,16 +899,19 @@
 rization
+%0A *
  informa
@@ -963,19 +963,16 @@
 e in the
-%0A *
  file co
@@ -991,16 +991,19 @@
 rname, a
+%0A *
  passwor
@@ -1053,16 +1053,23 @@
 ormat is
+%0A * %0A *
  %3Cpre%3E%0A 
@@ -1160,16 +1160,23 @@
 * %3C/pre%3E
+%0A * %0A *
  where:%0A
@@ -1508,19 +1508,16 @@
 n follow
-%0A *
  %3Ca href
@@ -1517,16 +1517,19 @@
 %3Ca href=
+%0A *
  %22https:
@@ -1570,13 +1570,15 @@
 ion/
-9.3.x
+current
 /con
@@ -1625,17 +1625,17 @@
 %3Ethe
+%0A *
  jetty
-%0A *
  doc
@@ -1680,16 +1680,159 @@
 assword.
+ Note that the %7B@code CRYPT%7D style is%0A * based on Unix Crypt which is considered weak and insecure (you probably shouldn't be using it).%0A * %0A *
  %3Cpre%3E%0A 
@@ -2104,27 +2104,26 @@
 %7D%0A * %3C/pre%3E%0A
+
  *
- 
 %0A * @author 

Add note to not use CRYPT: