9.5 KiB
Aşağıdaki metni aynen VSCode Copilot’a (veya başka bir kod üretecine) ver — tek istekte tam bir Rust web projesi iskeleti oluşturacak şekilde ayrıntılı, ama gereksiz karmaşıklıktan kaçınan, dosyalar ayrı ayrı olacak ve PostgreSQL kullanacak bir hesap sistemi üretmesini istiyorum. ÖNEMLİ: Kesinlikle bir ORM ve bir web framework kullanılsın — SeaORM (ORM) ve Axum (web framework) kullanılacak. Kod istemiyorum — sadece bu metni Copilot'a yapıştır ve proje oluşturmasını bekle.
Ek değişiklikler / kesin gereksinimler:
- Database: PostgreSQL olacak (default DATABASE_URL örneği .env.example içinde postgres://user:pass@localhost:5432/dbname).
- Tüm API yolları /api/v1/ prefix'i altında olacak (ör. /api/v1/auth/register, /api/v1/users/me).
- Auth: access_token (short-lived) ve refresh_token (long-lived) olacak.
- Parola hash algoritması: Argon2 yerine BCryptSHA256PasswordHasher uygulanacak şekilde iste — yani parola önce SHA-256 ile ön-hash edilecek, sonra bcrypt ile hash edilecek (Rust tarafında sha2 crate ile pre-hash + bcrypt crate ile bcrypt uygulaması). Copilot'a açıkça "Implement BCrypt-SHA256: SHA256(password) then bcrypt on hex/base64 of digest" diye belirt.
- OAuth: Google ve GitHub OAuth2 desteklenecek.
İstek (kopyala-yapıştır için; İngilizce olarak verilecek çünkü Copilot daha iyi anlar):
"Generate a complete, minimal and well-structured Rust web project that implements a user account system with these exact characteristics:
Project-wide:
- Use async Rust with Tokio runtime.
- Use Axum as web framework and SeaORM as ORM (SeaORM entities / ActiveModels).
- Use tracing for structured logs.
- Default database: PostgreSQL (connection via DATABASE_URL). The project must be structured so switching DBs only requires changing DATABASE_URL and running migrations via sea-orm-migration / sea-orm-cli.
- All endpoints MUST be under the prefix /api/v1/.
- Load configuration and secrets from .env (use dotenvy or envy). Provide a .env.example.
Authentication & Security:
- Email/password registration + login using BCrypt-SHA256 password hasher:
- Pre-hash the raw password with SHA-256 (use sha2 crate), then hash the resulting digest with bcrypt (use bcrypt crate).
- Provide helper functions to verify password with the same process.
- Document clearly in comments where to change to another hasher.
- Social login via Google and GitHub (OAuth2 flows using oauth2 crate; use reqwest or oauth2's HTTP client for provider calls).
- JWT access tokens and refresh tokens:
- Use jsonwebtoken crate.
- Sign tokens with SECRET_KEY from .env.
- Respect ACCESS_TOKEN_EXPIRE_MINUTES and REFRESH_TOKEN_EXPIRE_DAYS settings.
- Include both access_token and refresh_token in responses where applicable.
- Store refresh tokens in DB (store UUID string; include comment about switching to hashed storage if desired).
- Validate emails using a validator crate (e.g., validator).
Endpoints to implement (minimal but runnable):
- POST /api/v1/auth/register
- Accept JSON { "email": "...", "password": "..." }
- Validate email, pre-hash+bcrypt password, create user, create refresh token record, return { access_token, refresh_token, token_type, expires_in }.
- POST /api/v1/auth/login
- Accept JSON { "email": "...", "password": "..." }
- Verify credentials, return access + refresh tokens.
- POST /api/v1/auth/refresh
- Accept JSON { "refresh_token": "..." }
- Verify refresh token exists and not expired, return new access token (and optionally rotate refresh token).
- GET /api/v1/auth/oauth/{provider}
- provider ∈ {"google","github"} — build provider auth URL with required scopes and redirect the client.
- GET /api/v1/auth/oauth/{provider}/callback
- Exchange code for token, fetch user info (email), extract primary verified email, create/find user (hashed_password NULL, provider field set), create refresh token, return tokens (or redirect with tokens).
- POST /api/v1/auth/logout
- Accept JSON { "refresh_token": "..." } (or use header), delete/invalidate the refresh token in DB.
- GET /api/v1/users/me
- Protected with Authorization: Bearer <access_token>, returns current user info.
Data models (SeaORM / DB schema):
- users table / User entity (UUID primary key):
- id (UUID)
- email (unique)
- hashed_password (nullable for OAuth-only accounts)
- provider (nullable text: "google", "github", or NULL)
- is_active (boolean)
- created_at (timestamp)
- refresh_tokens table / RefreshToken entity:
- id (UUID)
- user_id (UUID FK)
- token (UUID string)
- created_at
- expires_at
Project layout (generator MUST create these files/modules — produce working Rust code for each):
- Cargo.toml (include: axum, tokio, sea-orm, sea-orm-migration, sea-orm-macros, dotenvy or envy, serde, serde_json, uuid, bcrypt, sha2, jsonwebtoken, oauth2, reqwest, chrono or time, validator, tracing, anyhow, thiserror)
- src/
- main.rs (app startup, router composition with /api/v1 prefix, load config, init SeaORM DB connection and run migrations at startup option)
- core/
- config.rs (Config struct loading env vars; typed fields for secrets, expirations, DB URL, OAuth client ids/secrets, OAUTH_REDIRECT_BASE)
- security.rs (BCrypt-SHA256 password helpers, JWT create/verify helpers, token payload types)
- oauth.rs (provider configs and helper functions to build auth URLs and exchange codes)
- db/
- mod.rs (SeaORM Database connection setup, run migrations helper)
- entities/ (SeaORM entities: users.rs, refresh_tokens.rs or a generated entities mod)
- schemas/
- mod.rs (request/response DTOs: RegisterRequest, LoginRequest, TokenResponse, RefreshRequest, UserResponse)
- services/
- auth_service.rs (register/login/refresh/oauth logic; create tokens; persist refresh tokens; rotate tokens if desired)
- user_service.rs (basic user CRUD and lookup using SeaORM ActiveModels)
- api/
- deps.rs (extractors for DB connection, typed config, and current_user extractor/middleware)
- routers/
- auth.rs (auth endpoints)
- users.rs (users/me)
- errors.rs (custom error types and conversions to HTTP responses)
- utils.rs (helpers e.g., time helpers, uuid helpers)
- migrations/
- sea-orm compatible migrations (or raw SQL) to create users and refresh_tokens for PostgreSQL (include at least initial migration file).
- .env.example (include all required env vars and example values; for PostgreSQL example: DATABASE_URL=postgres://user:password@localhost:5432/your_db)
- README.md (how to install, set up environment, run migrations with sea-orm-cli or sea-orm-migration runner, run app, env variables, how to register OAuth apps for Google & GitHub and set callback URLs — note callbacks will like be
${OAUTH_REDIRECT_BASE}/api/v1/auth/oauth/google/callbackand similarly for github) - tests/
- integration_tests.rs (basic integration tests that register a user, login, and call /api/v1/users/me using the access token; minimal and runnable)
Config & env vars (must be in .env.example):
- DATABASE_URL=postgres://user:password@localhost:5432/dbname
- SECRET_KEY=some_long_random_value
- ACCESS_TOKEN_EXPIRE_MINUTES=15
- REFRESH_TOKEN_EXPIRE_DAYS=30
- GOOGLE_CLIENT_ID=
- GOOGLE_CLIENT_SECRET=
- GITHUB_CLIENT_ID=
- GITHUB_CLIENT_SECRET=
- OAUTH_REDIRECT_BASE=http://localhost:3000
- SERVER_HOST=127.0.0.1
- SERVER_PORT=3000
Developer notes for the code generator (be explicit):
- Use SeaORM entities / ActiveModel for DB operations; keep queries simple and idiomatic.
- Migrations: provide sea-orm-migration or migration SQL and README instructions using sea-orm-cli:
- e.g., install: cargo install sea-orm-cli
- run migrations: DATABASE_URL="postgres://..." sea-orm-cli migrate up
- Implement BCrypt-SHA256 password hasher: pre-hash the UTF-8 password with SHA-256 (sha2::Sha256), encode digest (hex or base64), then pass that string to bcrypt::hash with a configurable cost. Provide verify routine that repeats pre-hash + bcrypt::verify.
- For OAuth: use oauth2 crate to construct authorize URL and to exchange code; use reqwest to fetch user info (emails) if needed. Scopes: Google ["openid","email","profile"] and GitHub ["user:email"].
- JWT tokens: use jsonwebtoken; include standard claims and expiry. Use typed structs for token claims.
- For refresh tokens: generate UUID strings and store them in DB with expiry. Provide optional rotation logic (brief comment).
- Provide clear error handling using thiserror and map to HTTP responses (axum::response::IntoResponse with proper status codes).
- The app should mount routes under /api/v1/ (e.g., router.route("/api/v1/auth/register", post(...)) ).
- Tests: include at least one integration test that runs a test server, registers a user, logs in, and calls /api/v1/users/me with the access token.
- Keep functions small, typed, and well-documented with comments explaining major steps.
Output expectation from Copilot:
- Create all files listed above with working Rust code (no pseudocode) and comments.
- The resulting project must be runnable:
- cargo build
- set .env from .env.example
- run sea-orm-cli migrate up (or provided migration runner)
- cargo run
- Test endpoints using curl/Postman at http://SERVER_HOST:SERVER_PORT with prefix /api/v1/
- README must explain how to switch DBs by changing DATABASE_URL and running migrations with appropriate flags (e.g., to switch to MySQL or Postgres, change features/driver).
- Language for generated code and docs: English (comments or README may include short Turkish notes if helpful)."
Not: Bu metni VSCode Copilot'a yapıştırdığımda tam bir Rust web projesi oluştursun; ben yalnızca prompt istedim — kod istemiyorum.