This commit is contained in:
lkness 2024-07-22 22:44:23 +08:00
parent 74680b91b5
commit 869a13f72d
6 changed files with 1851 additions and 1 deletions

1413
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
workspace = { members = ["apps/account/domain/repo"] }
[package] [package]
name = "sold" name = "sold"
version = "0.1.0" version = "0.1.0"
@ -7,4 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
actix-swagger = "0.3.1"
actix-web = "4" actix-web = "4"

View File

@ -0,0 +1,66 @@
#![allow(dead_code, unused_imports)]
pub mod api {
#[doc = "Public API for Demo"]
pub struct DemoApi {
api: actix_swagger::Api,
}
impl DemoApi {
pub fn new() -> Self {
Self {
api: actix_swagger::Api::new(),
}
}
}
impl Default for DemoApi {
fn default() -> Self {
let api = Self::new();
api
}
}
impl actix_web::dev::HttpServiceFactory for DemoApi {
fn register(self, config: &mut actix_web::dev::AppService) {
self.api.register(config);
}
}
use super::paths;
use actix_swagger::{Answer, Method};
use actix_web::{dev::Factory, FromRequest};
use std::future::Future;
impl DemoApi {}
}
pub mod components {
pub mod parameters {
use serde::{Deserialize, Serialize};
}
pub mod request_bodies {
use serde::{Deserialize, Serialize};
}
pub mod responses {
use serde::{Deserialize, Serialize};
}
pub mod schemas {
use serde::{Deserialize, Serialize};
#[doc = "Current user in a session"]
#[derive(Debug, Serialize, Deserialize)]
pub struct SessionUser {
#[serde(rename = "firstName")]
pub first_name: String,
#[serde(rename = "lastName")]
pub last_name: String,
pub inner: Option<SessionUserInner>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SessionUserInner {
pub foo: Option<f32>,
pub bar: i32,
pub baz: SessionUserInnerBaz,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SessionUserInnerBaz {
pub demo: Option<String>,
}
}
}
pub mod paths {
use super::components::{parameters, responses};
}

View File

@ -0,0 +1,366 @@
openapi: 3.0.1
info:
title: Demo API.
version: 0.1.0
description: Public API for Demo
servers:
- url: http://localhost:9005/
paths:
"/oauth/authorize":
get:
operationId: oauthAuthorizeRequest
tags: [OAuth]
description: Authorization request
parameters:
- $ref: "#/components/parameters/OAuthResponseType"
- $ref: "#/components/parameters/OAuthClientId"
- $ref: "#/components/parameters/OAuthRedirectUri"
- $ref: "#/components/parameters/OAuthScope"
- $ref: "#/components/parameters/OAuthState"
responses:
303:
$ref: "#/components/responses/OAuthAuthorizeRequestDone"
"/oauth/token":
post:
operationId: oauthToken
tags: [OAuth]
description: Exchange the authorization code for an access token
requestBody:
$ref: "#/components/requestBodies/OAuthAccessTokenExchange"
responses:
201:
$ref: "#/components/responses/OAuthAccessTokenCreated"
"/register/request":
post:
operationId: registerRequest
tags: [Register]
# TODO: Add rate limit and CSRF protection
description: Send registration link to email
requestBody:
$ref: "#/components/requestBodies/Register"
responses:
201:
$ref: "#/components/responses/RegistrationRequestCreated"
400:
$ref: "#/components/responses/RegisterFailed"
500:
description: Something goes wrong
# Maybe add method to check code before fill form?
# Can improve a user experience
"/register/confirmation":
post:
operationId: registerConfirmation
tags: [Register]
# TODO: Add rate limit and CSRF protection
description: Confirm email, fill profile required fields and create user
requestBody:
$ref: "#/components/requestBodies/RegisterConfirmation"
responses:
201:
description: Okay, user created
400:
$ref: "#/components/responses/RegisterConfirmationFailed"
500:
description: Something goes wrong
"/session/create":
post:
operationId: sessionCreate
tags: [Session]
# TODO: Add rate limit and CSRF protection
description: Login and create new session tokens
requestBody:
$ref: "#/components/requestBodies/SessionCreate"
responses:
201:
$ref: "#/components/responses/SessionCreateSucceeded"
400:
$ref: "#/components/responses/SessionCreateFailed"
500:
description: Something went wrong
components:
responses:
OAuthAuthorizeRequestDone:
description: |
User redirected to `redirect_uri` with `error` or `code` <br/>
Possible errors: <br/>
If the user denies the authorization request, the server will redirect the user back to the redirect URL with error=`access_denied` in the query string, and no code will be present. It is up to the app to decide what to display to the user at this point.<br/>
`invalid_request` — The request is missing a required parameter, includes an invalid parameter value, or is otherwise malformed.<br/>
`unsupported_response_type` — The authorization server does not support obtaining an authorization code using this method.<br/>
`invalid_scope` — The requested scope is invalid, unknown, or malformed.<br/>
`server_error` — The authorization server encountered an unexpected condition which prevented it from fulfilling the request.<br/>
`temporarily_unavailable` — The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.<br/>
[OAuth2 Possible Errors](https://www.oauth.com/oauth2-servers/server-side-apps/possible-errors/)
headers:
Location:
schema:
type: string
format: uri
example: "https://example-app.com/oauth/callback?code=6a10d91379714605acb6c4b3f26a85aa"
OAuthAccessTokenCreated:
description:
The auth services validated the request and responds with an access token
[OAuth2 Example Flow](https://www.oauth.com/oauth2-servers/server-side-apps/example-flow/)
content:
application/json:
schema:
required:
- access_token
- token_type
- expires
properties:
access_token:
type: string
token_type:
type: string
enum: [bearer]
expires:
type: integer
format: int32
description: UTC Unix TimeStamp when the access token expires
RegistrationRequestCreated:
description: Registration link sent to email, now user can find out when the link expires
content:
application/json:
schema:
required:
- expiresAt
properties:
expiresAt:
type: integer
format: int32
description: UTC Unix TimeStamp when the link expires
RegisterFailed:
description: Please, login or recover password
content:
application/json:
schema:
required:
- error
properties:
error:
type: string
enum:
- "email_already_registered"
- "invalid_form"
- "invalid_payload"
RegisterConfirmationFailed:
description: Please, login or recover password
content:
application/json:
schema:
required:
- error
properties:
error:
type: string
enum:
- "code_invalid_or_expired"
- "email_already_activated"
- "invalid_form"
- "invalid_payload"
SessionCreateSucceeded:
description: Session created, token wrote to cookies
content:
application/json:
schema:
required:
- firstName
- lastName
properties:
firstName:
type: string
lastName:
type: string
SessionCreateFailed:
description: Login failed
content:
application/json:
schema:
required:
- error
properties:
error:
type: string
enum:
- "invalid_credentials"
- "invalid_form"
- "invalid_payload"
parameters:
OAuthResponseType:
name: response_type
in: query
required: true
description: response_type is set to code indicating that you want an authorization code as the response.
schema:
type: string
enum: [code]
OAuthClientId:
name: client_id
in: query
required: true
description: The client_id is the identifier for your app.
You will have received a client_id when first registering your app with the service.
schema:
type: string
format: uuid
example: 41190cee-5231-4dcc-8167-ebf798b55ce3
OAuthRedirectUri:
name: redirect_uri
in: query
required: true
description: |
The redirect_uri may be optional depending on the API, but is highly recommended.<br/>
This is the URL to which you want the user to be redirected after the authorization is complete.<br/>
This must match the redirect URL that you have previously registered with the service.<br/>
schema:
type: string
format: uri
example: https://example-app.com/oauth/callback
OAuthScope:
name: scope
in: query
required: false
description:
Include one or more scope values (space-separated) to request additional levels of access.<br/>
The values will depend on the particular service.<br/>
schema:
type: string
example: "user:view user:edit"
OAuthState:
name: state
in: query
required: false
description: The state parameter serves two functions.<br/>
When the user is redirected back to your app, whatever value you include as the state will also be included in the redirect.<br/>
This gives your app a chance to persist data between the user being directed to the authorization server and back again,
such as using the state parameter as a session key. This may be used to indicate what action in the app to perform after authorization is complete,
for example, indicating which of your apps pages to redirect to after authorization. This also serves as a CSRF protection mechanism.<br/>
When the user is redirected back to your app, double check that the state value matches what you set it to originally.
This will ensure an attacker cant intercept the authorization flow.
schema:
type: string
requestBodies:
OAuthAccessTokenExchange:
required: true
content:
application/json:
schema:
required:
- grant_type
- code
- redirect_uri
- client_id
- client_secret
properties:
grant_type:
type: string
enum: [authorization_code]
code:
type: string
description:
This parameter is for the authorization code received from the authorization server
which will be in the query string parameter “code” in this request.
redirect_uri:
type: string
format: uri
example: https://example-app.com/oauth/callback
description:
If the redirect URL was included in the initial authorization request,<br/>
it must be included in the token request as well, and must be identical.<br/>
Some services support registering multiple redirect URLs, and some require the redirect URL to be specified on each request.<br/>
client_id:
type: string
client_secret:
type: string
Register:
required: true
content:
application/json:
schema:
required:
- email
properties:
email:
type: string
RegisterConfirmation:
required: true
content:
application/json:
schema:
required:
- confirmationCode
- firstName
- lastName
- password
properties:
confirmationCode:
type: string
firstName:
type: string
lastName:
type: string
password:
type: string
SessionCreate:
required: true
content:
application/json:
schema:
required:
- email
- password
properties:
email:
type: string
format: email
password:
type: string
schemas:
SessionUser:
description: Current user in a session
type: object
required:
- firstName
- lastName
properties:
firstName:
type: string
lastName:
type: string
inner:
type: object
properties:
foo:
type: number
bar:
type: integer
baz:
type: object
properties:
demo:
type: string
required:
- baz
- bar

View File

@ -0,0 +1,5 @@
# 会报错cargo swagg ./openapi.yaml --out-file ./src/api.rs
cargo-swagger ./openapi.yaml --out-file ./src/api.rs
# Format file after
rustfmt ./src/api.rs