mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-06 03:20:13 +08:00
760 lines
19 KiB
YAML
760 lines
19 KiB
YAML
openapi: 3.0.0
|
|
servers:
|
|
- url: /api/v1
|
|
- url: https://linuxodyssey.xyz/api/v1
|
|
- url: http://localhost:3000/api/v1
|
|
info:
|
|
description: Linux Odyssey API
|
|
version: '1.0.0'
|
|
title: Session API
|
|
contact:
|
|
email: contact@linuxodyssey.xyz
|
|
license:
|
|
name: Apache 2.0
|
|
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
|
|
tags:
|
|
- name: admins
|
|
description: Secured Admin-only calls
|
|
- name: developers
|
|
description: Operations available to regular developers
|
|
paths:
|
|
/sessions:
|
|
get:
|
|
tags:
|
|
- signed-in
|
|
summary: list existing sessions of current user
|
|
security:
|
|
- cookieAuth: []
|
|
parameters:
|
|
- in: query
|
|
name: questId
|
|
description: find sessions by quest id
|
|
schema:
|
|
type: string
|
|
- in: query
|
|
name: status
|
|
description: find sessions by status
|
|
schema:
|
|
type: string
|
|
enum: [active, finished, inactive]
|
|
responses:
|
|
'200':
|
|
description: list of existing session
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/SessionSummary'
|
|
|
|
post:
|
|
summary: create a new session for current user
|
|
tags:
|
|
- signed-in
|
|
security:
|
|
- cookieAuth: []
|
|
requestBody:
|
|
description: session data
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
questId:
|
|
type: string
|
|
example: helloworld
|
|
responses:
|
|
'201':
|
|
description: session created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Session'
|
|
'400':
|
|
description: Invalid input
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
'403':
|
|
description: This quest is locked.
|
|
|
|
/sessions/active:
|
|
post:
|
|
summary: 'Get or create an active session.'
|
|
tags:
|
|
- signed-in
|
|
description: 'This endpoint returns the latest active session for the user, or creates a new one if no active session exists.'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: 'object'
|
|
required:
|
|
- questId
|
|
properties:
|
|
questId:
|
|
type: 'string'
|
|
description: 'The ID of the quest.'
|
|
example: 'helloworld'
|
|
responses:
|
|
200:
|
|
description: 'Return a active session.'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Session'
|
|
400:
|
|
description: 'Bad Request. The request is invalid or malformed.'
|
|
403:
|
|
description: This quest is locked.
|
|
500:
|
|
description: 'Internal Server Error.'
|
|
|
|
/sessions/{sessionId}:
|
|
get:
|
|
tags:
|
|
- signed-in
|
|
summary: get a specific session of current user by ID
|
|
security:
|
|
- cookieAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: sessionId
|
|
description: ID of the session to retrieve
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: objectId
|
|
example: 64b7a3a3c182b4826dd1aaa1
|
|
responses:
|
|
'200':
|
|
description: the session
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Session'
|
|
'404':
|
|
description: cannot find specific session
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
|
|
/auth/register:
|
|
post:
|
|
summary: Register a new user
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
format: username
|
|
example: alex
|
|
email:
|
|
type: string
|
|
format: email
|
|
example: alex@example.com
|
|
password:
|
|
type: string
|
|
format: password
|
|
example: 123456
|
|
responses:
|
|
'201':
|
|
description: User created
|
|
headers:
|
|
Set-Cookie:
|
|
schema:
|
|
type: string
|
|
example: connect.sid=s%3Aq1Z; Path=/; HttpOnly; SameSite=Strict; Secure
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
token:
|
|
type: string
|
|
description: Access token
|
|
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
'400':
|
|
description: Bad Request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Missing username, email or password
|
|
'409':
|
|
description: Conflict
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: User already exists
|
|
|
|
/auth/register-from-session:
|
|
post:
|
|
summary: Register a new user from a session, for social login to pick a username
|
|
security:
|
|
- cookieAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
format: username
|
|
example: alex
|
|
responses:
|
|
'201':
|
|
description: User created
|
|
headers:
|
|
Set-Cookie:
|
|
schema:
|
|
type: string
|
|
example: connect.sid=s%3Aq1Z; Path=/; HttpOnly; SameSite=Strict; Secure
|
|
|
|
/auth/register-guest:
|
|
post:
|
|
summary: Register a new guest user
|
|
responses:
|
|
201:
|
|
description: User created
|
|
headers:
|
|
Set-Cookie:
|
|
schema:
|
|
type: string
|
|
example: connect.sid=s%3Aq1Z; Path=/; HttpOnly; SameSite=Strict; Secure
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/User'
|
|
|
|
/auth/login:
|
|
post:
|
|
summary: Log in a user
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
format: username
|
|
example: alex
|
|
password:
|
|
type: string
|
|
format: password
|
|
example: 123456
|
|
responses:
|
|
'200':
|
|
description: User logged in
|
|
headers:
|
|
Set-Cookie:
|
|
schema:
|
|
type: string
|
|
example: connect.sid=s%3Aq1Z; Path=/; HttpOnly; SameSite=Strict; Secure
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Logged in successfully
|
|
'400':
|
|
description: Bad Request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Missing username or password
|
|
'401':
|
|
description: Unauthorized
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Incorrect username or password
|
|
|
|
/auth/logout:
|
|
post:
|
|
summary: Log out a user
|
|
tags:
|
|
- signed-in
|
|
security:
|
|
- cookieAuth: []
|
|
responses:
|
|
'200':
|
|
description: User logged out
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Logged out successfully
|
|
|
|
/auth/check-username:
|
|
get:
|
|
summary: Check if the username is already taken
|
|
parameters:
|
|
- in: query
|
|
name: username
|
|
description: username to check
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: username
|
|
example: alex
|
|
- in: query
|
|
name: email
|
|
description: email to check
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: email
|
|
example: alex@example.com
|
|
responses:
|
|
'200':
|
|
description: Username / Email checking result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
example: Username is available
|
|
available:
|
|
type: boolean
|
|
example: true
|
|
'400':
|
|
description: Bad Request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Username is already taken
|
|
|
|
/auth/available-methods:
|
|
get:
|
|
summary: Get available login methods
|
|
responses:
|
|
'200':
|
|
description: Available login methods
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
local:
|
|
type: boolean
|
|
example: true
|
|
github:
|
|
type: boolean
|
|
example: true
|
|
google:
|
|
type: boolean
|
|
example: true
|
|
facebook:
|
|
type: boolean
|
|
example: true
|
|
|
|
/auth/check-session:
|
|
get:
|
|
summary: Check if the session is valid
|
|
responses:
|
|
'200':
|
|
description: Result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
loggedIn:
|
|
type: boolean
|
|
example: true
|
|
|
|
/auth/google:
|
|
get:
|
|
summary: Initiate OAuth2 login with Google
|
|
operationId: initiateOAuth
|
|
security:
|
|
- GoogleOAuth: []
|
|
responses:
|
|
302:
|
|
description: Redirect to Google's OAuth 2.0 authorization endpoint
|
|
500:
|
|
description: Internal Server Error
|
|
/auth/google/callback:
|
|
get:
|
|
summary: OAuth2 callback endpoint
|
|
operationId: oauthCallback
|
|
parameters:
|
|
- name: code
|
|
in: query
|
|
description: Authorization code from Google
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
200:
|
|
description: Successful Operation
|
|
400:
|
|
description: Bad Request
|
|
500:
|
|
description: Internal Server Error
|
|
|
|
/quests:
|
|
get:
|
|
summary: Get quests list
|
|
responses:
|
|
'200':
|
|
description: Quests summary list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/QuestSummary'
|
|
|
|
/quests/{questId}:
|
|
get:
|
|
summary: get a quest's detail by name
|
|
parameters:
|
|
- in: path
|
|
name: questId
|
|
description: name of the quest to retrieve
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: the quest
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Quest'
|
|
'404':
|
|
description: cannot find specific quest
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
|
|
/commands:
|
|
post:
|
|
summary: Record a command that was executed in a session
|
|
tags:
|
|
- signed-in
|
|
security:
|
|
- cookieAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Command'
|
|
responses:
|
|
'201':
|
|
description: Command recorded successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CommandResponse'
|
|
'400':
|
|
description: Invalid request body
|
|
'401':
|
|
description: Unauthorized
|
|
/ip:
|
|
get:
|
|
summary: Get client IP address
|
|
responses:
|
|
'200':
|
|
description: IP address
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
ip:
|
|
type: string
|
|
example: '127.0.0.1'
|
|
|
|
/users/me:
|
|
get:
|
|
summary: Get current user's profile
|
|
tags:
|
|
- signed-in
|
|
security:
|
|
- cookieAuth: []
|
|
responses:
|
|
'200':
|
|
description: User profile
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UserProfile'
|
|
'401':
|
|
description: Unauthorized
|
|
|
|
components:
|
|
schemas:
|
|
User:
|
|
type: object
|
|
properties:
|
|
_id:
|
|
type: string
|
|
format: objectId
|
|
example: 64b7a3a3c182b4826dd1aaa1
|
|
username:
|
|
type: string
|
|
example: 'alex'
|
|
email:
|
|
type: string
|
|
format: email
|
|
|
|
UserProfile:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
example: 'alex'
|
|
email:
|
|
type: string
|
|
format: email
|
|
example: alex@example.com
|
|
progress:
|
|
type: object
|
|
additionalProperties:
|
|
$ref: '#/components/schemas/Progress'
|
|
|
|
Progress:
|
|
type: object
|
|
properties:
|
|
questId:
|
|
type: string
|
|
example: helloworld
|
|
sessions:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: objectId
|
|
example: 64b7a3a3c182b4826dd1aaa1
|
|
completed:
|
|
type: boolean
|
|
example: true
|
|
startedAt:
|
|
type: string
|
|
format: date-time
|
|
example: 2020-01-01T00:00:00.000Z
|
|
finishedAt:
|
|
type: string
|
|
format: date-time
|
|
example: 2020-01-01T00:00:00.000Z
|
|
|
|
Quest:
|
|
type: object
|
|
properties:
|
|
_id:
|
|
type: string
|
|
example: helloworld
|
|
title:
|
|
type: string
|
|
example: Hello World
|
|
instruction:
|
|
type: string
|
|
example: 'In this quest, you need to learn how to use `ls` to list the file.'
|
|
order:
|
|
type: number
|
|
|
|
QuestSummary:
|
|
type: object
|
|
properties:
|
|
_id:
|
|
type: string
|
|
example: helloworld
|
|
title:
|
|
type: string
|
|
example: Hello World
|
|
order:
|
|
type: number
|
|
|
|
Session:
|
|
type: object
|
|
properties:
|
|
_id:
|
|
type: string
|
|
format: objectId
|
|
example: 64b7a3a3c182b4826dd1aaa1
|
|
user:
|
|
$ref: '#/components/schemas/User'
|
|
quest:
|
|
$ref: '#/components/schemas/Quest'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
finishedAt:
|
|
type: string
|
|
format: date-time
|
|
hints:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: '`ls -al` to list detail information of all files.'
|
|
progress:
|
|
type: string
|
|
description: current stage id
|
|
example: helloworld
|
|
completed:
|
|
type: array
|
|
description: list of completed stage ids
|
|
items:
|
|
type: string
|
|
example: helloworld
|
|
|
|
SessionSummary:
|
|
type: object
|
|
properties:
|
|
_id:
|
|
type: string
|
|
format: objectId
|
|
example: 64b7a3a3c182b4826dd1aaa1
|
|
quest:
|
|
$ref: '#/components/schemas/Quest'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
finishedAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
TreeNode:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
display:
|
|
type: boolean
|
|
children:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/TreeNode'
|
|
|
|
Command:
|
|
type: object
|
|
required:
|
|
- pwd
|
|
- command
|
|
properties:
|
|
pwd:
|
|
type: string
|
|
example: '/root'
|
|
description: The current working directory
|
|
command:
|
|
type: string
|
|
example: 'ls -al /'
|
|
description: The command that was executed
|
|
output:
|
|
type: string
|
|
description: The output of the command
|
|
error:
|
|
type: string
|
|
description: The error message of the command
|
|
|
|
CommandResponse:
|
|
type: object
|
|
properties:
|
|
responses:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/CommandResponseItem'
|
|
hints:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: '`ls -al` to list detail information of all files.'
|
|
end:
|
|
type: boolean
|
|
description: Whether the session has ended
|
|
|
|
CommandResponseItem:
|
|
type: object
|
|
required:
|
|
- type
|
|
- content
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [narrative, dialogue]
|
|
content:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: 'You have completed the quest!'
|
|
color:
|
|
type: string
|
|
enum: [red, green, blue, yellow, purple, cyan, white, gray, black]
|
|
speaker:
|
|
type: string
|
|
example: 'Unix Spirit'
|
|
|
|
securitySchemes:
|
|
cookieAuth:
|
|
type: apiKey
|
|
in: cookie
|
|
name: connect.sid
|
|
|
|
GoogleOAuth:
|
|
type: oauth2
|
|
flows:
|
|
authorizationCode:
|
|
authorizationUrl: https://accounts.google.com/o/oauth2/auth
|
|
tokenUrl: https://accounts.google.com/o/oauth2/token
|
|
scopes:
|
|
# Define your scopes here
|
|
openid: OpenID
|
|
profile: User profile
|
|
email: User email
|