kopia lustrzana https://github.com/backface/turtlestitch
login, logout, signup
rodzic
51998503a3
commit
13c05e3082
729
cloud.js
729
cloud.js
|
@ -4,8 +4,10 @@
|
|||
|
||||
a backend API for SNAP!
|
||||
|
||||
written by Jens Mönig
|
||||
written by Bernat Romagosa
|
||||
inspired in old cloud API by Jens Mönig
|
||||
|
||||
Copyright (C) 2017 by Bernat Romagosa
|
||||
Copyright (C) 2015 by Jens Mönig
|
||||
|
||||
This file is part of Snap!.
|
||||
|
@ -27,598 +29,31 @@
|
|||
|
||||
// Global settings /////////////////////////////////////////////////////
|
||||
|
||||
/*global modules, IDE_Morph, SnapSerializer, hex_sha512, alert, nop,
|
||||
localize*/
|
||||
/*global modules, IDE_Morph, SnapSerializer, nop, localize*/
|
||||
|
||||
modules.cloud = '2015-December-15';
|
||||
|
||||
// Global stuff
|
||||
|
||||
var Cloud;
|
||||
var SnapCloud = new Cloud(
|
||||
'https://snap.apps.miosoft.com/SnapCloud'
|
||||
);
|
||||
|
||||
// Cloud /////////////////////////////////////////////////////////////
|
||||
|
||||
function Cloud(url) {
|
||||
this.username = null;
|
||||
this.password = null; // hex_sha512 hashed
|
||||
this.init(url);
|
||||
};
|
||||
|
||||
Cloud.prototype.init = function (url) {
|
||||
this.url = url;
|
||||
this.session = null;
|
||||
this.limo = null;
|
||||
this.route = null;
|
||||
this.api = {};
|
||||
}
|
||||
this.username = null;
|
||||
this.checkCredentials();
|
||||
};
|
||||
|
||||
Cloud.prototype.clear = function () {
|
||||
this.username = null;
|
||||
this.password = null;
|
||||
this.session = null;
|
||||
this.limo = null;
|
||||
this.route = null;
|
||||
this.api = {};
|
||||
};
|
||||
|
||||
Cloud.prototype.hasProtocol = function () {
|
||||
return this.url.toLowerCase().indexOf('http') === 0;
|
||||
};
|
||||
|
||||
Cloud.prototype.setRoute = function (username) {
|
||||
var routes = 20,
|
||||
userNum = 0,
|
||||
i;
|
||||
|
||||
for (i = 0; i < username.length; i += 1) {
|
||||
userNum += username.charCodeAt(i);
|
||||
}
|
||||
userNum = userNum % routes + 1;
|
||||
this.route = '.sc1m' +
|
||||
(userNum < 10 ? '0' : '') +
|
||||
userNum;
|
||||
};
|
||||
|
||||
// Cloud: Snap! API
|
||||
|
||||
Cloud.prototype.signup = function (
|
||||
username,
|
||||
email,
|
||||
callBack,
|
||||
errorCall
|
||||
) {
|
||||
// both callBack and errorCall are two-argument functions
|
||||
var request = new XMLHttpRequest(),
|
||||
myself = this;
|
||||
try {
|
||||
request.open(
|
||||
"GET",
|
||||
(this.hasProtocol() ? '' : 'http://')
|
||||
+ this.url + 'SignUp'
|
||||
+ '?Username='
|
||||
+ encodeURIComponent(username)
|
||||
+ '&Email='
|
||||
+ encodeURIComponent(email),
|
||||
true
|
||||
);
|
||||
request.setRequestHeader(
|
||||
"Content-Type",
|
||||
"application/x-www-form-urlencoded"
|
||||
);
|
||||
request.withCredentials = true;
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
if (request.responseText) {
|
||||
if (request.responseText.indexOf('ERROR') === 0) {
|
||||
errorCall.call(
|
||||
this,
|
||||
request.responseText,
|
||||
'Signup'
|
||||
);
|
||||
} else {
|
||||
callBack.call(
|
||||
null,
|
||||
request.responseText,
|
||||
'Signup'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
errorCall.call(
|
||||
null,
|
||||
myself.url + 'SignUp',
|
||||
localize('could not connect to:')
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send(null);
|
||||
} catch (err) {
|
||||
errorCall.call(this, err.toString(), 'Snap!Cloud');
|
||||
}
|
||||
};
|
||||
|
||||
Cloud.prototype.getPublicProject = function (
|
||||
id,
|
||||
callBack,
|
||||
errorCall
|
||||
) {
|
||||
// id is Username=username&projectName=projectname,
|
||||
// where the values are url-component encoded
|
||||
// callBack is a single argument function, errorCall take two args
|
||||
var request = new XMLHttpRequest(),
|
||||
myself = this;
|
||||
try {
|
||||
request.open(
|
||||
"GET",
|
||||
(this.hasProtocol() ? '' : 'http://')
|
||||
+ this.url + 'RawPublic'
|
||||
+ '?'
|
||||
+ id,
|
||||
true
|
||||
);
|
||||
request.setRequestHeader(
|
||||
"Content-Type",
|
||||
"application/x-www-form-urlencoded"
|
||||
);
|
||||
request.withCredentials = true;
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
if (request.responseText) {
|
||||
if (request.responseText.indexOf('ERROR') === 0) {
|
||||
errorCall.call(
|
||||
this,
|
||||
request.responseText
|
||||
);
|
||||
} else {
|
||||
callBack.call(
|
||||
null,
|
||||
request.responseText
|
||||
);
|
||||
}
|
||||
} else {
|
||||
errorCall.call(
|
||||
null,
|
||||
myself.url + 'Public',
|
||||
localize('could not connect to:')
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send(null);
|
||||
} catch (err) {
|
||||
errorCall.call(this, err.toString(), 'Snap!Cloud');
|
||||
}
|
||||
};
|
||||
|
||||
Cloud.prototype.resetPassword = function (
|
||||
username,
|
||||
callBack,
|
||||
errorCall
|
||||
) {
|
||||
// both callBack and errorCall are two-argument functions
|
||||
var request = new XMLHttpRequest(),
|
||||
myself = this;
|
||||
try {
|
||||
request.open(
|
||||
"GET",
|
||||
(this.hasProtocol() ? '' : 'http://')
|
||||
+ this.url + 'ResetPW'
|
||||
+ '?Username='
|
||||
+ encodeURIComponent(username),
|
||||
true
|
||||
);
|
||||
request.setRequestHeader(
|
||||
"Content-Type",
|
||||
"application/x-www-form-urlencoded"
|
||||
);
|
||||
request.withCredentials = true;
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
if (request.responseText) {
|
||||
if (request.responseText.indexOf('ERROR') === 0) {
|
||||
errorCall.call(
|
||||
this,
|
||||
request.responseText,
|
||||
'Reset Password'
|
||||
);
|
||||
} else {
|
||||
callBack.call(
|
||||
null,
|
||||
request.responseText,
|
||||
'Reset Password'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
errorCall.call(
|
||||
null,
|
||||
myself.url + 'ResetPW',
|
||||
localize('could not connect to:')
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send(null);
|
||||
} catch (err) {
|
||||
errorCall.call(this, err.toString(), 'Snap!Cloud');
|
||||
}
|
||||
};
|
||||
|
||||
Cloud.prototype.login = function (
|
||||
username,
|
||||
password,
|
||||
callBack,
|
||||
errorCall
|
||||
) {
|
||||
// both callBack and errorCall are two-argument functions
|
||||
var request = new XMLHttpRequest(),
|
||||
usr = JSON.stringify({'__h': password, '__u': username}),
|
||||
myself = this;
|
||||
this.setRoute(username);
|
||||
try {
|
||||
request.open(
|
||||
"POST",
|
||||
(this.hasProtocol() ? '' : 'http://') +
|
||||
this.url +
|
||||
'?SESSIONGLUE=' +
|
||||
this.route,
|
||||
true
|
||||
);
|
||||
request.setRequestHeader(
|
||||
"Content-Type",
|
||||
"application/json; charset=utf-8"
|
||||
);
|
||||
// glue this session to a route:
|
||||
request.setRequestHeader('SESSIONGLUE', this.route);
|
||||
request.withCredentials = true;
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
if (request.responseText) {
|
||||
myself.api = myself.parseAPI(request.responseText);
|
||||
myself.session = request.getResponseHeader('MioCracker')
|
||||
.split(';')[0];
|
||||
// set the cookie identifier:
|
||||
myself.limo = this.getResponseHeader("miocracker")
|
||||
.substring(
|
||||
9,
|
||||
this.getResponseHeader("miocracker").indexOf("=")
|
||||
);
|
||||
if (myself.api.logout) {
|
||||
myself.username = username;
|
||||
myself.password = password;
|
||||
callBack.call(null, myself.api, 'Snap!Cloud');
|
||||
} else {
|
||||
errorCall.call(
|
||||
null,
|
||||
request.responseText,
|
||||
'connection failed'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
errorCall.call(
|
||||
null,
|
||||
myself.url,
|
||||
localize('could not connect to:')
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send(usr);
|
||||
} catch (err) {
|
||||
errorCall.call(this, err.toString(), 'Snap!Cloud');
|
||||
}
|
||||
};
|
||||
|
||||
Cloud.prototype.reconnect = function (
|
||||
callBack,
|
||||
errorCall
|
||||
) {
|
||||
if (!(this.username && this.password)) {
|
||||
this.message('You are not logged in');
|
||||
return;
|
||||
}
|
||||
this.login(
|
||||
this.username,
|
||||
this.password,
|
||||
callBack,
|
||||
errorCall
|
||||
);
|
||||
};
|
||||
|
||||
Cloud.prototype.saveProject = function (ide, callBack, errorCall) {
|
||||
var myself = this,
|
||||
pdata,
|
||||
media,
|
||||
size,
|
||||
mediaSize;
|
||||
|
||||
ide.serializer.isCollectingMedia = true;
|
||||
pdata = ide.serializer.serialize(ide.stage);
|
||||
media = ide.hasChangedMedia ?
|
||||
ide.serializer.mediaXML(ide.projectName) : null;
|
||||
ide.serializer.isCollectingMedia = false;
|
||||
ide.serializer.flushMedia();
|
||||
|
||||
mediaSize = media ? media.length : 0;
|
||||
size = pdata.length + mediaSize;
|
||||
if (mediaSize > 10485760) {
|
||||
new DialogBoxMorph().inform(
|
||||
'Snap!Cloud - Cannot Save Project',
|
||||
'The media inside this project exceeds 10 MB.\n' +
|
||||
'Please reduce the size of costumes or sounds.\n',
|
||||
ide.world(),
|
||||
ide.cloudIcon(null, new Color(180, 0, 0))
|
||||
);
|
||||
throw new Error('Project media exceeds 10 MB size limit');
|
||||
}
|
||||
|
||||
// check if serialized data can be parsed back again
|
||||
try {
|
||||
ide.serializer.parse(pdata);
|
||||
} catch (err) {
|
||||
ide.showMessage('Serialization of program data failed:\n' + err);
|
||||
throw new Error('Serialization of program data failed:\n' + err);
|
||||
}
|
||||
if (media !== null) {
|
||||
try {
|
||||
ide.serializer.parse(media);
|
||||
} catch (err) {
|
||||
ide.showMessage('Serialization of media failed:\n' + err);
|
||||
throw new Error('Serialization of media failed:\n' + err);
|
||||
}
|
||||
}
|
||||
ide.serializer.isCollectingMedia = false;
|
||||
ide.serializer.flushMedia();
|
||||
|
||||
ide.showMessage('Uploading ' + Math.round(size / 1024) + ' KB...');
|
||||
myself.reconnect(
|
||||
function () {
|
||||
myself.callService(
|
||||
'saveProject',
|
||||
function (response, url) {
|
||||
callBack.call(null, response, url);
|
||||
myself.disconnect();
|
||||
ide.hasChangedMedia = false;
|
||||
},
|
||||
errorCall,
|
||||
[
|
||||
ide.projectName,
|
||||
pdata,
|
||||
media,
|
||||
pdata.length,
|
||||
media ? media.length : 0
|
||||
]
|
||||
);
|
||||
},
|
||||
errorCall
|
||||
);
|
||||
};
|
||||
|
||||
Cloud.prototype.getProjectList = function (callBack, errorCall) {
|
||||
var myself = this;
|
||||
this.reconnect(
|
||||
function () {
|
||||
myself.callService(
|
||||
'getProjectList',
|
||||
function (response, url) {
|
||||
callBack.call(null, response, url);
|
||||
myself.disconnect();
|
||||
},
|
||||
errorCall
|
||||
);
|
||||
},
|
||||
errorCall
|
||||
);
|
||||
};
|
||||
|
||||
Cloud.prototype.changePassword = function (
|
||||
oldPW,
|
||||
newPW,
|
||||
callBack,
|
||||
errorCall
|
||||
) {
|
||||
var myself = this;
|
||||
this.reconnect(
|
||||
function () {
|
||||
myself.callService(
|
||||
'changePassword',
|
||||
function (response, url) {
|
||||
callBack.call(null, response, url);
|
||||
myself.disconnect();
|
||||
},
|
||||
errorCall,
|
||||
[hex_sha512(oldPW), hex_sha512(newPW)]
|
||||
);
|
||||
},
|
||||
errorCall
|
||||
);
|
||||
};
|
||||
|
||||
Cloud.prototype.logout = function (callBack, errorCall) {
|
||||
this.clear();
|
||||
this.callService(
|
||||
'logout',
|
||||
callBack,
|
||||
errorCall
|
||||
);
|
||||
};
|
||||
|
||||
Cloud.prototype.disconnect = function () {
|
||||
this.callService(
|
||||
'logout',
|
||||
nop,
|
||||
nop
|
||||
);
|
||||
};
|
||||
|
||||
// Cloud: backend communication
|
||||
|
||||
Cloud.prototype.callURL = function (url, callBack, errorCall) {
|
||||
// both callBack and errorCall are optional two-argument functions
|
||||
var request = new XMLHttpRequest(),
|
||||
stickyUrl,
|
||||
myself = this;
|
||||
try {
|
||||
// set the Limo. Also set the glue as a query paramter for backup.
|
||||
stickyUrl = url +
|
||||
'&SESSIONGLUE=' +
|
||||
this.route +
|
||||
'&_Limo=' +
|
||||
this.limo;
|
||||
request.open('GET', stickyUrl, true);
|
||||
request.withCredentials = true;
|
||||
request.setRequestHeader(
|
||||
"Content-Type",
|
||||
"application/x-www-form-urlencoded"
|
||||
);
|
||||
request.setRequestHeader('MioCracker', this.session);
|
||||
// Set the glue as a request header.
|
||||
request.setRequestHeader('SESSIONGLUE', this.route);
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
if (request.responseText) {
|
||||
var responseList = myself.parseResponse(
|
||||
request.responseText
|
||||
);
|
||||
callBack.call(null, responseList, url);
|
||||
} else {
|
||||
errorCall.call(
|
||||
null,
|
||||
url,
|
||||
'no response from:'
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send(null);
|
||||
} catch (err) {
|
||||
errorCall.call(this, err.toString(), url);
|
||||
}
|
||||
};
|
||||
|
||||
Cloud.prototype.callService = function (
|
||||
serviceName,
|
||||
callBack,
|
||||
errorCall,
|
||||
args
|
||||
) {
|
||||
// both callBack and errorCall are optional two-argument functions
|
||||
var request = new XMLHttpRequest(),
|
||||
service = this.api[serviceName],
|
||||
myself = this,
|
||||
stickyUrl,
|
||||
postDict;
|
||||
|
||||
if (!this.session) {
|
||||
errorCall.call(null, 'You are not connected', 'Cloud');
|
||||
return;
|
||||
}
|
||||
if (!service) {
|
||||
errorCall.call(
|
||||
null,
|
||||
'service ' + serviceName + ' is not available',
|
||||
'API'
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (args && args.length > 0) {
|
||||
postDict = {};
|
||||
service.parameters.forEach(function (parm, idx) {
|
||||
postDict[parm] = args[idx];
|
||||
});
|
||||
}
|
||||
try {
|
||||
stickyUrl = this.url +
|
||||
'/' +
|
||||
service.url +
|
||||
'&SESSIONGLUE=' +
|
||||
this.route +
|
||||
'&_Limo=' +
|
||||
this.limo;
|
||||
request.open(service.method, stickyUrl, true);
|
||||
request.withCredentials = true;
|
||||
request.setRequestHeader(
|
||||
"Content-Type",
|
||||
"application/x-www-form-urlencoded"
|
||||
);
|
||||
request.setRequestHeader('MioCracker', this.session);
|
||||
request.setRequestHeader('SESSIONGLUE', this.route);
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
var responseList = [];
|
||||
if (request.responseText &&
|
||||
request.responseText.indexOf('ERROR') === 0) {
|
||||
errorCall.call(
|
||||
this,
|
||||
request.responseText,
|
||||
localize('Service:') + ' ' + localize(serviceName)
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (serviceName === 'login') {
|
||||
myself.api = myself.parseAPI(request.responseText);
|
||||
}
|
||||
if (serviceName === 'getRawProject') {
|
||||
responseList = request.responseText;
|
||||
} else {
|
||||
responseList = myself.parseResponse(
|
||||
request.responseText
|
||||
);
|
||||
}
|
||||
callBack.call(null, responseList, service.url);
|
||||
}
|
||||
};
|
||||
request.send(this.encodeDict(postDict));
|
||||
} catch (err) {
|
||||
errorCall.call(this, err.toString(), service.url);
|
||||
}
|
||||
};
|
||||
|
||||
// Cloud: payload transformation
|
||||
|
||||
Cloud.prototype.parseAPI = function (src) {
|
||||
var api = {},
|
||||
services;
|
||||
services = src.split(" ");
|
||||
services.forEach(function (service) {
|
||||
var entries = service.split("&"),
|
||||
serviceDescription = {},
|
||||
parms;
|
||||
entries.forEach(function (entry) {
|
||||
var pair = entry.split("="),
|
||||
key = decodeURIComponent(pair[0]).toLowerCase(),
|
||||
val = decodeURIComponent(pair[1]);
|
||||
if (key === "service") {
|
||||
api[val] = serviceDescription;
|
||||
} else if (key === "parameters") {
|
||||
parms = val.split(",");
|
||||
if (!(parms.length === 1 && !parms[0])) {
|
||||
serviceDescription.parameters = parms;
|
||||
}
|
||||
} else {
|
||||
serviceDescription[key] = val;
|
||||
}
|
||||
});
|
||||
});
|
||||
return api;
|
||||
};
|
||||
|
||||
Cloud.prototype.parseResponse = function (src) {
|
||||
var ans = [],
|
||||
lines;
|
||||
if (!src) {return ans; }
|
||||
lines = src.split(" ");
|
||||
lines.forEach(function (service) {
|
||||
var entries = service.split("&"),
|
||||
dict = {};
|
||||
entries.forEach(function (entry) {
|
||||
var pair = entry.split("="),
|
||||
key = decodeURIComponent(pair[0]),
|
||||
val = decodeURIComponent(pair[1]);
|
||||
dict[key] = val;
|
||||
});
|
||||
ans.push(dict);
|
||||
});
|
||||
return ans;
|
||||
};
|
||||
// Dictionary handling
|
||||
|
||||
Cloud.prototype.parseDict = function (src) {
|
||||
var dict = {};
|
||||
|
@ -651,8 +86,142 @@ Cloud.prototype.encodeDict = function (dict) {
|
|||
return str;
|
||||
};
|
||||
|
||||
// Cloud: user messages (to be overridden)
|
||||
// Low level functionality
|
||||
|
||||
Cloud.prototype.message = function (string) {
|
||||
alert(string);
|
||||
Cloud.prototype.get = function (path, onSuccess, onError, errorMsg) {
|
||||
var request = new XMLHttpRequest(),
|
||||
myself = this;
|
||||
try {
|
||||
request.open(
|
||||
'GET',
|
||||
this.url + path,
|
||||
true
|
||||
);
|
||||
request.setRequestHeader(
|
||||
'Content-Type',
|
||||
'application/json; charset=utf-8'
|
||||
);
|
||||
request.withCredentials = true;
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
if (request.responseText) {
|
||||
var response = JSON.parse(request.responseText);
|
||||
if (response.errors) {
|
||||
onError.call(
|
||||
null,
|
||||
response.errors[0],
|
||||
errorMsg
|
||||
);
|
||||
} else {
|
||||
onSuccess.call(null, response.message || response);
|
||||
}
|
||||
} else {
|
||||
onError.call(
|
||||
null,
|
||||
myself.url,
|
||||
errorMsg
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send();
|
||||
} catch (err) {
|
||||
onError.call(this, err.toString(), 'Cloud Error');
|
||||
}
|
||||
};
|
||||
|
||||
Cloud.prototype.post = function (path, body, onSuccess, onError, errorMsg) {
|
||||
var request = new XMLHttpRequest(),
|
||||
myself = this;
|
||||
try {
|
||||
request.open(
|
||||
'POST',
|
||||
this.url + path,
|
||||
true
|
||||
);
|
||||
request.setRequestHeader(
|
||||
'Content-Type',
|
||||
'application/json'
|
||||
);
|
||||
request.withCredentials = true;
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
if (request.responseText) {
|
||||
var response = JSON.parse(request.responseText);
|
||||
if (response.errors) {
|
||||
onError.call(
|
||||
this,
|
||||
response.errors[0],
|
||||
'Cloud Error'
|
||||
);
|
||||
} else {
|
||||
onSuccess.call(null, response.message || response);
|
||||
}
|
||||
} else {
|
||||
onError.call(
|
||||
null,
|
||||
myself.url + path,
|
||||
localize('could not connect to:')
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send(body);
|
||||
} catch (err) {
|
||||
onError.call(this, err.toString(), 'Cloud Error');
|
||||
}
|
||||
};
|
||||
|
||||
// Credentials management
|
||||
|
||||
Cloud.prototype.checkCredentials = function (onSuccess, onError) {
|
||||
var myself = this;
|
||||
this.getCurrentUser(
|
||||
function (user) {
|
||||
if (user.username) {
|
||||
myself.username = user.username;
|
||||
}
|
||||
if (onSuccess) { onSuccess.call(null, user.username); }
|
||||
},
|
||||
onError);
|
||||
};
|
||||
|
||||
Cloud.prototype.getCurrentUser = function (onSuccess, onError) {
|
||||
this.get('/users/c', onSuccess, onError, 'Could not retrieve current user');
|
||||
};
|
||||
|
||||
Cloud.prototype.logout = function (onSuccess, onError) {
|
||||
this.post(
|
||||
'/users/' + this.username + '/logout',
|
||||
null,
|
||||
onSuccess,
|
||||
onError,
|
||||
'logout failed');
|
||||
};
|
||||
|
||||
Cloud.prototype.login = function (username, password, onSuccess, onError) {
|
||||
var myself = this;
|
||||
this.post(
|
||||
'/users/' + username + '/login?' + this.encodeDict({ password: password }),
|
||||
null,
|
||||
function () {
|
||||
myself.checkCredentials(onSuccess, onError);
|
||||
},
|
||||
onError,
|
||||
'login failed');
|
||||
};
|
||||
|
||||
Cloud.prototype.signup = function (username, password, password_repeat, email, onSuccess, onError){
|
||||
this.post(
|
||||
'/users/' + username + '?' + this.encodeDict({
|
||||
email: email,
|
||||
password: password,
|
||||
password_repeat: password_repeat
|
||||
}),
|
||||
null,
|
||||
onSuccess,
|
||||
onError,
|
||||
'signup failed');
|
||||
};
|
||||
|
||||
var SnapCloud = new Cloud('http://localhost:8080');
|
||||
|
|
33
gui.js
33
gui.js
|
@ -272,14 +272,16 @@ IDE_Morph.prototype.openIn = function (world) {
|
|||
if (this.hasLocalStorage()) {
|
||||
usr = localStorage['-snap-user'];
|
||||
if (usr) {
|
||||
usr = SnapCloud.parseResponse(usr)[0];
|
||||
if (usr) {
|
||||
SnapCloud.username = usr.username || null;
|
||||
SnapCloud.password = usr.password || null;
|
||||
if (SnapCloud.username) {
|
||||
this.source = 'cloud';
|
||||
SnapCloud.checkCredentials(
|
||||
function (username) {
|
||||
if (username) {
|
||||
this.source = 'cloud';
|
||||
}
|
||||
},
|
||||
function () {
|
||||
delete localStorage['-snap-user'];
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5050,20 +5052,12 @@ IDE_Morph.prototype.initializeCloud = function () {
|
|||
new DialogBoxMorph(
|
||||
null,
|
||||
function (user) {
|
||||
var pwh = hex_sha512(user.password),
|
||||
str;
|
||||
SnapCloud.login(
|
||||
user.username,
|
||||
pwh,
|
||||
user.password,
|
||||
function () {
|
||||
if (user.choice) {
|
||||
str = SnapCloud.encodeDict(
|
||||
{
|
||||
username: user.username,
|
||||
password: pwh
|
||||
}
|
||||
);
|
||||
localStorage['-snap-user'] = str;
|
||||
localStorage['-snap-user'] = user.username;
|
||||
}
|
||||
myself.source = 'cloud';
|
||||
myself.showMessage('now connected.', 2);
|
||||
|
@ -5098,13 +5092,14 @@ IDE_Morph.prototype.createCloudAccount = function () {
|
|||
function (user) {
|
||||
SnapCloud.signup(
|
||||
user.username,
|
||||
user.password,
|
||||
user.passwordRepeat,
|
||||
user.email,
|
||||
function (txt, title) {
|
||||
new DialogBoxMorph().inform(
|
||||
title,
|
||||
txt +
|
||||
'.\n\nAn e-mail with your password\n' +
|
||||
'has been sent to the address provided',
|
||||
'.\n\nYou can now log in.',
|
||||
world,
|
||||
myself.cloudIcon(null, new Color(0, 180, 0))
|
||||
);
|
||||
|
|
11
widgets.js
11
widgets.js
|
@ -2075,6 +2075,10 @@ DialogBoxMorph.prototype.promptCredentials = function (
|
|||
emlLabel = labelText('foo');
|
||||
inp.add(emlLabel);
|
||||
inp.add(eml);
|
||||
inp.add(labelText('Password:'));
|
||||
inp.add(pw1);
|
||||
inp.add(labelText('Repeat Password:'));
|
||||
inp.add(pw2);
|
||||
}
|
||||
|
||||
if (purpose === 'login') {
|
||||
|
@ -2182,7 +2186,7 @@ DialogBoxMorph.prototype.promptCredentials = function (
|
|||
if (purpose === 'login') {
|
||||
checklist = [usr, pw1];
|
||||
} else if (purpose === 'signup') {
|
||||
checklist = [usr, bmn, byr, eml];
|
||||
checklist = [usr, bmn, byr, eml, pw1, pw2];
|
||||
} else if (purpose === 'changePassword') {
|
||||
checklist = [opw, pw1, pw2];
|
||||
} else if (purpose === 'resetPassword') {
|
||||
|
@ -2205,12 +2209,12 @@ DialogBoxMorph.prototype.promptCredentials = function (
|
|||
return false;
|
||||
}
|
||||
if (em.indexOf(' ') > -1 || em.indexOf('@') === -1
|
||||
|| em.indexOf('.') === -1) {
|
||||
|| em.indexOf('.') === -1 || em.length < 5) {
|
||||
indicate(eml, 'please provide a valid\nemail address');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (purpose === 'changePassword') {
|
||||
if (purpose === 'changePassword' || purpose === 'signup') {
|
||||
if (pw1.getValue().length < 6) {
|
||||
indicate(pw1, 'password must be six\ncharacters or longer');
|
||||
return false;
|
||||
|
@ -2249,6 +2253,7 @@ DialogBoxMorph.prototype.promptCredentials = function (
|
|||
email: eml.getValue(),
|
||||
oldpassword: opw.getValue(),
|
||||
password: pw1.getValue(),
|
||||
passwordRepeat: pw2.getValue(),
|
||||
choice: agree
|
||||
};
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue