### Description
- In beta environment, `v0.3.0` migration has been run, a manual revertion is required; in real environment, there is nothing to do, but to do #97 and remove migration record for `v0.1.1` manually.
### Package Changes
_No response_
### Screenshots
_No response_
### Reference
Resolves#95
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #98
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
This PR introduces the functionality to persist user information in the database. When a user logs in via OIDC for the first time, a new user record is created. Subsequent logins will retrieve the existing user data from the database.
This change ensures that users have a persistent identity within our system, identified by their unique combination of OIDC issuer and subject ID.
#### Key Changes
* **User Persistence Logic**:
* In `ExchangeAuthCodeUseCase`, after successfully exchanging the authorization code, the logic now checks if the user exists in our database using their `issuer` and `source_id`.
* If the user is not found (`AuthError::UserNotFound`), a new record is created in the `user` table.
* The `User` entity returned by the use case now contains the internal database `id`.
* **Database Integration in Auth Feature**:
* Introduced a new `UserDbService` trait and its `sqlx`-based implementation, `UserDbServiceImpl`, to handle database operations for users.
* The `AuthRepository` is extended to include methods for querying (`get_user_by_source_id`) and saving (`save_user`) users, delegating the calls to the new `UserDbService`.
* The dependency injection container in `server/src/container.rs` has been updated to provide the `UserDbServiceImpl` to the `AuthRepositoryImpl`.
* **Domain and Data Model Updates**:
* The `User` domain entity now includes `id` (the database primary key) and `issuer` (from OIDC claims) to uniquely identify a user across different identity providers.
* The `UserResponseDto` now exposes the internal `id` instead of the `source_id`.
* **Session Management**:
* The user's session now stores the database `user_id` (`i32`) instead of the entire user object. This is more efficient and secure.
* Session keys have been centralized into a `constants.rs` file for better maintainability.
#### Database Changes
* A new database migration has been added to create the `user` table.
* The table includes columns for `id`, `issuer`, `source_id`, `displayed_name`, and `email`.
* A **`UNIQUE` index** has been created on `(source_id, issuer)` to guarantee that each user from a specific identity provider is stored only once.
#### Refactoring
* Minor refactoring in the `image` feature to change `id: Option<i32>` to `id: i32` for consistency with the new `User` entity model.
### Package Changes
_No response_
### Screenshots
_No response_
### Reference
Resolves#94
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #96
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
- Add some endpoints about image:
- POST `/image/upload`
- GET `/image/{id}`
> [!NOTE]
> Since there isn't identity authentication, the `/image` endpoints should be restricted to private network in nginx.
> [!NOTE]
> Volume for backend should be configured in `pod.yaml`.
### Package Changes
```toml
actix-multipart = "0.7.2"
```
### Screenshots
_No response_
### Reference
Resolves#78
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #84
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
- `GET` `/post_info`
Get all the info of the posts.
- `200` Without any post
```json
[]
```
- `200` With posts
```json
[
{
"description": "This is the first post.",
"id": 1,
"labels": [
{
"color": "#FF666666",
"id": 2,
"name": "Rust"
}
],
"preview_image_url": "https://squidspirit.com/icon/logo-light.svg",
"published_time": null,
"title": "The First Post"
}
]
```
- `GET` `/post/{id}`
Get the full post content with the given `id`
- `200` With result
```json
{
"content": "Hello! I'm Squid!!",
"id": 1,
"info": {
"description": "This is the first post.",
"id": 1,
"labels": [
{
"color": "#FF666666",
"id": 2,
"name": "Rust"
}
],
"preview_image_url": "https://squidspirit.com/icon/logo-light.svg",
"published_time": null,
"title": "The First Post"
}
}
```
- `404` There is no post with the `id`
### Package Changes
```toml
[workspace.package]
version = "0.1.1"
edition = "2024"
[workspace.dependencies]
actix-web = "4.10.2"
async-trait = "0.1.88"
chrono = "0.4.41"
dotenv = "0.15.0"
env_logger = "0.11.8"
futures = "0.3.31"
log = "0.4.27"
serde = { version = "1.0.219", features = ["derive"] }
sqlx = { version = "0.8.5", features = [
"chrono",
"macros",
"postgres",
"runtime-tokio-rustls",
] }
tokio = { version = "1.45.0", features = ["full"] }
```
### Screenshots
_No response_
### Reference
Resolves#43
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #55
Reviewed-by: zoe <zoe@noreply.localhost>
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>