Group users in Firebase RTDB - qt

I am using Firebase in my Qt app for Authentication and Realtime Database features, when users register they need to be assigned into the selected groups then departments of that group. Each group will have admin(s), who can access the entire group database, but the users will only access their department.
Below is my code for my registration form which assigns certain user values, how would i go about grouping the users in the database with additional options on my registration form?
onUserRegistered: {
indicator.stopAnimating()
console.debug("User login " + success + " - " + message)
if(success) {
loginDialog.title = "Success!"
firebaseDb.setUserValue("Firstname", firstname.text)
firebaseDb.setUserValue("Surname", surname.text)
} else {
loginDialog.title = "An Issue occured!"
}
loginDialog.text = message
loginbutton.visible = true
registerCheckbox.visible = true
loginDialog.open()
}
I would like my database to be laid out as below, if this is appropriate for use? Multiple location groups with users within to access thier part of the database!
{
"groups" : {
"Colchester" : {
},
"Ipswich" : {
},
"CanaryWharf" : {
"Departments" : {
"Admin" : {
"members" : {
"user1" : true
}
},
"Assistant" : {
"members" : {
"user2" : true
}
},
"Reception" : {
"members" : {
"user3" : true,
"user1" : true
}
},
"Stylist" : {
"members" : {
"user4" : true
}
},
"Technician" : {
"members" : {
"user5" : true
}
}
}
}
}

Without access to the Firebase Cloud Firestore collections, detailed in the link;
Google Firebase Cloud Firestore Collections
I achieved the result of grouping of my users by the following code, if anyone still wants to add an improved version please do, but for now this works as intended for me:
App {
id: app
property var groupName
property var subGroupName
//these values are assigned when my user logs in from user values
//set in firebase on registration
firebaseDb.getUserValue("group", {
}, function(success, key, value) {
if(success){
groupName = value
console.log("GROUPNAME LOG: " + groupName)}})
}
//I then use these values across my app when storing data in the database
//an example of which is an AppButton elsewhere in my app
AppButton {
id: saveButton
onClicked: {
userData = ({"date": calendar.selectedDate, "name": userName +" "+ userSurname, "details": dayCycle.text, "status": "pending"})
var time = new Date().getTime()
firebaseDb.setValue("groups" + "/" + groupName + "/" + subGroupName + "/" + time, userData)
}
}

Related

MSAL redirecturi for vue3 app with vue router hash mode resolving as my_host/#/code=....rest-of-aad-response

Since fragments are not supported in aad redirect_uris, I made the redirect_uri my homepage with navigateToLoginRequestUrl. After sign-in, instead of being directed to my_host/#code=...reest-of-aad-response, vue router seems to jump in and hashbang the url to my_host/#/code=...rest-of-aad-response which 404s.
Do I need to switch to history or is there something I am missing and a way to accomplish this in hash mode? Should I use loginPopup instead of loginRedirect?
msal service
import * as msal from '#azure/msal-browser';
export default class msalAuth {
constructor(config) {
const msalConfig = {
auth : {
clientId : config.clientId,
authority : config.authority,
redirectUri : config.redirectUrl,
navigateToLoginRequestUrl : true
},
cache : {
cacheLocation : 'localStorage',
storeAuthStateInCookie : true
},
system: {
loggerOptions: {
loggerCallback: (level, message, containsPii) => {
if (containsPii) {
return;
}
switch (level) {
case msal.LogLevel.Error:
console.error(message);
return;
case msal.LogLevel.Info:
console.info(message);
return;
case msal.LogLevel.Verbose:
console.debug(message);
return;
case msal.LogLevel.Warning:
console.warn(message);
return;
}
}
}
}
};
let graphScopes = Object.values(config.graphScopes);
let state = window.location.origin;
let postLogoutRedirectUri = config.logoutRedirect;
let graphUrl = config.graphUrl;
this.msalAppConfig = {
graphScopes,
state,
loginRequest: {
scopes: graphScopes,
state
},
postLogoutRedirectUri,
graphUrl
};
this.app = new msal.PublicClientApplication(msalConfig);
}
login() {
this.app.loginRedirect(this.msalAppConfig.loginRequest);
}
logout(userName) {
const logoutRequest = {
account : this.app.getAccountByUsername(userName),
postLogoutRedirectUri : this.msalAppConfig.postLogoutRedirectUri,
mainWindowRedirectUri : this.msalAppConfig.postLogoutRedirectUri
}
this.app.logoutPopup(logoutRequest);
}
async handleRedirectPromise() {
return await this.app.handleRedirectPromise();
}
processRedirectResponse(response) {
let accountId = '';
console.log('processRedirectResponse', response);
if (response) {
accountId = response.account.homeAccountId;
// Display signed-in user content, call API, etc.
} else {
// In case multiple accounts exist, you can select
const currentAccounts = this.app.getAllAccounts();
if (currentAccounts.length === 0) {
// no accounts signed-in, attempt to sign a user in
//this.loginRedirect();
} else if (currentAccounts.length > 1) {
// Add choose account code here
accountId = currentAccounts[0].homeAccountId;
} else if (currentAccounts.length === 1) {
accountId = currentAccounts[0].homeAccountId;
}
}
return accountId;
}
}
redirectUri is http://localhost:8080 as am still developing
Thanks!
I switched vue router mode to history instead of hash, and it resolved the issue for anyone coming here with the same problem
Edit: for anyone coming to this and being dismayed that I switched to history mode and are using Azure static webapps. I added a staticwebapp.config.json to my public folder (or anywhere which will place it in root of output when built). This file lets you provide some configuration to the static web app. You can read about it in the ms docs but mine was the following which you can edit / build off of
{
"routes": [
{
"route": "/*",
"serve": "/index.html",
"statusCode": 200
}
],
"navigationFallback": {
"rewrite": "/index.html",
"exclude": [
"/icons/*.{png,jpg,gif,webp,svg}",
"/css/*",
"favicon.ico",
"/fonts/*"
]
},
"mimeTypes": {
".woff2": "font/woff2",
".woff": "font/woff",
".json": "text/json",
".ico": "image/x-icon"
}
}

firebase realtime database query

I have the following structure:
{
"Campaign" : {
"-KtghP_NMOFrjN_RrI6f" : {
"Projects" : {
"-Kz5g4j8dKgxtqQsPfN1" : {
"createByName" : "Michal",
"profileId" : "-KtlDwI3Bq4Bi7R23kya"
},
"-KzGCaLblTxzu4Nje15Z" : {
"createByName" : "Roy",
"profileId" : "-Kxx_egu9h4GOrxqM1nB"
}
}
},
"-KyjE0HPNSg27Kpurq8l" : {
"Projects" : {
"-KzBUZBsI947HckV296O" : {
"createByName" : "Roy",
"profileId" : "-Kxx_egu9h4GOrxqM1nB"
}
}
}
},
"UserProfile" : {
"-Kxx_egu9h4GOrxqM1nB" : {
"MyProjects" : {
"-KzGC3Yn4bAAorcwDhUT" : {
"CampaignId" : "-KyjE0HPNSg27Kpurq8l",
"projectId" : "-KzBUZBsI947HckV296O"
},
"-KzGCaeTqMm_g1Jq6u6i" : {
"CampaignId" : "-KtghP_NMOFrjN_RrI6f",
"projectId" : "-KzGCaLblTxzu4Nje15Z"
}
},
"firstName" : "roy"
}
}
}
i have the profile id.
I need to get the different projects of the user, under the different Campaigns..
I want to get the list of MyProjects by the userid, and then iterate (with the keys i got from MyProjects) over the campaigns -(key)-> projects -(key)-> profileId and compare them...
(hope it was clear enough...)
HOW DO I DO THAT?
Ok, after some more research, i went a different way.
it seems like i don't need "MyProjects".
var userId = "-Kxx_egu9h4GOrxqM1nB";
var campaignRef = this.db.app.database().ref('Campaign'); //root
var projectsRef = campaignRef.child('Projects');
projectsRef.orderByChild('profileId').equalTo(userId).once("value", (snap) => {
console.log(snap.val());
});
but still i get NULL..
(tried "child_added" and .on in different combinations - nothing...)
After logging in, and pulling the Campaign object, you can try running the following code:
// user is an object from the userProfile. You can also just directly access the object and get what you need. Really, it's up to you. I'll assume that you also stored the user ID (uid) here too.
var user = {},
campaigns = {},
uid = {},
myProjects = [];
function getProjects() {
for (var i in campaigns) {
for (var k in campaigns[i]) {
// Make sure that the profileId of the project and the uid match, then push object into myProjects array
campaigns[i][k].profileId === uid ? myProjects.push(campaigns[i][k]) : 'nada';
}
}
}
In the myProjects array will you find your projects.

Looping through firebase unique keys and adding data to each

I have firebase database in this form.
"items":{
"-Jp9VLYBwENfNVLKYyCG" : {
"-Jp9VMKkTUggcMrUCO8S" : {
"author" : "facebook:#########",
"created" : 1431474107638,
},
"-Jp9VobJP0qbSbbEdyW0" : {
"author" : "facebook:#########",
"created" : 1431474227548
}
},
"-JpEbifKeRj-_H7TWhQ2" : {
"-JpEbrnT6SFRFc6U_HWX" : {
"author" : "facebook:#########",
"created" : 1431559961683
},
"-JpEby5mZuQMsU-9YCpk" : {
"author" : "facebook:##########",
"created" : 1431559987495
}
}
}
I want to add the following object to each $id containing author and created key-value pairs.
upVote: {
active: true,
total: 0
},
downVote: {
active: true,
total: 0
}
I am first trying to fetch the values using DataSnapshot. But it doesn't print the keys in console. What is wrong here?
var ref = new Firebase(FBURL + "/items");
ref.once("value", function(snapshot) {
console.log("snapshot key: " + snapshot.key());
snapshot.forEach(function(childSnapshot){
var key = childSnapshot.key();
var val = childSnapshot.val();
console.log("child snapshot key: " + key);
childSnapshot.forEach(function(deepSnap){
console.log("deep shot key: " + deepSnap.key());
});
});
});
RESOLVED The problem was that I had some security rules set up with read and write permissions. Therefore wasn't allowing me to read the element from the user scope that I was calling the script. It was one gotcha like problems.
After this step, it was easy to update the database with values:
var deepRef = ref.child(key).child(deepSnap.key());
deepRef.update({upVote: {
active: true,
total: 0
},downVote: {
active: true,
total: 0
}});

Fetching denormalized data with firebase, angularFire

I'm trying to fetch all flowers data which belongs to a certain user, in this case simplelogin:69.
I'm starting with fetching all flower keys from the user, like this:
/users/simplelogin:69/flowers/
var ref = new Firebase("https://URL.firebaseio.com/users/"+uid+"/flowers");
var sync = $firebase(ref);
Now im stuck figuring out a clean way to fetch all the flower data by looping thrue every flower key from simplelogin:69 without looping thrue EVERY key in /flowers/ (in example below i only have three flower keys but in production i might have 10k).
I tried FirebaseIndex and firebase-util, but can't get it to work properly. Do anyone have any tips or anything? I've read previous posts here on stack but most seems out of date or not really suited for what im going for. Would really appriciate anything that can be solved with AngularFire.
Kind regards,
Elias
{
"flowers" : {
"-JiU57sFAfQwYtIq-LCl" : {
"image" : "test",
"name" : "test",
"type" : "Roses",
"uid" : "simplelogin:69"
},
"-JiU9-3ajlnFLpyUmBvL" : {
"image" : "dasdasd",
"name" : "sadasdas",
"type" : "Roses",
"uid" : "simplelogin:69"
},
"-JiUF-mioK3jQCYy6ZiG" : {
"image" : "ss",
"name" : "ss",
"type" : "Lilies",
"uid" : "simplelogin:69"
}
},
"users" : {
"simplelogin:69" : {
"flowers" : {
"-JiU57sFAfQwYtIq-LCl" : true,
"-JiU9-3ajlnFLpyUmBvL" : true,
"-JiUF-mioK3jQCYy6ZiG" : true
}
},
"simplelogin:70" : {
},
"simplelogin:71" : {
}
}
}
Got it to work now, thanks to #Kato 's answer on thread:
Firebase data normalized. How should I fetch a collection based on this structure? (tried it before creating this thread but didnt get it to work, so made som small changes and now it works).
Posting the solution for anyone stubling upon the same situation:
$scope.flowers = {};
var flowerRef = new Firebase('https://URL.firebaseio.com/flowers/');
var keyRef = new Firebase('https://URL.firebaseio.com/users/'+checkAuth.auth.uid+'/flowers');
keyRef.on('child_added', function(snap) {
var flowerId = snap.key();
flowerRef.child(flowerId).on('value', function(snap) {
$timeout(function() {
if( snap.val() === null ) {
delete $scope.flowers[flowerId];
}
else {
$scope.flowers[flowerId] = snap.val();
}
});
});
});
keyRef.on('child_removed', function(snap) {
var flowerId = snap.key();
$timeout(function(snap) {
delete $scope.flowers[flowerId];
});
});
This really is a tough issue with Firebase. If you implement a custom factory object for the user's flower list, you could dynamically request new flower data as the list changes.

Meteor - New user created after validating login is not recognized

I have a login validation function setup to check if a new user registered outside of the app. That users info is stored in a temporary collection. If the users info validates I want to be able to use Accounts.createUser on the Client side, but I can't figure out how to do that. The documentation says that "registered validate login callbacks are called with a single argument, the attempt info object", but I can't find any examples of how to do this.
environment.js
Accounts.config({
forbidClientAccountCreation : true
});
server.js
Accounts.validateLoginAttempt(function(info){
if (!info.allowed)
{
var userEmail = info.methodArguments[0].user['email'].toLowerCase();
var userPass = info.methodArguments[0].password['digest'];
// check if this is a temp user
if (tmpUsers.find({'email': userEmail}).count() == 1)
{
var user = tmpUsers.findOne({'email': userEmail})
// check for active
if (user.active == "Yes")
{
// check password
if (userPass == user.password)
{
var accountId = Accounts.createUser({
'password': userPass,
'email': userEmail,
'profile': ({'acctType': user.type})
});
return true;
} else {
throw new Meteor.Error(403, "Incorrect password.");
return false;
}
} else {
throw new Meteor.Error(403, "Your account has yet to be activated.);
return false;
}
} else {
throw new Meteor.Error(403, "Can not find user " + userEmail);
return false;
}
} else {
return true;
}
});
Update:
I ended up putting the Account.userCreate part on the server side and now it does get the user created but when I try to login I get "Email already exists." So it appears as though it doesn't expect the login to be successful and tries to create the user again.
{ // This user works
"_id" : "hCBLo3AJJwmtR6s62",
"createdAt" : ISODate("2014-12-26T20:27:58.44Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$pxlEy.JFomgwQwV2cpm72.TBG4.llP98BF9ssTCptC4WsekLzJO9G"
},
"resume" : {
"loginTokens" : []
}
},
"emails" : [{
"address" : "demo#demo.com",
"verified" : false
}]
}
{ // This one does not
"_id" : "w6SGuqJJPs5LoCTTj",
"createdAt" : ISODate("2015-01-10T20:54:16.032Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$VJFj0UOrQiLs7djfGWAeMeruDactDFrl1nlEsXh/r5Z/895C5ubAW"
}
},
"emails" : [{
"address" : "demo2#demo.com",
"verified" : false
}],
"profile" : {
"acctType" : null
}
}
Would something like this work for you?
var options = {
username: "username", // you'll need to fill this in
email: userEmail,
password: userPass,
profile: {name: "name"} // you'll need to fill this in
};
Accounts.createUser(options, function (error) {
if (error) {
console.log("Cannot create user");
}
});

Resources