001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io.auth; 003 004import java.awt.Component; 005import java.net.Authenticator.RequestorType; 006import java.net.PasswordAuthentication; 007import java.util.Objects; 008 009import org.openstreetmap.josm.data.UserIdentityManager; 010import org.openstreetmap.josm.data.oauth.OAuthToken; 011import org.openstreetmap.josm.io.OsmApi; 012import org.openstreetmap.josm.tools.CheckParameterUtil; 013import org.openstreetmap.josm.tools.Logging; 014 015/** 016 * CredentialManager is a factory for the single credential agent used. 017 * 018 * Currently, it defaults to replying an instance of {@link JosmPreferencesCredentialAgent}. 019 * @since 2641 020 */ 021public class CredentialsManager implements CredentialsAgent { 022 023 private static volatile CredentialsManager instance; 024 025 /** 026 * Replies the single credential agent used in JOSM 027 * 028 * @return the single credential agent used in JOSM 029 */ 030 public static CredentialsManager getInstance() { 031 if (instance == null) { 032 CredentialsAgent delegate; 033 if (agentFactory == null) { 034 delegate = new JosmPreferencesCredentialAgent(); 035 } else { 036 delegate = agentFactory.getCredentialsAgent(); 037 } 038 instance = new CredentialsManager(delegate); 039 } 040 return instance; 041 } 042 043 private static CredentialsAgentFactory agentFactory; 044 045 /** 046 * Credentials agent factory. 047 */ 048 @FunctionalInterface 049 public interface CredentialsAgentFactory { 050 /** 051 * Returns the credentials agent instance. 052 * @return the credentials agent instance 053 */ 054 CredentialsAgent getCredentialsAgent(); 055 } 056 057 /** 058 * Plugins can register a CredentialsAgentFactory, thereby overriding 059 * JOSM's default credentials agent. 060 * @param agentFactory The Factory that provides the custom CredentialsAgent. 061 * Can be null to clear the factory and switch back to default behavior. 062 */ 063 public static void registerCredentialsAgentFactory(CredentialsAgentFactory agentFactory) { 064 CredentialsManager.agentFactory = agentFactory; 065 CredentialsManager.instance = null; 066 } 067 068 /* non-static fields and methods */ 069 070 /** 071 * The credentials agent doing the real stuff 072 */ 073 private final CredentialsAgent delegate; 074 075 /** 076 * Constructs a new {@code CredentialsManager}. 077 * @param delegate The credentials agent backing this credential manager. Must not be {@code null} 078 */ 079 public CredentialsManager(CredentialsAgent delegate) { 080 CheckParameterUtil.ensureParameterNotNull(delegate, "delegate"); 081 this.delegate = delegate; 082 } 083 084 /** 085 * Returns type of credentials agent backing this credentials manager. 086 * @return The type of credentials agent 087 */ 088 public final Class<? extends CredentialsAgent> getCredentialsAgentClass() { 089 return delegate.getClass(); 090 } 091 092 /** 093 * Returns the username for OSM API 094 * @return the username for OSM API 095 */ 096 public String getUsername() { 097 return getUsername(OsmApi.getOsmApi().getHost()); 098 } 099 100 /** 101 * Returns the username for a given host 102 * @param host The host for which username is wanted 103 * @return The username for {@code host} 104 */ 105 public String getUsername(String host) { 106 String username = null; 107 try { 108 PasswordAuthentication auth = lookup(RequestorType.SERVER, host); 109 if (auth != null) { 110 username = auth.getUserName(); 111 } 112 } catch (CredentialsAgentException ex) { 113 Logging.debug(ex); 114 return null; 115 } 116 if (username == null) return null; 117 username = username.trim(); 118 return username.isEmpty() ? null : username; 119 } 120 121 @Override 122 public PasswordAuthentication lookup(RequestorType requestorType, String host) throws CredentialsAgentException { 123 return delegate.lookup(requestorType, host); 124 } 125 126 @Override 127 public void store(RequestorType requestorType, String host, PasswordAuthentication credentials) throws CredentialsAgentException { 128 if (requestorType == RequestorType.SERVER && Objects.equals(OsmApi.getOsmApi().getHost(), host)) { 129 String username = credentials.getUserName(); 130 if (username != null && !username.trim().isEmpty()) { 131 UserIdentityManager.getInstance().setPartiallyIdentified(username); 132 } 133 } 134 delegate.store(requestorType, host, credentials); 135 } 136 137 @Override 138 public CredentialsAgentResponse getCredentials(RequestorType requestorType, String host, boolean noSuccessWithLastResponse) 139 throws CredentialsAgentException { 140 return delegate.getCredentials(requestorType, host, noSuccessWithLastResponse); 141 } 142 143 @Override 144 public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException { 145 return delegate.lookupOAuthAccessToken(); 146 } 147 148 @Override 149 public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException { 150 delegate.storeOAuthAccessToken(accessToken); 151 } 152 153 @Override 154 public Component getPreferencesDecorationPanel() { 155 return delegate.getPreferencesDecorationPanel(); 156 } 157 158 @Override 159 public void purgeCredentialsCache(RequestorType requestorType) { 160 delegate.purgeCredentialsCache(requestorType); 161 } 162}