Saving Attributes on a User Fetched from a Query (I.E. Not on the Currentuser)

How do I retrieve information from the document of the current logged in user of my app?

I would suggest you to create a field with the uid of your users from firebase auth in your document or the document-id itself. In this repo under usersEndpoint.js take a look ath the exports.createUser.

...
usersCollection.doc(userRecord.uid).set({
uid: userRecord.uid,
firstname: user.firstname,
lastname: user.lastname,
dateOfBirth: user.dateOfBirth,
sex: user.sex,
city: user.city,
activities: user.activities,
offers: user.offers
})
...

With this approach you can change your code like this:

func loadUserData() {
...
let uid= Auth.auth().currentUser?.uid

self.db.collection("users").get(uid) { (snapshot, error) in
if let err = error {
print("Error: \(err)")
} else {
...
}
}
}

That way it should be much easier for you to get the right document of your users.

Sorry, that my code is not in swift. It's been a while that I coded in swift. But I hope that helps.

EDIT

Alternatively you could do is to use a query like described in the docs of Firestore. It could look like this:

...
guard let email = Auth.auth().currentUser?.email else { return }
emailString = "\(email)"

self.db.collection("users").whereField("email", isEqualTo: emailString)
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
print("\(document.documentID) => \(document.data())")
}
}
}
...

Fetch the data from firestore in the User Profile

Ultimately your problem comes down to two things: How you manage the current user and it's linked variables and how you manage the ID of the user who's profile you are viewing. I'll cover the fundamentals of each issue, but it'll be up to you to fully adapt them to your code.

Signed-in User State

When your page is first loaded, firebase.auth().currentUser is in an intermediate state and will return null. In addition, if a user were to logout, your component will not update to reflect that causing your resource listeners to throw errors depending on your security rules. To correctly listen for the current user, you should use an effect hook with firebase.auth().onAuthStateChanged(). This listener reports when a user logs in, when they log out, when their session is validated and when the user is switched.

This can be done using these hooks:

const [user, setUser] = useState(undefined);
// type of user: firebase.User | null | undefined
// - `undefined` means the user state is still being checked (e.g. show a loading icon)
// - `null` means not signed in
// - `firebase.User` means a user is signed in and has been validated

// NOTE: onAuthStateChanged conveniently returns it's own cleanup function
// NOTE: Make sure to pass in `[]`, otherwise `user` will get updated in an infinite loop
useEffect(() => firebase.auth().onAuthStateChanged(setUser), []);

You can also listen for errors:

const [user, setUser] = useState(undefined);
// type of user: firebase.User | null | undefined
// - `undefined` means the user state is still being checked (e.g. show a loading icon)
// - `null` means not signed in
// - `firebase.User` means a user is signed in and has been validated

useEffect(() => {
return firebase.auth() // return listener's cleanup function
.onAuthStateChanged({
next: setUser,
error(err) {
// something unexpected went wrong with Firebase Auth
console.error('onAuthStateChanged Error:', err);
setUser(null); // treat as signed out for safety
}
});
}, []); // make sure to use `[]` here, otherwise `user` will be updated in an infinite loop

Obtaining the user ID to be viewed

Now that you can guarantee that user works correctly, you can get the user ID of the profile to be viewed. Based on your existing code, this can either be given as a parameter or uses the current user ID. However, we need to be able to handle the following situations:

















































ID paramUsertype: viewedProfileIdAction
providedsigned instringaccess given profile's data
providedsigned outstringaccess given profile's data (if public) OR
navigate to login page (if auth required)
providedinitializingstringaccess given profile's data (if public) OR
show loading icon (if auth required)
omittedsigned instringaccess own user's profile data
omittedsigned outnullnavigate to login page
omittedinitializingundefinedshow loading icon

How to get the currently logged in user's user id in Django?

First make sure you have SessionMiddleware and AuthenticationMiddleware middlewares added to your MIDDLEWARE_CLASSES setting.

The current user is in request object, you can get it by:

def sample_view(request):
current_user = request.user
print current_user.id

request.user will give you a User object representing the currently logged-in user. If a user isn't currently logged in, request.user will be set to an instance of AnonymousUser. You can tell them apart with the field is_authenticated, like so:

if request.user.is_authenticated:
# Do something for authenticated users.
else:
# Do something for anonymous users.

Problem with getting data from firestore and display it on the screen

The error message indicates that the value passed to the doc() method is an empty string.

The problem most probably comes from the fact that, at the moment you call this method, this.authservice.currentUserId is null. currentUserId is probably null because the authservice object has not finished initializing: see the doc for more details.

You should either use the onAuthStateChanged observer or check that this.authservice.currentUserId is not null.

How do you get the user db details related to an authUser in Firestore?

If anyone else is similarly stuck, I found the solution here: Firebase & React: CollectionReference.doc() argument type

It doesn't work on page refresh (still throws an error that the uid is null) but react hooks to useEffect should replace the componentDidMount function with a combination of Mount and Update. Im trying that next.

Fetch users data only if it matches current users data

First. Don't use arrays. They are extremely situational and there are usually other, better ways to store data.

Answer to first question:

Given a Firebase structure where you want to store the user data and some attributes, here's one structure that will do it

users
uid_0
name: "Frank"
attribs
fav_food: "Pizza"
fav_car: "Camaro"

and to read the above node

usersRef.observe(.value, with: { snapshot in

for child in (snapshot?.children)! {
let snap = child as! FDataSnapshot
let dict = snap.value as! [String: AnyObject]

let name = dict["name"] //it's Frank

let attribs = dict["attribs"] as! [String: AnyObject]
let food = attribs["fav_food"] //pizza
let car = attribs["fav_car"] //camaro
}
}

Answer to second question:

The second problem is that I don't know how to fetch a new user and
add it to my tableView IF ONLY that user has the same attributes as
the current user. Here is my current code that fetches ALL users,
without any filtering:

So what you are asking is how to find other users that have the same attribs as the current user.

Firebase doesn't have the ability to perform comparisons upon multiple children (i.e. there is no: where food == pizza and car = Camaro).

One option is to store the attribs as a string

pizza_Camaro

then you can easily check to see if the attribs' strings are equal.

Another option is a recursive query. Here's the idea at a 10k foot level

query for all users where fav_food is pizza
query from that set of users where fav_car is Camaro
query from that set of users where....

You get the idea. It's not super efficient but for small datasets it can work.

Spring Security - get current user fields from database

The JDBC service you defined in the Spring Security configuration will only fetch username, password and enabled status using the users-by-username-query query and username's authorities using the authorities-by-username-query query. This means that any extra attributes will not be mapped to the user principal object which will be created to populate the security context.

One way to get all information of your user is to create custom implementation of UserDetailsService which will be able to retrieve user data including all of its custom attributes. Here is an example of this approach (it assumes that you are using JPA/Hibernate for your data layer):

Entity

@Entity
@Table(name="users")
public class User implements UserDetails {
private BigDecimal balance;
// Other properties omitted ...
// Getters and setters omitted ...
// Implementation of UserDetails methods omitted ...
}

UserService

Service responsible for loading the user information. Note that in real world you should probably have separate DAO querying users, program against interfaces, etc. This example is deliberately kept as short as possible.

@Service
public class UserService implements UserDetailsService {
@Autowired
private SessionFactory sessionFactory;

@Override
public User loadUserByUsername(String username) throws UsernameNotFoundException {
Query query = sessionFactory.getCurrentSession().createQuery("FROM User u WHERE u.username = :username");
query.setParameter("username", username);
User user = (User) query.uniqueResult();
if (user == null) {
throw new UsernameNotFoundException("User with username '" + username + "' does not exist.");
}
return user;
}
}

Configuration

Create AuthenticationProvider bean and supply your custom user service as its property.

<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userService" />
<!-- Other required properties ... -->
</bean>

Controller

You can access the current user and its properties in the controller using:

User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
BigDecimal balance = user.getBalance();

As a final remark, please note that this is not 100% working copy and paste solution to your problem, rather a demonstration of the approach you can take to achive the desired result. I recommend looking through the documentation of core classes/interfaces such as AuthenticationProvider, UserDetailsService, UserDetails, and Spring Security guides for more details.

Query to retrieve a BOOL from Parse DB for the current logged in user, which will determine what segue to go to

You can just retrieve the profileCompleted value from the current user -

PFUser *currentUser = [PFUser currentUser];
BOOL profileCompleted= [[currentUser[@"profileCompleted"] boolValue];

if (profileCompleted) {
...
}

if the data held in PFUser may be stale (e.g. profile was completed somewhere else) then you will need to fetch the user -

PFUser *currentUser = [PFUser currentUser];
if (currentUser != nil) {
[currentUser fetchInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (error == nil) {
BOOL profileCompleted= [[object[@"profileCompleted"] boolValue];

if (profileCompleted) {
...
}
}
}];
}

Parse.com PFUser Retrieve/Update Property of Array Type

Here is the original code, with the correct answer inside the { callback code block }. See the comments in there. By the way, this only adds the actual "username" of the PFUser to the friendsList Array. If you want to you can modify the code to save the actual PFUser in the array.

PFQuery *friendQuery = [PFUser query];
[friendQuery whereKey:@"username" equalTo:userNameToAdd];
[friendQuery getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error)
{
/* This is how you add 'userNameToAdd' to the Array called friendsList that
* belongs to the special parse class called User (PFUser type): */

// This is your current user
PFUser *currentUser = [PFUser currentUser];

// Adds object to friendList array
[currentUser addObject:userNameToAdd forKey:@"friendsList"];

// Saves the changes on the Parse server. This is necessary to update the actual Parse server. If you don't "save" then the changes will be lost
[[PFUser currentUser] saveInBackground];

}



Related Topics



Leave a reply



Submit