Nella lezione precedente abbiamo conosciuto gli Appcelerator Cloud Services (ACS); in questa approfondiremo l'argomento esaminando la gestione degli utenti.
L'oggetto Users rappresenta un account.Gli utenti possono essere creati sia dalla dashboard che via software utilizzando gli oggetti e i metodi offerti dal modulo ti.cloud. In questa lezione vedremo come implementare una piccola app che, con l'interfaccia per il login che abbiamo visto in passato, permette
la creazione, l’autenticazione e il logout di un utente.
Iniziamo creando un progetto Alloy e chiamiamolo html_it-acslogin; ricordiamoci di indicare che vogliamo abilitare il cloud. Al termine del wizard
di creazione progetto verifichiamo che il modulo ti.cloud sia caricato, e nella sezione cloud services di tiapp.xml siano indicate le
chiavi di produzione e di sviluppo necessarie per abilitare ACS e per visualizzare correttamente la dashboard.
Modifichiamo quindi il file alloy.js e aggiungiamo la seguente riga:
Alloy.Globals.Cloud = require("ti.cloud");
In questo modo creiamo una reference globale agli oggetti del modulo ti.cloud ed evitiamo di scrivere (o dimenticarci di farlo) la funzione require in tutti i controller dove sarebbe necessaria. L'uso di una reference globale permette anche di avere una posizione centralizzata dove si
richiamano i moduli che vengono utilizzati più spesso, rendendo il codice più gestibile, leggibile e corretto. Per esempio, l'autocomplete dell'editor di
Titanium Studio riconosce gli oggetti del namespace Alloy.Globals, mentre invece non è in grado di riconoscere una chiamata require con
un argomento sbagliato (“ticloud” invece di “ti.cloud”).
A questo punto consideriamo il controller di default index (per essere precisi, la terna vista/controller/stile) e modifichiamone i file per implementare
la funzione di login e di logout:
index.xml
<Alloy>
<Window class="container" onFocus="update">
<View height=Ti.UI.SIZE layout="vertical">
<TextField id="username" value="" hintText="Username"></TextField>
<TextField id="password" value="" hintText="Password"></TextField>
<Label id="newuser" top="10" text="New user" on-Click="doNewUser"></Label>
<Button id="confirm" title="Login" onClick="doLogin"></Button>
<Button id="logout" title="Logout" onClick="doLogout"></Button>
</View>
</Window>
</Alloy>
La view definisce i campi per inserire username e password, una etichetta che una volta premuta ci permetterà di creare un nuovo utente, e due pulsanti per il login e il logout.
Il controller ci permetterà di effettuare il login
una volta inseriti lo username (che dovrà essere una email) e la password. Ovviamente la prima volta che eseguiremo questa app dovremo
necessariamente creare un nuovo utente, a meno che non sia stato creato manualmente attraverso la dashboard.
index.tss
".container": {
backgroundColor: "gray"
},
"TextField": {
top: 10,
width: "100%",
borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
color: "#000"
},
"#password": {
passwordMask:true
},
"#confirm": {
top: 20,
width : "33%",
borderColor: "black",
borderRadius : 5,
backgroundColor : "fff"
}
"#logout": {
top: 20,
width : "33%",
borderColor: "black",
borderRadius : 5,
backgroundColor : "fff"
}
Il controller index.js definirà le funzioni doLogin e doLogout, la chiamata ad un nuovo controller che contiene la form di
creazione utente e una funzione di update che cambierà l'aspetto della vista a seconda che l'utente sia loggato oppure no.
index.js
var Cloud = Alloy.Globals.Cloud;
function update() {
Ti.API.info("update " + Cloud.sessionId);
$.logout.visible = (Cloud.sessionId != null);
$.username.visible = !(Cloud.sessionId);
$.password.visible = !(Cloud.sessionId);
$.confirm.visible = !(Cloud.sessionId);
$.newuser.visible = !(Cloud.sessionId);
}
function doLogin(e) {
if ($.username.value && $.password.value) {
Cloud.Users.login({
login : $.username.value,
password : $.password.value
}, function(e) {
update();
Ti.API.info(JSON.stringify(e));
if (e.success) {
var user = e.users[0];
alert('Success:\n' + 'id: ' + user.id + '\n' + 'sessionId: ' + Cloud.sessionId + '\n' + 'first name: ' + user.first_name + '\n' + 'last name: ' + user.last_name);
} else {
alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
} else {
alert("Username o password mancanti");
}
$.username.blur();
$.password.blur();
}
function doLogout(e) {
Ti.API.info(JSON.stringify(e));
Cloud.Users.logout(function(e) {
update();
if (e.success) {
alert('Success: Logged out');
} else {
alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
}
function doNewUser() {
var controller = Alloy.createController('newuser');
var win = controller.getView();
win.open();
}
$.index.open();
Sia la funzione di login che quella di logout utilizzano metodi di ti.cloud, ed entrambe hanno una struttura simile.
Users.login
richiede due argomenti: un oggetto contenente le credenziali dell'utente, e una callback che riceve un parametro contenente l'esito dell'operazione e altre
informazioni utili. Nella nostra app, se il processo di login ha avuto esito positivo riceveremo un array di un solo elemento di tipoUsers, dal quale possiamo estrarre i membri che ci interessano, come first_name e last_name oppure l'id dell'utente.
Il login di un utente ha come effetto anche la valorizzazione del membro Cloud.session_id, utile sia per verificare se un utente è loggato o meno,
oppure per effettuare una login automatica all’avvio dell'app (salvando la session_id in una proprietà del namespaceTi.App.Properties, per esempio, e assegnandola a Cloud.session_id all'avvio).
La session_id ha validità di 6 mesi, per cui una volta scaduto questo tempo occorrerà rigenerarla con una nuova operazione di login,
questa volta con username e password.
Cloud.Users.login(args, function(e) {
if (e.success) {
...
} else {
...
}
})
Tutte le chiamate ACS hanno la stessa struttura a due parametri (args, callback) oppure a parametro singolo (solo callback),
come avviene nel caso del metodo di Users.logout: in questo caso, se il
primo parametro contiene solo argomenti opzionali può essere omesso.
Cloud.Users.logout(function(e) {
if (e.success) {
...
} else {
...
}
});
Il secondo gruppo di file è quello relativo al controller che dovrà gestire la creazione di un nuovo utente. Selezioniamo quindi dal
Project Explorer il nome del nostro progetto, clicchiamo con il pulsante destro e scegliamo New -> Alloy controller. Dopo aver inserito il nome
“newuser” (senza estensioni) nella finestra “New Controller”, andremo a modificare i file appena generati nel seguente modo:
newuser.xml
<Alloy>
<Window class="container" >
<View height=Ti.UI.SIZE layout="vertical">
<TextField id="email" value="" hintText="Email"></TextField>
<TextField id="name" value="" hintText="Name"></TextField>
<TextField id="lastname" value="" hintText="Lastname"></TextField>
<TextField id="password" value="" hintText="Password"></TextField>
<TextField id="confirmpassword" value="" hintText="Confirm Pass-word"></TextField>
<Label id="cancel" top="10" text="Cancel" onClick="doCancel"></Label>
<Button id="confirm" title="Confirm" onClick="doRegister"></Button>
</View>
</Window>
</Alloy>
Questa view contiene la descrizione di una form con email, nome, cognome e password, una label per tornare indietro e un pulsante di conferma.
newuser.tss
Il foglio stile newuser.tss è molto simile al precedente index.tss:
".container": {
backgroundColor: "gray"
},
"TextField": {
top: 10,
width: "100%",
borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
color: "#000"
},
"#password": {
passwordMask: true
},
"#confirmpassword":{
passwordMask: true
},
"#cancel": {
font: {
size: 9
}
},
"#confirm": {
top: 20,
width: "33%",
borderColor: "black",
borderRadius: 5,
backgroundColor: "fff"
}
newuser.js
Il controller
newuser.js
conterrà la funzione di registrazione dell'utente, che richiamerà il metodo
di ACS. Per
creare un utente
sono considerati obbligatori la coppia email e username oppure, se lo username viene omesso, la tripla email, nome e cognome. Una volta creato l'utente
sarà automaticamente effettuato il login (a meno che non si fosse già precedentemente loggati come administrator; in tal caso occorre indicare tra gli
argomenti anche
admin=true
).
var args = arguments[0] || {};
var Cloud = Alloy.Globals.Cloud;
function doRegister() {
Cloud.Users.create({
email : $.email.value,
first_name : $.name.value,
last_name : $.lastname.value,
password : $.password.value,
password_confirmation : $.confirmpassword.value
}, function(e) {
if (e.success) {
var user = e.users[0];
alert('Success:\n' + 'id: ' + user.id + '\n' + 'sessionId: ' + Cloud.sessionId + '\n' + 'first name: ' + user.first_name + '\n' + 'last name: ' + user.last_name);
$.newuser.close();
} else {
alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
}
function doCancel() {
$.newuser.close();
}
Come abbiamo visto le funzioni di base per creare un utente, nonché quelle per effettuare il login e il logout, sono estremamente semplici. L'oggetto Users contiene altri metodi, tra cui quelli che consentono l'aggiornamento, il reset
della password e la cancellazione. Una volta che il formato delle chiamate risulterà familiare, è consigliabile riprendere l'app della lezione scorsa che
contiene esempi già pronti praticamente per tutte le chiamate degli oggetti di ACS.
Il codice sorgente dell'app di esempio di questa lezione è allegato a questo articolo e disponibile su GitHub.