Parse User是Parse App內建的class,只要建立app,就會自動產生。Parse User class預設有9個欄位如下圖所示,視需求可自行擴充。
以下以EnrollApp的雲端資料庫(如下圖)為例,說明如何以Parse REST API進行會員註冊與登入的動作。
|
圖2. EnrollApp雲端資料庫 |
如圖2所示,Role, Session, User都是預設classes,可用來作為會員管理。另外Activity與Instructor則是自建classes,用來記錄活動與活動講師。會員註冊、登入與登出部分將會用到User class(欄位見圖1)。
Parse REST API: 註冊與登入
Parse REST API的基本網址是:
https://api.parse.com/
跟註冊、登入與登出有關的API如下圖所示:
以註冊為例,官網上curl語法是:
curl -X POST \
-H "X-Parse-Application-Id: 你的applicaiton id" \
-H "X-Parse-REST-API-Key: 你的API Key" \
-H "Content-Type: application/json" \
-d '{"username":"cooldude6","password":"p_n7!-e8","phone":"415-392-0202"}' \
https://api.parse.com/1/users
將上述curl改為AngularJS的寫法,則是:
var user={"username":"cooldude6","password":"p_n7!-e8","phone":"415-392-0202"};
... [略] ...
$scope.signin = function ($http) {
$http.post('https://api.parse.com/1/classes/users', user, {
headers: {'X-Parse-Application-Id': "你的Application ID",
'X-Parse-REST-API-Key': "你的REST-API-Key",
'Content-Type': 'application/json'
}
});
}
其實註冊動作與一般新增一筆資料的做法(參考
Hybrid Apps開發系列之5.5:以REST API存取Parse雲端資料庫)雷同,差別只有API不同,因此實作上,可以直接運用之前範例的DBA服務。
建立Ionic專案
ionic start ParseUser blank
cd ParseUser
bower install ngstorage
bower install angular-messages
bower install angular-validation-match
ionic platform add android
此範例用到
ngStorage儲存token,
ngMessages,
Angular Validation: Match進行表單驗證與密碼欄位內容比對。安裝好上述模組後,在bower_components資料夾內找到這些模組的.js檔,複製到專案內的lib資料夾,接著再修改index.html,例如:
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="lib/validate/angular-input-match.min.js"></script>
<script src="lib/angular-messages/angular-messages.js"></script>
<script src="lib/ngstorage/ngStorage.min.js"></script>
修改app.js,注入相對dependencies:
angular.module('starter', ['ionic', 'starter.services','starter.controllers',
'ngStorage','ngMessages','validation.match'])
...[略]...
程式碼解說
頁面states定義如下 (js/app.js)
angular.module('starter', ['ionic', 'starter.services','starter.controllers',
'ngStorage','ngMessages','validation.match'])
.config(function($stateProvider, $urlRouterProvider){
$stateProvider
.state('signin',{
url:'/signin',
templateUrl: 'templates/signin.html',
controller: 'signinCtrl'
})
.state('login',{
url:'/login',
templateUrl : 'templates/login.html',
controller : 'loginCtrl'
})
.state('activities',{
url: '/activities',
templateUrl : 'templates/activities.html',
controller : 'activityCtrl'
})
$urlRouterProvider.otherwise('/login');
})
.run(function ($ionicPlatform) {
$ionicPlatform.ready(function () {
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
});
})
- 三個頁面,登入(login),註冊(signin)與活動(activities):
|
圖3.三個頁面執行情況 |
- 第1-2行:注入前述安裝的模組,還有自訂controllers, services。
js/services.js為Parse雲端資料庫介接程式碼:
angular.module('starter.services', [])
.factory('DBA', function ($http, $q) {
var self = this;
self.query = function (method, api, data, header) {
var q = $q.defer();
switch (method) {
case 'GET':
$http.get(api, header).then(function (result) {
q.resolve(result);
}, function (error) {
console.warn(error);
q.reject(error);
})
break;
case 'POST':
$http.post(api, data, header).then(function (result) {
q.resolve(result);
}, function (error) {
console.warn(error);
q.reject(error);
})
break;
case 'PUT':
$http.put(api, data, header).then(function (result) {
q.resolve(result);
}, function (error) {
console.warn(error);
q.reject(error);
})
break;
case 'DELETE':
$http.delete(api, header).then(function (result) {
q.resolve(result);
}, function (error) {
console.warn(error);
q.reject(error);
})
break;
}
return q.promise;
}
return self
})
.factory('Enroll', function (DBA, PARSE_KEYS, PARSE_API, LOGIN_API, SIGNIN_API, LOGOUT_API) {
var self = this;
var header = {headers: {
'X-Parse-Application-Id': PARSE_KEYS.APP_ID,
'X-Parse-REST-API-Key': PARSE_KEYS.REST_API_KEY
}
}
var headerJson = {
headers: {
'X-Parse-Application-Id': PARSE_KEYS.APP_ID,
'X-Parse-REST-API-Key': PARSE_KEYS.REST_API_KEY,
'Content-Type': 'application/json'
}
}
self.signin = function (object) {
return DBA.query('POST', SIGNIN_API, object, headerJson);
}
self.login = function (object) {
return DBA.query(
'GET',
LOGIN_API + "?" + encodeURI('username=' + object.username + '&password=' + object.password),
'',
header);
}
self.logout = function(sessionToken) {
header.headers['X-Parse-Session-Token']=sessionToken;
return DBA.query('POST',LOGOUT_API,'',header);
}
self.getAll = function (classname) {
return DBA.query('GET', PARSE_API + classname, '', header);
}
self.get = function (classname, objectId) {
return DBA.query('GET', PARSE_API + classname + '/' + objectId, '', header);
};
self.getWithChild = function (classname, child) {
return DBA.query('GET', PARSE_API + classname +
"?" + encodeURI('include=' + child), '', header);
}
self.query = function (classname, object) {
return DBA.query('GET', PARSE_API + classname, '', header);
};
self.create = function (classname, object) {
return DBA.query('POST', PARSE_API + classname, object, headerJson);
}
self.update = function (classname, objectId, object) {
return DBA.query('PUT', PARSE_API + classname + '/' + objectId, object, headerJson);
}
self.delete = function (classname, objectId) {
return DBA.query('DELETE', PARSE_API + classname + '/' + objectId, '', headerJson);
}
return self;
})
.value('PARSE_KEYS', {
APP_ID: '2Lr9N9wK...略...',
REST_API_KEY: 'n0kVeRn...略...'
})
.value('PARSE_API', "https://api.parse.com/1/classes/")
.value('LOGIN_API', "https://api.parse.com/1/login")
.value('SIGNIN_API', "https://api.parse.com/1/users")
.value('LOGOUT_API',"https://api.parse.com/1/logout");
- 第2-43行:DBA服務與Hybrid Apps開發系列之5.5:以REST API存取Parse雲端資料庫完全相同。
- 第59-61:使用Parse Rest API進行註冊,此處object包含帳號、密碼、與email。在輸入帳號、密碼、email的註冊表單必須做輸入驗證,驗證條件可自訂,但email必須符合格式,否則會註冊失敗。另外注意email部分可在Parse App處設定要做email驗證,如此系統便會自動寄信。詳請請參考Parse官網。
- 第62-68行:登入。同樣需提供帳號、密碼。
- 第69-72行:登出。需提供登入或註冊時拿到的sessionToken。登出成功會將Parse Session內的資料移除。
- 第79-82行:此函式專為取得Parse Pointer的物件內容。由於活動Activities類別裡有一欄位instructor指向另一個Instructor物件,因此需用此函式才能取得Instructor物件內容。(註:Pointer並不是關聯式資料庫的東西,這是Parse雲端資料庫用來實作多對多關連的方法,詳情請參考Parse官網Relational Queries的說明)
js/controllers.js檔內容如下:
angular.module('starter.controllers', [])
.controller('loginCtrl', function ($scope, Enroll, $location, $localStorage) {
$scope.username = '';
$scope.password = ''
$scope.logon = function (username, password) {
var object = {'username': username, 'password': password};
Enroll.login(object).then(function (result) {
$localStorage.token = result.data.sessionToken;
$location.path('/activities');
}, function (error) {
console.warn(error);
$location.path('/login');
})
}
$scope.signin = function () {
$location.path('/signin');
}
})
.controller('activityCtrl', function ($scope, Enroll, $location, $localStorage,$window) {
if ($localStorage.hasOwnProperty("token") === true) { // 已登入
$scope.login = true; // 顯示登出按鈕
Enroll.getWithChild('Activity', 'instructor').then(function (result) {
$scope.activities = result.data.results;
})
} else {
$scope.login = false;
$location.path('/login');
}
$scope.logout = function () {
Enroll.logout($localStorage.token).then(function (result) {
delete $localStorage.token;
$window.location.reload('true');
$window.location.href= '#login';
}, function (error){
console.warn(error);
})
}
})
.controller('signinCtrl', function ($scope, Enroll, $location, $window, $localStorage) {
$scope.user = {};
$scope.password02 = ''; // confirmpassword
$scope.signin = function (user) {
Enroll.signin(user).then(function (result) {
$localStorage.token = result.data.sessionToken;
$location.path('/activities');
}, function (error) {
console.warn(error.data.error);
})
}
})
- 第5-14行:登入函式logon()。第7行使用了services.js定義的login()進行雲端資料庫登入。登入成功的話,雲端資料庫Session class會多一筆token紀錄,並回傳到controller。此處將sessionToken存到$localStorage.token內,隨之轉往activities頁面。
|
圖4. Activity類別內有Pointer類型的欄位instructor |
- 第19-38行:activities頁面之controller。如已成功登入,便會顯示登出按鈕,同時取得Activity類別內所有活動記錄。第22行以getWithChild('Activity', 'instructor')指定除了取得Activity所有物件,同時對Pointer欄位instructor,也要進一步取得資料。如圖4所示,Activity有一instructor欄位為Pointer,儲存objectId,但實際內容則在Instuctor類別內。因此要靠getWithChild('Activity', 'instructor')才能取得實際資料。
- 第39-50行:註冊頁面controller。呼叫Enroll.signin()進行註冊。成功同樣回傳seesionToken。
其他templates/login.html, templates/signin.html, 內使用了ngMessages指令進行表單驗證,可參考
ngMessages。此兩個html檔,index.html,templates/activities.html與其他.js檔完整內容
放置於Gist,請自行參考。
沒有留言:
張貼留言