Package org.openstreetmap.josm.gui

Source Code of org.openstreetmap.josm.gui.JosmUserIdentityManager

// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui;

import static org.openstreetmap.josm.tools.I18n.tr;

import java.awt.Component;
import java.text.MessageFormat;

import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
import org.openstreetmap.josm.data.Preferences.StringSetting;
import org.openstreetmap.josm.data.osm.UserInfo;
import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
import org.openstreetmap.josm.io.OsmApi;
import org.openstreetmap.josm.io.OsmServerUserInfoReader;
import org.openstreetmap.josm.io.OsmTransferException;
import org.openstreetmap.josm.io.auth.CredentialsManager;
import org.openstreetmap.josm.tools.CheckParameterUtil;

/**
* JosmUserIdentityManager is a global object which keeps track of what JOSM knows about
* the identity of the current user.
*
* JOSM can be operated anonymously provided the current user never invokes an operation
* on the OSM server which required authentication. In this case JOSM neither knows
* the user name of the OSM account of the current user nor its unique id. Perhaps the
* user doesn't have one.
*
* If the current user supplies a user name and a password in the JOSM preferences JOSM
* can partially identify the user.
*
* The current user is fully identified if JOSM knows both the user name and the unique
* id of the users OSM account. The latter is retrieved from the OSM server with a
* <tt>GET /api/0.6/user/details</tt> request, submitted with the user name and password
* of the current user.
*
* The global JosmUserIdentityManager listens to {@link PreferenceChangeEvent}s and keeps track
* of what the current JOSM instance knows about the current user. Other subsystems can
* let the global JosmUserIdentityManager know in case they fully identify the current user, see
* {@link #setFullyIdentified}.
*
* The information kept by the JosmUserIdentityManager can be used to
* <ul>
*   <li>safely query changesets owned by the current user based on its user id, not on its user name</li>
*   <li>safely search for objects last touched by the current user based on its user id, not on its user name</li>
* </ul>
*
*/
public final class JosmUserIdentityManager implements PreferenceChangedListener{

    private static JosmUserIdentityManager instance;

    /**
     * Replies the unique instance of the JOSM user identity manager
     *
     * @return the unique instance of the JOSM user identity manager
     */
    public static JosmUserIdentityManager getInstance() {
        if (instance == null) {
            instance = new JosmUserIdentityManager();
            if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken()) {
                try {
                    instance.initFromOAuth(Main.parent);
                } catch (Exception e) {
                    Main.error(e);
                    // Fall back to preferences if OAuth identification fails for any reason
                    instance.initFromPreferences();
                }
            } else {
                instance.initFromPreferences();
            }
            Main.pref.addPreferenceChangeListener(instance);
        }
        return instance;
    }

    private String userName;
    private UserInfo userInfo;
    private boolean accessTokenKeyChanged;
    private boolean accessTokenSecretChanged;

    private JosmUserIdentityManager() {
    }

    /**
     * Remembers the fact that the current JOSM user is anonymous.
     */
    public void setAnonymous() {
        userName = null;
        userInfo = null;
    }

    /**
     * Remebers the fact that the current JOSM user is partially identified
     * by the user name of its OSM account.
     *
     * @param userName the user name. Must not be null. Must not be empty (whitespace only).
     * @throws IllegalArgumentException thrown if userName is null
     * @throws IllegalArgumentException thrown if userName is empty
     */
    public void setPartiallyIdentified(String userName) throws IllegalArgumentException {
        CheckParameterUtil.ensureParameterNotNull(userName, "userName");
        if (userName.trim().isEmpty())
            throw new IllegalArgumentException(MessageFormat.format("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
        this.userName = userName;
        userInfo = null;
    }

    /**
     * Remembers the fact that the current JOSM user is fully identified with a
     * verified pair of user name and user id.
     *
     * @param username the user name. Must not be null. Must not be empty.
     * @param userinfo additional information about the user, retrieved from the OSM server and including the user id
     * @throws IllegalArgumentException thrown if userName is null
     * @throws IllegalArgumentException thrown if userName is empty
     * @throws IllegalArgumentException thrown if userinfo is null
     */
    public void setFullyIdentified(String username, UserInfo userinfo) throws IllegalArgumentException {
        CheckParameterUtil.ensureParameterNotNull(username, "username");
        if (username.trim().isEmpty())
            throw new IllegalArgumentException(tr("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
        CheckParameterUtil.ensureParameterNotNull(userinfo, "userinfo");
        this.userName = username;
        this.userInfo = userinfo;
    }

    /**
     * Replies true if the current JOSM user is anonymous.
     *
     * @return {@code true} if the current user is anonymous.
     */
    public boolean isAnonymous() {
        return userName == null && userInfo == null;
    }

    /**
     * Replies true if the current JOSM user is partially identified.
     *
     * @return true if the current JOSM user is partially identified.
     */
    public boolean isPartiallyIdentified() {
        return userName != null && userInfo == null;
    }

    /**
     * Replies true if the current JOSM user is fully identified.
     *
     * @return true if the current JOSM user is fully identified.
     */
    public boolean isFullyIdentified() {
        return userName != null && userInfo != null;
    }

    /**
     * Replies the user name of the current JOSM user. null, if {@link #isAnonymous()} is true.
     *
     * @return  the user name of the current JOSM user
     */
    public String getUserName() {
        return userName;
    }

    /**
     * Replies the user id of the current JOSM user. 0, if {@link #isAnonymous()} or
     * {@link #isPartiallyIdentified()} is true.
     *
     * @return  the user id of the current JOSM user
     */
    public int getUserId() {
        if (userInfo == null) return 0;
        return userInfo.getId();
    }

    /**
     * Replies verified additional information about the current user if the user is
     * {@link #isFullyIdentified()}.
     *
     * @return verified additional information about the current user
     */
    public UserInfo getUserInfo() {
        return userInfo;
    }

    /**
     * Initializes the user identity manager from Basic Authentication values in the {@link org.openstreetmap.josm.data.Preferences}
     * This method should be called if {@code osm-server.auth-method} is set to {@code basic}.
     * @see #initFromOAuth
     */
    public void initFromPreferences() {
        String userName = CredentialsManager.getInstance().getUsername();
        if (isAnonymous()) {
            if (userName != null && !userName.trim().isEmpty()) {
                setPartiallyIdentified(userName);
            }
        } else {
            if (userName != null && !userName.equals(this.userName)) {
                setPartiallyIdentified(userName);
            } else {
                // same name in the preferences as JOSM already knows about.
                // keep the state, be it partially or fully identified
            }
        }
    }

    /**
     * Initializes the user identity manager from OAuth request of user details.
     * This method should be called if {@code osm-server.auth-method} is set to {@code oauth}.
     * @param parent component relative to which the {@link PleaseWaitDialog} is displayed.
     * @see #initFromPreferences
     * @since 5434
     */
    public void initFromOAuth(Component parent) {
        try {
            UserInfo info = new OsmServerUserInfoReader().fetchUserInfo(NullProgressMonitor.INSTANCE);
            setFullyIdentified(info.getDisplayName(), info);
        } catch (IllegalArgumentException | OsmTransferException e) {
            Main.error(e);
        }
    }

    /**
     * Replies true if the user with name <code>username</code> is the current
     * user
     *
     * @param username the user name
     * @return true if the user with name <code>username</code> is the current
     * user
     */
    public boolean isCurrentUser(String username) {
        if (username == null || this.userName == null) return false;
        return this.userName.equals(username);
    }

    /* ------------------------------------------------------------------- */
    /* interface PreferenceChangeListener                                  */
    /* ------------------------------------------------------------------- */
    @Override
    public void preferenceChanged(PreferenceChangeEvent evt) {
        switch (evt.getKey()) {
        case "osm-server.username":
            String newUserName = null;
            if (evt.getNewValue() instanceof StringSetting) {
                newUserName = ((StringSetting) evt.getNewValue()).getValue();
            }
            if (newUserName == null || newUserName.trim().isEmpty()) {
                setAnonymous();
            } else {
                if (!newUserName.equals(userName)) {
                    setPartiallyIdentified(newUserName);
                }
            }
            return;

        case "osm-server.url":
            String newUrl = null;
            if (evt.getNewValue() instanceof StringSetting) {
                newUrl = ((StringSetting) evt.getNewValue()).getValue();
            }
            if (newUrl == null || newUrl.trim().isEmpty()) {
                setAnonymous();
            } else if (isFullyIdentified()) {
                setPartiallyIdentified(getUserName());
            }
            break;

        case "oauth.access-token.key":
            accessTokenKeyChanged = true;
            break;

        case "oauth.access-token.secret":
            accessTokenSecretChanged = true;
            break;
        }

        if (accessTokenKeyChanged && accessTokenSecretChanged) {
            accessTokenKeyChanged = false;
            accessTokenSecretChanged = false;
            if (OsmApi.isUsingOAuth()) {
                try {
                    instance.initFromOAuth(Main.parent);
                } catch (Exception e) {
                    Main.error(e);
                }
            }
        }
    }
}
TOP

Related Classes of org.openstreetmap.josm.gui.JosmUserIdentityManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.