init
This commit is contained in:
21
app/app.go
21
app/app.go
@@ -42,6 +42,17 @@ func NewApp(cfg *config.Config) *App {
|
|||||||
// Channel pour les erreurs
|
// Channel pour les erreurs
|
||||||
errChan := make(chan error, 1)
|
errChan := make(chan error, 1)
|
||||||
|
|
||||||
|
// database init
|
||||||
|
dbConfig := database.DBConfig{
|
||||||
|
Driver: cfg.Database.Type,
|
||||||
|
DSN: cfg.GetDSN(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1) Initialiser la DB
|
||||||
|
if err := database.Initialize(dbConfig); err != nil {
|
||||||
|
//return fmt.Errorf("failed to initialize database: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Servers
|
// Servers
|
||||||
udpServer := udp.NewServer(cfg.Server.BindAddr)
|
udpServer := udp.NewServer(cfg.Server.BindAddr)
|
||||||
httpServer := http.NewServer(cfg.Server.BindAddr)
|
httpServer := http.NewServer(cfg.Server.BindAddr)
|
||||||
@@ -61,16 +72,6 @@ func (app *App) Run() error {
|
|||||||
// Context pour gérer l'arrêt gracieux
|
// Context pour gérer l'arrêt gracieux
|
||||||
defer app.cancel()
|
defer app.cancel()
|
||||||
|
|
||||||
dbConfig := database.DBConfig{
|
|
||||||
Driver: app.cfg.Database.Type,
|
|
||||||
DSN: app.cfg.GetDSN(),
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1) Initialiser la DB
|
|
||||||
if err := database.Initialize(dbConfig); err != nil {
|
|
||||||
return fmt.Errorf("failed to initialize database: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// (optionnel) garder une référence locale si tu veux utiliser app.db ailleurs
|
// (optionnel) garder une référence locale si tu veux utiliser app.db ailleurs
|
||||||
app.db = database.DB
|
app.db = database.DB
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,13 @@ func Initialize(config DBConfig) error {
|
|||||||
return fmt.Errorf("erreur lors de la connexion à la base de données: %w", err)
|
return fmt.Errorf("erreur lors de la connexion à la base de données: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Activation du mode foreign keys pour SQLite
|
||||||
|
if config.Driver == "sqlite" {
|
||||||
|
if err := DB.Exec("PRAGMA foreign_keys = ON;").Error; err != nil {
|
||||||
|
return fmt.Errorf("impossible d'activer les foreign keys SQLite: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Connexion à la base de données (%s) établie avec succès", config.Driver)
|
log.Printf("Connexion à la base de données (%s) établie avec succès", config.Driver)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Attachment struct {
|
type Attachment struct {
|
||||||
@@ -17,3 +18,10 @@ type Attachment struct {
|
|||||||
// Relation optionnelle vers le message
|
// Relation optionnelle vers le message
|
||||||
Message *Message `gorm:"foreignKey:MessageID" json:"message,omitempty"`
|
Message *Message `gorm:"foreignKey:MessageID" json:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Attachment) BeforeCreate(tx *gorm.DB) (err error) {
|
||||||
|
if s.ID == uuid.Nil {
|
||||||
|
s.ID = uuid.New()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Category struct {
|
type Category struct {
|
||||||
@@ -14,5 +15,12 @@ type Category struct {
|
|||||||
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
||||||
|
|
||||||
// Relation optionnelle vers le serveur
|
// Relation optionnelle vers le serveur
|
||||||
Server *Server `gorm:"foreignKey:ServerID" json:"server,omitempty"`
|
Server *Server `gorm:"foreignKey:ServerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"server,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Category) BeforeCreate(tx *gorm.DB) (err error) {
|
||||||
|
if s.ID == uuid.Nil {
|
||||||
|
s.ID = uuid.New()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// #[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)]
|
// #[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)]
|
||||||
@@ -48,3 +49,10 @@ type Channel struct {
|
|||||||
Server *Server `gorm:"foreignKey:ServerID" json:"server,omitempty"`
|
Server *Server `gorm:"foreignKey:ServerID" json:"server,omitempty"`
|
||||||
Category *Category `gorm:"foreignKey:CategoryID" json:"category,omitempty"`
|
Category *Category `gorm:"foreignKey:CategoryID" json:"category,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Channel) BeforeCreate(tx *gorm.DB) (err error) {
|
||||||
|
if s.ID == uuid.Nil {
|
||||||
|
s.ID = uuid.New()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ChannelUser struct {
|
type ChannelUser struct {
|
||||||
ChannelID uuid.UUID `gorm:"primaryKey" json:"channel_id"`
|
ID uuid.UUID `gorm:"primaryKey" json:"id"`
|
||||||
UserID uuid.UUID `gorm:"primaryKey" json:"user_id"`
|
ChannelID uuid.UUID `gorm:"index;not null" json:"channel_id"`
|
||||||
|
UserID uuid.UUID `gorm:"index;not null" json:"user_id"`
|
||||||
|
|
||||||
Role string `gorm:"default:'member'" json:"role"`
|
Role string `gorm:"default:'member'" json:"role"`
|
||||||
JoinedAt time.Time `gorm:"autoCreateTime" json:"joined_at"`
|
JoinedAt time.Time `gorm:"autoCreateTime" json:"joined_at"`
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// #[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
|
// #[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
|
||||||
@@ -26,3 +27,10 @@ type Message struct {
|
|||||||
EditedAt *time.Time `gorm:"default:null" json:"edited_at,omitempty"`
|
EditedAt *time.Time `gorm:"default:null" json:"edited_at,omitempty"`
|
||||||
ReplyToID *uuid.UUID `gorm:"index" json:"reply_to_id,omitempty"`
|
ReplyToID *uuid.UUID `gorm:"index" json:"reply_to_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Message) BeforeCreate(tx *gorm.DB) (err error) {
|
||||||
|
if s.ID == uuid.Nil {
|
||||||
|
s.ID = uuid.New()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
@@ -13,3 +14,10 @@ type Server struct {
|
|||||||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) BeforeCreate(tx *gorm.DB) (err error) {
|
||||||
|
if s.ID == uuid.Nil {
|
||||||
|
s.ID = uuid.New()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,12 +19,11 @@ func NewCategoryHandler(h *handler.Handler) *CategoryHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *CategoryHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
func (h *CategoryHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
||||||
category := rg.Group("/category")
|
rg.GET("/", h.getCategories)
|
||||||
category.GET("/", h.getCategories)
|
rg.GET("/:id/", h.getCategory)
|
||||||
category.GET("/:id/", h.getCategory)
|
rg.POST("/", h.addCategory)
|
||||||
category.POST("/", h.addCategory)
|
rg.PUT("/:id/", h.updateCategory)
|
||||||
category.PUT("/:id/", h.updateCategory)
|
rg.DELETE("/:id/", h.deleteCategory)
|
||||||
category.DELETE("/:id/", h.deleteCategory)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *CategoryHandler) getCategories(c *gin.Context) {
|
func (h *CategoryHandler) getCategories(c *gin.Context) {
|
||||||
|
|||||||
@@ -19,12 +19,11 @@ func NewChannelHandler(h *handler.Handler) *ChannelHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *ChannelHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
func (h *ChannelHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
||||||
channel := rg.Group("/channel")
|
rg.GET("/", h.getChannels)
|
||||||
channel.GET("/", h.getChannels)
|
rg.GET("/:id/", h.getChannel)
|
||||||
channel.GET("/:id/", h.getChannel)
|
rg.POST("/", h.addChannel)
|
||||||
channel.POST("/", h.addChannel)
|
rg.PUT("/:id/", h.updateChannel)
|
||||||
channel.PUT("/:id/", h.updateChannel)
|
rg.DELETE("/:id/", h.deleteChannel)
|
||||||
channel.DELETE("/:id/", h.deleteChannel)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,11 @@ func NewMessageHandler(h *handler.Handler) *MessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *MessageHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
func (h *MessageHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
||||||
message := rg.Group("/message")
|
rg.GET("/", h.getMessages)
|
||||||
message.GET("/", h.getMessages)
|
rg.GET("/:id/", h.getMessage)
|
||||||
message.GET("/:id/", h.getMessage)
|
rg.POST("/", h.addMessage)
|
||||||
message.POST("/", h.addMessage)
|
rg.PUT("/:id/", h.updateMessage)
|
||||||
message.PUT("/:id/", h.updateMessage)
|
rg.DELETE("/:id/", h.deleteMessage)
|
||||||
message.DELETE("/:id/", h.deleteMessage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *MessageHandler) getMessages(c *gin.Context) {
|
func (h *MessageHandler) getMessages(c *gin.Context) {
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ func NewServerHandler(h *handler.Handler) *ServerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *ServerHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
func (h *ServerHandler) RegisterRoutes(rg *gin.RouterGroup) {
|
||||||
server := rg.Group("/server")
|
rg.GET("/", h.serverList)
|
||||||
server.GET("/", h.serverList)
|
rg.GET("/:id/", h.serverDetail)
|
||||||
server.GET("/:id/", h.serverDetail)
|
rg.POST("/", h.serverAdd)
|
||||||
server.POST("/", h.serverAdd)
|
rg.PUT("/:id/", h.serverUpdate)
|
||||||
server.PUT("/:id/", h.serverUpdate)
|
rg.DELETE("/:id/", h.serverDelete)
|
||||||
server.DELETE("/:id/", h.serverDelete)
|
rg.POST("/:id/join/", h.serverJoin)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ServerHandler) serverList(c *gin.Context) {
|
func (h *ServerHandler) serverList(c *gin.Context) {
|
||||||
@@ -126,3 +126,31 @@ func (h *ServerHandler) serverDelete(c *gin.Context) {
|
|||||||
|
|
||||||
c.Status(http.StatusNoContent)
|
c.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *ServerHandler) serverJoin(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
var server models.Server
|
||||||
|
result := h.DB.First(&server, "id = ?", id)
|
||||||
|
if result.Error != nil {
|
||||||
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"error": "Server not found"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req JoinServerRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if server.Password != req.Password {
|
||||||
|
c.JSON(http.StatusForbidden, gin.H{"error": "Wrong password"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, server)
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,3 +9,7 @@ type UpdateServerRequest struct {
|
|||||||
Name string `json:"name" binding:"required"`
|
Name string `json:"name" binding:"required"`
|
||||||
Password *string `json:"password,omitempty"`
|
Password *string `json:"password,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JoinServerRequest struct {
|
||||||
|
Password *string `json:"password,omitempty"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func (h *AuthHandler) authenticate(c *gin.Context) {
|
|||||||
// Generate token
|
// Generate token
|
||||||
claims := jwt.MapClaims{
|
claims := jwt.MapClaims{
|
||||||
"user_id": user.ID,
|
"user_id": user.ID,
|
||||||
"expiration_date": time.Now().Add(time.Hour * 72).Unix(),
|
"expiration_date": time.Now().Add(time.Minute * 15).Unix(),
|
||||||
"creation_date": time.Now().Unix(),
|
"creation_date": time.Now().Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,14 +32,19 @@ func CreateRouter() *gin.Engine {
|
|||||||
|
|
||||||
apiGroup := router.Group("/api")
|
apiGroup := router.Group("/api")
|
||||||
{
|
{
|
||||||
serverHandler.RegisterRoutes(apiGroup)
|
serverHandler.RegisterRoutes(apiGroup.Group("/server"))
|
||||||
channelHandler.RegisterRoutes(apiGroup)
|
channelHandler.RegisterRoutes(apiGroup.Group("/channel"))
|
||||||
categoryHandler.RegisterRoutes(apiGroup)
|
categoryHandler.RegisterRoutes(apiGroup.Group("/category"))
|
||||||
messageHandler.RegisterRoutes(apiGroup)
|
messageHandler.RegisterRoutes(apiGroup.Group("/message"))
|
||||||
}
|
}
|
||||||
|
|
||||||
router.GET("/health", healthcheck)
|
router.GET("/health", healthcheck)
|
||||||
|
|
||||||
|
// Expose OpenAPI specification (static file placed at repository root)
|
||||||
|
router.GET("/openapi.yaml", func(c *gin.Context) {
|
||||||
|
c.File("openapi.yaml")
|
||||||
|
})
|
||||||
|
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|
||||||
492
openapi.yaml
Normal file
492
openapi.yaml
Normal file
@@ -0,0 +1,492 @@
|
|||||||
|
openapi: 3.1.0
|
||||||
|
info:
|
||||||
|
title: OXSpeak Server API
|
||||||
|
version: 1.0.0
|
||||||
|
description: API HTTP exposée par le serveur OXSpeak.
|
||||||
|
servers:
|
||||||
|
- url: http://localhost:7000
|
||||||
|
paths:
|
||||||
|
/health:
|
||||||
|
get:
|
||||||
|
summary: Vérifie l'état du service
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: ok
|
||||||
|
|
||||||
|
/auth/channel/login/:
|
||||||
|
get:
|
||||||
|
summary: Authentification par clé publique (renvoie un JWT)
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/AuthRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Jeton JWT généré
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/AuthResponse'
|
||||||
|
'400':
|
||||||
|
description: Requête invalide
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
'500':
|
||||||
|
description: Erreur interne
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
|
||||||
|
/api/server/:
|
||||||
|
get:
|
||||||
|
summary: Liste des serveurs
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Liste de serveurs
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Server'
|
||||||
|
'500':
|
||||||
|
description: Erreur serveur
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
post:
|
||||||
|
summary: Crée un serveur
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/CreateServerRequest'
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Serveur créé
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Server'
|
||||||
|
'400': { description: Requête invalide }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
|
||||||
|
/api/server/{id}/:
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
get:
|
||||||
|
summary: Détail d'un serveur
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Serveur
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Server'
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
put:
|
||||||
|
summary: Met à jour un serveur
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/UpdateServerRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Serveur mis à jour
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Server'
|
||||||
|
'400': { description: Requête invalide }
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
delete:
|
||||||
|
summary: Supprime un serveur
|
||||||
|
responses:
|
||||||
|
'204': { description: Supprimé }
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
|
||||||
|
/api/category/:
|
||||||
|
get:
|
||||||
|
summary: Liste des catégories
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Liste des catégories
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Category'
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
post:
|
||||||
|
summary: Crée une catégorie
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/CreateCategoryRequest'
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Catégorie créée
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Category'
|
||||||
|
'400': { description: Requête invalide }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
|
||||||
|
/api/category/{id}/:
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
get:
|
||||||
|
summary: Détail d'une catégorie
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Catégorie
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Category'
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
put:
|
||||||
|
summary: Met à jour une catégorie
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/UpdateCategoryRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Catégorie mise à jour
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Category'
|
||||||
|
'400': { description: Requête invalide }
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
delete:
|
||||||
|
summary: Supprime une catégorie
|
||||||
|
responses:
|
||||||
|
'204': { description: Supprimé }
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
|
||||||
|
/api/channel/:
|
||||||
|
get:
|
||||||
|
summary: Liste des canaux
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Liste des canaux
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Channel'
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
post:
|
||||||
|
summary: Crée un canal
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/CreateChannelRequest'
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Canal créé
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Channel'
|
||||||
|
'400': { description: Requête invalide }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
|
||||||
|
/api/channel/{id}/:
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
get:
|
||||||
|
summary: Détail d'un canal
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Canal
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Channel'
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
put:
|
||||||
|
summary: Met à jour un canal
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/UpdateChannelRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Canal mis à jour
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Channel'
|
||||||
|
'400': { description: Requête invalide }
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
delete:
|
||||||
|
summary: Supprime un canal
|
||||||
|
responses:
|
||||||
|
'204': { description: Supprimé }
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
|
||||||
|
/api/message/:
|
||||||
|
get:
|
||||||
|
summary: Liste des messages
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Liste des messages
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Message'
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
post:
|
||||||
|
summary: Crée un message
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/CreateMessageRequest'
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Message créé
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Message'
|
||||||
|
'400': { description: Requête invalide }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
|
||||||
|
/api/message/{id}/:
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
get:
|
||||||
|
summary: Détail d'un message
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Message
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Message'
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
put:
|
||||||
|
summary: Met à jour un message
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/UpdateMessageRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Message mis à jour
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Message'
|
||||||
|
'400': { description: Requête invalide }
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
delete:
|
||||||
|
summary: Supprime un message
|
||||||
|
responses:
|
||||||
|
'204': { description: Supprimé }
|
||||||
|
'404': { description: Introuvable }
|
||||||
|
'500': { description: Erreur interne }
|
||||||
|
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
UUID:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
|
||||||
|
Error:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
AuthRequest:
|
||||||
|
type: object
|
||||||
|
required: [pub_key]
|
||||||
|
properties:
|
||||||
|
pub_key:
|
||||||
|
type: string
|
||||||
|
description: Clé publique du client
|
||||||
|
|
||||||
|
AuthResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
JWT:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
Server:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
name: { type: string }
|
||||||
|
created_at: { type: string, format: date-time }
|
||||||
|
updated_at: { type: string, format: date-time }
|
||||||
|
required: [id, name, created_at, updated_at]
|
||||||
|
|
||||||
|
CreateServerRequest:
|
||||||
|
type: object
|
||||||
|
required: [name]
|
||||||
|
properties:
|
||||||
|
name: { type: string }
|
||||||
|
password: { type: string, nullable: true }
|
||||||
|
|
||||||
|
UpdateServerRequest:
|
||||||
|
type: object
|
||||||
|
required: [name]
|
||||||
|
properties:
|
||||||
|
name: { type: string }
|
||||||
|
password: { type: string, nullable: true }
|
||||||
|
|
||||||
|
Category:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
server_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
name: { type: string }
|
||||||
|
created_at: { type: string, format: date-time }
|
||||||
|
updated_at: { type: string, format: date-time }
|
||||||
|
required: [id, server_id, name, created_at, updated_at]
|
||||||
|
|
||||||
|
CreateCategoryRequest:
|
||||||
|
type: object
|
||||||
|
required: [server_id, name]
|
||||||
|
properties:
|
||||||
|
server_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
name: { type: string }
|
||||||
|
|
||||||
|
UpdateCategoryRequest:
|
||||||
|
type: object
|
||||||
|
required: [name]
|
||||||
|
properties:
|
||||||
|
name: { type: string }
|
||||||
|
|
||||||
|
Channel:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
server_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
category_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
position: { type: integer, format: int32 }
|
||||||
|
type: { $ref: '#/components/schemas/ChannelType' }
|
||||||
|
name: { type: string, nullable: true }
|
||||||
|
created_at: { type: string, format: date-time }
|
||||||
|
updated_at: { type: string, format: date-time }
|
||||||
|
required: [id, position, type, created_at, updated_at]
|
||||||
|
|
||||||
|
ChannelType:
|
||||||
|
type: string
|
||||||
|
enum: [text, voice, dm]
|
||||||
|
|
||||||
|
CreateChannelRequest:
|
||||||
|
type: object
|
||||||
|
required: [type]
|
||||||
|
properties:
|
||||||
|
server_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
category_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
position: { type: integer, format: int32 }
|
||||||
|
type: { $ref: '#/components/schemas/ChannelType' }
|
||||||
|
name: { type: string, nullable: true }
|
||||||
|
|
||||||
|
UpdateChannelRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
server_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
category_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
position: { type: integer, format: int32 }
|
||||||
|
type: { $ref: '#/components/schemas/ChannelType' }
|
||||||
|
name: { type: string, nullable: true }
|
||||||
|
|
||||||
|
Message:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
channel_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
user_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
content: { type: string }
|
||||||
|
created_at: { type: string, format: date-time }
|
||||||
|
edited_at: { type: string, format: date-time, nullable: true }
|
||||||
|
reply_to_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
required: [id, channel_id, user_id, content, created_at]
|
||||||
|
|
||||||
|
CreateMessageRequest:
|
||||||
|
type: object
|
||||||
|
required: [channel_id, user_id, content]
|
||||||
|
properties:
|
||||||
|
channel_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
user_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
content: { type: string }
|
||||||
|
reply_to_id: { $ref: '#/components/schemas/UUID' }
|
||||||
|
|
||||||
|
UpdateMessageRequest:
|
||||||
|
type: object
|
||||||
|
required: [content]
|
||||||
|
properties:
|
||||||
|
content: { type: string }
|
||||||
|
reply_to_id: { $ref: '#/components/schemas/UUID' }
|
||||||
Reference in New Issue
Block a user