App not authenticated with Firebase. Permission Denied error - ios

I have been following this guide to add and retrieve items from firebase using React Native. If I set my rules on firebase to public, everything works but if I set it to the following, I get a permission denied error.
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
I have added all of my config data properly in my ios.js. Is there some basic step that I am missing here?
index.ios.js:
// Initialize Firebase
const firebaseConfig = {
apiKey: 'myapikey',
authDomain: 'myauthdomain',
databaseURL: 'https://url.firebaseio.com',
projectId: 'myProjectId',
storageBucket: 'projectid.appspot.com',
messagingSenderId: 'myMessagingSenderId'
};
const firebaseApp = firebase.initializeApp(firebaseConfig);
class MyNewAppreactold extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
})
};
this.itemsRef = this.getRef().child('items');
}
getRef() {
return firebaseApp.database().ref();
}
listenForItems(itemsRef) {
itemsRef.on('value', (snap) => {
// get children as an array
var items = [];
snap.forEach((child) => {
items.push({
title: child.val().title,
_key: child.key
});
});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(items)
});
});
}
// componentWillMount() {
// firebase.initializeApp(firebaseConfig);
// }
componentDidMount() {
this.listenForItems(this.itemsRef);
}
render() {
return (
<View style={styles.container}>
<StatusBar title="Grocery List" />
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderItem.bind(this)}
enableEmptySections={true}
style={styles.listview}/>
<ActionButton onPress={this._addItem.bind(this)} title="Add" />
</View>
)
}
_addItem() {
AlertIOS.prompt(
'Add New Item',
null,
[
{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{
text: 'Add',
onPress: (text) => {
this.itemsRef.push({ title: text })
}
},
],
'plain-text'
);
}
_renderItem(item) {
const onPress = () => {
AlertIOS.alert(
'Complete',
null,
[
{text: 'Complete', onPress: (text) => this.itemsRef.child(item._key).remove()},
{text: 'Cancel', onPress: (text) => console.log('Cancelled')}
]
);
};
return (
<ListItem item={item} onPress={onPress} />
);
}
}
AppRegistry.registerComponent('MyNewAppreactold', () => MyNewAppreactold);

The code you shared doesn't authenticate the user. Since your security rules require that the user is authenticated to be allowed access to the data, they reject the unauthenticated user of your app.
To solve this problem, you'll need to authenticate the user. The simplest way to do that is to sign the user in anonymously:
firebase.auth().signInAnonymously();
Then attach your database listeners after the user is authenticated:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.listenForItems(this.itemsRef);
} else {
// User is signed out.
// ...
}
// ...
});

Related

Cordova Plugin Purchase - redirect after successful subscription

I am using this plugin (https://github.com/j3k0/cordova-plugin-purchase) to handle a in app subscription.
iap.validator = "https://validator.fovea.cc/v1/validate?appName=XXX";
//initiate initInAppPurchase function
useEffect(() => {
const init = async () => {
await initInAppPurchase();
}
init();
}, []);
//if on an ios or android device, then get product info
const initInAppPurchase = () => {
if ((isPlatform('ios')) || (isPlatform('android'))) {
iap.verbosity = iap.DEBUG;
iap.register({
id: "tpmonthly",
alias: "Monthly",
type: iap.PAID_SUBSCRIPTION
});
iap.ready(() => {
let product = iap.get('Monthly');
setPrice(product.price)
setProduct(product)
})
iap.refresh();
}
}
//if user clicks purchase button
const purchaseProduct = () => {
if (product.owned) {
alert('A subscription is currently active.')
} else {
iap.order('Monthly').then(() => {
iap.when("tpmonthly").approved((p: IAPProduct) => {
p.verify();
});
iap.when("tpmonthly").verified((p: IAPProduct) => {
p.finish();
history.push("/ios-signup/");
});
})
}
}
return (
<Button size="large" variant="outlined" onClick={purchaseProduct}>Subscribe Monthly for {productPrice}</Button>
);
What I am hoping to get is that once the subscription is verified that it then redirects the app to /ios-signup/ .. this is not happening.
Is this code correct? And why would it not redirect after p.finish?

IOS Notification Permission alert does not show

SDK Version: 39.0.0
Platforms(Android/iOS/web/all): All
I am not getting accept or decline notifications permissions alert when loading my app in production.
I have tried clearing certificates and keys and allowing expo to add everything from a clean slate, but still no luck. I am starting to think maybe it’s my code which is the reason why the alert doesn’t get fired.
import Constants from "expo-constants";
import * as Notifications from "expo-notifications";
import { Permissions } from "expo-permissions";
import { Notifications as Notifications2 } from "expo";
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: false
})
});
export default class LoginScreen extends React.Component {
state = {
email: "",
password: "",
notification: {},
errorMessage: null
};
async componentDidMount() {
this.registerForPushNotificationsAsync();
//Notifications.addNotificationReceivedListener(this._handleNotification);
Notifications2.addListener(data => {
this.setState({ notification: data });
});
Notifications.addNotificationResponseReceivedListener(
this._handleNotificationResponse
);
}
_handleNotification = notification => {
this.setState({ notification: notification });
};
_handleNotificationResponse = response => {
console.log(response);
};
handleLogin = async () => {
try {
const { email, password } = this.state;
const expoPushToken = await Notifications.getExpoPushTokenAsync();
console.log(expoPushToken);
const userinfo = await firebase
.auth()
.signInWithEmailAndPassword(email, password);
console.log("user ID ", userinfo.user.uid);
await firebase
.firestore()
.collection("users")
.doc(userinfo.user.uid.toString())
.update({
expo_token: expoPushToken["data"]
})
.then(function() {
console.log("token successfully updated!");
})
.catch(function(error) {
// The document probably doesn't exist.
console.error("Error updating document: ", error);
});
} catch (error) {
console.log("=======Error in login", error);
this.setState({ errorMessage: error.message });
}
};
registerForPushNotificationsAsync = async () => {
if (Constants.isDevice) {
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const { status } = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
finalStatus = status;
}
if (finalStatus !== "granted") {
alert("Failed to get push token for push notification!");
return;
}
const token = await Notifications.getExpoPushTokenAsync();
console.log(token);
//this.setState({ expoPushToken: token });
} else {
alert("Must use physical device for Push Notifications");
}
if (Platform.OS === "android") {
Notifications.setNotificationChannelAsync("default", {
name: "default",
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#FF231F7C"
});
}
};
import { Permissions } from "expo-permissions";
should of been
import * as Permissions from 'expo-permissions';
Sometimes we all make simple mistakes.

Dart Streams blocking

I am using the BLoC pattern for a Futter app but I can't get both listeners to work.
If I call the loggedIn.listen() before the register.listen() the register.listen() won't work anymore and vice versa.
AuthBloc({this.authService}) {
Stream<CrendentialsDetail> detailStream = Observable.combineLatest2(
emailStream,
passwordStream,
(email, password) {
return CrendentialsDetail(email: email, password: password);
},
);
Stream<AuthResponse> loggedIn ... code ...
Stream<RegisterResponse> register ... code ...
register.listen((RegisterResponse res) {
Scaffold.of(_context).showSnackBar(
new SnackBar(
content: new Text(res.message),
),
);
}, onError: (error) {
Scaffold.of(_context).showSnackBar(
new SnackBar(
content: new Text(error.message),
),
);
});
loggedIn.listen((AuthResponse user) {
currentUserSubject.add(user);
_goToHome();
}, onError: (error) {
Scaffold.of(_context).showSnackBar(
new SnackBar(
content: new Text(error.message),
),
);
});
}
Any help will be appreciated!
This is the solution I'm using right now. Could someone explain to me why is works and my question not?
AuthBloc({this.authService}) {
Observable(loginSubject.stream).withLatestFrom(
Observable.combineLatest2(
emailStream,
passwordStream,
(email, password) {
return CrendentialsDetail(email: email, password: password);
},
), (_, d) {
return d;
}).flatMap((d) {
return Observable.fromFuture(authService.loginUser(d)).doOnListen(() {
loadingSubject.add(true);
}).doOnDone(() {
loadingSubject.add(false);
});
}).listen((AuthResponse user) {
currentUserSubject.add(user);
_goToHome();
}, onError: (error) {
Scaffold.of(_context).showSnackBar(
new SnackBar(
content: new Text(error.message),
),
);
});
Observable(signUpSubject.stream).withLatestFrom(
Observable.combineLatest2(
emailStream,
passwordStream,
(email, password) {
return CrendentialsDetail(email: email, password: password);
},
), (_, d) {
return d;
}).flatMap((d) {
return Observable.fromFuture(authService.register(d)).doOnListen(() {
loadingSubject.add(true);
}).doOnDone(() {
loadingSubject.add(false);
});
}).listen((RegisterResponse res) {
Scaffold.of(_context).showSnackBar(
new SnackBar(
content: new Text(res.message),
),
);
}, onError: (error) {
Scaffold.of(_context).showSnackBar(
new SnackBar(
content: new Text(error.message),
),
);
});
}

Retrieve user's email in twitter -react native

I've used react-native-twitter-signin lib to login through twitter. It works well but doesn't give user's email. It is mentioned that you have to apply for a permission for your app to retrieve user's email
How can I ask for a permission to make it work?
Code:
const Constants = {
TWITTER_COMSUMER_KEY: 'XXXXXXX',
TWITTER_CONSUMER_SECRET: 'XXXXXXXXXXXX',
};
export default class twitterLogin extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: false,
}
this.handleLogout = this.handleLogout.bind(this);
}
_twitterSignIn() {
RNTwitterSignIn.init(Constants.TWITTER_COMSUMER_KEY, Constants.TWITTER_CONSUMER_SECRET);
RNTwitterSignIn.logIn()
.then((loginData)=>{
console.log(loginData);
const { authToken, authTokenSecret } = loginData;
if (authToken && authTokenSecret) {
this.setState({
isLoggedIn: true,
});
}
}).catch((error)=>{
console.log(error);
});
}
handleLogout() {
console.log('logout');
RNTwitterSignIn.logOut();
this.setState({
isLoggedIn: false,
});
}
render() {
const { isLoggedIn } = this.state;
return (
<View style={{flex: 1}}>
{
isLoggedIn
?
<TouchableOpacity
onPress={this.handleLogout}
>
<Text>Log out</Text>
</TouchableOpacity>
:
<Icon.Button name='logo-twitter' size={32} color='white' style={styles.icon} onPress={this._twitterSignIn.bind(this)}>
Login with Twitter
</Icon.Button>
}
</View>
);
}
}
In your permission tab => 'Request email addresses from users' check
and enter 'Privacy Policy URL' & 'Terms of Service URL' it will give user email

Angular 2 Reactive Forms Async Custom Validation throws "subscribe not a function"

I've already tried every permutation of the answers to [angular2 async validation this.subscribe exception? but i'm still getting the exception.
import {AsyncValidatorFn, AbstractControl } from '#angular/forms';
export function userNameShouldBeUnique(): AsyncValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
return new Promise(resolve => {
setTimeout(() => {
if (control.value == 'mosh')
resolve({ shouldBeUnique: true });
else
resolve(null);
}, 1000);
});
}
}
and in the component (the last attempt):
this.myForm = this.fb.group({
username: [
'',
Validators.compose([Validators.required, forbiddenNameValidator(/bob/)]),
Validators.composeAsync([userNameShouldBeUnique])
],
password: ['', Validators.required]
});
so what am I doing wrong? Thanks
The solution is:
import { AsyncValidatorFn, AbstractControl } from '#angular/forms';
export function UniqueValidator(): AsyncValidatorFn {
return (control: AbstractControl): Promise<any> => {
return new Promise<any>(resolve => {
setTimeout(() => {
if (control.value === 'mosh')
resolve({ shouldBeUnique: true });
else
resolve(null);
}, 1000);
});
};
};
Now you have return types well configured. To be added as custom validation:
username: ['', Validators.required, UniqueValidator()]
Just tested and it works ;)

Resources