Role-based authentification in android app using Firebase - android

I am developing an android app and using firebase database. It contains authorization and few activities for different roles. If you are entering as "Installer" opens one activity and if as "Contact-Centre" - another, but now it's not important. So I need to check a role of entered pair of email and password. So what I should to do?
Here is my database structure:
Sign in code:
mAuth.signInWithEmailAndPassword(email,pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
Toast.makeText(MainActivity.this,"Аутентификация прошла успешно",Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(),RoleInstallerForm.class));
}
else {
Toast.makeText(MainActivity.this,"Проверьте правильность введённых данных", Toast.LENGTH_SHORT).show();
ProgressBar.setVisibility(View.GONE);
}
}
});

Modify your code to this:
mAuth.signInWithEmailAndPassword(email,pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
Toast.makeText(MainActivity.this,"Àóòåíòèôèêàöèÿ ïðîøëà óñïåøíî",Toast.LENGTH_SHORT).show();
try {
currentUserUID = FirebaseAuth.getInstance().getCurrentUser().getUid();
}catch (Throwable throwable){
throwable.printStackTrace();
}
roleRef = FirebaseDatabase.getInstance().getReference().child("Users").child(currentUserUID).child("Role");
roleRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
try {
String userRole = dataSnapshot.getValue().toString();
//Add if-else here if you need any
//For example:
//I DONT UNDERSTAND RUSSIAN ROLE YOU TYPE
// JUST REPLACE THE ROLE NAMES
if(userRole.equals(leader)){
startActivity(new Intent(MainActivity.this, some-activity.class));
}else{
startActivity(new Intent(MainActivity.this, other-activity.class));
}
}catch (Throwable e){
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), databaseError.toString(), Toast.LENGTH_SHORT).show();
}
});
}
else {
Toast.makeText(MainActivity.this,"Ïðîâåðüòå ïðàâèëüíîñòü ââåä¸ííûõ äàííûõ", Toast.LENGTH_SHORT).show();
ProgressBar.setVisibility(View.GONE);
}
}
});

Related

login different users from different collections on android studio using firebase firestore auth

I have 2 kinds of users for my android app -User and Donor and they are from different collections.
the problem is when I try to use the email and password of a User for the Donor instead of making a Toast saying "cannot log in" the app just crashes. I tried using .addOnFailureListener here but it doesnt work
anyways here's my code.
public class log_in extends AppCompatActivity {
EditText lEmail, lPassword;
Button btnLogIn;
Spinner UserDonor;
FirebaseAuth lFirebaseAuth;
FirebaseFirestore lFirestoreFirebase;
String userID, donorID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activtiy_log_in);
lEmail = findViewById(R.id.etxtEmailLogIn);
lPassword = findViewById(R.id.etxtPasswordLogIn);
UserDonor = findViewById(R.id.spnUserDonor);
lFirebaseAuth = FirebaseAuth.getInstance();
lFirestoreFirebase = FirebaseFirestore.getInstance();
btnLogIn = findViewById(R.id.btnLogIn);
//button log-in
btnLogIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String Email = lEmail.getText().toString().trim();
String Password = lPassword.getText().toString().trim();
String userDonor = UserDonor.getSelectedItem().toString().trim();
//if User is selected on spinner
if (userDonor.equals("User")){
// authenticate the user
lFirebaseAuth.signInWithEmailAndPassword(Email, Password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
userID = lFirebaseAuth.getCurrentUser().getUid();
DocumentReference userRef = lFirestoreFirebase.collection("users").document(userID);
userRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
String usertype;
usertype = documentSnapshot.getString("userType");
if (usertype.equals("user")){
startActivity(new Intent(getApplicationContext(), main_user.class));
finish();
}
else {
Toast.makeText(log_in.this, "no user account is Registered", Toast.LENGTH_SHORT).show();
lFirebaseAuth.signOut();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(log_in.this, "cannot login" + task.getException().getMessage() , Toast.LENGTH_SHORT).show();
lFirebaseAuth.signOut();
}
});
}
else {
Toast.makeText(log_in.this, "cannot login" + task.getException().getMessage() , Toast.LENGTH_SHORT).show();
lFirebaseAuth.signOut();
}
}
});
}
//if Donor is selected on spinner
else if (userDonor.equals("Donor")){
// authenticate the donor
lFirebaseAuth.signInWithEmailAndPassword(Email, Password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
donorID = lFirebaseAuth.getCurrentUser().getUid();
DocumentReference donorRef = lFirestoreFirebase.collection("donors").document(donorID);
donorRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
String usertype;
usertype = documentSnapshot.getString("userType");
if (usertype.equals("donor")){
startActivity(new Intent(getApplicationContext(), main_user.class));
Toast.makeText(log_in.this, "donor Logged in", Toast.LENGTH_SHORT).show();
finish();
}
else {
Toast.makeText(log_in.this, "no donor account is Registered", Toast.LENGTH_SHORT).show();
lFirebaseAuth.signOut();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(log_in.this, "cannot login" + task.getException().getMessage() , Toast.LENGTH_SHORT).show();
lFirebaseAuth.signOut();
}
});
}
else {
Toast.makeText(log_in.this, "cannot log in" + task.getException().getMessage() , Toast.LENGTH_SHORT).show();
lFirebaseAuth.signOut();
}
}
});
}
}
});
}
}
or is there a better way for this to work?

How to create a account with Email And Password method after Verifying Phone with PhoneAuthProvider?

I am working on a kind of shopping Android app and at the time of creating new user account i want to verify the user with his Phone number and want to log in the user by there email.
PhoneAuthProvider.getInstance().verifyPhoneNumber(users.getPhoneNumber(), 120, TimeUnit.SECONDS, Otp_Activity.this,
new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
#Override
public void onCodeSent(#NonNull #NotNull String s, #NonNull #NotNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
otpID = s;
progressDialog.dismiss();
Toast.makeText(Otp_Activity.this, "Otp sent", Toast.LENGTH_SHORT).show();
}
#Override
public void onVerificationCompleted(#NonNull #NotNull PhoneAuthCredential phoneAuthCredential) {
signInWithPhoneAuthCredential(phoneAuthCredential);
}
#Override
public void onVerificationFailed(#NonNull #NotNull FirebaseException e) {
Toast.makeText(Otp_Activity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
});
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
firebaseAuth = SplashScreen.firebaseAuthForPhone;
firebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful())
{
Toast.makeText(Otp_Activity.this, "Account Created", Toast.LENGTH_SHORT).show();
createAccountWithEmail(userEmail, userPassword);
}
else
{
Toast.makeText(Otp_Activity.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
public void createAccountWithEmail(String email, String passWord)
{
firebaseAuthForEmail.createUserWithEmailAndPassword(email, passWord)
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
firebaseAuth.signOut();
Toast.makeText(Otp_Activity.this, "Email Account Created", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(), MainActivity.class));
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull #NotNull Exception e) {
Toast.makeText(Otp_Activity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
Why i cant logout with the account created with email?
do PhoneAuthProvider logs in after verifying account? if yes is there any way to stop it?
You could use one specific authentication process for each user. If you need to authenticate the user with the email and password, follow this process.
private FirebaseAuth mAuth;
// Initialize Firebase Auth
mAuth = FirebaseAuth.getInstance();
Then create account with email and password.
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// add the logic
} else {
// add the logic
}
}
});
After account creating process, you could use this process for the sign in process.
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// add the logic
} else {
// add the logic
}
}
});
And you could use this method for sign out the user.
FirebaseAuth.getInstance().signOut();

Role base login with Firebase database is failing

I'm doing a project called e-school. It has 4 types of users which uses Firebase authentication and Firebase realtime database to login to their accounts, Anyway, I'm getting issues while working with Firebase realtime database and Firebase authentication. I'm letting users to their respective dashboards comparing the authentication data with the realtime database.
//Registration Code
auth.createUserWithEmailAndPassword(email.getText().toString(), password.getText().toString())
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Users user = new Users();
user.setE_mail(email.getText().toString());
user.setNumber(Phone.getText().toString());
user.setPassword(password.getText().toString());
user.setU_name(username.getText().toString());
users.child("principal").child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(user)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Snackbar.make(rootLayout, "Registration Success",Snackbar.LENGTH_LONG)
.show();
return;
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Snackbar.make(rootLayout, "Registration Failed: "+e.getMessage(), Snackbar.LENGTH_LONG)
.show();
return;
}
});
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Snackbar.make(rootLayout, "Failed :"+e.getMessage(),Snackbar.LENGTH_LONG)
.show();
return;
}
});
}
});
//Login COde
auth.signInWithEmailAndPassword(t_email.getText().toString(), t_password.getText().toString())
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
id = auth.getUid();
teacherValidation(id);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Snackbar.make(rootLayout,"Authentication Failed", Snackbar.LENGTH_SHORT).show();
}
});
//TeacherValidate
private void teacherValidation(final String id) {
users = db.getInstance().getReference("Users/teachers");
users.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.getKey().equals(id)){
Toast.makeText(MainActivity.this," "+id,Toast.LENGTH_SHORT).show();
Intent it = new Intent(MainActivity.this, teachers.class);
it.putExtra("UID", id);
startActivity(it);
finish();
}else{
Toast.makeText(MainActivity.this, "No Teacher Esxist With the Given Credientialss", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
It is not necessary to get all teachers details on client side. Instead you can directly check in database for that user, it'll increase the performance of app also.
Just modify teacherValidation method like this.
private void teacherValidation(final String id) {
users = db.getInstance().getReference("Users/teachers").child(id);
users. addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// If below condition checks true,
// that means user exists on teacher node, so probably he/she is a teacher.
if(dataSnapshot.getValue() != null){
Toast.makeText(MainActivity.this," "+id,Toast.LENGTH_SHORT).show();
Intent it = new Intent(MainActivity.this, teachers.class);
it.putExtra("UID", id);
startActivity(it);
finish();
}else{
Toast.makeText(MainActivity.this, "No Teacher Exist With the Given Credientialss", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
I got this code snippet. Probably addListenerForSingleValueEvent is your method.
Pay special attention in the way the query is built, calling a first child which is the table called "users" and then a second child which is a user with a specific userId. FUser is equivalent to your Users class.
Try it...
private void getFirebaseUserInfo(final String userId, final GetUserInfoListener userInfoListener) {
DatabaseReference userIdReference = getDatabaseReference().child("users").child(userId);
userIdReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
try {
final Users user = dataSnapshot.getValue(FUser.class);
if (!user.email.isEmpty()) {
// Do whatever
} else {
userInfoListener.onSuccess(user);
}
} catch(DatabaseException e) {
userInfoListener.onFailure(new Exception(e.getMessage()));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
userInfoListener.onFailure(new Exception(databaseError.getMessage()));
}
});
}
Also, look at the difference:
Difference between addValueEventListener() and addListenerForSingleValueEvent() of firebase

Calling too many firebase function in one method

I'm currently making a method that allows current logged in user to sign up a new user and add them into as their downline friends using firebase. And while i was developing this method i realise that I've been bloating too much firebase functions into one method and i believe this would cause trouble when something is wrong with the inner function.
private void ValidateAccount(final String name, final String phone,final String email,
final String password, final String confirmPassword,
final String points,
final DatabaseReference RootRef, final FirebaseAuth firebaseAuth) {
firebaseAuth.createUserWithEmailAndPassword(email,password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
final FirebaseUser userkey = firebaseAuth.getCurrentUser();
final String userkeyString = userkey.getUid();
RootRef.child(userkeyString)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(!(dataSnapshot.exists())){
HashMap<String, Object> userDatamap = new HashMap<>();
final HashMap<String, Object> currentUserDatamap = new HashMap<>();
userDatamap.put("id",userkeyString);
userDatamap.put("phone",phone);
userDatamap.put("name",name);
userDatamap.put("email",email);
userDatamap.put("upline", upline);
addNewDownline(userkeyString);
currentUserDatamap.put("downlines", downlinesMaps);
RootRef.child(userkeyString).updateChildren(userDatamap)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
RootRef.child(currentUser.getId()).updateChildren(currentUserDatamap)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
Toast.makeText(RegisterDownlineActivity.this, "Congratulations your account has been created.", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
firebaseAuth.signOut();
Intent intent = new Intent(RegisterDownlineActivity.this, HomeActivity.class);
startActivity(intent);
}
else{
loadingBar.dismiss();
Toast.makeText(RegisterDownlineActivity.this, "Network Error: Please try again.", Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegisterDownlineActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegisterDownlineActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
else{
Toast.makeText(RegisterDownlineActivity.this,"The username already belong to someone else.",Toast.LENGTH_LONG).show();
loadingBar.dismiss();
Toast.makeText(RegisterDownlineActivity.this, "Please try again using another username.", Toast.LENGTH_LONG).show();
Intent intent = new Intent(RegisterDownlineActivity.this, MainActivity.class);
startActivity(intent);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(RegisterDownlineActivity.this, "System Error. Please try again later.", Toast.LENGTH_SHORT).show();
}
});
}
else{
Log.d( "FAIL", String.valueOf(task.getException()));
Toast.makeText(RegisterDownlineActivity.this, "Authentication failed."+String.valueOf(task.getResult()),
Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
try{
Toast.makeText(RegisterDownlineActivity.this, "Authentication failed: Email is already being used",
Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
catch (RuntimeExecutionException task){
Toast.makeText(RegisterDownlineActivity.this, "Authentication failed: Email is already being used",
Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
}
});
}
For example, if something is wrong with the updateChildren() then the method will show failure at the updateChildren() part, but the createUserWithEmailAndPassword() will still execute.
What i wish to achieve is that whenever there's an error in the function all the function will not execute and shows the error.
If createUserWithEmailAndPassword() executed and updateChildren() failed, then inside .addOnFailureListener you can delete the user:
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.delete();
Toast.makeText(RegisterDownlineActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});

Android (Firestore): Unable to add or update or set (SetOptions.merge) fields in already created document in Firestore

I am trying to add new fields to an already created document under "users" collection in firestore database.
From first activity I added basic information like name and description and gender to the firestore database (collection("users").document(uid)) and it worked. But when I am trying to add new fields (from second activity) to the same document it is not working. I tried to use set, SetOptions.merge, update, but nothing is working. Even I tried to add new collection then also it is not working. Can someone please help me to figure this out. Thanks in advance.
My codes are below from both the activities.
First Activity (BasicInfo.java) (working)
String uid = user.getUid();
Map<String, Object> dataToSave = new HashMap<>();
dataToSave.put(NAME, nameText);
dataToSave.put(ABOUT, aboutText);
dataToSave.put(GENDER, userGender);
db.collection("users").document(uid).set(dataToSave).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Intent userPreIntent = new Intent(BasicInfo.this, UserPre.class);
startActivity(userPreIntent);
finish();
} else {
Toast.makeText(getApplicationContext(), "There was some problem", Toast.LENGTH_SHORT).show();
}
}
});
Second Activity (UserPre.java) (Not working)
Map<String, Object> data = new HashMap<>();
data.put(STYLE, styleBeauty);
data.put(HUMOR, humor);
data.put(FITNESS, fitness);
data.put(TRAVEL, travel);
data.put(PHOTOGRAPHY, photography);
data.put(MUSIC, music);
data.put(DANCE, dance);
data.put(ART, art);
data.put(FASHION, fashion);
String uid = user.getUid();
db.collection("user").document(uid).set(data).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(getApplicationContext(), "Data Added", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "There was some problem", Toast.LENGTH_SHORT).show();
}
}
});
You can add a FailureListener and it will tell you what's wrong in logcat.
db.collection("user").document(uid).set(data).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(getApplicationContext(), "Data Added", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "There was some problem", Toast.LENGTH_SHORT).show();
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error writing document", e);
}
});

Categories

Resources