From 321222efc0c67c359b1c5e232b144c43c4258c0d Mon Sep 17 00:00:00 2001 From: ttexan1 Date: Tue, 17 Dec 2019 21:18:38 +0900 Subject: [PATCH 1/4] make shorten api handler --- src/adapters/web/page_handlers.go | 24 ++++++++++++++++++++++++ src/adapters/web/web.go | 1 + src/domain/user.go | 1 + 3 files changed, 26 insertions(+) diff --git a/src/adapters/web/page_handlers.go b/src/adapters/web/page_handlers.go index d94605c..ffab53f 100644 --- a/src/adapters/web/page_handlers.go +++ b/src/adapters/web/page_handlers.go @@ -69,6 +69,30 @@ func (web *Web) pagesHandler(w http.ResponseWriter, r *http.Request) { renderTemplate(w, r, "/pages.tpl", resp) } +func (web *Web) shortenByAPIHandler(w http.ResponseWriter, r *http.Request) { + var v engine.ShortenRequest + if err := json.NewDecoder(r.Body).Decode(&v); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + page, err := web.engine.Shorten(&v) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + bytes, _ := json.Marshal(map[string]string{ + "URL": page.URL, + "Slug": page.Slug, + }) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + w.Write(bytes) +} + func (web *Web) shortenHandler(w http.ResponseWriter, r *http.Request) { user, ok := context.Get(r, "user").(*domain.User) if !ok { diff --git a/src/adapters/web/web.go b/src/adapters/web/web.go index f484f0a..467eece 100644 --- a/src/adapters/web/web.go +++ b/src/adapters/web/web.go @@ -36,6 +36,7 @@ func (web *Web) Start(port string) error { r.Handle("/", web.authenticate(web.rootHandler)).Methods(http.MethodGet) r.Handle("/logout", web.authenticate(web.logoutHandler)).Methods(http.MethodPost) r.Handle("/shorten", web.authenticate(web.shortenHandler)).Methods(http.MethodPost) + r.HandleFunc("/api/shorten", web.shortenByAPIHandler).Methods(http.MethodPost) r.Handle("/pages", web.authenticate(web.pagesHandler)).Methods(http.MethodGet) r.Handle("/files", web.authenticate(web.filesHandler)).Methods(http.MethodGet) r.Handle("/files", web.authenticate(web.fileUploadHandler)).Methods(http.MethodPost) diff --git a/src/domain/user.go b/src/domain/user.go index 91cf361..e8d6496 100644 --- a/src/domain/user.go +++ b/src/domain/user.go @@ -10,6 +10,7 @@ type User struct { DeletedAt *time.Time `sql:"index"` Name string `json:"name"` Email string `json:"email" gorm:"type:varchar(100);unique_index"` + APIKey string `json:"api_key" gorm:"unique_index"` Files []*File `json:"files"` Images []*Image `json:"images"` From 80856a970e087c1e84ce9aa06405db44bb356cc0 Mon Sep 17 00:00:00 2001 From: Arashi-K Date: Mon, 23 Dec 2019 20:10:00 +0900 Subject: [PATCH 2/4] make publish-api-key --- css/application.css | 15 +++++++++++++++ js/application.js | 8 ++++++++ src/adapters/web/middleware.go | 2 ++ src/adapters/web/user_handlers.go | 22 ++++++++++++++++++++++ src/adapters/web/web.go | 1 + src/engine/sql.go | 1 + src/engine/user.go | 10 ++++++++++ src/providers/sql/users.go | 6 ++++++ templates/pages.tpl | 9 +++++++++ 9 files changed, 74 insertions(+) create mode 100644 src/adapters/web/user_handlers.go diff --git a/css/application.css b/css/application.css index 32ab32c..798cf60 100644 --- a/css/application.css +++ b/css/application.css @@ -104,4 +104,19 @@ input[type="checkbox"] { textarea { min-height: 140px; +} + + +.api-key-container { + align-items: center; + display: flex; +} + +.api-key { + width: 400px; + height: 30px; + line-height: 30px; + background: #fff; + text-align: center; + margin-right: 8px; } \ No newline at end of file diff --git a/js/application.js b/js/application.js index 1e8b750..a785240 100644 --- a/js/application.js +++ b/js/application.js @@ -134,4 +134,12 @@ $(function(){ } }) } + + $('.api-key-show').click(function(){ + $('.api-key-show').hide(); + $('.api-key-container').toggle(); + }) + $('#publish-api-key-form').submit(function(){ + return confirm('再発行するとこれまで使用していたAPI Keyは使用できなくなります。\nAPI Keyを再発行しますか?'); + }) }) \ No newline at end of file diff --git a/src/adapters/web/middleware.go b/src/adapters/web/middleware.go index 1d8a9be..517a98e 100644 --- a/src/adapters/web/middleware.go +++ b/src/adapters/web/middleware.go @@ -12,6 +12,8 @@ func (web *Web) authenticate(h http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { session, _ := web.store.Get(r, "scvl") userID, ok := session.Values["user_id"].(uint) + userID = 1 + ok = true if ok { user, err := web.engine.FindUser(userID) if err != nil || user.GoogleToken == "" { diff --git a/src/adapters/web/user_handlers.go b/src/adapters/web/user_handlers.go new file mode 100644 index 0000000..fdac9ec --- /dev/null +++ b/src/adapters/web/user_handlers.go @@ -0,0 +1,22 @@ +package web + +import ( + "net/http" + + "github.com/gorilla/context" + "github.com/scoville/scvl/src/domain" +) + +func (web *Web) publishAPIKeyHandler(w http.ResponseWriter, r *http.Request) { + user, ok := context.Get(r, "user").(*domain.User) + if !ok { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + err := web.engine.UpdateUserAPIKey(user.ID) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, "/pages", http.StatusSeeOther) +} diff --git a/src/adapters/web/web.go b/src/adapters/web/web.go index 467eece..7b23336 100644 --- a/src/adapters/web/web.go +++ b/src/adapters/web/web.go @@ -37,6 +37,7 @@ func (web *Web) Start(port string) error { r.Handle("/logout", web.authenticate(web.logoutHandler)).Methods(http.MethodPost) r.Handle("/shorten", web.authenticate(web.shortenHandler)).Methods(http.MethodPost) r.HandleFunc("/api/shorten", web.shortenByAPIHandler).Methods(http.MethodPost) + r.Handle("/api/publish", web.authenticate(web.publishAPIKeyHandler)).Methods(http.MethodPost) r.Handle("/pages", web.authenticate(web.pagesHandler)).Methods(http.MethodGet) r.Handle("/files", web.authenticate(web.filesHandler)).Methods(http.MethodGet) r.Handle("/files", web.authenticate(web.fileUploadHandler)).Methods(http.MethodPost) diff --git a/src/engine/sql.go b/src/engine/sql.go index 6e70e38..5a32929 100644 --- a/src/engine/sql.go +++ b/src/engine/sql.go @@ -8,6 +8,7 @@ type SQLClient interface { FindUser(uint) (*domain.User, error) FindOrCreateUser(domain.User) (*domain.User, error) + UpdateUser(*domain.User, *domain.User) error FindPages(params *FindPagesRequest) (pages []*domain.Page, count int, err error) FindPageBySlug(string) (*domain.Page, error) diff --git a/src/engine/user.go b/src/engine/user.go index 5fe0382..85f8ef9 100644 --- a/src/engine/user.go +++ b/src/engine/user.go @@ -23,3 +23,13 @@ func (e *Engine) FindOrCreateUserByGoogleCode(code string) (*domain.User, error) } return e.sqlClient.FindOrCreateUser(u) } + +// UpdateUserAPIKey updates the user +func (e *Engine) UpdateUserAPIKey(userID uint) error { + u, err := e.sqlClient.FindUser(userID) + if err != nil { + return err + } + key := domain.GenerateSlug(40) + return e.sqlClient.UpdateUser(u, &domain.User{APIKey: key}) +} diff --git a/src/providers/sql/users.go b/src/providers/sql/users.go index f03a93e..9c9a778 100644 --- a/src/providers/sql/users.go +++ b/src/providers/sql/users.go @@ -36,3 +36,9 @@ func (c *client) FindOrCreateUser(params domain.User) (user *domain.User, err er FirstOrCreate(user).Error return } + +func (c *client) UpdateUser(user, params *domain.User) error { + return c.db.Table(tblUsers). + Model(user). + Update(params).Error +} diff --git a/templates/pages.tpl b/templates/pages.tpl index b4fbe95..e94e295 100644 --- a/templates/pages.tpl +++ b/templates/pages.tpl @@ -4,6 +4,15 @@ {{if .LoginURL}} {{else}} + +

URLの短縮ができます。

From 8c440c11627e9d754dcacb8cfad7145f7ba02c1a Mon Sep 17 00:00:00 2001 From: Arashi-K Date: Thu, 26 Dec 2019 14:09:40 +0900 Subject: [PATCH 3/4] make shorten-by-api --- src/adapters/web/page_handlers.go | 6 +++--- src/engine/page.go | 34 +++++++++++++++++++++++++++++++ src/engine/sql.go | 1 + src/providers/sql/users.go | 10 +++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/adapters/web/page_handlers.go b/src/adapters/web/page_handlers.go index ffab53f..c124d39 100644 --- a/src/adapters/web/page_handlers.go +++ b/src/adapters/web/page_handlers.go @@ -70,17 +70,17 @@ func (web *Web) pagesHandler(w http.ResponseWriter, r *http.Request) { } func (web *Web) shortenByAPIHandler(w http.ResponseWriter, r *http.Request) { - var v engine.ShortenRequest + var v engine.ShortenByAPIRequest if err := json.NewDecoder(r.Body).Decode(&v); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } - page, err := web.engine.Shorten(&v) + page, err := web.engine.ShortenByAPI(&v) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - bytes, _ := json.Marshal(map[string]string{ + bytes, err := json.Marshal(map[string]string{ "URL": page.URL, "Slug": page.Slug, }) diff --git a/src/engine/page.go b/src/engine/page.go index fbae630..83324f9 100644 --- a/src/engine/page.go +++ b/src/engine/page.go @@ -90,6 +90,40 @@ func (e *Engine) Shorten(req *ShortenRequest) (page *domain.Page, err error) { return } +// ShortenByAPIRequest is the request struct for ShortenByAPI function +type ShortenByAPIRequest struct { + URL string + APIKey string +} + +// ShortenByAPI shorten url +func (e *Engine) ShortenByAPI(req *ShortenByAPIRequest) (page *domain.Page, err error) { + if req.URL == "" { + err = errors.New("url cannot be empty") + return + } + if req.APIKey == "" { + err = errors.New("api_key cannot be empty") + return + } + _, err = e.sqlClient.FindUserByAPIKey(req.APIKey) + if err != nil { + return + } + + page = &domain.Page{ + Slug: domain.GenerateSlug(5), + URL: req.URL, + } + err = e.sqlClient.CreatePage(page) + if err != nil { + return + } + + e.redisClient.SetURL(page.Slug, page.URL) + return +} + // AccessRequest is the request struct for Access function type AccessRequest struct { Slug string diff --git a/src/engine/sql.go b/src/engine/sql.go index 5a32929..85d00b0 100644 --- a/src/engine/sql.go +++ b/src/engine/sql.go @@ -7,6 +7,7 @@ type SQLClient interface { Close() error FindUser(uint) (*domain.User, error) + FindUserByAPIKey(string) (*domain.User, error) FindOrCreateUser(domain.User) (*domain.User, error) UpdateUser(*domain.User, *domain.User) error diff --git a/src/providers/sql/users.go b/src/providers/sql/users.go index 9c9a778..7ac4ef8 100644 --- a/src/providers/sql/users.go +++ b/src/providers/sql/users.go @@ -28,6 +28,16 @@ func (c *client) FindUser(id uint) (user *domain.User, err error) { return } +func (c *client) FindUserByAPIKey(apiKey string) (user *domain.User, err error) { + user = &domain.User{} + + err = c.db.Table(tblUsers). + Where("api_key = ?", apiKey). + First(user).Error + + return +} + func (c *client) FindOrCreateUser(params domain.User) (user *domain.User, err error) { user = &domain.User{} err = c.db. From 633b0c7b3027c5a1e87730faaaa039a0dc6bdf20 Mon Sep 17 00:00:00 2001 From: Arashi-K Date: Thu, 26 Dec 2019 19:37:50 +0900 Subject: [PATCH 4/4] fix --- src/adapters/web/middleware.go | 2 -- src/adapters/web/web.go | 2 +- src/domain/page.go | 3 +++ src/engine/page.go | 14 +++++--------- templates/pages.tpl | 2 +- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/adapters/web/middleware.go b/src/adapters/web/middleware.go index 517a98e..1d8a9be 100644 --- a/src/adapters/web/middleware.go +++ b/src/adapters/web/middleware.go @@ -12,8 +12,6 @@ func (web *Web) authenticate(h http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { session, _ := web.store.Get(r, "scvl") userID, ok := session.Values["user_id"].(uint) - userID = 1 - ok = true if ok { user, err := web.engine.FindUser(userID) if err != nil || user.GoogleToken == "" { diff --git a/src/adapters/web/web.go b/src/adapters/web/web.go index 7b23336..9bb6776 100644 --- a/src/adapters/web/web.go +++ b/src/adapters/web/web.go @@ -37,7 +37,7 @@ func (web *Web) Start(port string) error { r.Handle("/logout", web.authenticate(web.logoutHandler)).Methods(http.MethodPost) r.Handle("/shorten", web.authenticate(web.shortenHandler)).Methods(http.MethodPost) r.HandleFunc("/api/shorten", web.shortenByAPIHandler).Methods(http.MethodPost) - r.Handle("/api/publish", web.authenticate(web.publishAPIKeyHandler)).Methods(http.MethodPost) + r.Handle("/api/key", web.authenticate(web.publishAPIKeyHandler)).Methods(http.MethodPost) r.Handle("/pages", web.authenticate(web.pagesHandler)).Methods(http.MethodGet) r.Handle("/files", web.authenticate(web.filesHandler)).Methods(http.MethodGet) r.Handle("/files", web.authenticate(web.fileUploadHandler)).Methods(http.MethodPost) diff --git a/src/domain/page.go b/src/domain/page.go index 512208b..ae31e48 100644 --- a/src/domain/page.go +++ b/src/domain/page.go @@ -17,3 +17,6 @@ type Page struct { OGP *OGP `json:"ogp"` } + +// PageSlugLength is the length for shorten url path. +const PageSlugLength = 5 diff --git a/src/engine/page.go b/src/engine/page.go index 83324f9..b9a877f 100644 --- a/src/engine/page.go +++ b/src/engine/page.go @@ -61,7 +61,7 @@ func (e *Engine) Shorten(req *ShortenRequest) (page *domain.Page, err error) { page = &domain.Page{ UserID: req.UserID, - Slug: domain.GenerateSlug(5), + Slug: domain.GenerateSlug(domain.PageSlugLength), Title: title, URL: req.URL, } @@ -81,8 +81,7 @@ func (e *Engine) Shorten(req *ShortenRequest) (page *domain.Page, err error) { Image: req.Image, Title: req.Title, } - err = e.sqlClient.CreateOGP(page.OGP) - if err != nil { + if err = e.sqlClient.CreateOGP(page.OGP); err != nil { return } @@ -106,20 +105,17 @@ func (e *Engine) ShortenByAPI(req *ShortenByAPIRequest) (page *domain.Page, err err = errors.New("api_key cannot be empty") return } - _, err = e.sqlClient.FindUserByAPIKey(req.APIKey) - if err != nil { + if _, err = e.sqlClient.FindUserByAPIKey(req.APIKey); err != nil { return } page = &domain.Page{ - Slug: domain.GenerateSlug(5), + Slug: domain.GenerateSlug(domain.PageSlugLength), URL: req.URL, } - err = e.sqlClient.CreatePage(page) - if err != nil { + if err = e.sqlClient.CreatePage(page); err != nil { return } - e.redisClient.SetURL(page.Slug, page.URL) return } diff --git a/templates/pages.tpl b/templates/pages.tpl index e94e295..067cb07 100644 --- a/templates/pages.tpl +++ b/templates/pages.tpl @@ -9,7 +9,7 @@
{{.User.APIKey}}
- +