UNPKG

@darwino/darwino

Version:

A set of Javascript classes and utilities

417 lines (382 loc) 11.7 kB
/*!COPYRIGHT HEADER! - CONFIDENTIAL * * Darwino Inc Confidential. * * (c) Copyright Darwino Inc. 2014-2016. * * Notice: The information contained in the source code for these files is the property * of Darwino Inc. which, with its licensors, if any, owns all the intellectual property * rights, including all copyright rights thereto. Such information may only be used * for debugging, troubleshooting and informational purposes. All other uses of this information, * including any production or commercial uses, are prohibited. */ import Utils from "./Utils" import {fetchJson,fetchText,makeUrl} from './Fetch'; // Inline image so we display it even if there is an authentication error with the server // it makes the image always available const ANONYMOUS_PHOTO = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD0AAAA9CAIAAACRAPa+AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAWdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjA76PVpAAAESUlEQVRoQ+2ZaVfaQBSG/f9fW7e2WmRRNgHZFFBBUMqigiwmLAmboO2v6NvSpvbWJpOZQeW05zxfPAdzn0zunbk3WRnff1lG/ns/L3K8R7PPYDh90MYzfTIbfv8TkJ9JRMhbG08vm2q6UPZFUx/2wm8/et9s74F1p98ZiEVSuUK13urqi7gBTm8sbfGq4fBH13b8c9cnwZ1suoLBxLHSH45m9CIi8HjX2l0ssLG6LGy4Apnzcm90Ry7FjT1vPPF8uYYlJFos4D49oWRHH5Nr8mHDezB9OLmorDp8RMgWH30HDbVPrswBqzdW+rRYFZSes+2NqMKrzupdublddwaIATe74aRgrjN5K9rw/W6IxBYBuZ7Ol0T2R2tvXD1xck4Ci4MNVCTRrb2V/sh8k+bGG03hHCDhGLH2xrFH4skC+yn3klt4K9ronXufxJNIOl8mERmx8MZhLmXv+xvYzvmq08z7W0Weyq9IQrs3IHFZMPNG0ewdHJEw0kHjQOKyYOY9uLtHd0rCSCd+XCBxWTDz1if3a4tM7jm+WJrEZcHMG2MBibEIPOFDjtI080YLQWIsAk84Kdkbk+KqneGAD+9BisRlwaIu33tktlNPcpA+I3FZMPWePmBCIWGkky1ekrgsmHkj7WKZPAkjnRulR+KyYOYN8pWarfnXLmh++FpCC+9mR8coToJJJMZ16AALb6TK4o56tPXX7Q6JyIiFN6grvVXHQlLFvZ/QJjMSjhFrb+Rf6PCUhBQHZVOut0ksdqy9wY3Sl57lkXSO45g0YPIG2GUlDhAYF5T+kISwBas3siV2nJeyJ244A9zlaMDqDVBDgXhGUH3THRRJawMb3gDqyewFt/rWXuSyqYqktYE9b4CohUp9y+YchPnDG03diuX0Y2x7z0FVHeWKG2wvlF3BeKnW0u/uyUVE4PQGo9mX7nByfF5B448xFNU2b9aRRWs7PjQe2DSCiZPLhjKcSkgMAr+3AbYaRRuhrbtqqtXGLUSxXbS6usSvC38iwftF+Pe8kR790VTVx+3eoNnR0AvUb7u1n6Aba6h9ZAtSCGWgT2QWJbDnjU0QirnSdSSV2w0f7gRiW94ISnAdRenwPd7XUaNoUzddwQ+7YYc/6g4lcGalz0ooAG3M2QM+xtob0zFW9NN1M3KUhaLgefkWt+Tw4Z5PL6oo5d6Qs3bNvHE6op3CNvfOs5BXyXggeBSY5xuqRkJb8oQ3EhfJcJi9kPghyhw8BExVlXqbfeuk3kgJTAl8X1YFQUk4g/FCtc7SwPzy7ujj1NmnZ3iRaYk7lLxqqXjshtuf/PAuXjVxLJP/f0HWnf7wUbb/97RZQUXHJQ0E0sFSomV4Mm1WXPuJ1yk9B3PtWfmaSIMV8rvXSaZQHtz9lu7L4Y2jKn5yvnzec9L5krHJLJM3zldjpl4mb4AybX3/3rlk3sAfz6DVWz5vnOgYCJfPG+wEYl8BFq48VCWZ4dcAAAAASUVORK5CYII=" const ANONYMOUS_PHOTO_URL = "$darwino-social/users/images/anonymous-photo.png"; // // User class // class User { constructor(attrs,svc) { this._attrs = attrs; this._svc = svc; } isAnonymous() { return this._attrs["dn"]=="anonymous"; } getProvider() { return this._provider; } exists() { return !(this._loading || this._error); } isLoading() { return !!this._loading; } getDn() { return this._attrs["dn"]; } getCn() { return this._attrs["cn"]; } getPhotoUrl() { if(!this._svc) return ANONYMOUS_PHOTO return this._svc.getUserPhotoUrl(this._attrs["dn"]); } getGroupCount() { return this.getGroups().length; } getGroup(index) { return this.getGroups()[index]; } getGroups() { return this._attrs._groups||[]; } getRoleCount() { return this.getRoles().length; } getRole(index) { return this.getRoles()[index]; } getRoles() { return this._attrs._roles||[]; } hasUserId(id) { return this._attrs["dn"]==id; } hasGroup(id) { var groups = this.getGroups(); for(var i=0; i<groups.length; i++) { if(groups[i]==id) { return true; } } return false; } hasRole(id) { var roles = this.getRoles(); for(var i=0; i<roles.length; i++) { if(roles[i]==id) { return true; } } return false; } getAttribute(attrName) { return this._attrs[attrName]; } getAttributes() { return this._attrs; } findAttribute(attrName) { var v = this._attrs[attrName]; if(v!=undefined) { return v; } if(this._attrs._providers) { for(var p in this._attrs._providers) { var v = this._attrs._providers[p][attrName]; if(v!=undefined) { return v } } } return null; } getContentAsBinaryString(type,cb) { return getContent(this,null,type,cb,null); } getContentAsBase64(type,cb) { return getContent(this,null,type,cb,Utils.btoa); } getContentAsString(type,cb) { return getContent(this,null,type,cb,Utils.fromUtf8); } getUserData(provider) { var p = this._attrs._providers; return p && p[provider] ? new UserData(provider,p[provider],this) : null; } } class UserData { constructor(user,name,attrs) { this._user = user; this._name = name; this._attrs = attrs; } getAttribute(attrName) { return this._attrs[attrName]; } getAttributes() { return this._attrs; } getContentAsBinaryString(type,cb) { return getContent(this._user,this._name,type,cb,null); } getContentAsBase64(type,cb) { return getContent(this._user,this._name,type,cb,Utils.btoa); } getContentAsString(type,cb) { return getContent(this._user,this._name,type,cb,Utils.fromUtf8); } } function getContent(user,provider,type,cb,process) { if(user._svc) { var p = provider ? {provider:provider} : null; const url = makeUrl(this.baseUrl,["users",user.getDn(),"content",type],p); return fetchText(url),then((text) => { if(process) { text=process(text) } if(cb) (cb.success||cb)(text) }).catch((error) => { if(cb&&cb.failure) cb.failure(error); }) } return null; }; // Anonymous user const ANONYMOUS_DN = "anonymous"; const ANONYMOUS_USER = new User({dn:ANONYMOUS_DN,cn:"Anonymous",photoUrl:ANONYMOUS_PHOTO}); // This could go to a redux store!! const userMap = {} // // UserService // class UserService { // Export static ANONYMOUS_PHOTO = ANONYMOUS_PHOTO static ANONYMOUS_PHOTO_URL = ANONYMOUS_PHOTO_URL static ANONYMOUS_DN = ANONYMOUS_DN static ANONYMOUS_USER = ANONYMOUS_USER constructor() { this.requests = {}; this.baseUrl = "$darwino-social/users" this.users = userMap; } createUser(dn,cn) { return new User({dn:dn,cn:cn||dn},this); } // The methods bellow return a user // The calls are asynchronous, so if the user is not already available, it temporarily returns anonymous getCurrentUser(cb) { return this._findUser("@me",false,cb); } getUser(id,cb) { return this._findUser(id,false,cb); } getUserByLoginId(id,cb) { return this._findUser(id,true,cb); } _findUser(id,loginid,cb) { var _this=this; // An ID is case insensitive if(id) { var dn = id.toLowerCase(); if(dn!="anonymous") { var u = this.users[dn]; // if the user exists and there is an ongoing request for, add the callback to the list and return the user if(u) { if(cb) { if(this.requests[dn]) { this.requests[dn].push(cb); } else { Utils.execAsyncCb(cb,u,false); } } return u; } // The user is not yet loaded // Create the temporary user object and add it to the cache if(id=="@me") { u = new User({...ANONYMOUS_USER._attrs},_this); this.users["@me"] = u; } else { u = new User({dn:id,cn:id},_this); this.users[dn] = this.users[id] = u; } u._loading = true; // Create a list of callbacks for the request and eventually add the current one this.requests[dn] = []; if(cb) { this.requests[dn].push(cb); } // Execute the remote service var params = {}; if(loginid) params.loginid=true; if(id=="@me") params.providers="" // No providers to make @me as fast as possible for now fetchJson(makeUrl(this.baseUrl,["users",dn],params)).then( function(json) { delete u._loading; if(json) { u._attrs = json; u._exists = true; _this.users[dn] = u; // If @me, then no providers are added => don't store the user in the main list // An access by dn will later get all the providers, if any if(id!="@me") { _this.users[u.getDn().toLowerCase()] = u; // May already be there... if(json._current) { _this.users["@me"] = u; } } else { if(!_this.users["@me"]) _this.users["@me"] = u; // Might have been updated by another request by Id (complete) } var req = _this.requests[dn]; if(req) { for(var i=0; i<req.length; i++) { (req[i].success||req[i])(u,true); } delete _this.requests[dn]; } } }).catch( function(error) { delete u._loading; u._error = error; var req = _this.requests[dn]; if(req) { for(var i=0; i<req.length; i++) { if(req[i].failure) { req[i].failure(error); } } delete _this.requests[dn]; } } ) // Return the default user return u; } } return this.ANONYMOUS_USER; } getUserFromCache(dn) { return dn ? this.users[dn.toLowerCase()] : null; } preloadUsers(ids,loginid,cb) { var _this=this; if(ids) { // Find the users that are not already in the cache var dns = []; for(var i=0; i<ids.length; i++) { var id = ids[i]; if(id) { var dn = id.toLowerCase(); if(!this.users[dn]) { // Create a user being loaded var u = new User({dn:id,cn:id},_this); u._loading = true; this.users[dn] = this.users[id] = u; dns.push(dn); } } } if(dns.length) { var params = {}; if(loginid) params.loginid=true; const url = fetchJson(makeUrl(this.baseUrl,["users"], params), { method: 'POST', body: dns }).then((array) => { if(array) { for(var i=0; i<array.length; i++) { var u = _this.users[dns[i]]; delete u._loading; if(array[i]) { u._attrs = array[i]; u._exists = true; _this.users[u.getDn().toLowerCase()] = u; // May already be there... if(u._attrs._current) { _this.users["@me"] = u; } } else { u._error = "Unknown user"; } } } if(cb) (cb.success||cb)(); }).catch((error) => { for(var i=0; i<dns.length; i++) { var u = _this.users[dns[i]]; delete u._loading; u._error = error; } if(cb&&cb.failure) cb.failure(error); }) } } } getUserPhotoUrl(dn) { return this.getUserDataUrl(dn,"photo"); } getUserDataUrl(dn,type) { if(!dn) { dn = ANONYMOUS_DN; } if(type) { if(type=="photo") { if(dn==ANONYMOUS_DN) { return ANONYMOUS_PHOTO; } let u = this.getUserFromCache(dn); if(u) { if(u._attrs.photoUrl) { return u._attrs.photoUrl; } } } return makeUrl(this.baseUrl,["users",dn,"content",type]); } return null; } query(query,attributes,skip,limit,options,cb) { var params = {}; if(query) params.query = query; if(attributes) params.attributes = attributes.join(','); if(skip) params.skip = skip; if(limit) params.limit = limit; if(options) params.options = Utils.toJson(options); return fetchJson(makeUrl(this.baseUrl,["query"], params)).then((json) => { if(cb) (cb.success||cb)(json) }).catch((error) => { if(cb&&cb.failure) cb.failure(error) }) } typeAhead(query,attributes,skip,limit,options,cb) { var params = {}; if(query) params.query = query; if(attributes) params.attributes = attributes.join(','); if(skip) params.skip = skip; if(limit) params.limit = limit; if(options) params.options = Utils.toJson(options); return fetchJson(makeUrl(this.baseUrl,["typeahead"], params)).then((json) => { if(cb) (cb.success||cb)(json) }).catch((error) => { if(cb&&cb.failure) cb.failure(error) }) } } export default UserService;