Implementar autenticación con tokens en un API requiere pruebas enfocadas y repetibles. Aquí se construye, con Test Driven Development, una suite en RSpec que valida el acceso a posts según su visibilidad y la identidad del usuario, usando headers de Authorization, context y subject para asegurar un payload y response correctos.
¿Qué objetivo tiene la autenticación con tokens en el API?
El objetivo es crear una implementación propia basada en tokens y empezar por las pruebas. Se separa el alcance en tres endpoints: detalle, creación y actualización. Se inicia por el de detalle, que resulta más directo. Para organizar, se crea un nuevo archivo de pruebas dedicado a posts con autenticación y se aprovecha context para describir escenarios.
En el flujo planteado se prioriza:
Empezar por pruebas y dejar que fallen primero.
Aislar el recurso de posts que requiere autenticación.
Dividir por endpoints y por visibilidad del post: público o borrador.
Probar acceso a contenido de otro usuario y del mismo usuario.
¿Cómo se estructura la suite de pruebas con RSpec?
Se organiza el spec con bloques describe y context para expresar intención. Se usan let para datos de prueba, subject para enfocar las expectativas en response y payload, y se simulan requests con get hacia el endpoint de detalle.
¿Cómo se preparan los datos con factory bot y let?
Se generan dos usuarios y al menos un post por cada uno. En los posts se referencia explícitamente el user_id para diferenciar autorías. Esto permite cubrir el caso de “post de otro autor” y “post del mismo usuario”.
# private_posts_spec.rbRSpec.describe 'Posts with authentication',type::requestdo describe 'GET /posts/:id'do context 'with authentication'do let(:user){ create(:user)} let(:other_user){ create(:user)} let(:user_post){ create(:post,user_id: user.id)} let(:other_user_post){ create(:post,user_id: other_user.id)}# Variante publicada y borrador del post de otro autor. let(:public_post){ other_user_post }# aquí garantiza que esté publicado. let(:draft_post){ other_user_post }# aquí configura que sea borrador.# ...endendend
¿Cómo se modelan los headers de autenticación en HTTP?
La autenticación viaja en un header adicional: Authorization. Por convención, el valor comienza con "bitter" seguido del token. Se define como un hash para pasarlo al request y se crean variantes para cada usuario.
Esta convención sigue lo usado en OAuth y permite enviar el token en cada request autenticado.
¿Cómo se usan context y subject para validar response y payload?
Se declara un subject para el response y otro para el payload. Así, las expectativas quedan expresivas y centradas en el objeto bajo prueba.
subject(:response){super()}subject(:payload){JSON.parse(response.body)}context 'when asking for other author post'do context 'when post is public'do before { get "/posts/#{public_post.id}",headers: auth_headers } it 'incluye el id en el payload'do expect(payload).to include('id'=> public_post.id)end it 'responde con status ok'do expect(response).to have_http_status(:ok)endend context 'when post is draft'do before { get "/posts/#{draft_post.id}",headers: auth_headers } it 'incluye un error en el payload'do expect(payload).to include('error')end it 'responde con not found'do expect(response).to have_http_status(:not_found)endendend
¿Qué comportamientos se validan en el endpoint de detalle?
Se cubren escenarios clave para restringir el acceso cuando corresponde y permitirlo cuando procede. La petición se realiza con get al endpointposts/:id usando headers de autenticación válidos.
Post público de otro autor: el payload incluye el id.
Post público de otro autor: el response tiene status ok.
Post en borrador de otro autor: el payload incluye un error.
Post en borrador de otro autor: el response devuelve not found.
Se ejecutan las pruebas y fallan al inicio: falta implementar la lógica de autenticación.
Así, la suite define un contrato verificable antes de escribir la lógica. En el siguiente paso, se implementa la autenticación para que todas las expectativas pasen.
¿Agregarías más casos, como acceso al post del mismo usuario o creación y actualización? Deja tus ideas y dudas en los comentarios.
Deberian desde estos cursos motivar las buenas prácticas, convenciones o guías de estilo en ruby…
Segun rubocop
No deberíamos escribir lineas de codigo de mas de 80 caracteres de largo
Los bloques de código no deberían sobrepasar las 25 lineas
Solo a mi me arrojan estas observaciones?
Tal vez en Uber no usan rubocop como linter de estilo. Sé que algunas empresas tienen sus propios standard de estilos.
Pero tal vez sí valdría la pena agregar un documento en el curso hablando de ese tema (Rubocop, Reek y demás).
@diegoalejojo, que interesante tu respuesta, no se me había ocurrido pensar en ello. Por otro lado seria muy bueno que estas detallitos los explicaran en algún lado, una posibilidad puede ser el documento que sugieres. Gracias por la info.
Con esta clase quede mas perdido que el chavo del 8, a veces el profe no explica casi nada y solo escribe codigo seria bueno que mejore su metodología de enseñanza a mi parecer
CurrentAttributes son como variables globales dentro de la aplicación!
¿Alguien sabe por qué no utiliza el método delete?
O sea quiero decir que dentro del CRUD que hace con posts nunca ve la funciòn de delete solo create, read y update...
No la usa porque no fue planeado usarla desde el inicio. Osea esta app no borra posts. Solo es por eso