Firebase 인증 모델로 생성 된 속성과 병합 된 사용자 모음에 저장된 속성 인 사용자 이름을 얻는 방법을 알아 내려고합니다.
authUser에 액세스 할 수 있습니다. 인증 도구에서 firebase가 수집하는 제한된 필드를 제공하고 거기에서 관련 사용자 컬렉션 (같은 uid를 사용)으로 이동하려고합니다.
다음과 같은 반응 컨텍스트 소비자가 있습니다.
import React from 'react';
const AuthUserContext = React.createContext(null);
export default AuthUserContext;
그런 다음 내 구성 요소에서 사용하려고합니다.
const Test = () => (
<AuthUserContext.Consumer>
{authUser => (
<div>
{authUser.email} // I can access the attributes in the authentication collection
{authUser.uid.user.name} //i cannot find a way to get the details in the related user collection document - where the uid on the collection is the same as the uid on the authentication table
</div>
)}
</AuthUserContext.Consumer>
);
const condition = authUser => !!authUser;
export default compose(
withEmailVerification,
withAuthorization(condition),
)(Test);
내 firebase.js에서-인증 모델의 authUser 속성을 다음과 같이 사용자 컬렉션 속성과 병합하려고했습니다.
class Firebase {
constructor() {
app.initializeApp(config).firestore();
/* helpers */
this.fieldValue = app.firestore.FieldValue;
/* Firebase APIs */
this.auth = app.auth();
this.db = app.firestore();
onAuthUserListener = (next, fallback) =>
this.auth.onAuthStateChanged(authUser => {
if (authUser) {
this.user(authUser.uid)
.get()
.then(snapshot => {
const dbUser = snapshot.data();
// default empty roles
if (!dbUser.roles) {
dbUser.roles = {};
}
// merge auth and db user
authUser = {
uid: authUser.uid,
email: authUser.email,
emailVerified: authUser.emailVerified,
providerData: authUser.providerData,
...dbUser,
};
next(authUser);
});
} else {
fallback();
}
});
authUser (인증 속성으로 연결되도록 작동)에서 인증 콜렉션과 동일한 uid를 가진 사용자 콜렉션으로 이동하는 방법을 찾을 수 없습니다.
나는 이 게시물 을 보았습니다. 이 게시물 은 같은 문제가있는 것으로 보이며 대답이 암시 해야하는 것을 해결하려고 시도했지만 인증 컬렉션에서 사용자 컬렉션으로 가져 오는 방법을 찾지 못하는 것 같습니다. authUser에서 사용자 컬렉션의 속성에 액세스 할 수없는 경우 병합이 나를 위해 무엇을하고 있는지 알 수 없습니다.
firebase.js에서 도우미를 사용하여 uid의 사용자를 제공하려고 시도했지만 도움이되지 않는 것 같습니다.
user = uid => this.db.doc(`users/${uid}`);
users = () => this.db.collection('users');
다음 시도
배경을 더 추가하기 위해 다음과 같이 authUser를 기록 할 수 있지만 렌더링 할 수없는 테스트 구성 요소를 만들었습니다.
import React, { Component } from 'react';
import { withFirebase } from '../Firebase/Index';
import { Button, Layout } from 'antd';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
class Test extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
user: null,
...props.location.state,
};
}
componentDidMount() {
if (this.state.user) {
return;
}
this.setState({ loading: true });
// this.unsubscribe = this.props.firebase
// .user(authUser.uid)
// .onSnapshot(snapshot => {
// const userData = snapshot.data();
// console.log(userData);
// this.setState({
// user: snapshot.data(),
// loading: false,
// });
// });
}
componentWillUnmount() {
this.unsubscribe && this.unsubscribe();
}
render() {
const { user, loading } = this.state;
return (
<div>
<AuthUserContext.Consumer>
{authUser => (
console.log(authUser),
<p>
</p>
)}
</AuthUserContext.Consumer>
</div>
);
};
}
export default Test;
로그에는 로그에 uid, 전자 메일 등에 대한 세부 정보가 표시되지만 긴 항목 목록에 있습니다. 대부분은 1 또는 2 문자로 시작합니다 (이 접두사 각각이 무엇인지 알 수있는 키를 찾을 수 없습니다) 글자 의미). 아래에서 추출한 예 :
이 의견에 대한 업데이트 :
이전에 나는 말했다 : uid, email 등의 필드는 이러한 접두사 아래에 중첩되지 않은 것처럼 보이지만 다음과 같이하려고하면 :
console.log(authUser.email)
, 다음과 같은 오류가 발생합니다.
TypeError : null의 속성 '이메일'을 읽을 수 없습니다
업데이트 : 방금 콘솔 로그에서 레이블이 지정된 드롭 다운 메뉴를 확장해야한다는 것을 깨달았습니다.
Q {I : 배열 (0), l :
이메일 속성을 확인하십시오. 이 혼란스러운 점을 아는 사람이 있습니까? 인증 테이블의 관련 속성을 얻기 위해 이러한 것들을 참조해야하는지 알기 위해 Q, I 또는 l의 의미를 알아내는 열쇠를 찾을 수 없습니다. 어쩌면 내가 알아낼 수 있다면 Authentication 컬렉션의 uid를 사용하여 사용자 컬렉션에 액세스하는 방법을 찾을 수 있습니다.
현재 사용자가 누구인지 알아 내기 위해 컨텍스트 소비자와 함께 프런트 엔드에서 반응 한 사람이 있습니까? 그렇다면 인증 모델에서 해당 속성에 어떻게 액세스하고 관련 사용자 콜렉션 (사용자 문서의 docId가 인증 테이블의 uid 임)의 속성에 어떻게 액세스 했습니까?
다음 공격
다음 시도는 매우 이상한 결과를 낳았습니다.
컨텍스트 소비자 인 2 개의 개별 페이지가 있습니다. 차이점은 하나는 함수이고 다른 하나는 클래스 구성 요소입니다.
함수 구성 요소에서 {authUser.email}을 렌더링 할 수 있습니다. 클래스 구성 요소에서 동일한 작업을 수행하려고하면 다음과 같은 오류가 발생합니다.
TypeError : null의 속성 '이메일'을 읽을 수 없습니다
이 오류는 동일한 로그인 사용자와 동일한 세션에서 발생합니다.
참고 : Firebase 설명서에 auth에서 currentUser 속성을 사용할 수 있다고 나와 있지만 전혀 작동하지 않습니다.
내 기능 구성 요소는 다음과 같습니다.
import React from 'react';
import { Link } from 'react-router-dom';
import { compose } from 'recompose';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
const Account = () => (
<AuthUserContext.Consumer>
{authUser => (
<div>
{authUser.email}
</div>
)}
</AuthUserContext.Consumer>
);
// const condition = authUser => !!authUser;
// export default compose(
// withEmailVerification,
// withAuthorization(condition),
// )(Account);
export default Account;
이 문서에서 사용자 문서의 docId가 인증 된 사용자의 uid와 동일한 User collection 속성을 얻을 수 없지만이 사용자의 auth collection에 email 속성을 출력 할 수 있습니다.
Firebase 설명서에서 사용자 관리 및 속성 액세스에 대한 조언을 제공 하지만 이 방법을 구현할 방법을 찾지 못했습니다. firebase.js에서 도우미를 만들고 구성 요소를 처음부터 시작하여 시도하면 Firebase에 액세스하는 데 오류가 발생합니다. 그러나 사용자 목록과 관련 사용자 수집 정보를 생성 할 수 있습니다 (authUser가 누구인지에 따라 사용자를 얻을 수 없습니다).
내 수업 구성 요소는 다음과 같습니다.
import React from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
} from 'react-router-dom';
import * as ROUTES from '../../constants/Routes';
import { compose } from 'recompose';
import { withFirebase } from '../Firebase/Index';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
class Dashboard extends React.Component {
state = {
collapsed: false,
};
onCollapse = collapsed => {
console.log(collapsed);
this.setState({ collapsed });
};
render() {
const { loading } = this.state;
// const dbUser = this.props.firebase.app.snapshot.data();
// const user = Firebase.auth().currentUser;
return (
<AuthUserContext.Consumer>
{authUser => (
<div>
{authUser.email} // error message as shown above
{console.log(authUser)} // output logged in amongst a long list of menus prefixed with either 1 or 2 characters. I can't find a key to decipher what these menus mean or do.
</div>
)}
</AuthUserContext.Consumer>
);
}
}
//export default withFirebase(Dashboard);
export default Dashboard;
내 AuthContext.Provider에서-나는 :
import React from 'react';
import { AuthUserContext } from '../Session/Index';
import { withFirebase } from '../Firebase/Index';
const withAuthentication = Component => {
class WithAuthentication extends React.Component {
constructor(props) {
super(props);
this.state = {
authUser: null,
};
}
componentDidMount() {
this.listener = this.props.firebase.auth.onAuthStateChanged(
authUser => {
authUser
? this.setState({ authUser })
: this.setState({ authUser: null });
},
);
}
componentWillUnmount() {
this.listener();
};
render() {
return (
<AuthUserContext.Provider value={this.state.authUser}>
<Component {...this.props} />
</AuthUserContext.Provider>
);
}
}
return withFirebase(WithAuthentication);
};
export default withAuthentication;
다음 공격
이 시도로 데이터베이스에 존재하는 값을 콘솔 로그에 기록하려고하는데 name 값이 '정의되지 않음'으로 반환되고 db에 문자열이있는 경우 정말 이상합니다.
이 시도는 다음과 같습니다.
import React from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
useRouteMatch,
} from 'react-router-dom';
import * as ROUTES from '../../constants/Routes';
import { compose } from 'recompose';
import { withFirebase } from '../Firebase/Index';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
class Dash extends React.Component {
// state = {
// collapsed: false,
// };
constructor(props) {
super(props);
this.state = {
collapsed: false,
loading: false,
user: null,
...props.location.state,
};
}
componentDidMount() {
if (this.state.user) {
return;
}
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.user(this.props.match.params.id)
// .user(this.props.user.uid)
// .user(authUser.uid)
// .user(authUser.id)
// .user(Firebase.auth().currentUser.id)
// .user(Firebase.auth().currentUser.uid)
.onSnapshot(snapshot => {
this.setState({
user: snapshot.data(),
loading: false,
});
});
}
componentWillUnmount() {
this.unsubscribe && this.unsubscribe();
}
onCollapse = collapsed => {
console.log(collapsed);
this.setState({ collapsed });
};
render() {
// const { loading } = this.state;
const { user, loading } = this.state;
// let match = useRouteMatch();
// const dbUser = this.props.firebase.app.snapshot.data();
// const user = Firebase.auth().currentUser;
return (
<AuthUserContext.Consumer>
{authUser => (
<div>
{loading && <div>Loading ...</div>}
<Layout style={{ minHeight: '100vh' }}>
<Sider collapsible collapsed={this.state.collapsed} onCollapse={this.onCollapse}>
<div />
</Sider>
<Layout>
<Header>
{console.log("authUser:", authUser)}
// this log returns the big long list of outputs - the screen shot posted above is an extract. It includes the correct Authentication table (collection) attributes
{console.log("authUser uid:", authUser.uid)}
// this log returns the correct uid of the current logged in user
{console.log("Current User:", this.props.firebase.auth.currentUser.uid)}
// this log returns the correct uid of the current logged in user
{console.log("current user:", this.props.firebase.db.collection("users").doc(this.props.firebase.auth.currentUser.uid
))}
// this log returns a big long list of things under a heading: DocumentReference {_key: DocumentKey, firestore: Firestore, _firestoreClient: FirestoreClient}. One of the attributes is: id: (...) (I can't click to expand this).
{console.log("current user:", this.props.firebase.db.collection("users").doc(this.props.firebase.auth.currentUser.uid
).name)}
//this log returns: undefined. There is an attribute in my user document called 'name'. It has a string value on the document with the id which is the same as the currentUser.uid.
<Text style={{ float: 'right', color: "#fff"}}>
{user && (
<Text style={{ color: "#fff"}}>{user.name}
//this just gets skipped over in the output. No error but also does not return the name.
</Text>
)}
</Text>
</Header>
</Layout>
</Layout>
</div>
)}
</AuthUserContext.Consumer>
);
}
}
export default withFirebase(Dash);
다음 공격
따라서이 시도는 어색하고 위에서 사용하려고 한 도우미 또는 스냅 샷 쿼리를 사용하지 않지만 다음과 같이 사용자 컬렉션 문서 속성을 콘솔에 기록합니다.
{this.props.firebase.db.collection ( 'users'). doc (authUser.uid) .get ()
.then(doc => {
console.log(doc.data().name)
})
}
그래도 할 수없는 것은 jsx에서 해당 이름을 렌더링하는 방법을 찾는 것입니다.
실제로 출력물을 어떻게 인쇄합니까?
내가 시도 할 때 :
{
this.props.firebase.db.collection('users').doc(authUser.uid).get().data().name
}
다음과 같은 오류가 발생합니다.
TypeError : this.props.firebase.db.collection (...). doc (...). get (...). data는 함수가 아닙니다
내가 시도 할 때 :
{
this.props.firebase.db.collection('users').doc(authUser.uid).get()
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
다음과 같은 오류가 발생합니다.
Line 281 : 23 : 할당 또는 함수 호출을 예상하고 대신 사용하지 않은 표현식을 보았습니다.
내가 시도 할 때 :
{
this.props.firebase.db.collection('users').doc(authUser.uid).get("name")
.then(doc => {
console.log(doc.data().name),
<p>doc.data().name</p>
})
}
오류 메시지는 다음과 같습니다.
할당 또는 함수 호출을 예상하고 대신 표현식을 보았습니다.
화면에 렌더링 할 사용자 모음의 이름을 얻을 수 있다면 스냅 샷 쿼리를 작동시키는 방법을 찾으려고 포기할 준비가되었습니다. 누구든지 그 단계를 도울 수 있습니까?
다음 공격
이 게시물을 찾았 습니다 . 어떤 일이 발생해야하는지에 대한 좋은 설명이 있지만 componentDidMount가 authUser가 무엇인지 알지 못하므로 표시된대로 구현할 수 없습니다.
내 현재 시도는 다음과 같습니다-그러나 현재 작성된 것처럼 authUser는 반환 값의 래퍼이며 componentDidMount 세그먼트는 authUser가 무엇인지 알지 못합니다.
import React from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
useRouteMatch,
} from 'react-router-dom';
import * as ROUTES from '../../constants/Routes';
import { compose } from 'recompose';
import { Divider, Layout, Card, Tabs, Typography, Menu, Breadcrumb, Icon } from 'antd';
import { withFirebase } from '../Firebase/Index';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
const { Title, Text } = Typography
const { TabPane } = Tabs;
const { Header, Content, Footer, Sider } = Layout;
const { SubMenu } = Menu;
class Dashboard extends React.Component {
// state = {
// collapsed: false,
// loading: false,
// };
constructor(props) {
super(props);
this.state = {
collapsed: false,
loading: false,
user: null,
...props.location.state,
};
}
componentDidMount() {
if (this.state.user) {
return;
}
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.user(this.props.match.params.id)
.onSnapshot(snapshot => {
this.setState({
user: snapshot.data(),
loading: false,
});
});
// }
// firebase.firestore().collection("users")
// .doc(this.state.uid)
// .get()
// .then(doc => {
// this.setState({ post_user_name: doc.data().name });
// });
// }
this.props.firebase.db
.collection('users')
.doc(authUser.uid)
.get()
.then(doc => {
this.setState({ user_name: doc.data().name });
// loading: false,
});
}
componentWillUnmount() {
this.unsubscribe && this.unsubscribe();
}
onCollapse = collapsed => {
console.log(collapsed);
this.setState({ collapsed });
};
render() {
// const { loading } = this.state;
// const { user, loading } = this.state;
// let match = useRouteMatch();
// const dbUser = this.props.firebase.app.snapshot.data();
// const user = Firebase.auth().currentUser;
return (
<AuthUserContext.Consumer>
{ authUser => (
<div>
<Header>
{/*
{
this.props.firebase.db.collection('users').doc(authUser.uid).get()
.then(doc => {
console.log( doc.data().name
)
})
}
*/}
</Text>
</Header>
<Switch>
</Switch>
</div>
)}
</AuthUserContext.Consumer>
);
}
}
export default withFirebase(Dashboard);
다음 공격
다음으로 전체 구성 요소가 사용할 수 있도록 AuthContext.Consumer 내부에 대시 보드 경로를 래핑하여 componentDidMount 함수에서 로그인 한 사용자에게 액세스 할 수있었습니다.
경로를 다음과 같이 변경했습니다.
<Route path={ROUTES.DASHBOARD} render={props => (
<AuthUserContext.Consumer>
{ authUser => (
<Dashboard authUser={authUser} {...props} />
)}
</AuthUserContext.Consumer>
)} />
대시 보드 구성 요소 렌더링 문에서 소비자를 제거했습니다.
그런 다음 Dashboard 구성 요소의 componentDidMount에서 다음을 시도했습니다.
componentDidMount() {
if (this.state.user) {
return;
}
this.setState({ loading: true });
this.unsubscribe =
this.props.firebase.db
.collection('users')
//.doc(this.props.firebase.db.collection('users').doc(this.props.firebase.authUser.uid))
.doc(this.props.firebase.db.collection('users').doc(this.props.authUser.uid))
.get()
.then(doc => {
this.setState({ name: doc.data().name });
loading: false,
});
}
이것을 시도하면 다음과 같은 오류가 발생합니다.
FirebaseError : Function CollectionReference.doc ()에는 첫 번째 인수가 비어 있지 않은 문자열 유형이어야하지만 사용자 정의 DocumentReference 객체입니다.
다음 공격 아래 사람들은 첫 번째 제안 된 솔루션에 도움이 될 것 같습니다. 유용한 정보를 찾을 수 없었지만 제안 사항을 다시 읽으면서 Firebase 설명서의 예제를 확인하는 데 어려움을 겪고 있습니다 (.doc () 요청에 : uid 값을 제공하는 방법은 공개하지 않음) )는 다음과 같습니다.
db.collection("cities").doc("SF");
docRef.get().then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
componentDidMount 함수에서의 시도와 근본적으로 다릅니다.
this.unsubscribe =
this.props.firebase.db
.collection('users')
// .doc(this.props.firebase.db.collection('users').doc(this.props.firebase.authUser.uid))
// .doc(this.props.firebase.db.collection('users').uid: this.props.firebase.auth().currentUser.uid )
.doc(this.props.authUser.uid)
.get()
.then(doc => {
this.setState({ user.name: doc.data().name });
// loading: false,
}else {
// doc.data() will be undefined in this case
console.log("Can't find this record");
}
);
}
아마도 그 단계를 해결하는 것이 결과를 향해 나아가는 데 도움이 될 단서 일 것입니다. 누구나 로그인 된 사용자 리스너 uid를 사용하여 사용자 콜렉션 레코드를 얻는 방법을 보여주는 더 나은 firestore 문서를 찾을 수 있습니까?
이를 위해 FriendlyEats 코드 랩 예제 에서 코드 의 id 검색 값에 doc.id를 제공하려는 시도가 있음을 알 수 있습니다. 이 코드가 어떤 언어로 작성되었는지는 알지 못합니다. 그러나 시도하고있는 것과 비슷해 보입니다. 예제에서 작업 방법을 알고있는 것으로 이동하는 방법을 볼 수 없습니다.
display: function(doc) {
var data = doc.data();
data['.id'] = doc.id;
data['go_to_restaurant'] = function() {
that.router.navigate('/restaurants/' + doc.id);
};