How to use roles? - reactjs

login = async (creds: UserFormValues) => {
try {
const user = await agent.Account.login(creds);
store.commonStore.setToken(user.token);
runInAction(() => this.user = user);
history.push('/activities');
store.modalStore.closeModal();
} catch (error) {
throw error;
}
}
I have this "login" that I want to edit it to make it with roles. Like:
login = async (creds: UserFormValues) => {
try {
const user = await agent.Account.login(creds);
store.commonStore.setToken(user.token);
runInAction(() => this.user = user);
if(user.role = "admin"){
history.push('/activities');
}
else{
history.push('/home');
}
store.modalStore.closeModal();
} catch (error) {
throw error;
}
}
But I get the warning "Expected a conditional expression and instead saw an assignment no-cond-assign" and still the platform runs but it ignores the if statement. How can I make a conditional expression about this(If you can also show me the code about it)? Also I have 5 roles which should go all on different pages.
login = async (creds: UserFormValues) => {
try {
const user = await agent.Account.login(creds);
store.commonStore.setToken(user.token);
runInAction(() => this.user = user);
if(user.role === "admin"){
history.push('/activities');
}
else{
history.push('/home');
}
store.modalStore.closeModal();
} catch (error) {
throw error;
}
}
This is the updated code, when I login as admin it redirects me to home and not into activities, like the if doesn't exist.

Related

Why is my Azure redirect running twice and not stopping the fuction

I want to add the functionality for admins to disable end users access if necessary. It works just fine with non-SSO users. The check will prevent the user from logging in and show them a 'user is not active error'. When a non-active user tries to use Azure SSO to log in, the Azure SSO is still successful and displaying a spinner because there is not an active user. It should not allow them to 'log in' and redirect them to the home page with a displayed error that says 'user is not active'
Here is the function to change the user's isActive status on the backend
const changeUserStatus = asyncHandler(async (req, res) => {
const currentUser = await User.findById(req.user._id);
if (!currentUser) {
res.status(401);
throw new Error('User not found');
}
const user = await User.findByIdAndUpdate(req.params.id, req.body, {
new: true,
});
console.log(user);
res.status(201).json(user);
});
From the backend as well, here is the check for a user's isActive status in the normal login function
//check isActive status
if (user.isActive === false) {
res.status(400);
throw new Error('Not an active user');
}
Here is the check in the Azure SSO log in
if (!user.isActive) {
errors.azure = 'User is no longer permitted to access this application';
res.status(400);
throw new Error(errors.azure);
// console.log(errors);
// return res.status(401).json(errors);
}
Here is my authService.js
// Login user
const login = async (userData) => {
const response = await axios.post(API_URL + 'login', userData);
if (response.data) {
localStorage.setItem('user', JSON.stringify(response.data));
}
return response.data;
};
const azureLogin = async () => {
const response = await axios.get(API_URL + 'az-login');
return response.data;
};
Here is my authSlice
// Login user
export const login = createAsyncThunk('auth/login', async (user, thunkAPI) => {
try {
return await authService.login(user);
} catch (error) {
return thunkAPI.rejectWithValue(extractErrorMessage(error));
}
});
// Login user using AAD - this action sends the user to the AAD login page
export const azureLogin = createAsyncThunk(
'users/azureLogin',
async (thunkAPI) => {
try {
return await authService.azureLogin();
} catch (error) {
return thunkAPI.rejectWithValue(extractErrorMessage(error));
}
}
);
// Login user using AAD - this action redirects the user from the AAD login page
// back to the app with a code
export const azureRedirect = createAsyncThunk(
'users/azureRedirect',
async (code, thunkAPI) => {
try {
return await authService.azureRedirect(code);
} catch (error) {
return thunkAPI.rejectWithValue(extractErrorMessage(error));
}
}
);
And here is the AzureRedirect.jsx component. This is the component that receives the flow from the Microsoft/AAD login page. It is the re-entry point of the application, so to speak.
useEffect(() => {
const code = {
code: new URLSearchParams(window.location.search).get('code'),
};
if (user) {
toast.success(`Logged in as ${user.firstName} ${user.lastName}`);
navigate('/');
} else if (code) {
// This CANNOT run more than once
const error = dispatch(azureRedirect(code));
console.log(error);
} else {
console.log('No code found in URL');
}
}, [dispatch, navigate, user]);
if (!user) {
displayedOutput = <Spinner />;
} else {
displayedOutput = (
<div>
An error has been encountered, please contact your administrator.
<br />
<Link to='/login'>Return to Login</Link>
</div>
);
}
return <div className='pt-4'>{displayedOutput}</div>;

Why is this private class member out of scope at the point where I try to call it?

I want to be able to call "setUser", but it's out of scope for some reason. This is in a MobX store that I've created. I'm sure it's something I'm doing fundamentally wrong, but I don't know what it is. Here's the code:
private setUser = (user: UserType) => {
this.userRegistry.set(user.Username, user);
}
loadUsersFromPoolGroups = () => {
this.loadingInitial = true;
try {
var congitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
const USER_POOL_ID = 'us-east-2_kWOEamV6i';
var params = {
UserPoolId: USER_POOL_ID
}
congitoidentityserviceprovider.listGroups(params, function(err, data) {
if (err) console.log(err, err.stack);
else {
data.Groups.forEach(group => {
var params = {
GroupName: group.GroupName,
UserPoolId: USER_POOL_ID
}
congitoidentityserviceprovider.listUsersInGroup(params, function(err1, data1) {
if (err1) console.log(err1, err1.stack);
else {
data1.Users.forEach((user) => {
this.setUser(user);
})
}
})
})
}
});
} catch (error) {
console.log('error loading users from pool groups', error)
}
}
I'm doing a similar thing in a different store with no issues.
private setSubmittal = (submittal: Submittal) => {
this.submittalRegistry.set(submittal.submittalId, submittal);
}
loadSubmittals = async () => {
this.loadingInitial = true;
try {
const submittals = await agent.Submittals.list();
submittals.data.forEach((submittal: Submittal) => {
this.setSubmittal(submittal);
})
this.setLoadingInitial(false);
} catch (error) {
console.log(error);
this.setLoadingInitial(false);
}
}
I expected to be able to call setUser and it won't let me.

Failed assertion : 'email != null'?

does anyone know why my result is null? When I want to SignUp the debug console display : Failed assertion: line 183 pos 12: 'email != null': is not true. And it displays null. This is my SignUp code when I press SignUp Button and the other code ist my auth class. If anyone knows please comment.
Future <void> signUp() async {
if(_formKey.currentState.validate()){
setState(() {
isLoading = true;
});
await authService.signUpWithEmailAndPassword(_email,
_password).then((result) {
if(result != null){
Map<String,String> userDataMap = {
"Username" : _Username,
"Email" : _email,
"Nation" : _Nation,
};
databaseService.addUserInfo(userDataMap);
HelperFunction.saveUserLoggedInSharedPreference(true);
HelperFunction.saveUserNameSharedPreference(_Username);
HelperFunction.saveUserEmailSharedPreference(_email);
HelperFunction.saveUserNationSharedPreference(_Nation);
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => LoadingBarForUserCreation()
));
}else{
print(result);
}
}).catchError((e){
_showSettingPanelForEmail();
});
}
AuthService
class AuthService{
final FirebaseAuth _auth = FirebaseAuth.instance;
Userf _userFromFirebaseUser(User user){
return user != null ? Userf(uid: user.uid) : null;
}
Stream<Userf> get user {
return _auth.onAuthStateChanged
.map(_userFromFirebaseUser);
}
Future signInWithEmailAndPassword(String email, String password) async {
try {
User user = (await _auth.signInWithEmailAndPassword(
email: email, password: password)).user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
Future signUpWithEmailAndPassword(String email, String password) async {
try {
User user = (await _auth.createUserWithEmailAndPassword(
email: email, password: password)).user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
}

How to pass additional data to a function that adds things to an object?

I am trying to create a user profile document for regular users and for merchants on Firebase. I am trying to add additional to data this document when a merchant signs up, but haven't succeeded. The difference is that merchants are supposed to have a roles array with their roles. If this is not the right approach to deal with differentiating users, I'd also be happy to hear what's best practice.
My userService file
async createUserProfileDocument(user, additionalData) {
console.log('additionalData: ', additionalData) //always undefined
if (!user) return
const userRef = this.firestore.doc(`users/${user.uid}`)
const snapshot = await userRef.get()
if (!snapshot.exists) {
const { displayName, email } = user
try {
await userRef.set({
displayName,
email,
...additionalData,
})
} catch (error) {
console.error('error creating user: ', error)
}
}
return this.getUserDocument(user.uid)
}
async getUserDocument(uid) {
if (!uid) return null
try {
const userDocument = await this.firestore.collection('users').doc(uid).get()
return { uid, ...userDocument.data() }
} catch (error) {
console.error('error getting user document: ', error)
}
}
This is what happens when the user signs up as a merchant in the RegisterMerchant component:
onSubmit={(values, { setSubmitting }) => {
async function writeToFirebase() {
//I can't pass the 'roles' array as additionalData
userService.createUserProfileDocument(values.user, { roles: ['businessOnwer'] })
authService.createUserWithEmailAndPassword(values.user.email, values.user.password)
await merchantsPendingApprovalService.collection().add(values)
}
writeToFirebase()
I am afraid this might have something to do with onAuthStateChange, which could be running before the above and not passing any additionalData? This is in the Middleware, where I control all of the routes.
useEffect(() => {
authService.onAuthStateChanged(async function (userAuth) {
if (userAuth) {
//is the below running before the file above and not passing any additional data?
const user = await userService.createUserProfileDocument(userAuth) //this should return the already created document?
//** do logic here depending on whether user is businessOwner or not
setUserObject(user)
} else {
console.log('no one signed in')
}
})
}, [])
There is onCreate callback function which is invoked when user is authenticated.
Here's how you could implement it
const onSubmit = (values, { setSubmitting }) => {
const { user: {email, password} } = values;
const additionalData = { roles: ['businessOnwer'] };
auth.user().onCreate((user) => {
const { uid, displayName, email } = user;
this.firestore.doc(`users/${uid}`).set({
displayName,
email,
...additionalData
});
});
authService.createUserWithEmailAndPassword(email, password);
}

No function is getting called inside firebase get function

I am trying to write login code, but this firebase get function is refraining me to do so. I am unable to call any function (except alert), within this get function. Navigating to another component also does not work here. I know I have to use async/await keywords but I dont know how to. Can someone please help me with this?
Pasting the code below.
navigate() {
alert("Aya");
}
login() {
const { uname } = this.state;
const { password } = this.state;
var userid = "";
var data;
if (uname && password) {
firebase
.auth()
.signInWithEmailAndPassword(uname, password)
.then(async user => {
userid = await firebase.auth().currentUser.uid;
await db.collection("Users").doc(userid)
.get()
.then(function (doc) {
if (doc.exists) {
data = doc.data();
alert(JSON.stringify(data.role));
if (data.role === "Company Admin") {
logged = true;
alert("Yahoo");
this.navigate();
}
else {
logged = false;
}
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function (error) {
console.log("Error getting document:", error);
});
})
.catch(error => {
alert(error);
this.setState({ error });
});
if (logged) {
alert(logged);
}
else {
alert("Nope");
}
}
else {
alert("Enter all fields data");
}
}
Don't use normal function, you are going to lose the context of this. The this in the callback function is not pointing to your class. So this.navigate() line of code won't work
.then(function (doc) {
As a solution, Use arrow function.
...
.then((doc) => {
...

Resources