source: josm/trunk/src/org/openstreetmap/josm/gui/JosmUserIdentityManager.java@ 9171

Last change on this file since 9171 was 9059, checked in by Don-vip, 8 years ago

checkstyle

  • Property svn:eol-style set to native
File size: 10.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.text.MessageFormat;
7
8import org.openstreetmap.josm.Main;
9import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
10import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
11import org.openstreetmap.josm.data.Preferences.StringSetting;
12import org.openstreetmap.josm.data.osm.UserInfo;
13import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
14import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
15import org.openstreetmap.josm.io.OnlineResource;
16import org.openstreetmap.josm.io.OsmApi;
17import org.openstreetmap.josm.io.OsmServerUserInfoReader;
18import org.openstreetmap.josm.io.OsmTransferException;
19import org.openstreetmap.josm.io.auth.CredentialsManager;
20import org.openstreetmap.josm.tools.CheckParameterUtil;
21
22/**
23 * JosmUserIdentityManager is a global object which keeps track of what JOSM knows about
24 * the identity of the current user.
25 *
26 * JOSM can be operated anonymously provided the current user never invokes an operation
27 * on the OSM server which required authentication. In this case JOSM neither knows
28 * the user name of the OSM account of the current user nor its unique id. Perhaps the
29 * user doesn't have one.
30 *
31 * If the current user supplies a user name and a password in the JOSM preferences JOSM
32 * can partially identify the user.
33 *
34 * The current user is fully identified if JOSM knows both the user name and the unique
35 * id of the users OSM account. The latter is retrieved from the OSM server with a
36 * <tt>GET /api/0.6/user/details</tt> request, submitted with the user name and password
37 * of the current user.
38 *
39 * The global JosmUserIdentityManager listens to {@link PreferenceChangeEvent}s and keeps track
40 * of what the current JOSM instance knows about the current user. Other subsystems can
41 * let the global JosmUserIdentityManager know in case they fully identify the current user, see
42 * {@link #setFullyIdentified}.
43 *
44 * The information kept by the JosmUserIdentityManager can be used to
45 * <ul>
46 * <li>safely query changesets owned by the current user based on its user id, not on its user name</li>
47 * <li>safely search for objects last touched by the current user based on its user id, not on its user name</li>
48 * </ul>
49 *
50 */
51public final class JosmUserIdentityManager implements PreferenceChangedListener {
52
53 private static JosmUserIdentityManager instance;
54
55 /**
56 * Replies the unique instance of the JOSM user identity manager
57 *
58 * @return the unique instance of the JOSM user identity manager
59 */
60 public static synchronized JosmUserIdentityManager getInstance() {
61 if (instance == null) {
62 instance = new JosmUserIdentityManager();
63 if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken() &&
64 !Main.isOffline(OnlineResource.OSM_API)) {
65 try {
66 instance.initFromOAuth();
67 } catch (Exception e) {
68 Main.error(e);
69 // Fall back to preferences if OAuth identification fails for any reason
70 instance.initFromPreferences();
71 }
72 } else {
73 instance.initFromPreferences();
74 }
75 Main.pref.addPreferenceChangeListener(instance);
76 }
77 return instance;
78 }
79
80 private String userName;
81 private UserInfo userInfo;
82 private boolean accessTokenKeyChanged;
83 private boolean accessTokenSecretChanged;
84
85 private JosmUserIdentityManager() {
86 }
87
88 /**
89 * Remembers the fact that the current JOSM user is anonymous.
90 */
91 public void setAnonymous() {
92 userName = null;
93 userInfo = null;
94 }
95
96 /**
97 * Remebers the fact that the current JOSM user is partially identified
98 * by the user name of its OSM account.
99 *
100 * @param userName the user name. Must not be null. Must not be empty (whitespace only).
101 * @throws IllegalArgumentException if userName is null
102 * @throws IllegalArgumentException if userName is empty
103 */
104 public void setPartiallyIdentified(String userName) {
105 CheckParameterUtil.ensureParameterNotNull(userName, "userName");
106 if (userName.trim().isEmpty())
107 throw new IllegalArgumentException(
108 MessageFormat.format("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
109 this.userName = userName;
110 userInfo = null;
111 }
112
113 /**
114 * Remembers the fact that the current JOSM user is fully identified with a
115 * verified pair of user name and user id.
116 *
117 * @param username the user name. Must not be null. Must not be empty.
118 * @param userinfo additional information about the user, retrieved from the OSM server and including the user id
119 * @throws IllegalArgumentException if userName is null
120 * @throws IllegalArgumentException if userName is empty
121 * @throws IllegalArgumentException if userinfo is null
122 */
123 public void setFullyIdentified(String username, UserInfo userinfo) {
124 CheckParameterUtil.ensureParameterNotNull(username, "username");
125 if (username.trim().isEmpty())
126 throw new IllegalArgumentException(tr("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
127 CheckParameterUtil.ensureParameterNotNull(userinfo, "userinfo");
128 this.userName = username;
129 this.userInfo = userinfo;
130 }
131
132 /**
133 * Replies true if the current JOSM user is anonymous.
134 *
135 * @return {@code true} if the current user is anonymous.
136 */
137 public boolean isAnonymous() {
138 return userName == null && userInfo == null;
139 }
140
141 /**
142 * Replies true if the current JOSM user is partially identified.
143 *
144 * @return true if the current JOSM user is partially identified.
145 */
146 public boolean isPartiallyIdentified() {
147 return userName != null && userInfo == null;
148 }
149
150 /**
151 * Replies true if the current JOSM user is fully identified.
152 *
153 * @return true if the current JOSM user is fully identified.
154 */
155 public boolean isFullyIdentified() {
156 return userName != null && userInfo != null;
157 }
158
159 /**
160 * Replies the user name of the current JOSM user. null, if {@link #isAnonymous()} is true.
161 *
162 * @return the user name of the current JOSM user
163 */
164 public String getUserName() {
165 return userName;
166 }
167
168 /**
169 * Replies the user id of the current JOSM user. 0, if {@link #isAnonymous()} or
170 * {@link #isPartiallyIdentified()} is true.
171 *
172 * @return the user id of the current JOSM user
173 */
174 public int getUserId() {
175 if (userInfo == null) return 0;
176 return userInfo.getId();
177 }
178
179 /**
180 * Replies verified additional information about the current user if the user is
181 * {@link #isFullyIdentified()}.
182 *
183 * @return verified additional information about the current user
184 */
185 public UserInfo getUserInfo() {
186 return userInfo;
187 }
188
189 /**
190 * Initializes the user identity manager from Basic Authentication values in the {@link org.openstreetmap.josm.data.Preferences}
191 * This method should be called if {@code osm-server.auth-method} is set to {@code basic}.
192 * @see #initFromOAuth
193 */
194 public void initFromPreferences() {
195 String userName = CredentialsManager.getInstance().getUsername();
196 if (isAnonymous()) {
197 if (userName != null && !userName.trim().isEmpty()) {
198 setPartiallyIdentified(userName);
199 }
200 } else {
201 if (userName != null && !userName.equals(this.userName)) {
202 setPartiallyIdentified(userName);
203 }
204 // else: same name in the preferences as JOSM already knows about.
205 // keep the state, be it partially or fully identified
206 }
207 }
208
209 /**
210 * Initializes the user identity manager from OAuth request of user details.
211 * This method should be called if {@code osm-server.auth-method} is set to {@code oauth}.
212 * @see #initFromPreferences
213 * @since 5434
214 */
215 public void initFromOAuth() {
216 try {
217 UserInfo info = new OsmServerUserInfoReader().fetchUserInfo(NullProgressMonitor.INSTANCE);
218 setFullyIdentified(info.getDisplayName(), info);
219 } catch (IllegalArgumentException | OsmTransferException e) {
220 Main.error(e);
221 }
222 }
223
224 /**
225 * Replies true if the user with name <code>username</code> is the current
226 * user
227 *
228 * @param username the user name
229 * @return true if the user with name <code>username</code> is the current
230 * user
231 */
232 public boolean isCurrentUser(String username) {
233 if (username == null || this.userName == null) return false;
234 return this.userName.equals(username);
235 }
236
237 /* ------------------------------------------------------------------- */
238 /* interface PreferenceChangeListener */
239 /* ------------------------------------------------------------------- */
240 @Override
241 public void preferenceChanged(PreferenceChangeEvent evt) {
242 switch (evt.getKey()) {
243 case "osm-server.username":
244 String newUserName = null;
245 if (evt.getNewValue() instanceof StringSetting) {
246 newUserName = ((StringSetting) evt.getNewValue()).getValue();
247 }
248 if (newUserName == null || newUserName.trim().isEmpty()) {
249 setAnonymous();
250 } else {
251 if (!newUserName.equals(userName)) {
252 setPartiallyIdentified(newUserName);
253 }
254 }
255 return;
256
257 case "osm-server.url":
258 String newUrl = null;
259 if (evt.getNewValue() instanceof StringSetting) {
260 newUrl = ((StringSetting) evt.getNewValue()).getValue();
261 }
262 if (newUrl == null || newUrl.trim().isEmpty()) {
263 setAnonymous();
264 } else if (isFullyIdentified()) {
265 setPartiallyIdentified(getUserName());
266 }
267 break;
268
269 case "oauth.access-token.key":
270 accessTokenKeyChanged = true;
271 break;
272
273 case "oauth.access-token.secret":
274 accessTokenSecretChanged = true;
275 break;
276 }
277
278 if (accessTokenKeyChanged && accessTokenSecretChanged) {
279 accessTokenKeyChanged = false;
280 accessTokenSecretChanged = false;
281 if (OsmApi.isUsingOAuth()) {
282 try {
283 getInstance().initFromOAuth();
284 } catch (Exception e) {
285 Main.error(e);
286 }
287 }
288 }
289 }
290}
Note: See TracBrowser for help on using the repository browser.