Compare commits
3 Commits
473e46ee19
...
f31adca326
Author | SHA1 | Date |
---|---|---|
Adrien Marquès | f31adca326 | |
Adrien Marquès | 32afe3ae05 | |
Adrien Marquès | 73ef0570fd |
80
api.json
80
api.json
|
@ -7,7 +7,7 @@
|
|||
"info": "returns the list of existing users",
|
||||
"in": {},
|
||||
"out": {
|
||||
"users": { "info": "users list", "type": "any" }
|
||||
"users": { "info": "users list", "type": "any", "name": "Users" }
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -16,14 +16,14 @@
|
|||
"scope": [],
|
||||
"info": "returns info about an existing user",
|
||||
"in": {
|
||||
"{id}": { "info": "the target user id", "name": "user_id", "type": "uint" }
|
||||
"{id}": { "info": "the target user id", "name": "ID", "type": "uint" }
|
||||
},
|
||||
"out": {
|
||||
"id": { "info": "user id", "type": "uint" },
|
||||
"username": { "info": "username", "type": "string(3,30)" },
|
||||
"firstname": { "info": "first name", "type": "string(1,30)" },
|
||||
"lastname": { "info": "last name", "type": "string(1,30)" },
|
||||
"articles": { "info": "user articles", "type": "any" }
|
||||
"id": { "info": "user id", "type": "uint", "name": "ID" },
|
||||
"username": { "info": "username", "type": "string(3,30)", "name": "Username" },
|
||||
"firstname": { "info": "first name", "type": "string(1,30)", "name": "Firstname" },
|
||||
"lastname": { "info": "last name", "type": "string(1,30)", "name": "Lastname" },
|
||||
"articles": { "info": "user articles", "type": "any", "name": "Articles" }
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -33,15 +33,15 @@
|
|||
"scope": [["admin"]],
|
||||
"info": "creates a new user",
|
||||
"in": {
|
||||
"username": { "info": "username", "type": "string(3,30)" },
|
||||
"firstname": { "info": "first name", "type": "string(1,30)" },
|
||||
"lastname": { "info": "last name", "type": "string(1,30)" }
|
||||
"username": { "info": "username", "type": "string(3,30)", "name": "Username" },
|
||||
"firstname": { "info": "first name", "type": "string(1,30)", "name": "Firstname" },
|
||||
"lastname": { "info": "last name", "type": "string(1,30)", "name": "Lastname" }
|
||||
},
|
||||
"out": {
|
||||
"id": { "info": "new user's id", "type": "uint" },
|
||||
"username": { "info": "new user's username", "type": "string(3,30)" },
|
||||
"firstname": { "info": "new user's first name", "type": "string(1,30)" },
|
||||
"lastname": { "info": "new user's last name", "type": "string(1,30)" }
|
||||
"id": { "info": "user id", "type": "uint", "name": "ID" },
|
||||
"username": { "info": "username", "type": "string(3,30)", "name": "Username" },
|
||||
"firstname": { "info": "first name", "type": "string(1,30)", "name": "Firstname" },
|
||||
"lastname": { "info": "last name", "type": "string(1,30)", "name": "Lastname" }
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -50,16 +50,16 @@
|
|||
"scope": [["admin"], ["self"]],
|
||||
"info": "updates an existing user",
|
||||
"in": {
|
||||
"{id}": { "info": "the target user id", "type": "uint", "name": "user_id" },
|
||||
"username": { "info": "updated username", "type": "?string(3,30)" },
|
||||
"firstname": { "info": "updated first name", "type": "?string(1,30)" },
|
||||
"lastname": { "info": "updated last name", "type": "?string(1,30)" }
|
||||
"{id}": { "info": "the target user id", "type": "uint", "name": "ID" },
|
||||
"username": { "info": "updated username", "type": "?string(3,30)", "name": "Username" },
|
||||
"firstname": { "info": "updated first name", "type": "?string(1,30)", "name": "Firstname" },
|
||||
"lastname": { "info": "updated last name", "type": "?string(1,30)", "name": "Lastname" }
|
||||
},
|
||||
"out": {
|
||||
"id": { "info": "new user's id", "type": "uint" },
|
||||
"username": { "info": "new user's username", "type": "string(3,30)" },
|
||||
"firstname": { "info": "new user's first name", "type": "string(1,30)" },
|
||||
"lastname": { "info": "new user's last name", "type": "string(1,30)" }
|
||||
"id": { "info": "user id", "type": "uint", "name": "ID" },
|
||||
"username": { "info": "username", "type": "string(3,30)", "name": "Username" },
|
||||
"firstname": { "info": "first name", "type": "string(1,30)", "name": "Firstname" },
|
||||
"lastname": { "info": "last name", "type": "string(1,30)", "name": "Lastname" }
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
|||
"scope": [["admin"], ["self"]],
|
||||
"info": "deletes an existing user",
|
||||
"in": {
|
||||
"{id}": { "info": "the target user id", "name": "user_id", "type": "uint" }
|
||||
"{id}": { "info": "the target user id", "name": "ID", "type": "uint" }
|
||||
},
|
||||
"out": {}
|
||||
},
|
||||
|
@ -83,10 +83,10 @@
|
|||
"scope": [[]],
|
||||
"info": "returns the list of existing articles a user wrote",
|
||||
"in": {
|
||||
"{id}": { "info": "author user id", "name": "author_id", "type": "uint" }
|
||||
"{id}": { "info": "author user id", "name": "ID", "type": "uint" }
|
||||
},
|
||||
"out": {
|
||||
"articles": { "info": "articles list", "type": "any" }
|
||||
"articles": { "info": "articles list", "type": "any", "name": "Articles" }
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -97,7 +97,7 @@
|
|||
"info": "returns the list of existing articles",
|
||||
"in": {},
|
||||
"out": {
|
||||
"articles": { "info": "articles list", "type": "any" }
|
||||
"articles": { "info": "articles list", "type": "any", "name": "Articles" }
|
||||
}
|
||||
}, {
|
||||
"method": "GET",
|
||||
|
@ -105,14 +105,14 @@
|
|||
"scope": [[]],
|
||||
"info": "returns an existing article",
|
||||
"in": {
|
||||
"{id}": { "info": "the target article id", "name": "article_id", "type": "uint" }
|
||||
"{id}": { "info": "the target article id", "name": "ID", "type": "uint" }
|
||||
},
|
||||
"out": {
|
||||
"id": { "info": "the article id", "type": "uint" },
|
||||
"title": { "info": "the article title", "type": "string(5,255)" },
|
||||
"body": { "info": "the article body", "type": "string" },
|
||||
"author": { "info": "the author user id", "type": "uint" },
|
||||
"score": { "info": "absolute vote score", "type": "uint" }
|
||||
"id": { "info": "the article id", "type": "uint", "name": "ID" },
|
||||
"title": { "info": "the article title", "type": "string(5,255)", "name": "Title" },
|
||||
"body": { "info": "the article body", "type": "string", "name": "Body" },
|
||||
"author": { "info": "the author user id", "type": "uint", "name": "Author" },
|
||||
"score": { "info": "absolute vote score", "type": "uint", "name": "Score" }
|
||||
}
|
||||
}, {
|
||||
"method": "POST",
|
||||
|
@ -120,15 +120,15 @@
|
|||
"scope": [["author"]],
|
||||
"info": "post a new article",
|
||||
"in": {
|
||||
"title": { "info": "the article title", "type": "string(5,255)" },
|
||||
"body": { "info": "the article body", "type": "string" }
|
||||
"title": { "info": "the article title", "type": "string(5,255)", "name": "Title" },
|
||||
"body": { "info": "the article body", "type": "string", "name": "Body" }
|
||||
},
|
||||
"out": {
|
||||
"id": { "info": "the article id", "type": "uint" },
|
||||
"title": { "info": "the article title", "type": "string(5,255)" },
|
||||
"body": { "info": "the article body", "type": "string" },
|
||||
"author": { "info": "the author user id", "type": "uint" },
|
||||
"score": { "info": "absolute vote score", "type": "uint" }
|
||||
"id": { "info": "the article id", "type": "uint", "name": "ID" },
|
||||
"title": { "info": "the article title", "type": "string(5,255)", "name": "Title" },
|
||||
"body": { "info": "the article body", "type": "string", "name": "Body" },
|
||||
"author": { "info": "the author user id", "type": "uint", "name": "Author" },
|
||||
"score": { "info": "absolute vote score", "type": "uint", "name": "Score" }
|
||||
}
|
||||
}, {
|
||||
"method": "DELETE",
|
||||
|
@ -136,7 +136,7 @@
|
|||
"scope": [["admin"], ["author"]],
|
||||
"info": "deletes an article",
|
||||
"in": {
|
||||
"{id}": { "info": "the target article id", "name": "article_id", "type": "uint" }
|
||||
"{id}": { "info": "the target article id", "name": "ID", "type": "uint" }
|
||||
},
|
||||
"out": { }
|
||||
}
|
||||
|
|
8
main.go
8
main.go
|
@ -38,8 +38,12 @@ func main() {
|
|||
articleService := &article.Service{DB: db}
|
||||
|
||||
// 4. wire services
|
||||
userService.Wire(server)
|
||||
articleService.Wire(server)
|
||||
if err = userService.Wire(server); err != nil {
|
||||
log.Fatalf("/!\\ cannot wire service 'user': %s", err)
|
||||
}
|
||||
if err = articleService.Wire(server); err != nil {
|
||||
log.Fatalf("/!\\ cannot wire service 'article': %s", err)
|
||||
}
|
||||
|
||||
// 5. create http server
|
||||
httpServer, err := server.ToHTTPServer()
|
||||
|
|
|
@ -15,66 +15,87 @@ type Service struct {
|
|||
}
|
||||
|
||||
// Wire services to their paths
|
||||
func (s Service) Wire(server *aicra.Server) {
|
||||
func (s Service) Wire(server *aicra.Server) error {
|
||||
if !s.DB.HasTable(&model.Article{}) {
|
||||
s.DB.CreateTable(&model.Article{})
|
||||
}
|
||||
|
||||
server.Handle(http.MethodGet, "/articles", s.getAllArticles)
|
||||
server.Handle(http.MethodGet, "/user/{id}/articles", s.getArticlesByAuthor)
|
||||
server.Handle(http.MethodGet, "/article/{id}", s.getArticleByID)
|
||||
server.Handle(http.MethodPost, "/article", s.postArticle)
|
||||
server.Handle(http.MethodDelete, "/article/{id}", s.deleteArticle)
|
||||
}
|
||||
|
||||
func (s Service) getArticlesByAuthor(req api.Request, res *api.Response) api.Error {
|
||||
id, err := req.Param.GetUint("author_id")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
if err := server.Handle(http.MethodGet, "/articles", s.getAllArticles); err != nil {
|
||||
return err
|
||||
}
|
||||
articles := make([]model.Article, 0)
|
||||
s.DB.Where("author = ?", id).Find(&articles)
|
||||
res.SetData("articles", articles)
|
||||
return api.ErrorSuccess
|
||||
if err := server.Handle(http.MethodGet, "/user/{id}/articles", s.getArticlesByAuthor); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := server.Handle(http.MethodGet, "/article/{id}", s.getArticleByID); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := server.Handle(http.MethodPost, "/article", s.postArticle); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := server.Handle(http.MethodDelete, "/article/{id}", s.deleteArticle); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Service) getAllArticles(req api.Request, res *api.Response) api.Error {
|
||||
type iByID struct {
|
||||
ID uint
|
||||
}
|
||||
|
||||
type oArticle struct {
|
||||
ID uint
|
||||
Author uint
|
||||
Title string
|
||||
Body string
|
||||
Score uint
|
||||
}
|
||||
type iCreate struct {
|
||||
Title string
|
||||
Body string
|
||||
}
|
||||
|
||||
type oArticleList struct {
|
||||
Articles []model.Article
|
||||
}
|
||||
|
||||
func (s Service) getArticlesByAuthor(param iByID) (*oArticleList, api.Error) {
|
||||
articles := make([]model.Article, 0)
|
||||
s.DB.Where("author = ?", param.ID).Find(&articles)
|
||||
return &oArticleList{
|
||||
Articles: articles,
|
||||
}, api.ErrorSuccess
|
||||
}
|
||||
|
||||
func (s Service) getAllArticles() (*oArticleList, api.Error) {
|
||||
articles := make([]model.Article, 0)
|
||||
s.DB.Find(&articles)
|
||||
res.SetData("articles", articles)
|
||||
return api.ErrorSuccess
|
||||
return &oArticleList{
|
||||
Articles: articles,
|
||||
}, api.ErrorSuccess
|
||||
}
|
||||
|
||||
func (s Service) getArticleByID(req api.Request, res *api.Response) api.Error {
|
||||
id, err := req.Param.GetUint("article_id")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
}
|
||||
|
||||
func (s Service) getArticleByID(param iByID) (*oArticle, api.Error) {
|
||||
var article model.Article
|
||||
if s.DB.First(&article, id).RecordNotFound() {
|
||||
return api.ErrorNoMatchFound
|
||||
if s.DB.First(&article, param.ID).RecordNotFound() {
|
||||
return nil, api.ErrorNoMatchFound
|
||||
}
|
||||
|
||||
res.SetData("id", article.ID)
|
||||
res.SetData("title", article.Title)
|
||||
res.SetData("body", article.Body)
|
||||
res.SetData("author", article.Author)
|
||||
return api.ErrorSuccess
|
||||
return &oArticle{
|
||||
ID: article.ID,
|
||||
Title: article.Title,
|
||||
Body: article.Body,
|
||||
Author: article.Author,
|
||||
}, api.ErrorSuccess
|
||||
}
|
||||
|
||||
func (s Service) postArticle(req api.Request, res *api.Response) api.Error {
|
||||
return api.ErrorNotImplemented
|
||||
func (s Service) postArticle(param iCreate) (*oArticle, api.Error) {
|
||||
return nil, api.ErrorNotImplemented
|
||||
}
|
||||
|
||||
func (s Service) deleteArticle(req api.Request, res *api.Response) api.Error {
|
||||
id, err := req.Param.GetUint("user_id")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
func (s Service) deleteArticle(param iByID) api.Error {
|
||||
article := model.Article{
|
||||
ID: param.ID,
|
||||
}
|
||||
|
||||
article := model.Article{}
|
||||
article.ID = id
|
||||
s.DB.Delete(&article)
|
||||
|
||||
return api.ErrorSuccess
|
||||
|
|
|
@ -6,5 +6,5 @@ type User struct {
|
|||
Username string `json:"username"`
|
||||
Firstname string `json:"firstname"`
|
||||
Lastname string `json:"lastname"`
|
||||
Articles []Article `gorm:"foreignKey:Author"`
|
||||
Articles []Article `json:"articles" gorm:"foreignKey:Author"`
|
||||
}
|
||||
|
|
|
@ -15,109 +15,132 @@ type Service struct {
|
|||
}
|
||||
|
||||
// Wire services to their paths
|
||||
func (s Service) Wire(server *aicra.Server) {
|
||||
func (s Service) Wire(server *aicra.Server) error {
|
||||
if !s.DB.HasTable(&model.User{}) {
|
||||
s.DB.CreateTable(&model.User{})
|
||||
}
|
||||
|
||||
server.Handle(http.MethodGet, "/users", s.getAllUsers)
|
||||
server.Handle(http.MethodGet, "/user/{id}", s.getUserByID)
|
||||
server.Handle(http.MethodPost, "/user", s.createUser)
|
||||
server.Handle(http.MethodPut, "/user/{id}", s.updateUser)
|
||||
server.Handle(http.MethodDelete, "/user/{id}", s.deleteUser)
|
||||
}
|
||||
|
||||
func (s Service) getAllUsers(req api.Request, res *api.Response) api.Error {
|
||||
users := make([]model.User, 0)
|
||||
s.DB.Find(&users)
|
||||
res.SetData("users", users)
|
||||
return api.ErrorSuccess
|
||||
}
|
||||
func (s Service) getUserByID(req api.Request, res *api.Response) api.Error {
|
||||
id, err := req.Param.GetUint("user_id")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
if err := server.Handle(http.MethodGet, "/user/{id}", s.getUserByID); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := server.Handle(http.MethodGet, "/users", s.getAllUsers); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := server.Handle(http.MethodPost, "/user", s.createUser); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := server.Handle(http.MethodPut, "/user/{id}", s.updateUser); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := server.Handle(http.MethodDelete, "/user/{id}", s.deleteUser); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type oUserList struct {
|
||||
Users []model.User
|
||||
}
|
||||
|
||||
type oUser struct {
|
||||
ID uint
|
||||
Username string
|
||||
Firstname string
|
||||
Lastname string
|
||||
Articles interface{}
|
||||
}
|
||||
type iByID struct {
|
||||
ID uint
|
||||
}
|
||||
|
||||
type iCreate struct {
|
||||
Username string
|
||||
Firstname string
|
||||
Lastname string
|
||||
}
|
||||
type iUpdate struct {
|
||||
ID uint
|
||||
Username *string
|
||||
Firstname *string
|
||||
Lastname *string
|
||||
}
|
||||
|
||||
func (s Service) getAllUsers() (*oUserList, api.Error) {
|
||||
users := oUserList{}
|
||||
s.DB.Find(&users.Users)
|
||||
return &users, api.ErrorSuccess
|
||||
}
|
||||
func (s Service) getUserByID(param iByID) (*oUser, api.Error) {
|
||||
var user model.User
|
||||
if s.DB.First(&user, id).RecordNotFound() {
|
||||
return api.ErrorNoMatchFound
|
||||
if s.DB.First(&user, param.ID).RecordNotFound() {
|
||||
return nil, api.ErrorNoMatchFound
|
||||
}
|
||||
|
||||
res.SetData("id", user.ID)
|
||||
res.SetData("username", user.Username)
|
||||
res.SetData("firstname", user.Firstname)
|
||||
res.SetData("lastname", user.Lastname)
|
||||
res.SetData("articles", user.Articles)
|
||||
return api.ErrorSuccess
|
||||
return &oUser{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Firstname: user.Firstname,
|
||||
Lastname: user.Lastname,
|
||||
Articles: user.Articles,
|
||||
}, api.ErrorSuccess
|
||||
}
|
||||
|
||||
func (s Service) createUser(req api.Request, res *api.Response) api.Error {
|
||||
var user model.User
|
||||
var err error
|
||||
user.Username, err = req.Param.GetString("username")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
}
|
||||
user.Firstname, err = req.Param.GetString("firstname")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
}
|
||||
user.Lastname, err = req.Param.GetString("lastname")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
func (s Service) createUser(param iCreate) (*oUser, api.Error) {
|
||||
user := model.User{
|
||||
Username: param.Username,
|
||||
Firstname: param.Firstname,
|
||||
Lastname: param.Lastname,
|
||||
}
|
||||
|
||||
s.DB.Create(&user)
|
||||
if s.DB.Last(&user).RecordNotFound() {
|
||||
return api.ErrorNoMatchFound
|
||||
return nil, api.ErrorNoMatchFound
|
||||
}
|
||||
|
||||
res.SetData("id", user.ID)
|
||||
res.SetData("username", user.Username)
|
||||
res.SetData("firstname", user.Firstname)
|
||||
res.SetData("lastname", user.Lastname)
|
||||
res.SetData("articles", user.Articles)
|
||||
return api.ErrorSuccess
|
||||
return &oUser{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Firstname: user.Firstname,
|
||||
Lastname: user.Lastname,
|
||||
Articles: user.Articles,
|
||||
}, api.ErrorSuccess
|
||||
}
|
||||
|
||||
func (s Service) updateUser(req api.Request, res *api.Response) api.Error {
|
||||
id, err := req.Param.GetUint("user_id")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
}
|
||||
|
||||
func (s Service) updateUser(param iUpdate) (*oUser, api.Error) {
|
||||
var user model.User
|
||||
if s.DB.First(&user, id).RecordNotFound() {
|
||||
return api.ErrorNoMatchFound
|
||||
if s.DB.First(&user, param.ID).RecordNotFound() {
|
||||
return nil, api.ErrorNoMatchFound
|
||||
}
|
||||
|
||||
// override with updated values
|
||||
if updated, err := req.Param.GetString("username"); err == nil {
|
||||
user.Username = updated
|
||||
if param.Username != nil {
|
||||
user.Username = *param.Username
|
||||
}
|
||||
if updated, err := req.Param.GetString("firstname"); err == nil {
|
||||
user.Firstname = updated
|
||||
if param.Firstname != nil {
|
||||
user.Firstname = *param.Firstname
|
||||
}
|
||||
if updated, err := req.Param.GetString("lastname"); err == nil {
|
||||
user.Lastname = updated
|
||||
if param.Lastname != nil {
|
||||
user.Lastname = *param.Lastname
|
||||
}
|
||||
|
||||
// update
|
||||
if s.DB.Save(&user).RowsAffected < 1 {
|
||||
return api.ErrorFailure
|
||||
return nil, api.ErrorFailure
|
||||
}
|
||||
return api.ErrorSuccess
|
||||
|
||||
return &oUser{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Firstname: user.Firstname,
|
||||
Lastname: user.Lastname,
|
||||
Articles: user.Articles,
|
||||
}, api.ErrorSuccess
|
||||
}
|
||||
|
||||
func (s Service) deleteUser(req api.Request, res *api.Response) api.Error {
|
||||
id, err := req.Param.GetUint("user_id")
|
||||
if err != nil {
|
||||
return api.ErrorInvalidParam
|
||||
func (s Service) deleteUser(param iByID) api.Error {
|
||||
user := model.User{
|
||||
ID: param.ID,
|
||||
}
|
||||
|
||||
user := model.User{}
|
||||
user.ID = id
|
||||
s.DB.Delete(&user)
|
||||
return api.ErrorSuccess
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue