usuario paginas con angularjs firebase angularfire

angularjs - paginas - Aplicar nombres de usuario únicos con Firebase simplelogin



paginas web con angularjs (2)

Hay dos cosas que hacer aquí, una verificación del lado del cliente y una regla del lado del servidor.

En el lado del cliente, desea verificar si el nombre de usuario ya existe, para que pueda decirle al usuario que su entrada no es válida, antes de enviarla al servidor. Donde exactamente implementas esto, pero el código se vería así:

var ref = new Firebase(''https://YourFirebase.firebaseio.com''); var q = ref.child(''profiles'').orderByChild(''username'').equalTo(newUsername); q.once(''value'', function(snapshot) { if (snapshot.val() === null) { // username does not yet exist, go ahead and add new user } else { // username already exists, ask user for a different name } });

Puede usar esto para verificar antes de escribir en el servidor. Sin embargo, ¿qué sucede si un usuario es malicioso y decide usar la consola JS para escribir en el servidor de todos modos? Para evitar esto, necesita seguridad del lado del servidor.

Traté de encontrar una solución de ejemplo, pero me encontré con un problema. Con suerte, vendrá alguien más conocedor. Mi problema es el siguiente. Digamos que la estructura de su base de datos se ve así:

{ "profiles" : { "profile1" : { "username" : "Nick", "md5_hash" : "..." }, "profile2" : { "username" : "Marein", "md5_hash" : "..." } } }

Al agregar un nuevo perfil, querrá tener una regla que garantice que no exista ningún objeto de perfil con la misma propiedad de username . Sin embargo, hasta donde yo sé, el lenguaje de seguridad de Firebase no es compatible con esto, con esta estructura de datos.

Una solución sería cambiar la estructura de datos para usar el username como clave para cada perfil (en lugar de profile1 , profile1 , ...). De esa manera, solo puede haber un objeto con ese nombre de usuario, automáticamente. La estructura de la base de datos sería:

{ "profiles" : { "Nick" : { "md5_hash" : "..." }, "Marein" : { "md5_hash" : "..." } } }

Esta podría ser una solución viable en este caso. Sin embargo, ¿qué sucede si no solo el nombre de usuario, sino también el correo electrónico tiene que ser único? Ambos no pueden ser la clave del objeto (a menos que usemos concatenación de cadenas ...).

Una cosa más que viene a la mente es, además de la lista de perfiles, mantener una lista separada de nombres de usuario y una lista separada de correos electrónicos también. Luego, se pueden usar fácilmente en las reglas de seguridad para verificar si el nombre de usuario y el correo electrónico ya existen. Las reglas se verían así:

{ "rules" : { ".write" : true, ".read" : true, "profiles" : { "$profile" : { "username" : { ".validate" : "!root.child(''usernames'').child(newData.val()).exists()" } } }, "usernames" : { "$username" : { ".validate" : "newData.isString()" } } } }

Sin embargo, ahora nos encontramos con otro problema; ¿Cómo asegurarse de que cuando se crea un nuevo perfil, el nombre de usuario (y el correo electrónico) también se colocan en estas nuevas listas? [1]

Esto, a su vez, puede resolverse sacando el código de creación de perfil del cliente y colocándolo en un servidor. El cliente necesitaría pedirle al servidor que cree un nuevo perfil, y el servidor se aseguraría de que se ejecuten todas las tareas necesarias.

Sin embargo, parece que hemos ido muy lejos para responder esta pregunta. Quizás he pasado por alto algo y las cosas son más simples de lo que parecen. Cualquier pensamiento es apreciado.

Además, disculpas si esta respuesta se parece más a una pregunta que a una respuesta, soy nuevo en SO y aún no estoy seguro de qué es lo apropiado como respuesta.

[1] Aunque quizás podría argumentar que no es necesario garantizar esto, ya que un usuario malintencionado solo se dañaría a sí mismo al no reclamar su identidad única.

Recientemente he seguido un tutorial sobre Thinkster para crear una aplicación web usando Angular y Firebase.

El tutorial usa el método Firebase simpleLogin que permite crear un ''perfil'' que incluye un nombre de usuario.

Fábrica:

app.factory(''Auth'', function($firebaseSimpleLogin, $firebase, FIREBASE_URL, $rootScope) { var ref = new Firebase(FIREBASE_URL); var auth = $firebaseSimpleLogin(ref); var Auth = { register: function(user) { return auth.$createUser(user.email, user.password); }, createProfile: function(user) { var profile = { username: user.username, md5_hash: user.md5_hash }; var profileRef = $firebase(ref.child(''profile'')); return profileRef.$set(user.uid, profile); }, login: function(user) { return auth.$login(''password'', user); }, logout: function() { auth.$logout(); }, resolveUser: function() { return auth.$getCurrentUser(); }, signedIn: function() { return !!Auth.user.provider; }, user: {} }; $rootScope.$on(''$firebaseSimpleLogin:login'', function(e, user) { angular.copy(user, Auth.user); Auth.user.profile = $firebase(ref.child(''profile'').child(Auth.user.uid)).$asObject(); console.log(Auth.user); }); $rootScope.$on(''$firebaseSimpleLogin:logout'', function() { console.log(''logged out''); if (Auth.user && Auth.user.profile) { Auth.user.profile.$destroy(); } angular.copy({}, Auth.user); }); return Auth; });

Controlador:

$scope.register = function() { Auth.register($scope.user).then(function(user) { return Auth.login($scope.user).then(function() { user.username = $scope.user.username; return Auth.createProfile(user); }).then(function() { $location.path(''/''); }); }, function(error) { $scope.error = error.toString(); }); };

Al final del tutorial hay una sección de "próximos pasos" que incluye:

Haga cumplir la unicidad del nombre de usuario: este es complicado, consulte las prioridades de Firebase y vea si puede usarlas para consultar los perfiles de usuario por nombre de usuario

He buscado y buscado pero no puedo encontrar una explicación clara de cómo hacer esto, particularmente en términos de la función setPriority() de Firebase

Soy un novato de Firebase, por lo que cualquier ayuda aquí sería agradecida.

Hay algunas preguntas similares , pero parece que no puedo entender cómo resolver esto.

Enormes gracias de antemano.

EDITAR

De la respuesta de Marein, he actualizado la función de registro en mi controlador para:

$scope.register = function() { var ref = new Firebase(FIREBASE_URL); var q = ref.child(''profile'').orderByChild(''username'').equalTo($scope.user.username); q.once(''value'', function(snapshot) { if (snapshot.val() === null) { Auth.register($scope.user).then(function(user) { return Auth.login($scope.user).then(function() { user.username = $scope.user.username; return Auth.createProfile(user); }).then(function() { $location.path(''/''); }); }, function(error) { $scope.error = error.toString(); }); } else { // username already exists, ask user for a different name } }); };

Pero arroja un error ''indefinido no es una función'' en la línea var q = ref.child(''profile'').orderByChild(''username'').equalTo($scope.user.username); . He comentado el código después y probé solo console.log (q) pero aún así no me alegro.

EDITAR 2

El problema con lo anterior fue que el tutorial de Thinkster usa Firebase 0.8 y orderByChild solo está disponible en versiones posteriores. Actualizado y la respuesta de Marein es perfecta.


Tuve un problema similar. Pero fue después de registrar al usuario con contraseña y correo electrónico. En el perfil de usuario podría guardar un nombre de usuario que debe ser único y he encontrado una solución, tal vez esto pueda servirle.

Consulta para nombre de usuario único en Firebase

var ref = new Firebase(FIREBASE_URL + ''/users''); ref.orderByChild("username").equalTo(profile.username).on("child_added", function(snapshot) { if (currentUser != snapshot.key()) { scope.used = true; } }); ref.orderByChild("username").equalTo(profile.username).once("value", function(snap) { //console.log("initial data loaded!", Object.keys(snap.val()).length === count); if (scope.used) { console.log(''username already exists''); scope.used = false; }else{ console.log(''username doesnt exists, update it''); userRef.child(''username'').set(profile.username); } }); };