Hi,
I am trying to implement Login and Sign up functionality with username and password using couchbaseLite + ionic. Can you please Guide me on this topic.
I’m also interested in this option, since at the moment I only managed to login with Ionic/Couchbase using Facebook.
can you share the code of login with Ionic/Couchbase using Facebook.
This is the config code, then you can use Facebook Connect Plugin (https://github.com/Wizcorp/phonegap-facebook-plugin) for the connection with FB.
At the startup of the application you have the create DB function with config.startDB(), then when you execute config.login() it will start the login/replication process.
angular.module("Config", [])
.factory("$config", ["$q", "$http", "$rootScope", "$state", "FBService","$ionicLoading","$cordovaToast",function($q, $http, $rootScope, $state,FBService,$ionicLoading,$cordovaToast) {
/*
* Construct a new Login object
*
* @return promise
*/
var config = function() {
this.debug = true
this.stringify = false
this.databaseName = "...";
this.designDocName = "...";
this.REMOTE_SERVER = "http://...";
this.REMOTE_DB = "...";
this.REMOTE_URL = this.REMOTE_SERVER+"/"+this.REMOTE_DB;
this.user = null
this.checkConnection = function() {
var _this = this
var networkState = navigator.connection.type;
networkState = networkState.toLowerCase()
/*
var states = {};
states[Connection.UNKNOWN] = 'Unknown connection';
states[Connection.ETHERNET] = 'Ethernet connection';
states[Connection.WIFI] = 'WiFi connection';
states[Connection.CELL_2G] = 'Cell 2G connection';
states[Connection.CELL_3G] = 'Cell 3G connection';
states[Connection.CELL_4G] = 'Cell 4G connection';
states[Connection.CELL] = 'Cell generic connection';
states[Connection.NONE] = 'No network connection';*/
if (networkState.indexOf("unknown") != -1 || networkState.indexOf("none") != -1) {
$rootScope.isOnline=false
$rootScope.$broadcast("offline");
return false
} else {
$rootScope.isOnline=true
$rootScope.$broadcast("online");
return true
}
}
this.diveplanViews =
{
...
}
};
config.prototype = {
/*
* @param
* @return promise
*/
startDB: function(fbLogin) {
var _this = this
// check if database is existing
divePlanDatabase.getDesignDocument(_this.designDocName).then(function(ok) {
//database exists
log("database existing",divePlanDatabase)
divePlanDatabase.listen();
//update design document if changeda
divePlanDatabase.updateDesignDocument(_this.designDocName, _this.diveplanViews)
divePlanDatabase.getLocalDocument("user").then(function(user) {
_this.user = user
if (user.guest) {
_this.guestLogin()
} else {
_this.login()
}
},function(err) {
if (fbLogin) {
_this.login()
} else {
$state.go('login')
}
})
}, function(error) {
// no database exisiting
divePlanDatabase.createDatabase().then(function(result) {
divePlanDatabase.createDesignDocument(_this.designDocName, _this.diveplanViews);
log("database created",divePlanDatabase)
divePlanDatabase.listen();
$ionicLoading.hide()
if (fbLogin) {
_this.login()
} else {
$state.go('login')
}
}, function(error) {
// There was an error creating the database
});
});
},
guestLogin: function() {
var _this = this
if (_this.user) {
//existing guest logi
guestReplicate()
} else {
//new guest login
_this.user = {
guest: true
}
divePlanDatabase.createLocalDocument("user",_this.user).then(function(result) {
log("guest_user",result)
guestReplicate()
}, function(error) {
// Document creation
log("guest_user error",error)
});
}
function guestReplicate() {
_this.replicateDatabase().then(function(ok){
log("replicateDatabase guest",ok)
$ionicLoading.hide()
$state.go('app.sites')
}, function(err){
log("replicateDatabase guest err",err)
})
}
},
login: function() {
var _this = this
facebookConnectPlugin.getLoginStatus(function(success){
if(success.status === 'connected'){
var user_data = FBService.getUser()
//update access token
user_data.authResponse.accessToken = success.authResponse.accessToken
FBService.setUser(user_data)
// the user is logged in and has authenticated your app, and response.authResponse supplies
// the user's ID, a valid access token, a signed request, and the time the access token
// and signed request each expire
//log('getLoginStatus success',success.status);
/*
Get user email address from Facebook, and access code to verify on Sync Gateway
*/
//check and ask user email
if (!user_data.profileInfo.email) {
_this.requestEmail("Please insert your email address for registration.")
} else {
_this.userEmailOK()
}
} else {
//if (success.status === 'not_authorized') the user is logged in to Facebook, but has not authenticated your app
//else The person is not logged into Facebook, so we're not sure if they are logged into this app or not.
log('getLoginStatus login',success.status);
$ionicLoading.show({
template: 'Logging in...'
});
//ask the permissions you need. You can learn more about FB permissions here: https://developers.facebook.com/docs/facebook-login/permissions/v2.4
FBService.fbStartLogin()
}
});
},
userEmailOK: function() {
var _this = this
var user_data = FBService.getUser()
_this.user = user_data.profileInfo
_this.user.access_token = user_data.authResponse.accessToken;
_this.user.user_id= _this.user.email
_this.checkUser().then(function(res){
//replicated DB
_this.replicateDatabase().then(function(ok){
log("replicateDatabase",ok)
$ionicLoading.hide()
$state.go('app.sites')
}, function(err){
log("replicateDatabase err",err)
})
}, function(err){
log("checkUser err",err)
})
},
fbLogin: function() {
//reset database and login with facebook after user guest
var _this = this
divePlanDatabase.deleteDatabase().then(function(result) {
_this.user = null
FBService.setUser(null)
_this.startDB(true)
}, function(error) {
// There was an error deleting the database
});
},
logout: function() {
var _this = this
// check if database is existing
facebookConnectPlugin.logout(function(){
//success
divePlanDatabase.deleteDatabase().then(function(result) {
log("delete db",result)
_this.user = null
FBService.setUser(null)
_this.startDB()
}, function(error) {
// There was an error deleting the database
});
},
function(fail){
$ionicLoading.hide();
});
},
requestEmail: function(message) {
var emailCheck=/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i;
var email = prompt(message, "");
if (emailCheck.test(email)) {
var user_data = FBService.getUser()
user_data.profileInfo.email = email
FBService.setUser(user_data)
this.userEmailOK()
} else {
this.requestEmail("Not a valid email address! Please enter a valid email address.")
}
},
checkUser: function() {
var deferred = $q.defer();
var _this = this
//check if user is already registered in the database
divePlanDatabase.getLocalDocument("user").then(function(local_user) {
log("local_user",local_user)
//register token
_this.registerFacebookToken().then(function(ok) {
log("fbtoken res",ok)
deferred.resolve(local_user);
}, function(error) {
// There was an error replicating to the local device
log("registerFacebookToken error",error)
deferred.reject(error);
});
}, function(err){
log("local_user non existing",err)
//create user
divePlanDatabase.createLocalDocument("user",_this.user).then(function(result) {
log("local_user",result,_this.user)
// Document created successfully
//create user profile
_this.registerFacebookToken().then(function(ok) {
log("fbtoken res",ok)
_this.createMyProfile().then(function(profile) {
log("profile created",profile)
deferred.resolve(profile);
}, function(error) {
// There was an error replicating to the local device
log("createMyProfile error",error)
deferred.reject(error);
});
}, function(error) {
// There was an error replicating to the local device
log("registerFacebookToken error",error)
deferred.reject(error);
});
}, function(error) {
// Document creation
log("local_user error",error)
deferred.reject(error);
});
});
return deferred.promise;
},
createMyProfile : function() {
var _this = this
//log("createMyProfile user "+JSON.stringify(config.user))
var profileData = angular.copy(_this.user)
profileData.type = "profile"
profileData.user_id = profileData.email
delete profileData.email
//log("createMyProfile", profileData)
return divePlanDatabase.updateDocument("p:"+profileData.user_id, profileData)
},
registerFacebookToken : function() {
var _this = this
_this.registerData = {
remote_url : _this.REMOTE_URL,
email : _this.user.email,
access_token : _this.user.access_token
}
log("registerFacebookToken",_this.registerData)
return divePlanDatabase.updateFBToken(_this.registerData)
},
replicateDatabase: function() {
var deferred = $q.defer();
var _this = this
//replicate local to remote
var auth = false
if (_this.user && _this.user.email) {
auth = {facebook : {email : _this.user.email}}
}
divePlanDatabase.replicate(_this.databaseName, _this.REMOTE_URL , true, auth).then(function(result1) {
log("replicate local to remote",_this.databaseName,result1)
//replicate remote to local
divePlanDatabase.replicate(_this.REMOTE_URL, _this.databaseName, true, auth).then(function(result2) {
log("replicate remote to local",result2)
if (_this.checkConnection())
_this.showToast("Downloading data from main database...", "short", "bottom")
deferred.resolve(result2);
}, function(error) {
// There was an error replicating to the local device
log("replicate error",error)
deferred.reject(error);
});
}, function(error) {
// There was an error replicating to the Sync Gateway
log("replicate error",error)
deferred.reject(error);
});
return deferred.promise;
},
showToast: function(message, duration, location) {
$cordovaToast.show(message, duration, location).then(function(success) {
//console.log("The toast was shown");
}, function (error) {
log("The toast was not shown due to " + error);
});
}
};
return config;
}]);`
Thank Lucapale, for sharing your code.
Hi Lucapale,
I want to create a view after syncing with database.
I called this below function to create view…
$scope.createview= function() {
var todoViews = {
lists: {
map: function(doc) {
console.log(doc);
if(doc.type== “list”) {
emit(doc._id, {type:doc.type,Name: doc.Name, Email: doc.Email, Company: doc.Company, Phone: doc.Phone, experiance: doc.experiance,
Drone: doc.Drone,Pilot:doc.Pilot,Equipment:doc.Equipment,Location:doc.Location,rev: doc._rev})
}
}.toString()
}
};
todoDatabase.createDesignDocument("_design/todo", todoViews);
todoDatabase.listen();};
And After this i am calling below mentioned function to get value from view that i am creating but it giving an empty result
$scope.getvalue = function(){
todoDatabase.queryView("_design/todo", “lists”).then(function(result) {
if(result.rows !== undefined && result.rows !== null){
alert(“Result is ::”+result);
}else{
alert(“result in local database is undefined or null”);
}
}, function(error) {
// alert("ERROR QUERYING VIEW -> " + error);
});
}
Can you guide me on this?
Hi. I can give you my code that you can apply to your case.
I have created a factory to access Couchbase:
.factory('CouchBase', ['$window',function($window) {
var couchbase = {}
//load sites list
couchbase.refreshSitesView = function() {
var options = {
descending : false
}
return divePlanDatabase.queryView("sites",options)
}
return couchbase;
}
in the config I have defined the views and the divePlanDatabase general variable:
this.diveplanViews =
{
sites : {
map : function(doc, meta)
{
if (doc.type == "site" && doc.name && doc.geography && doc.geography.country) {
emit([doc.geography.country,doc.name],{
name : doc.name,
lat : doc.geography.latitude,
lng : doc.geography.longitude
})
}
}.toString()
}
And finally in the view controller you can call a function that can be refreshed everytime the database receives some update:
function refreshSites() {
CouchBase.refreshSitesView().then(function(sitesList) {
$scope.sites = sitesList.rows;
}
}
refreshSites()
//refresh on database change
$rootScope.$on("couchbase:change:site", function(event) {
refreshSites()
});
$rootScope.$on("couchbase:deleted", function(event) {
refreshSites()
});
This is done using ngCouchbaseLite with a little tweak that sends a:
$rootScope.$broadcast("couchbase:change:" + doc.type);
from within the “listen” function.