angularjs - register - registrar usuario firebase
¿Cómo previene las propiedades duplicadas de los usuarios en Firebase? (2)
Estoy usando FirebaseSimpleLogin
para crear usuarios y manejar la autenticación.
Cuando intento crear un nuevo usuario con un inicio de sesión sencillo a través del $createUser()
, firebase no creará el usuario si la dirección de correo electrónico ya se ha utilizado. Sin embargo, también estoy usando $set()
para guardar mis usuarios creados en mi firebase después de crearlos y estoy usando user.uid
como la clave. Al intentar escribir en la base de datos, firebase guardará el registro, incluso si el nombre de usuario no es único, ya que solo se requieren un correo electrónico y una contraseña para iniciar sesión. Entonces, ¿cómo puedo validar que un nombre de usuario sea único cuando no se usa como la clave del objeto del usuario?
Estoy creando nuevos usuarios como este:
$scope.createUser = function() {
$scope.auth.$createUser(''[email protected]'', ''password'').then(function(user, err) {
if (!err) {
ref.child(''users/'' + user.uid).set({
email: user.email,
username: user.username
});
console.log("success!");
}else{
console.log(err.message);
}
});
}
Y mi objeto de usuario se ve así:
{
"users" : {
"simplelogin:28" : {
"email" : "[email protected]",
"username" : "jtrinker"
},
"simplelogin:30" : {
"email" : "[email protected]",
"username" : "jtrinker"
}
}
}
}
Necesito usar el uid como clave para cada usuario, pero aún necesito que el nombre de usuario sea único.
¿Cómo puedo evitar que Firebase guarde registros si las propiedades dentro de un objeto no son exclusivas de las propiedades dentro de un objeto diferente?
¿No sería más fácil simplemente usar las reglas de seguridad para verificar su existencia? Tengo el mío configurado de la siguiente manera:
"usernames": {
"$usernameid": {
".read": "auth != null",
".write": "auth != null && (!data.exists() || !newData.exists())"
}
}
Esto permite escribir si el nombre de usuario no existe. Creo que lo obtuve directamente de los documentos de Firebase.
En primer lugar, si los usuarios ya tienen un username
, es único y esto no va a desaparecer, les recomiendo que abandonen el uso de los sencillos de inicio de sesión. Esto no creará más que problemas al tratar de ir y venir entre los dos, como ya has descubierto aquí. Investigue la creación de sus propios tokens con una herramienta como firebase-passport-login y luego almacene los registros por username
de username
.
Pero como esa no era su pregunta, resolvamos eso mientras estamos aquí, ya que es posible que desee seguir adelante y entrar en el espino espinoso de las identidades duales a través de las cuales he pasado muchas veces.
Para que el nombre de usuario sea único, almacene un índice de nombres de usuario.
/users/$userid/username/$username
/usernames/$username/$userid
Para garantizar que sean únicos, agregue una regla de seguridad de la siguiente manera en la identificación del usuario en los nombres de usuario / ruta, lo que asegura que solo se le puede asignar un usuario por nombre de usuario y que el valor es la identificación del usuario:
".write": "newData.val() === auth.uid && !data.exists()"
Ahora aplique que coincidan agregando lo siguiente al nombre de usuario en los usuarios / registro:
"users": {
"$userid": {
"username": {
".validate": "root.child(''usernames/''+newData.val()).val() === $userid"
}
}
}
Esto asegurará que los identificadores sean únicos. Tenga cuidado con los privilegios de lectura. Es posible que desee evitarlos por completo, ya que no desea que nadie busque correos electrónicos o nombres de usuario privados. Algo como lo demostré en apoyo para salvar estos sería ideal.
La idea aquí es que trates de asignar el nombre de usuario y el correo electrónico, si fallan, entonces ya existen y pertenecen a otro usuario. De lo contrario, los inserta en el registro del usuario y ahora los usuarios lo indexan mediante uid y correo electrónico.
Para cumplir con el protocolo SO, aquí está el código de esa esencia, que es mejor leer a través del enlace:
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);
);
}
Y las reglas:
{
"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"
}
},
}
}