I'm currently trying to add new users to Firebase via the AngularFire $set() method. I'm creating new users via the $createUser method from AngularFire. My code looks like this:
$scope.createUser = function() {
$scope.auth.$createUser('dolly#gmail.com', 'password').then(function(user, err) {
if (err) {
console.log('ERROR: ' + err);
} else {
sync.$set('users', user);
}
});
}
This is a creating new user and placing the new user object inside of users:{..}, however, it is also adding an additional user child object thats just duplicate data -- this is what the code is adding to Firebase:
{
"users": {
"email": "dolly#gmail.com",
"id": "11",
"isTemporaryPassword": false,
"md5_hash": "xxxxxxxxxxxxxxx",
"provider": "password",
"sessionKey": "xxxxxxxxxxxxx",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MDc5NDQ2NDYsInYiOjAsImQiOnsicHJvdmlkZXIiOiJwYXNzd29yZCIsImlkIjoiMTEiLCJ1aWQiOiJzaW1wbGVsb2dpbjoxMSIsImVtYWlsIjoiZG9sbHlAZ21haWwuY29tIiwibWQ1X2hhc2giOiIzsdrggfeedsaadrfcDc0ZDRhMTU5NTk2NzI1NzFmMDk2ZTZlNyIsImlzVGVtcG9yYXJ5UGFzc3dvcmQiOmZhbHNlLCJzZXNzaW9uS2V5IjoiM2MwMDNjODkxMDEzOWE5MjhlZTZjNWI1NjU5ZTRiZjMifSwiaWF0IjoxNDA3ODU4MjQ2fQ.p7-9GDtaNpBn1ICTLIUSwlPytaUGi-jyBgcO-LKHUys",
"uid": "simplelogin:11",
"user": {
"email": "dolly#gmail.com",
"id": "11",
"isTemporaryPassword": false,
"md5_hash": "xxxxxxxxxxxxxxx",
"provider": "dfrggrssxxxxxxx",
"sessionKey": "xxxxxxxxxxxxxxx",
"uid": "simplelogin:11"
}
}
I ideally want my users object to look like the example in firebase, except with each user key to be whatever is inside user.uid
users: {
user1: {
name: "Alice"
},
user2: {
name: "Bob"
}
}
Where each new user will be added to the users: {...} key without the duplicate user child tacked on?
If you create a reference to users/ and then call $set on that path, then whatever data you include will replace anything at that path. This is AngularFire 101. You should begin by reading at least that section if not the entire guide.
Choose the path you want to set data at when creating your sync object.
var ref = new Firebase('.../users/'+user.uid);
var sync = $firebase(ref);
sync.$set({ email: user.email, provider: user.provider });
Or, better yet, just set it on the reference since you aren't utilizing this for client-side bindings.
var ref = new Firebase('.../users/'+user.uid);
ref.set({ email: user.email, provider: user.provider });
Creating profiles is explained in the Firebase docs and covered in the AngularFire-Seed repo's createProfile service, nearly verbatim to your example.
Related
I am trying to extend what is returned in the StravaProvider profile() in nextAuth
pages/api/auth/[...nextauth].js
export default NextAuth({
providers: [
StravaProvider({
clientId: process.env.STRAVA_CLIENT_ID,
clientSecret: process.env.STRAVA_CLIENT_SECRET,
profile(profile) {
// LOGS FINE IN CONSOLE
console.log("profile", profile);
return {
id: profile.id,
image: profile.profile,
name: `${profile.firstname} ${profile.lastname}`,
// THE FOLLOWING DOES NOT RETURN
profile: profile,
};
},
}),
],
How do I expose the full profile object?. It's only returning the image and name.
In my console log - within my StravaProvider of profile - I can see the whole object, but can't seem to return it?
If I assign profile to the name key this works. I seem to be limited with the keys I can add?
StravaProvider{...
profile(profile) {
return {
// THE FOLLOWING WORKS
name: profile,
};
},
The returned session object from my initial example and how I am accessing it is:
const { data: session } = useSession();
console.log(session);
{
"user": {
"name": "JOE BLOGGS",
"image": "https://dgalywyr863hv.cloudfront.net/pictures/athletes/2909982/3009569/1/large.jpg"
},
"expires": "2023-02-03T13:39:01.521Z"
}
I realise I can use a callback and modify the session, but I need the entire profile there in the first place from the Provider to do that.
Repo - https://github.com/webknit/NextAuth/
I'm trying to upload 2 functions to Firebase Cloud functions but it always ends up giving an error saying:
"Error: Functions did not deploy properly."
When I go to the Firebase Cloud Functions Logs this is the only Info I get:
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","status":{"code":3,"message":"Function failed on loading user code. This is likely due to a bug in the user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging. Please visit https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting documentation."},"authenticationinfo":{"principalemail":"xxxxxxx#gmail.com"},"servicename":"cloudfunctions.googleapis.com","methodname":"google.cloud.functions.v1.cloudfunctionsservice.updatefunction","resourceName":"projects/xxxxxxxxx-ad581/locations/us-central1/functions/newUserSignup"}
Now in here it says there is a bug on my Code but I can't seem to find it:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const randomstring = require("randomstring");
admin.initializeApp();
exports.newUserSignup = functions.auth.user().onCreate((user) => {
const provid = user.providerData[0].providerId;
switch (provid) {
case "facebook.com": {
let username;
const tokens = user.displayName.split(" ");
const nameLength = tokens.length;
if (nameLength > 1) {
username = tokens[0] + randomstring.generate(12) + tokens[1];
} else {
username = tokens[0] + randomstring.generate(17);
}
return admin.firestore().collection("users").doc(user.uid).set({
"username": username,
"email": user.email,
"image_url": user.photoURL,
"name": user.displayName,
});
}
case "google.com": {
let username;
const tokens = user.displayName.split(" ");
const nameLength = tokens.length;
if (nameLength > 1) {
username = tokens[0] + randomstring.generate(12) + tokens[1];
} else {
username = tokens[0] + randomstring.generate(17);
}
return admin.firestore().collection("users").doc(user.uid).set({
"username": username,
"email": user.email,
"image_url": user.photoURL,
"name": user.displayName,
});
}
case "apple.com": {
return admin.firestore().collection("users").doc(user.uid).set({
"username": null,
"email": user.email,
"image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/647px-Apple_logo_black.svg.png",
"name": null,
});
}
case "password": {
return admin.firestore().collection("users").doc(user.uid).set({
"username": null,
"email": user.email,
"image_url": null,
"name": null,
});
}
default: {
return;
}
}
});
exports.userDeleted = functions.auth.user().onDelete((user) => {
const doc = admin.firestore().collection("users").doc(user.uid);
return doc.delete();
});
Basically what I'm trying to do is that with the first Function newUserSignup is that when a new user access it gets the providerId which I save to the variable provid and then do a switch where if facebook.com is the provider has some logic, or changes the logic depending on the provider.
On the second Function userDeleted I only want to delete the user entry from the the Firestore when the user deleted.
Additional Information
The part of Collection with Double Quotes was requested by ESLint, the randomstring is from a package call RandomString on NPM https://www.npmjs.com/package/randomstring this is to generate a random hash to my usernames. Also the Whole project is already Firebase Init so it has the .firebaserc for the connection.
Any Ideas what the Bug might be?
Kind Regards
I finally found out what the problem is:
Inside the project, I had 2 node modules in the folder, one outside and one inside the Functions Folder, and I use a node module (RandomString), in the functions, so I needed to add the npm install inside the Functions folder.
Sorry for the question Guys.
Kind Regards.
I'm trying to add security rules to a new Firestore project I'm working on. I have a collection named users that has all my user data in it in this format in my Firestore database:
var users = {
"userId": {
friend_requests: [],
friends: [
/users/friendId1,
/users/friendId2
],
name: "User One",
username: "user1"
},
"friendId1": {
friend_requests: [],
friends: [
/users/userId
],
name: "User Two",
username: "user2"
},
"friendId2": {
friend_requests: [],
friends: [
/users/userId
],
name: "User Three",
username: "user3"
},
"lonelyUser": {
friend_requests: [],
friends: [],
name: "Lonely User",
username: "lonely_user"
}
}
My Firestore rules are this, verbatim:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
match /users/{userId} {
allow read: if isOwner(userId) || isFriendOf(userId);
}
}
function isOwner(userId) {
return userId == currentUser().uid;
}
function isFriendOf(userId) {
return getUserPath(userId) in getUserData().friends;
}
function currentUser() {
return request.auth;
}
function getUserData() {
return get(getUserPath(currentUser().uid)).data;
}
function getUserPath(userId) {
return /databases/$(database)/documents/users/$(userId);
}
}
The keys in the map I outlined above are Firebase user ids in my actual db, so when logged in as user "userId" I'd expect to be able to read the user document for both "friendId1" and "friendId2" users.
The problem I'm having is that isFriendOf is returning false. I've tried a few variants of wrapping the comparison data in a get call and passing in other values like id and data off the resource it returns.
I've also tried wrapping the getUserPath call in isFriendOf in a get and then using the __name__ property of the document as the comparison value as well. No luck there either.
Any help would be greatly appreciated.
Edit: Including a screenshot of the actual documents for clarification.
Screenshot of Firebase Documents
Edit 2: I've made a clean firebase project with only the information in these new screenshots in it. I'm including screenshots of Firebase Authentication page, both user entries in the database, as well as a failed simulator run as one user trying to get the document of the other user.
Authentication Configuration
user1
user2
Simulated Request
I'm trying to add accountStatus to the users I create when I first run the application however it keeps crashing. accountStatus is not part of user.profile.
Can someone please look at my code and tell me what I'm doing wrong.
Thanks for any help.
Path: server.js
// run at Meteor app startup
Meteor.startup(function(options, user) {
// if users database is empty, seed these values
if(Meteor.users.find().count() < 1) {
// users array
var users = [
{firstName: 'Sam', lastName: 'Smith', email: 'sam#gmail.com', roles: ['is_student']},
];
// user creation
_.each(users, function(userData) {
// return id for use in roles assignment below
var userId = Accounts.createUser({
email: userData.email,
password: 'password',
profile: {
firstName: userData.firstName,
lastName: userData.lastName,
}
});
// verify user email
Meteor.users.update({ _id: userId }, { $set: { 'emails.0.verified': true } });
// add roles to user
Roles.addUsersToRoles(userId, userData.roles);
// add accountStatus and set to true
_.extend(userId, { accountStatus: true });
});
console.log('New users created!');
}
});
Look at this line:
_.extend(userId, { accountStatus: true });
And look at _.extend definition:
Copy all of the properties in the source objects over to the destination object, and return the destination object. It's in-order, so the last source will override properties of the same name in previous arguments.
What this line is supposed to do?
I am creating default users on the server with a Meteor startup function. I want to create a user and also verify his/her email on startup (I'm assuming you can only do this after creating the account).
Here's what I have:
Meteor.startup(function() {
// Creates default accounts if there no user accounts
if(!Meteor.users.find().count()) {
// Set default account details here
var barry = {
username: 'barrydoyle18',
password: '123456',
email: 'myemail#gmail.com',
profile: {
firstName: 'Barry',
lastName: 'Doyle'
},
roles: ['webmaster', 'admin']
};
// Create default account details here
Accounts.createUser(barry);
Meteor.users.update(<user Id goes here>, {$set: {"emails.0.verified": true}});
}
});
As I said, I assume the user has to be created first before setting the the verified flag as true (if this statement is false please show a solution to making the flag true in the creation of the user).
In order to set the email verified flag to be true I know I can update the user after creation using Meteor.users.update(userId, {$set: {"emails.0.verified": true}});.
My problem is, I don't know how to get the userID of my newly created user, how do I do that?
You should be able to access the user id that is returned from the Accounts.createUser() function:
var userId = Accounts.createUser(barry);
Meteor.users.update(userId, {
$set: { "emails.0.verified": true}
});
Alternatively you can access newly created users via the Accounts.onCreateUser() function:
var barry = {
username: 'barrydoyle18',
password: '123456',
email: 'myemail#gmail.com',
profile: {
firstName: 'Barry',
lastName: 'Doyle'
},
isDefault: true, //Add this field to notify the onCreateUser callback that this is default
roles: ['webmaster', 'admin']
};
Accounts.onCreateUser(function(options, user) {
if (user.isDefault) {
Meteor.users.update(user._id, {
$set: { "emails.0.verified": true}
});
}
});