diff --git a/README.md b/README.md index c7aaa81..7170d19 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,23 @@ -# User service +## user-service +- **Purpose:** User registration/login and JWT issuance. +- **Base path:** `/api/users` -## Create users database + user on mysql server +### Create database ``` kubectl -n cloudshopt exec -it cloudshopt-mysql-0 -- bash -``` -``` +# mysql -u root -prootpass + CREATE DATABASE cloudshopt_users CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -CREATE USER 'users'@'%' IDENTIFIED BY 'userspass'; +CREATE USER 'users'@'%' IDENTIFIED BY 'CHANGE_ME_PASSWORD'; GRANT ALL PRIVILEGES ON cloudshopt_users.* TO 'users'@'%'; FLUSH PRIVILEGES; ``` -Ustvari še bazo za *dev* okolje -``` -CREATE DATABASE cloudshopt_users_dev CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -CREATE USER 'users_dev'@'%' IDENTIFIED BY 'userspass'; -GRANT ALL PRIVILEGES ON cloudshopt_users_dev.* TO 'users_dev'@'%'; -FLUSH PRIVILEGES; -``` - -## Crete external secrets for prod and dev -prod: -``` -kubectl -n cloudshopt create secret generic user-service-secrets \ - --from-literal=DB_PASSWORD="userspass" \ - --from-literal=REDIS_PASSWORD="redispass" \ - --dry-run=client -o yaml | kubectl apply -f - -``` - -dev: -``` -kubectl -n cloudshopt-dev create secret generic user-service-secrets \ - --from-literal=DB_PASSWORD="userspass" \ - --from-literal=REDIS_PASSWORD="redispass" \ - --dry-run=client -o yaml | kubectl apply -f - -``` - -check for secrets: -``` -kubectl get secret -n cloudshopt user-service-secrets -kubectl get secret -n cloudshopt-dev user-service-secrets -``` +### Migrations -## Install user-service for prod and dev -prod: ``` -helm upgrade --install user-service ./helm/user-service \ --n cloudshopt \ --f helm/user-service/values.yaml -``` - -dev: -``` -helm upgrade --install user-service-dev ./helm/user-service \ --n cloudshopt-dev \ --f helm/user-service/values-dev.yaml -``` - - - -## Migrations - -run migrations: -``` -kubectl exec -n cloudshopt-dev -it deploy/user-service-dev -c app -- sh - +kubectl exec -n cloudshopt -it deploy/user-service -c app -- sh # php artisan migrate ``` + diff --git a/docs/openapi.yaml b/docs/openapi.yaml new file mode 100644 index 0000000..76410b5 --- /dev/null +++ b/docs/openapi.yaml @@ -0,0 +1,244 @@ +openapi: 3.0.3 +info: + title: CloudShopt User Service API + version: 1.0.0 +tags: + - name: Health + - name: Diagnostics + - name: Auth + +paths: + /healthz: + get: + tags: [Health] + summary: Health check + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/StatusOkBool" + + /info: + get: + tags: [Diagnostics] + summary: Service info (sha, time) + responses: + "200": + description: Info + content: + application/json: + schema: + $ref: "#/components/schemas/InfoResponse" + + /database: + get: + tags: [Diagnostics] + summary: Database connectivity check + responses: + "200": + description: DB OK + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseOkResponse" + "500": + description: DB connection failed + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseFailResponse" + + /auth/register: + post: + tags: [Auth] + summary: Register user + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/RegisterRequest" + responses: + "201": + description: Registered + content: + application/json: + schema: + $ref: "#/components/schemas/AuthResponse" + "422": + $ref: "#/components/responses/ValidationError" + + /auth/login: + post: + tags: [Auth] + summary: Login user + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/LoginRequest" + responses: + "200": + description: Logged in + content: + application/json: + schema: + $ref: "#/components/schemas/AuthResponse" + "422": + $ref: "#/components/responses/ValidationError" + + /me: + get: + tags: [Auth] + summary: Get current user (JWT) + security: + - bearerAuth: [] + responses: + "200": + description: User + content: + application/json: + schema: + $ref: "#/components/schemas/MeResponse" + "401": + $ref: "#/components/responses/Unauthorized" + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + responses: + Unauthorized: + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorMessage" + examples: + missingToken: + value: { message: "Missing Bearer token" } + invalid: + value: { message: "Invalid or expired token" } + + ValidationError: + description: Validation error + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + + schemas: + ErrorMessage: + type: object + required: [message] + properties: + message: { type: string } + + ValidationError: + type: object + required: [message, errors] + properties: + message: { type: string } + errors: + type: object + additionalProperties: + type: array + items: { type: string } + + StatusOkBool: + type: object + required: [ok] + properties: + ok: + type: boolean + example: true + + InfoResponse: + type: object + required: [ok, service, sha, time] + properties: + ok: { type: boolean, example: true } + service: { type: string, example: user-service } + sha: + type: string + nullable: true + example: 0.0.1 + time: + type: string + format: date-time + example: "2026-01-29T10:15:30.123Z" + + DatabaseOkResponse: + type: object + required: [ok, db, time] + properties: + ok: { type: boolean, example: true } + db: + type: object + required: [connection, database, ping_ms] + properties: + connection: { type: string, example: mysql } + database: { type: string, example: cloudshopt_users_dev } + ping_ms: { type: number, format: float, example: 1.25 } + time: + type: string + format: date-time + example: "2026-01-29T10:15:30.123Z" + + DatabaseFailResponse: + type: object + required: [ok, error, message] + properties: + ok: { type: boolean, example: false } + error: { type: string, example: DB connection failed } + message: + type: string + nullable: true + example: "SQLSTATE[HY000] ..." + + User: + type: object + required: [id, name, email] + properties: + id: { type: integer, example: 2 } + name: { type: string, example: Timotej } + email: { type: string, format: email, example: timotej@test.com } + + RegisterRequest: + type: object + required: [name, email, password, password_confirmation] + properties: + name: { type: string } + email: { type: string, format: email } + password: { type: string, format: password } + password_confirmation: { type: string, format: password } + + LoginRequest: + type: object + required: [email, password] + properties: + email: { type: string, format: email } + password: { type: string, format: password } + + AuthResponse: + type: object + required: [token, token_type, expires_in, user] + properties: + token: { type: string } + token_type: { type: string, example: Bearer } + expires_in: { type: integer, example: 3600 } + user: + $ref: "#/components/schemas/User" + + MeResponse: + type: object + required: [user] + properties: + user: + $ref: "#/components/schemas/User" \ No newline at end of file diff --git a/resources/views/swagger.blade.php b/resources/views/swagger.blade.php new file mode 100644 index 0000000..038dc67 --- /dev/null +++ b/resources/views/swagger.blade.php @@ -0,0 +1,22 @@ + + +
+ + +