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

Last change on this file since 5508 was 5469, checked in by Don-vip, 12 years ago

Do not try to init JosmUserIdentityManager from OAuth if no access token is set

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