forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			279 lines
		
	
	
		
			No EOL
		
	
	
		
			9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			No EOL
		
	
	
		
			9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
// @ts-ignore
 | 
						|
import osmAuth from "osm-auth";
 | 
						|
import {UIEventSource} from "../UI/UIEventSource";
 | 
						|
 | 
						|
export class UserDetails {
 | 
						|
 | 
						|
    public loggedIn = false;
 | 
						|
    public name = "Not logged in";
 | 
						|
    public csCount = 0;
 | 
						|
    public img: string;
 | 
						|
    public unreadMessages = 0;
 | 
						|
    public totalMessages = 0;
 | 
						|
    public osmConnection: OsmConnection;
 | 
						|
    public dryRun: boolean;
 | 
						|
    home: { lon: number; lat: number };
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
export class OsmConnection {
 | 
						|
 | 
						|
 | 
						|
    private auth = new osmAuth({
 | 
						|
        oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem',
 | 
						|
        oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI',
 | 
						|
        auto: true // show a login form if the user is not authenticated and
 | 
						|
                   // you try to do a call
 | 
						|
    });
 | 
						|
    public userDetails: UIEventSource<UserDetails>;
 | 
						|
    private _dryRun: boolean;
 | 
						|
 | 
						|
    constructor(dryRun: boolean) {
 | 
						|
        this.userDetails = new UIEventSource<UserDetails>(new UserDetails());
 | 
						|
        this.userDetails.data.osmConnection = this;
 | 
						|
        this.userDetails.data.dryRun = dryRun;
 | 
						|
        this._dryRun = dryRun;
 | 
						|
 | 
						|
        if (this.auth.authenticated()) {
 | 
						|
            this.AttemptLogin(); // Also updates the user badge
 | 
						|
        }else{
 | 
						|
            console.log("Not authenticated");
 | 
						|
        }
 | 
						|
 | 
						|
        
 | 
						|
        if(dryRun){
 | 
						|
            console.log("DRYRUN ENABLED");
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    public LogOut() {
 | 
						|
        this.auth.logout();
 | 
						|
        this.userDetails.data.loggedIn = false;
 | 
						|
        this.userDetails.ping();
 | 
						|
        console.log("Logged out")
 | 
						|
    }
 | 
						|
 | 
						|
    public AttemptLogin() {
 | 
						|
        const self = this;
 | 
						|
        this.auth.xhr({
 | 
						|
            method: 'GET',
 | 
						|
            path: '/api/0.6/user/details'
 | 
						|
        }, function (err, details) {
 | 
						|
            if(err != null){
 | 
						|
                console.log(err);
 | 
						|
                self.auth.logout();
 | 
						|
                self.userDetails.data.loggedIn = false;
 | 
						|
                self.userDetails.ping();
 | 
						|
            }
 | 
						|
 | 
						|
            if (details == null) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            
 | 
						|
            self.UpdatePreferences();
 | 
						|
            // details is an XML DOM of user details
 | 
						|
            let userInfo = details.getElementsByTagName("user")[0];
 | 
						|
 | 
						|
            // let moreDetails = new DOMParser().parseFromString(userInfo.innerHTML, "text/xml");
 | 
						|
 | 
						|
            let data = self.userDetails.data;
 | 
						|
            data.loggedIn = true;
 | 
						|
            console.log("Login completed, userinfo is ", userInfo);
 | 
						|
            data.name = userInfo.getAttribute('display_name');
 | 
						|
            data.csCount = userInfo.getElementsByTagName("changesets")[0].getAttribute("count");
 | 
						|
 | 
						|
            data.img = undefined;
 | 
						|
            const imgEl = userInfo.getElementsByTagName("img");
 | 
						|
            if (imgEl !== undefined && imgEl[0] !== undefined) {
 | 
						|
                data.img = imgEl[0].getAttribute("href");
 | 
						|
            }
 | 
						|
            data.img = data.img ?? "./assets/osm-logo.svg";
 | 
						|
 | 
						|
            const homeEl = userInfo.getElementsByTagName("home");
 | 
						|
            if (homeEl !== undefined && homeEl[0] !== undefined) {
 | 
						|
                const lat = parseFloat(homeEl[0].getAttribute("lat"));
 | 
						|
                const lon = parseFloat(homeEl[0].getAttribute("lon"));
 | 
						|
                data.home = {lat: lat, lon: lon};
 | 
						|
            }
 | 
						|
 | 
						|
            const messages = userInfo.getElementsByTagName("messages")[0].getElementsByTagName("received")[0];
 | 
						|
            data.unreadMessages = parseInt(messages.getAttribute("unread"));
 | 
						|
            data.totalMessages = parseInt(messages.getAttribute("count"));
 | 
						|
            self.userDetails.ping();
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * All elements with class 'activate-osm-authentication' are loaded and get an 'onclick' to authenticate
 | 
						|
     */
 | 
						|
    registerActivateOsmAUthenticationClass() {
 | 
						|
 | 
						|
        const self = this;
 | 
						|
        const authElements = document.getElementsByClassName("activate-osm-authentication");
 | 
						|
        for (let i = 0; i < authElements.length; i++) {
 | 
						|
            let element = authElements.item(i);
 | 
						|
            // @ts-ignore
 | 
						|
            element.onclick = function () {
 | 
						|
                self.AttemptLogin();
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public preferences = new UIEventSource<any>({});
 | 
						|
    private UpdatePreferences() {
 | 
						|
        const self = this;
 | 
						|
        this.auth.xhr({
 | 
						|
            method: 'GET',
 | 
						|
            path: '/api/0.6/user/preferences'
 | 
						|
        }, function (error, value: XMLDocument) {
 | 
						|
            if(error){
 | 
						|
                console.log("Could not load preferences", error);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            const prefs = value.getElementsByTagName("preference");
 | 
						|
            for (let i = 0; i < prefs.length; i++) {
 | 
						|
                const pref = prefs[i];
 | 
						|
                const k = pref.getAttribute("k");
 | 
						|
                const v = pref.getAttribute("v");
 | 
						|
                self.preferences.data[k] = v;
 | 
						|
            }
 | 
						|
            self.preferences.ping();
 | 
						|
        });
 | 
						|
    }
 | 
						|
    
 | 
						|
    public SetPreference(k:string, v:string) {
 | 
						|
        if(!this.userDetails.data.loggedIn){
 | 
						|
            console.log("Not saving preference: user not logged in");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (this.preferences.data[k] === v) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        console.log("Updating preference", k, " to ", v);
 | 
						|
 | 
						|
        this.preferences.data[k] = v;
 | 
						|
        this.preferences.ping();
 | 
						|
        this.auth.xhr({
 | 
						|
            method: 'PUT',
 | 
						|
            path: '/api/0.6/user/preferences/' + k,
 | 
						|
            options: {header: {'Content-Type': 'text/plain'}},
 | 
						|
            content: v
 | 
						|
        }, function (error, result) {
 | 
						|
            if (error) {
 | 
						|
                console.log("Could not set preference", error);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            
 | 
						|
            console.log("Preference written!", result);
 | 
						|
            
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    private static parseUploadChangesetResponse(response: XMLDocument) {
 | 
						|
        const nodes = response.getElementsByTagName("node");
 | 
						|
        const mapping = {};
 | 
						|
        // @ts-ignore
 | 
						|
        for (const node of nodes) {
 | 
						|
            const oldId = parseInt(node.attributes.old_id.value);
 | 
						|
            const newId = parseInt(node.attributes.new_id.value);
 | 
						|
            if (oldId !== undefined && newId !== undefined &&
 | 
						|
                !isNaN(oldId) && !isNaN(newId)) {
 | 
						|
                mapping["node/"+oldId] = "node/"+newId;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return mapping;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    public UploadChangeset(comment: string, generateChangeXML: ((csid: string) => string),
 | 
						|
                           handleMapping: ((idMapping: any) => void),
 | 
						|
                           continuation: (() => void)) {
 | 
						|
 | 
						|
        if (this._dryRun) {
 | 
						|
            console.log("NOT UPLOADING as dryrun is true");
 | 
						|
            var changesetXML = generateChangeXML("123456");
 | 
						|
            console.log(changesetXML);
 | 
						|
            continuation();
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        const self = this;
 | 
						|
        this.OpenChangeset(comment,
 | 
						|
            function (csId) {
 | 
						|
                var changesetXML = generateChangeXML(csId);
 | 
						|
                self.AddChange(csId, changesetXML,
 | 
						|
                    function (csId, mapping) {
 | 
						|
                        self.CloseChangeset(csId, continuation);
 | 
						|
                        handleMapping(mapping);
 | 
						|
                    }
 | 
						|
                );
 | 
						|
 | 
						|
            }
 | 
						|
        );
 | 
						|
        
 | 
						|
        this.userDetails.data.csCount++;
 | 
						|
        this.userDetails.ping();
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    private OpenChangeset(comment: string, continuation: ((changesetId: string) => void)) {
 | 
						|
 | 
						|
 | 
						|
        this.auth.xhr({
 | 
						|
            method: 'PUT',
 | 
						|
            path: '/api/0.6/changeset/create',
 | 
						|
            options: { header: { 'Content-Type': 'text/xml' } },
 | 
						|
            content: '<osm><changeset>' +
 | 
						|
                '<tag k="created_by" v="MapComplete 0.0.0" />' +
 | 
						|
                '<tag k="comment" v="' + comment + '"/>' +
 | 
						|
                '</changeset></osm>'
 | 
						|
        }, function (err, response) {
 | 
						|
            if (response === undefined) {
 | 
						|
                console.log("err", err);
 | 
						|
                return;
 | 
						|
            } else {
 | 
						|
                continuation(response);
 | 
						|
            }
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    private AddChange(changesetId: string,
 | 
						|
                      changesetXML: string,
 | 
						|
                      continuation: ((changesetId: string, idMapping: any) => void)){
 | 
						|
        this.auth.xhr({
 | 
						|
            method: 'POST',
 | 
						|
            options: { header: { 'Content-Type': 'text/xml' } },
 | 
						|
            path: '/api/0.6/changeset/'+changesetId+'/upload',
 | 
						|
            content: changesetXML
 | 
						|
        }, function (err, response) {
 | 
						|
            if (response == null) {
 | 
						|
                console.log("err", err);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            const mapping = OsmConnection.parseUploadChangesetResponse(response);
 | 
						|
            console.log("Uplaoded changeset ", changesetId);
 | 
						|
            continuation(changesetId, mapping);
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    private CloseChangeset(changesetId: string, continuation : (() => void)) {
 | 
						|
        console.log("closing");
 | 
						|
        this.auth.xhr({
 | 
						|
            method: 'PUT',
 | 
						|
            path: '/api/0.6/changeset/'+changesetId+'/close',
 | 
						|
        }, function (err, response) {
 | 
						|
            if (response == null) {
 | 
						|
 | 
						|
                console.log("err", err);
 | 
						|
            }
 | 
						|
            console.log("Closed changeset ", changesetId);
 | 
						|
            
 | 
						|
            if(continuation !== undefined){
 | 
						|
                continuation();
 | 
						|
            }
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
} |