Ответ 1
Прежде всего, если у пользователей уже есть username
, он уникален, и это не исчезнет, я бы рекомендовал отказаться от использования простого входа uid
s. Это не создаст ничего, кроме вопросов, пытающихся перевернуться между ними, как вы уже открыли здесь. Изучите создание собственных токенов с помощью инструмента, такого как firebase-passport-login и затем сохраните записи username
.
Но так как это не было вашим вопросом, разрешите это, пока мы здесь, так как вы можете пойти вперед и войти в тернистый бриар двойных тождеств, через который я прошел много раз.
Чтобы сделать имя пользователя уникальным, сохраните индекс имени пользователя.
/пользователей/$Идентификатор_пользователя/имя пользователя/имя пользователя $ /Логины/$имя пользователя/$Идентификатор_пользователя
Чтобы убедиться, что они уникальны, добавьте правило безопасности, как указано в идентификаторе пользователя в именах пользователей/пути, что гарантирует, что для каждого пользователя может быть назначено только один пользователь и что это идентификатор пользователя:
".write": "newData.val() === auth.uid && !data.exists()"
Теперь убедитесь, что они совпадают, добавив следующее в имя пользователя в записи/записи:
"users": {
"$userid": {
"username": {
".validate": "root.child('usernames/'+newData.val()).val() === $userid"
}
}
}
Это гарантирует уникальность идентификаторов. Будьте осторожны с привилегиями чтения. Вы можете избежать этого, так как не хотите, чтобы кто-либо искал частные электронные письма или имена пользователей. Что-то вроде того, что я продемонстрировал в поддержке для сохранения, было бы идеально.
Идея здесь заключается в том, что вы пытаетесь назначить имя пользователя и адрес электронной почты, если они терпят неудачу, то они уже существуют и принадлежат другому пользователю. В противном случае вы вставляете их в пользовательскую запись, и теперь пользователи индексируются с помощью uid и электронной почты.
Чтобы соответствовать протоколу SO, вот код из этого gist, который лучше читать по ссылке:
var fb = new Firebase(URL);
function escapeEmail(email) {
return email.replace('.', ',');
}
function claimEmail(userId, email, next) {
fb.child('email_lookup').child(escapeEmail(email)).set(userId, function(err) {
if( err ) { throw new Error('email already taken'); }
next();
});
}
function claimUsername(userId, username, next) {
fb.child('username_lookup').child(username).set(userId, function(err) {
if( err ) { throw new Error('username already taken'); }
next();
});
}
function createUser(userId, data) {
claimEmail(userId, data.email, claimUsername.bind(null, userId, data.username, function() {
fb.child('users').child(userId).set(data);
);
}
И правила:
{
"rules": {
"users": {
"$user": {
"username": {
".validate": "root.child('username_lookup/'+newData.val()).val() === auth.uid"
},
"email": {
".validate": "root.child('email_lookup').child(newData.val().replace('.', ',')).val() === auth.uid"
}
}
},
"email_lookup": {
"$email": {
// not readable, cannot get a list of emails!
// can only write if this email is not already in the db
".write": "!data.exists()",
// can only write my own uid into this index
".validate": "newData.val() === auth.uid"
}
},
"username_lookup": {
"$username": {
// not readable, cannot get a list of usernames!
// can only write if this username is not already in the db
".write": "!data.exists()",
// can only write my own uid into this index
".validate": "newData.val() === auth.uid"
}
},
}
}