From d91951b49e15411cc946d780de89a6cdcd276a5c Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Tue, 10 Sep 2024 12:16:27 -0400 Subject: [PATCH 1/9] adding csv generation for resources --- .gitignore | 3 +- controllers/resourcesController.go | 47 +++++++++++++++++++++++++ database/entries.go | 8 +++++ models/models.go | 28 +++++++++++++++ public/csv/.placeholder | 0 router/routes.go | 1 + templates/resources/resources-show.html | 3 +- 7 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 public/csv/.placeholder diff --git a/.gitignore b/.gitignore index 4398987..608d0ea 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ build/* .idea/* *.log *.conf -sys/* \ No newline at end of file +sys/* +/public/csv/*.csv \ No newline at end of file diff --git a/controllers/resourcesController.go b/controllers/resourcesController.go index 4da1b57..7911597 100644 --- a/controllers/resourcesController.go +++ b/controllers/resourcesController.go @@ -1,9 +1,12 @@ package controllers import ( + "encoding/csv" "fmt" "log" "net/http" + "os" + "path/filepath" "strconv" "time" @@ -355,3 +358,47 @@ func DeleteResource(c *gin.Context) { c.Redirect(http.StatusFound, fmt.Sprintf("/repositories/%d/show", resource.RepositoryID)) } + +func GenCSV(c *gin.Context) { + + if err := isLoggedIn(c); err != nil { + ThrowError(http.StatusUnauthorized, err.Error(), c, false) + return + } + isLoggedIn := true + + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) + return + } + + resource, err := database.FindResource(uint(id)) + if err != nil { + ThrowError(http.StatusInternalServerError, err.Error(), c, isLoggedIn) + return + } + + entries, err := database.FindEntriesByResourceID(uint(id)) + if err != nil { + ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) + return + } + + csvFileName := fmt.Sprintf("%s_%s.csv", resource.Repository.Slug, resource.CollectionCode) + csvLocation := filepath.Join("public", "tmp", csvFileName) + csvFile, err := os.Create(csvLocation) + if err != nil { + ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) + return + } + defer csvFile.Close() + csvWriter := csv.NewWriter(csvFile) + csvWriter.Write(models.CSVHeader) + for _, entry := range entries { + csvWriter.Write(entry.ToCSV()) + csvWriter.Flush() + } + + c.Redirect(http.StatusTemporaryRedirect, "/public/tmp/"+csvFileName) +} diff --git a/database/entries.go b/database/entries.go index ac629d8..b766179 100644 --- a/database/entries.go +++ b/database/entries.go @@ -47,6 +47,14 @@ func FindEntryIDsByResourceID(id uint) ([]string, error) { return entries, nil } +func FindEntriesByResourceID(id uint) ([]models.Entry, error) { + entries := []models.Entry{} + if err := db.Preload(clause.Associations).Where("resource_id = ?", id).Find(&entries).Error; err != nil { + return []models.Entry{}, err + } + return entries, nil +} + func FindEntriesByResourceIDPaginated(id uint, pagination Pagination) ([]models.Entry, error) { entries := []models.Entry{} if err := db.Preload(clause.Associations).Where("resource_id = ?", id).Limit(pagination.Limit).Offset(pagination.Offset).Order(pagination.Sort).Find(&entries).Error; err != nil { diff --git a/models/models.go b/models/models.go index f9c1086..c9d91e8 100644 --- a/models/models.go +++ b/models/models.go @@ -2,6 +2,7 @@ package models import ( "fmt" + "regexp" "time" "github.com/google/uuid" @@ -82,6 +83,33 @@ type Entry struct { Location string `json:"location" form:"location"` } +var CSVHeader = []string{"id", "media_id", "mediatype", "label_text", "is_refreshed", "repository", "resource", "accession", "storage_location"} + +func (e Entry) ToCSV() []string { + re := regexp.MustCompile(`\r?\n`) + labelText := re.ReplaceAllString(e.LabelText, " ") + + csv := []string{ + e.ID.String(), + fmt.Sprintf("%d", e.MediaID), + e.Mediatype, + labelText, + boolToString(e.IsRefreshed), + e.Repository.Slug, + e.Resource.CollectionCode, + e.Accession.AccessionNum, + e.Location, + } + return csv +} + +func boolToString(b bool) string { + if b { + return "TRUE" + } + return "FALSE" +} + func (e *Entry) UpdateEntry(updatedEntry Entry) { e.Mediatype = updatedEntry.Mediatype e.DispositionNote = updatedEntry.DispositionNote diff --git a/public/csv/.placeholder b/public/csv/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/router/routes.go b/router/routes.go index 78e8e83..9462a1b 100644 --- a/router/routes.go +++ b/router/routes.go @@ -44,6 +44,7 @@ func LoadRoutes(router *gin.Engine) { resourceRoutes.GET(":id/edit", func(c *gin.Context) { controllers.EditResource(c) }) resourceRoutes.POST(":id/update", func(c *gin.Context) { controllers.UpdateResource(c) }) resourceRoutes.GET(":id/delete", func(c *gin.Context) { controllers.DeleteResource(c) }) + resourceRoutes.GET(":id/csv", func(c *gin.Context) { controllers.GenCSV(c) }) //Entries Group entryRoutes := router.Group("/entries") diff --git a/templates/resources/resources-show.html b/templates/resources/resources-show.html index 3492945..45c3c08 100644 --- a/templates/resources/resources-show.html +++ b/templates/resources/resources-show.html @@ -66,7 +66,8 @@
Accessions
Entries
-
+ From c262911f41d52eb8c45247463969196a43fef91a Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Tue, 10 Sep 2024 15:01:11 -0400 Subject: [PATCH 2/9] removing caching csv files in the file system --- controllers/accessionsController.go | 54 ++++++++++++++++++++++++- controllers/apiV0Controller.go | 2 +- controllers/resourcesController.go | 27 ++++++------- database/entries.go | 10 ++++- public/csv/.placeholder | 0 router/routes.go | 3 +- templates/resources/resources-show.html | 8 +++- 7 files changed, 82 insertions(+), 22 deletions(-) delete mode 100644 public/csv/.placeholder diff --git a/controllers/accessionsController.go b/controllers/accessionsController.go index 9a6ed65..9b4c9bd 100644 --- a/controllers/accessionsController.go +++ b/controllers/accessionsController.go @@ -1,9 +1,11 @@ package controllers import ( + "encoding/csv" "fmt" "net/http" "strconv" + "strings" "time" "github.com/gin-gonic/gin" @@ -111,7 +113,7 @@ func GetAccession(c *gin.Context) { pagination := database.Pagination{Limit: 10, Offset: (p * 10), Sort: "media_id"} - entries, err := database.FindEntriesByAccessionID(accession.ID, pagination) + entries, err := database.FindEntriesByAccessionIDPaginated(accession.ID, pagination) if err != nil { ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) return @@ -424,7 +426,7 @@ func SlewAccession(c *gin.Context) { pagination := database.Pagination{Limit: 10, Offset: 0, Sort: "media_id"} - entries, err := database.FindEntriesByAccessionID(accession.ID, pagination) + entries, err := database.FindEntriesByAccessionIDPaginated(accession.ID, pagination) if err != nil { ThrowError(http.StatusInternalServerError, err.Error(), c, isLoggedIn) return @@ -522,3 +524,51 @@ func createSlewEntry(slew Slew, accession models.Accession) error { } return nil } + +func AccessionGenCSV(c *gin.Context) { + + if err := isLoggedIn(c); err != nil { + ThrowError(http.StatusUnauthorized, err.Error(), c, false) + return + } + isLoggedIn := true + + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) + return + } + + accession, err := database.FindAccession(uint(id)) + if err != nil { + ThrowError(http.StatusInternalServerError, err.Error(), c, isLoggedIn) + return + } + + entries, err := database.FindEntriesByAccessionID(accession.ID) + if err != nil { + ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) + return + } + + repository, err := database.FindRepository(accession.Resource.RepositoryID) + if err != nil { + ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) + return + } + + csvFileName := fmt.Sprintf("%s_%s_%s.csv", repository.Slug, accession.Resource.CollectionCode, accession.AccessionNum) + csvBuffer := new(strings.Builder) + var csvWriter = csv.NewWriter(csvBuffer) + csvWriter.Write(models.CSVHeader) + for _, entry := range entries { + record := entry.ToCSV() + csvWriter.Write(record) + } + csvWriter.Flush() + + c.Header("content-type", "text/csv") + c.Header("Content-Description", "File Transfer") + c.Header("Content-Disposition", "attachment; filename="+csvFileName) + c.Writer.Write([]byte(csvBuffer.String())) +} diff --git a/controllers/apiV0Controller.go b/controllers/apiV0Controller.go index df8d517..0f61a03 100644 --- a/controllers/apiV0Controller.go +++ b/controllers/apiV0Controller.go @@ -723,7 +723,7 @@ func GetAccessionEntriesV0(c *gin.Context) { pagination.Limit = pageSize } - entries, err := database.FindEntriesByAccessionID(uint(accessionID), pagination) + entries, err := database.FindEntriesByAccessionIDPaginated(uint(accessionID), pagination) if err != nil { c.JSON(http.StatusInternalServerError, err.Error()) return diff --git a/controllers/resourcesController.go b/controllers/resourcesController.go index 7911597..404419d 100644 --- a/controllers/resourcesController.go +++ b/controllers/resourcesController.go @@ -5,9 +5,8 @@ import ( "fmt" "log" "net/http" - "os" - "path/filepath" "strconv" + "strings" "time" "github.com/gin-gonic/gin" @@ -359,7 +358,7 @@ func DeleteResource(c *gin.Context) { c.Redirect(http.StatusFound, fmt.Sprintf("/repositories/%d/show", resource.RepositoryID)) } -func GenCSV(c *gin.Context) { +func ResourceGenCSV(c *gin.Context) { if err := isLoggedIn(c); err != nil { ThrowError(http.StatusUnauthorized, err.Error(), c, false) @@ -385,20 +384,18 @@ func GenCSV(c *gin.Context) { return } - csvFileName := fmt.Sprintf("%s_%s.csv", resource.Repository.Slug, resource.CollectionCode) - csvLocation := filepath.Join("public", "tmp", csvFileName) - csvFile, err := os.Create(csvLocation) - if err != nil { - ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) - return - } - defer csvFile.Close() - csvWriter := csv.NewWriter(csvFile) + csvBuffer := new(strings.Builder) + var csvWriter = csv.NewWriter(csvBuffer) csvWriter.Write(models.CSVHeader) for _, entry := range entries { - csvWriter.Write(entry.ToCSV()) - csvWriter.Flush() + record := entry.ToCSV() + csvWriter.Write(record) } + csvWriter.Flush() - c.Redirect(http.StatusTemporaryRedirect, "/public/tmp/"+csvFileName) + csvFileName := fmt.Sprintf("%s_%s.csv", resource.Repository.Slug, resource.CollectionCode) + c.Header("content-type", "text/csv") + c.Header("Content-Description", "File Transfer") + c.Header("Content-Disposition", "attachment; filename="+csvFileName) + c.Writer.Write([]byte(csvBuffer.String())) } diff --git a/database/entries.go b/database/entries.go index b766179..2c794ae 100644 --- a/database/entries.go +++ b/database/entries.go @@ -71,7 +71,7 @@ func FindEntryIDsByAccessionID(id uint) ([]string, error) { return ids, nil } -func FindEntriesByAccessionID(id uint, pagination Pagination) ([]models.Entry, error) { +func FindEntriesByAccessionIDPaginated(id uint, pagination Pagination) ([]models.Entry, error) { entries := []models.Entry{} if err := db.Where("accession_id = ?", id).Limit(pagination.Limit).Offset(pagination.Offset).Order(pagination.Sort).Find(&entries).Error; err != nil { return entries, err @@ -79,6 +79,14 @@ func FindEntriesByAccessionID(id uint, pagination Pagination) ([]models.Entry, e return entries, nil } +func FindEntriesByAccessionID(id uint) ([]models.Entry, error) { + entries := []models.Entry{} + if err := db.Preload(clause.Associations).Where("accession_id = ?", id).Find(&entries).Error; err != nil { + return entries, err + } + return entries, nil +} + func FindEntriesByRepositoryID(repositoryID uint) ([]models.Entry, error) { entries := []models.Entry{} if err := db.Preload(clause.Associations).Where("repository_id = ?", repositoryID).Find(&entries).Error; err != nil { diff --git a/public/csv/.placeholder b/public/csv/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/router/routes.go b/router/routes.go index 9462a1b..bd68daa 100644 --- a/router/routes.go +++ b/router/routes.go @@ -24,6 +24,7 @@ func LoadRoutes(router *gin.Engine) { accessionsRoutes.GET(":id/delete", func(c *gin.Context) { controllers.DeleteAccession(c) }) accessionsRoutes.GET(":id/slew", func(c *gin.Context) { controllers.SlewAccession(c) }) accessionsRoutes.POST("slew", func(c *gin.Context) { controllers.CreateAccessionSlew(c) }) + accessionsRoutes.GET(":id/csv", func(c *gin.Context) { controllers.AccessionGenCSV(c) }) //Repository Group repositoryRoutes := router.Group("/repositories") @@ -44,7 +45,7 @@ func LoadRoutes(router *gin.Engine) { resourceRoutes.GET(":id/edit", func(c *gin.Context) { controllers.EditResource(c) }) resourceRoutes.POST(":id/update", func(c *gin.Context) { controllers.UpdateResource(c) }) resourceRoutes.GET(":id/delete", func(c *gin.Context) { controllers.DeleteResource(c) }) - resourceRoutes.GET(":id/csv", func(c *gin.Context) { controllers.GenCSV(c) }) + resourceRoutes.GET(":id/csv", func(c *gin.Context) { controllers.ResourceGenCSV(c) }) //Entries Group entryRoutes := router.Group("/entries") diff --git a/templates/resources/resources-show.html b/templates/resources/resources-show.html index 45c3c08..c8af7d6 100644 --- a/templates/resources/resources-show.html +++ b/templates/resources/resources-show.html @@ -66,9 +66,13 @@
Accessions
Entries
-
- CSV +
+ CSV +
+ +
From 3ef4aa6e0b33644ff5476a7e6192cb94031dcd50 Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Tue, 10 Sep 2024 17:27:58 -0400 Subject: [PATCH 3/9] updating accessions-show view to generate csv file. --- medialog_test.go | 37 +++++++++++++++++++++++ templates/accessions/accessions-show.html | 11 +++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/medialog_test.go b/medialog_test.go index 9946773..6d32e9b 100644 --- a/medialog_test.go +++ b/medialog_test.go @@ -3,6 +3,8 @@ package main import ( "net/http" "net/http/httptest" + "net/url" + "strings" "testing" "github.com/gin-gonic/gin" @@ -24,4 +26,39 @@ func TestApplication(t *testing.T) { assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("content-type")) }) + t.Run("test login to application", func(t *testing.T) { + recorder := httptest.NewRecorder() + c, _ := gin.CreateTestContext(recorder) + form := url.Values{} + form.Set("email", env.TestCreds.Username) + form.Add("password_1", env.TestCreds.Password) + req, err := http.NewRequestWithContext(c, "POST", "/users/authenticate", strings.NewReader(form.Encode())) + if err != nil { + t.Error(err) + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + r.ServeHTTP(recorder, req) + assert.Equal(t, http.StatusFound, recorder.Code) + + t.Log(recorder.Result().Header.Get("Set-Cookie")) + }) + + t.Run("test get index authenticated", func(t *testing.T) { + recorder := httptest.NewRecorder() + c, _ := gin.CreateTestContext(recorder) + c.SetCookie("medialog-sessions", + "MTcyNTk5NzI2MHxOd3dBTkZkRVFUZEhRazFKU1VWVldqVlRSRlpZUkVWSVYxQkRRMUpHTjAxTFdsVk9OME5HTWpWTVdqSkhURnBPUkVsVVNGWmFWVkU9fGYXoOEZhC7V7FyNzW3NZd0xiPTGNjOqHJg2LMMM5iex", + 2592000, "/", "", false, true, + ) + + req, err := http.NewRequestWithContext(c, "GET", "/", nil) + if err != nil { + t.Error(err) + } + r.ServeHTTP(recorder, req) + assert.Equal(t, 200, recorder.Code) + assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("content-type")) + + }) + } diff --git a/templates/accessions/accessions-show.html b/templates/accessions/accessions-show.html index 6bbd8f5..a279cd8 100644 --- a/templates/accessions/accessions-show.html +++ b/templates/accessions/accessions-show.html @@ -37,9 +37,14 @@
{{ .accession.AccessionNum }}
Entries
-
- prev 10 - next 10 +
+ CSV +
+
+ prev 10 +
+
From 37b41cc24f9c5695162cd760e1b0ce4ce7d9fca7 Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Fri, 13 Sep 2024 13:11:34 -0400 Subject: [PATCH 4/9] moving apicontroller out of controllers package --- {controllers => api/v0}/apiV0Controller.go | 11 +++-- controllers/sessionController.go | 4 +- controllers/userController.go | 2 +- go.mod | 3 -- go.sum | 26 +++++----- router/routes.go | 55 +++++++++++----------- 6 files changed, 50 insertions(+), 51 deletions(-) rename {controllers => api/v0}/apiV0Controller.go (99%) diff --git a/controllers/apiV0Controller.go b/api/v0/apiV0Controller.go similarity index 99% rename from controllers/apiV0Controller.go rename to api/v0/apiV0Controller.go index 0f61a03..c29f25c 100644 --- a/controllers/apiV0Controller.go +++ b/api/v0/apiV0Controller.go @@ -1,4 +1,4 @@ -package controllers +package api import ( "crypto/sha512" @@ -12,6 +12,7 @@ import ( "github.com/gin-gonic/gin" "github.com/google/uuid" + "github.com/nyudlts/go-medialog/controllers" "github.com/nyudlts/go-medialog/database" "github.com/nyudlts/go-medialog/models" ) @@ -54,7 +55,7 @@ type APIError struct { } func APILogin(c *gin.Context) { - expireTokens() + controllers.ExpireTokens() email := c.Param("user") password := c.Query("password") @@ -85,7 +86,7 @@ func APILogin(c *gin.Context) { return } - token := GenerateStringRunes(24) + token := controllers.GenerateStringRunes(24) tkHash := sha512.Sum512([]byte(token)) token = hex.EncodeToString(tkHash[:]) @@ -993,7 +994,7 @@ func UpdateEntryLocationV0(c *gin.Context) { return } - storageLocation := GetStorageLocation(location) + storageLocation := controllers.GetStorageLocation(location) if storageLocation == "No Match" { c.JSON(http.StatusBadRequest, fmt.Sprintf("`%s` is not a valid location", location)) @@ -1040,7 +1041,7 @@ func DeleteSessionsV0(c *gin.Context) { } func checkToken(c *gin.Context) (string, error) { - expireTokens() + controllers.ExpireTokens() token := c.Request.Header.Get("X-Medialog-Token") if token == "" { diff --git a/controllers/sessionController.go b/controllers/sessionController.go index 644dd91..667cae2 100644 --- a/controllers/sessionController.go +++ b/controllers/sessionController.go @@ -16,7 +16,7 @@ var isAdmin = "is-admin" var canAccessAPI = "can-access-api" var sessionToken = "token" -func expireTokens() { +func ExpireTokens() { tokens := database.GetTokens() log.Printf("[INFO] expiring api tokens") for _, token := range tokens { @@ -31,7 +31,7 @@ func expireTokens() { func isLoggedIn(c *gin.Context) error { - expireTokens() + ExpireTokens() session := sessions.Default(c) userIDCookie := session.Get(userkey) diff --git a/controllers/userController.go b/controllers/userController.go index c9ce14e..f0b3fe5 100644 --- a/controllers/userController.go +++ b/controllers/userController.go @@ -338,7 +338,7 @@ func AuthenticateUser(c *gin.Context) { Type: "application", } - expireTokens() + ExpireTokens() if err := database.ExpireAppTokensByUserID(user.ID); err != nil { ThrowError(http.StatusInternalServerError, "could not expire tokens for users", c, false) diff --git a/go.mod b/go.mod index 62a0501..d12211d 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,6 @@ require ( github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.2.2 // indirect github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect - github.com/jackc/pgx/v5 v5.5.5 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -54,6 +53,4 @@ require ( google.golang.org/protobuf v1.33.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gorm.io/driver/postgres v1.5.7 // indirect - gorm.io/driver/sqlite v1.5.5 // indirect ) diff --git a/go.sum b/go.sum index b26214f..8d24217 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,10 @@ github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pw github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= @@ -70,13 +72,16 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -84,6 +89,7 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= @@ -92,21 +98,18 @@ github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01C github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= -github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= -github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= -github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= @@ -144,8 +147,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= -github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -233,8 +236,6 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -291,12 +292,11 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.4.0 h1:P+gpa0QGyNma39khn1vZMS/eXEJxTwHz4Q26NR4C8fw= gorm.io/driver/mysql v1.4.0/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= +gorm.io/driver/postgres v1.4.1 h1:DutsKq2LK2Ag65q/+VygWth0/L4GAVOp+sCtg6WzZjs= gorm.io/driver/postgres v1.4.1/go.mod h1:whNfh5WhhHs96honoLjBAMwJGYEuA3m1hvgUbNXhPCw= -gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= -gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= gorm.io/driver/sqlite v1.4.1/go.mod h1:AKZZCAoFfOWHF7Nd685Iq8Uywc0i9sWJlzpoE/INzsw= -gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E= -gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE= +gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc= +gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.10/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= diff --git a/router/routes.go b/router/routes.go index bd68daa..4539489 100644 --- a/router/routes.go +++ b/router/routes.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/nyudlts/go-medialog/api/v0" "github.com/nyudlts/go-medialog/controllers" ) @@ -109,45 +110,45 @@ func LoadAPI(router *gin.Engine) { apiV0Routes := router.Group("/api/v0") //index - apiV0Routes.GET("", func(c *gin.Context) { controllers.GetV0Index(c) }) + apiV0Routes.GET("", func(c *gin.Context) { api.GetV0Index(c) }) //users - apiV0Routes.POST("users/:user/login", func(c *gin.Context) { controllers.APILogin(c) }) - apiV0Routes.DELETE("logout", func(c *gin.Context) { controllers.APILogout(c) }) + apiV0Routes.POST("users/:user/login", func(c *gin.Context) { api.APILogin(c) }) + apiV0Routes.DELETE("logout", func(c *gin.Context) { api.APILogout(c) }) //repositories - apiV0Routes.GET("repositories/:id", func(c *gin.Context) { controllers.GetRepositoryV0(c) }) - apiV0Routes.GET("repositories", func(c *gin.Context) { controllers.GetRepositoriesV0(c) }) - apiV0Routes.POST("repositories", func(c *gin.Context) { controllers.CreateRepositoryV0(c) }) - apiV0Routes.DELETE("repositories/:id", func(c *gin.Context) { controllers.DeleteRepositoryV0(c) }) - apiV0Routes.GET("repositories/:id/entries", func(c *gin.Context) { controllers.GetRepositoryEntriesV0(c) }) - apiV0Routes.GET("repositories/:id/summary", func(c *gin.Context) { controllers.GetRepositorySummaryV0(c) }) + apiV0Routes.GET("repositories/:id", func(c *gin.Context) { api.GetRepositoryV0(c) }) + apiV0Routes.GET("repositories", func(c *gin.Context) { api.GetRepositoriesV0(c) }) + apiV0Routes.POST("repositories", func(c *gin.Context) { api.CreateRepositoryV0(c) }) + apiV0Routes.DELETE("repositories/:id", func(c *gin.Context) { api.DeleteRepositoryV0(c) }) + apiV0Routes.GET("repositories/:id/entries", func(c *gin.Context) { api.GetRepositoryEntriesV0(c) }) + apiV0Routes.GET("repositories/:id/summary", func(c *gin.Context) { api.GetRepositorySummaryV0(c) }) //resources - apiV0Routes.POST("resources", func(c *gin.Context) { controllers.CreateResourceV0(c) }) - apiV0Routes.GET("resources", func(c *gin.Context) { controllers.GetResourcesV0(c) }) - apiV0Routes.GET("resources/:id", func(c *gin.Context) { controllers.GetResourceV0(c) }) - apiV0Routes.DELETE("resources/:id", func(c *gin.Context) { controllers.DeleteResourceV0(c) }) - apiV0Routes.GET("resources/:id/entries", func(c *gin.Context) { controllers.GetResourceEntriesV0(c) }) - apiV0Routes.GET("resources/:id/summary", func(c *gin.Context) { controllers.GetResourceSummaryV0(c) }) + apiV0Routes.POST("resources", func(c *gin.Context) { api.CreateResourceV0(c) }) + apiV0Routes.GET("resources", func(c *gin.Context) { api.GetResourcesV0(c) }) + apiV0Routes.GET("resources/:id", func(c *gin.Context) { api.GetResourceV0(c) }) + apiV0Routes.DELETE("resources/:id", func(c *gin.Context) { api.DeleteResourceV0(c) }) + apiV0Routes.GET("resources/:id/entries", func(c *gin.Context) { api.GetResourceEntriesV0(c) }) + apiV0Routes.GET("resources/:id/summary", func(c *gin.Context) { api.GetResourceSummaryV0(c) }) //accessions - apiV0Routes.POST("accessions", func(c *gin.Context) { controllers.CreateAccessionV0(c) }) - apiV0Routes.DELETE("accessions/:id", func(c *gin.Context) { controllers.DeleteAccessionV0(c) }) - apiV0Routes.GET("accessions", func(c *gin.Context) { controllers.GetAccessionsV0(c) }) - apiV0Routes.GET("accessions/:id", func(c *gin.Context) { controllers.GetAccessionV0(c) }) - apiV0Routes.GET("accessions/:id/entries", func(c *gin.Context) { controllers.GetAccessionEntriesV0(c) }) - apiV0Routes.GET("accessions/:id/summary", func(c *gin.Context) { controllers.GetAccessionSummaryV0(c) }) + apiV0Routes.POST("accessions", func(c *gin.Context) { api.CreateAccessionV0(c) }) + apiV0Routes.DELETE("accessions/:id", func(c *gin.Context) { api.DeleteAccessionV0(c) }) + apiV0Routes.GET("accessions", func(c *gin.Context) { api.GetAccessionsV0(c) }) + apiV0Routes.GET("accessions/:id", func(c *gin.Context) { api.GetAccessionV0(c) }) + apiV0Routes.GET("accessions/:id/entries", func(c *gin.Context) { api.GetAccessionEntriesV0(c) }) + apiV0Routes.GET("accessions/:id/summary", func(c *gin.Context) { api.GetAccessionSummaryV0(c) }) //entries - apiV0Routes.POST("entries", func(c *gin.Context) { controllers.CreateEntryV0(c) }) - apiV0Routes.DELETE("entries/:id", func(c *gin.Context) { controllers.DeleteEntryV0(c) }) - apiV0Routes.GET("entries", func(c *gin.Context) { controllers.GetEntriesV0(c) }) - apiV0Routes.GET("entries/:id", func(c *gin.Context) { controllers.GetEntryV0(c) }) - apiV0Routes.PATCH("entries/:id/update_location", func(c *gin.Context) { controllers.UpdateEntryLocationV0(c) }) + apiV0Routes.POST("entries", func(c *gin.Context) { api.CreateEntryV0(c) }) + apiV0Routes.DELETE("entries/:id", func(c *gin.Context) { api.DeleteEntryV0(c) }) + apiV0Routes.GET("entries", func(c *gin.Context) { api.GetEntriesV0(c) }) + apiV0Routes.GET("entries/:id", func(c *gin.Context) { api.GetEntryV0(c) }) + apiV0Routes.PATCH("entries/:id/update_location", func(c *gin.Context) { api.UpdateEntryLocationV0(c) }) //sessions - apiV0Routes.DELETE("delete_sessions", func(c *gin.Context) { controllers.DeleteSessionsV0(c) }) + apiV0Routes.DELETE("delete_sessions", func(c *gin.Context) { api.DeleteSessionsV0(c) }) } func Test(c *gin.Context) { From d1006640c240826aba61e38d9b1e649c0b21e4e3 Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Fri, 13 Sep 2024 13:31:43 -0400 Subject: [PATCH 5/9] refactoring directory structure -- renaming files --- .gitignore | 1 + api/v0/API-Accessions.go | 233 ++++ api/v0/API-Entries.go | 255 ++++ api/v0/API-Repositories.go | 215 ++++ api/v0/API-Resources.go | 223 ++++ api/v0/API-V0.go | 175 +++ api/v0/apiV0Controller.go | 1061 ----------------- ...errorController.go => ErrorsController.go} | 0 ...ionController.go => SessionsController.go} | 0 .../{userController.go => UsersController.go} | 0 ...ontroller.go => VocabulariesController.go} | 0 .../{accessions.go => Database-Accessions.go} | 0 database/{entries.go => Database-Entries.go} | 0 .../{migrations.go => Database-Migrations.go} | 0 ...positories.go => Database-Repositories.go} | 0 .../{resources.go => Database-Resources.go} | 0 .../{sessions.go => Database-Sessions.go} | 0 database/{Tokens.go => Database-Tokens.go} | 0 database/{users.go => Database-Users.go} | 0 router/routes.go | 2 +- 20 files changed, 1103 insertions(+), 1062 deletions(-) create mode 100644 api/v0/API-Accessions.go create mode 100644 api/v0/API-Entries.go create mode 100644 api/v0/API-Repositories.go create mode 100644 api/v0/API-Resources.go create mode 100644 api/v0/API-V0.go delete mode 100644 api/v0/apiV0Controller.go rename controllers/{errorController.go => ErrorsController.go} (100%) rename controllers/{sessionController.go => SessionsController.go} (100%) rename controllers/{userController.go => UsersController.go} (100%) rename controllers/{vocabularyController.go => VocabulariesController.go} (100%) rename database/{accessions.go => Database-Accessions.go} (100%) rename database/{entries.go => Database-Entries.go} (100%) rename database/{migrations.go => Database-Migrations.go} (100%) rename database/{repositories.go => Database-Repositories.go} (100%) rename database/{resources.go => Database-Resources.go} (100%) rename database/{sessions.go => Database-Sessions.go} (100%) rename database/{Tokens.go => Database-Tokens.go} (100%) rename database/{users.go => Database-Users.go} (100%) diff --git a/.gitignore b/.gitignore index 608d0ea..5192871 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.db *.exe build/* +bin/* .vscode/* .idea/* *.log diff --git a/api/v0/API-Accessions.go b/api/v0/API-Accessions.go new file mode 100644 index 0000000..675677f --- /dev/null +++ b/api/v0/API-Accessions.go @@ -0,0 +1,233 @@ +package api + +import ( + "fmt" + "net/http" + "strconv" + "time" + + "github.com/gin-gonic/gin" + "github.com/nyudlts/go-medialog/database" + "github.com/nyudlts/go-medialog/models" +) + +func CreateAccessionV0(c *gin.Context) { + token, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + accession := models.Accession{} + if err := c.Bind(&accession); err != nil { + c.JSON(http.StatusBadRequest, err) + return + } + + userId, err := database.FindUserIDByToken(token) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + resource, err := database.FindResource(accession.ResourceID) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + accession.CreatedBy = int(userId) + accession.UpdatedBy = int(userId) + accession.CreatedAt = time.Now() + accession.UpdatedAt = time.Now() + accession.Resource = resource + + _, err = database.InsertAccession(&accession) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, accession) + +} + +func GetAccessionsV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + accessions, err := database.FindAccessions() + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error) + return + } + + c.JSON(http.StatusOK, accessions) +} + +func GetAccessionV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, err.Error()) + return + } + + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error) + } + + accession, err := database.FindAccession(uint(id)) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error) + return + } + + repository, err := database.FindRepository(accession.Resource.RepositoryID) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error) + return + } + + accession.Resource.Repository = repository + + c.JSON(http.StatusOK, accession) +} + +func DeleteAccessionV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, err.Error()) + return + } + + accessionIDParam := c.Param("id") + accessionID, err := strconv.Atoi(accessionIDParam) + if err != nil { + c.JSON(http.StatusBadRequest, err) + return + } + + if err := database.DeleteAccession(uint(accessionID)); err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, fmt.Sprintf("Resource %d deleted", accessionID)) + +} + +func GetAccessionEntriesV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + accessionIDParam := c.Param("id") + accessionID, err := strconv.Atoi(accessionIDParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + } + + allIDsParam := c.Query("all_ids") + pageParam := c.Query("page") + pageSizeParam := c.Query("page_size") + var allIds bool + + if allIDsParam != "" { + var err error + allIds, err = strconv.ParseBool(allIDsParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + } + + if allIds { + entries, err := database.FindEntryIDsByAccessionID(uint(accessionID)) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + c.JSON(http.StatusOK, entries) + } else { + page, err := strconv.Atoi(pageParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + pagination := database.Pagination{} + pagination.Offset = page + + pageSize, err := strconv.Atoi(pageSizeParam) + if err != nil { + pagination.Limit = 25 + } else { + pagination.Limit = pageSize + } + + entries, err := database.FindEntriesByAccessionIDPaginated(uint(accessionID), pagination) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + e := EntryResultSet{} + e.Total = database.GetCountOfEntriesInAccession(uint(accessionID)) + e.FirstPage = 1 + e.ThisPage = page + e.Results = entries + r := int(e.Total / int64(pagination.Limit)) + m := int(e.Total % int64(pagination.Limit)) + var t int + if m > 0 { + t = r + 1 + } + e.LastPage = t + + c.JSON(http.StatusOK, e) + } + +} + +func GetAccessionSummaryV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + idParam := c.Param("id") + accessionID, err := strconv.Atoi(idParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + accession, err := database.FindAccession(uint(accessionID)) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + summaries, err := database.GetSummaryByAccession(uint(accessionID)) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + summaryAccession := SummaryTotalsAccession{} + summaryAccession.AccessionIdentifier = accession.AccessionNum + summaryAccession.Totals = summaries.GetTotals() + summaryAccession.Summaries = summaries.GetSlice() + + c.JSON(http.StatusOK, summaryAccession) + +} diff --git a/api/v0/API-Entries.go b/api/v0/API-Entries.go new file mode 100644 index 0000000..4ebdf3d --- /dev/null +++ b/api/v0/API-Entries.go @@ -0,0 +1,255 @@ +package api + +import ( + "fmt" + "net/http" + "strconv" + "time" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/nyudlts/go-medialog/controllers" + "github.com/nyudlts/go-medialog/database" + "github.com/nyudlts/go-medialog/models" +) + +func CreateEntryV0(c *gin.Context) { + token, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, err.Error()) + return + } + + userID, err := database.FindUserIDByToken(token) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + entry := models.Entry{} + if err := c.Bind(&entry); err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + entry.CreatedBy = int(userID) + entry.UpdatedBy = int(userID) + entry.CreatedAt = time.Now() + entry.UpdatedAt = time.Now() + entry.ID, _ = uuid.NewUUID() + + accession, err := database.FindAccession(entry.AccessionID) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + entry.Accession = accession + + resource, err := database.FindResource(accession.ResourceID) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + entry.Resource = resource + + repository, err := database.FindRepository(resource.RepositoryID) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + entry.Repository = repository + + _, err = database.InsertEntry(&entry) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + c.JSON(http.StatusOK, entry) +} + +func DeleteEntryV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, err.Error()) + return + } + + entryID := c.Param("id") + entryUUID, err := uuid.Parse(entryID) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + if err := database.DeleteEntry(entryUUID); err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + c.JSON(http.StatusOK, fmt.Sprintf("Entry %s deleted", entryUUID)) +} + +func GetEntryV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, err.Error()) + return + } + + id := c.Param("id") + + uId, err := uuid.Parse(id) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + entry, err := database.FindEntry(uId) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + c.JSON(http.StatusOK, entry) +} + +func GetEntriesV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + allIDsParam := c.Query("all_ids") + + var allIds bool + if allIDsParam != "" { + var err error + allIds, err = strconv.ParseBool(allIDsParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + } + + if allIds { + ids, err := database.GetEntryIDs() + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } else { + c.JSON(http.StatusOK, ids) + return + } + } else { + + pageSizeParam := c.Query("page_size") + var pageSize int + if pageSizeParam != "" { + var err error + pageSize, err = strconv.Atoi(pageSizeParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + } else { + pageSize = 25 + } + + pageParam := c.Query("page") + var entries []models.Entry + var page int + if pageParam != "" { + var err error + page, err = strconv.Atoi(pageParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + pagination := database.Pagination{Offset: page, Limit: pageSize} + fmt.Println(pagination) + entries, err = database.FindEntriesPaginated(pagination) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + } else { + page = 1 + } + + results := EntryResultSet{} + results.Total = database.GetCountOfEntriesInDB() + r := int(results.Total / int64(pageSize)) + m := int(results.Total % int64(pageSize)) + var t int + if m > 0 { + t = r + 1 + } + results.Results = entries + results.FirstPage = 1 + results.ThisPage = page + results.LastPage = t + + c.JSON(http.StatusOK, results) + return + } +} + +func UpdateEntryLocationV0(c *gin.Context) { + token, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, err.Error()) + return + } + + id := c.Param("id") + if id == "" { + c.JSON(http.StatusBadRequest, "no id provided") + return + } + + uid, err := uuid.Parse(id) + if err != nil { + c.JSON(http.StatusBadRequest, "provided id is not a valid uuid") + return + } + + location := c.Query("location") + if location == "" { + c.JSON(http.StatusBadRequest, "no location provided") + return + } + + storageLocation := controllers.GetStorageLocation(location) + + if storageLocation == "No Match" { + c.JSON(http.StatusBadRequest, fmt.Sprintf("`%s` is not a valid location", location)) + return + } + + entry, err := database.FindEntry(uid) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + userID, err := database.FindUserIDByToken(token) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + entry.Location = location + entry.UpdatedAt = time.Now() + entry.UpdatedBy = int(userID) + + if err := database.UpdateEntry(&entry); err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + c.JSON(http.StatusOK, fmt.Sprintf("id: %s, location: %s, storage location: %s", id, location, storageLocation)) + +} diff --git a/api/v0/API-Repositories.go b/api/v0/API-Repositories.go new file mode 100644 index 0000000..7f8a98f --- /dev/null +++ b/api/v0/API-Repositories.go @@ -0,0 +1,215 @@ +package api + +import ( + "fmt" + "log" + "net/http" + "strconv" + "time" + + "github.com/gin-gonic/gin" + "github.com/nyudlts/go-medialog/database" + "github.com/nyudlts/go-medialog/models" +) + +func GetRepositoriesV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + repositories, err := database.FindRepositories() + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error) + return + } + + c.JSON(http.StatusOK, repositories) +} + +func GetRepositoryV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error) + } + + repository, err := database.FindRepository(uint(id)) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error) + return + } + + c.JSON(http.StatusOK, repository) +} + +func CreateRepositoryV0(c *gin.Context) { + token, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + repo := models.Repository{} + if err := c.Bind(&repo); err != nil { + c.JSON(http.StatusBadRequest, err) + return + } + + userID, err := database.FindUserIDByToken(token) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + repo.CreatedBy = int(userID) + repo.UpdatedBy = int(userID) + repo.CreatedAt = time.Now() + repo.UpdatedAt = time.Now() + + _, err = database.CreateRepository(&repo) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, repo) +} + +func DeleteRepositoryV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + repositoryIDParam := c.Param("id") + repositoryID, err := strconv.Atoi(repositoryIDParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + if err := database.DeleteRepository(uint(repositoryID)); err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, fmt.Sprintf("Repository %d deleted", repositoryID)) + +} + +func GetRepositoryEntriesV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + repositoryIDParam := c.Param("id") + repositoryID, err := strconv.Atoi(repositoryIDParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + } + + allIDsParam := c.Query("all_ids") + pageParam := c.Query("page") + pageSizeParam := c.Query("page_size") + log.Println(allIDsParam) + var allIds bool + if allIDsParam != "" { + var err error + allIds, err = strconv.ParseBool(allIDsParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + } + + if allIds { + entries, err := database.FindEntryIDsByRepositoryID(uint(repositoryID)) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + c.JSON(http.StatusOK, entries) + return + } else { + page, err := strconv.Atoi(pageParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + pagination := database.Pagination{} + pagination.Offset = page + + pageSize, err := strconv.Atoi(pageSizeParam) + if err != nil { + pagination.Limit = 25 + } else { + pagination.Limit = pageSize + } + + entries, err := database.FindEntriesByRepositoryIDPaginated(uint(repositoryID), pagination) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + e := EntryResultSet{} + e.Total = database.GetCountOfEntriesInRepository(uint(repositoryID)) + e.FirstPage = 1 + e.ThisPage = page + e.Results = entries + r := int(e.Total / int64(pagination.Limit)) + m := int(e.Total % int64(pagination.Limit)) + var t int + if m > 0 { + t = r + 1 + } + e.LastPage = t + c.JSON(http.StatusOK, e) + } +} + +func GetRepositorySummaryV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + idParam := c.Param("id") + id, err := strconv.Atoi(idParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + } + + repository, err := database.FindRepository(uint(id)) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + summaryMap, err := database.GetSummaryByRepository(uint(id)) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + summaryTotals := SummaryTotalsRepo{ + Repository: repository.Title, + Totals: summaryMap.GetTotals(), + Summaries: summaryMap.GetSlice(), + } + + c.JSON(http.StatusOK, summaryTotals) +} diff --git a/api/v0/API-Resources.go b/api/v0/API-Resources.go new file mode 100644 index 0000000..a928eed --- /dev/null +++ b/api/v0/API-Resources.go @@ -0,0 +1,223 @@ +package api + +import ( + "fmt" + "net/http" + "strconv" + "time" + + "github.com/gin-gonic/gin" + "github.com/nyudlts/go-medialog/database" + "github.com/nyudlts/go-medialog/models" +) + +func CreateResourceV0(c *gin.Context) { + token, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + resource := models.Resource{} + if err := c.Bind(&resource); err != nil { + c.JSON(http.StatusBadRequest, err) + return + } + + userID, err := database.FindUserIDByToken(token) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + repository, err := database.FindRepository(resource.RepositoryID) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + resource.CreatedBy = int(userID) + resource.UpdatedBy = int(userID) + resource.CreatedAt = time.Now() + resource.UpdatedAt = time.Now() + resource.Repository = repository + + _, err = database.InsertResource(&resource) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, resource) +} + +func DeleteResourceV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + resourceIDParam := c.Param("id") + resourceID, err := strconv.Atoi(resourceIDParam) + if err != nil { + c.JSON(http.StatusBadRequest, err) + return + } + + if err := database.DeleteResource(uint(resourceID)); err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, fmt.Sprintf("Resource %d deleted", resourceID)) + +} + +func GetResourcesV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + resources, err := database.FindResources() + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error) + return + } + + c.JSON(http.StatusOK, resources) +} + +func GetResourceV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error) + } + + resource, err := database.FindResource(uint(id)) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error) + return + } + + c.JSON(http.StatusOK, resource) +} + +func GetResourceEntriesV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + resourceIDParam := c.Param("id") + resourceID, err := strconv.Atoi(resourceIDParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + } + + allIDsParam := c.Query("all_ids") + pageParam := c.Query("page") + pageSizeParam := c.Query("page_size") + + var allIds bool + if allIDsParam != "" { + var err error + allIds, err = strconv.ParseBool(allIDsParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + } + + if allIds { + entries, err := database.FindEntryIDsByResourceID(uint(resourceID)) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + c.JSON(http.StatusOK, entries) + } else { + page, err := strconv.Atoi(pageParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + pagination := database.Pagination{} + pagination.Offset = page + + pageSize, err := strconv.Atoi(pageSizeParam) + if err != nil { + pagination.Limit = 25 + } else { + pagination.Limit = pageSize + } + + entries, err := database.FindEntriesByResourceIDPaginated(uint(resourceID), pagination) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + e := EntryResultSet{} + e.Total = database.GetCountOfEntriesInResource(uint(resourceID)) + e.FirstPage = 1 + e.ThisPage = page + e.Results = entries + r := int(e.Total / int64(pagination.Limit)) + m := int(e.Total % int64(pagination.Limit)) + var t int + if m > 0 { + t = r + 1 + } + e.LastPage = t + c.JSON(http.StatusOK, e) + } +} + +func GetResourceSummaryV0(c *gin.Context) { + + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + idParam := c.Param("id") + id, err := strconv.Atoi(idParam) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + resource, err := database.FindResource(uint(id)) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + summaries, err := database.GetSummaryByResource(uint(id)) + if err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + resourceSummary := SummaryTotalsResource{} + resourceSummary.ResourceIdentifier = resource.CollectionCode + resourceSummary.ResourceTitle = resource.Title + resourceSummary.Totals = summaries.GetTotals() + resourceSummary.Summaries = summaries.GetSlice() + + c.JSON(http.StatusOK, resourceSummary) +} diff --git a/api/v0/API-V0.go b/api/v0/API-V0.go new file mode 100644 index 0000000..309b654 --- /dev/null +++ b/api/v0/API-V0.go @@ -0,0 +1,175 @@ +package api + +import ( + "crypto/sha512" + "encoding/hex" + "fmt" + "net/http" + "runtime" + "time" + + "github.com/gin-gonic/gin" + "github.com/nyudlts/go-medialog/controllers" + "github.com/nyudlts/go-medialog/database" + "github.com/nyudlts/go-medialog/models" +) + +type EntryResultSet struct { + FirstPage int `json:"first_page"` + LastPage int `json:"last_page"` + ThisPage int `json:"this_page"` + Total int64 `json:"total"` + Results []models.Entry `json:"results"` +} + +type SummaryTotalsRepo struct { + Repository string `json:"repository"` + Totals database.Totals `json:"totals"` + Summaries []database.Summary `json:"summaries"` +} + +type SummaryTotalsResource struct { + ResourceIdentifier string `json:"resource_identifier"` + ResourceTitle string `json:"resource_title"` + Totals database.Totals `json:"totals"` + Summaries []database.Summary `json:"summaries"` +} + +type SummaryTotalsAccession struct { + AccessionIdentifier string `json:"accession_identifier"` + Totals database.Totals `json:"totals"` + Summaries []database.Summary `json:"summaries"` +} + +const UNAUTHORIZED = "Please authenticate to access this service" +const apiVersion = "v0.1.3" +const medialogVersion = "v1.0.6" + +var ACCESS_DENIED = map[string]string{"error": "access denied"} + +type APIError struct { + Message map[string][]string `json:"error"` +} + +func APILogin(c *gin.Context) { + controllers.ExpireTokens() + email := c.Param("user") + password := c.Query("password") + + if password == "" { + apiError := APIError{} + e := map[string][]string{"password": []string{"Parameter required but no value provided"}} + apiError.Message = e + c.JSON(http.StatusBadRequest, apiError) + return + } + + user, err := database.FindUserByEmail(email) + if err != nil { + c.JSON(http.StatusUnauthorized, map[string]string{"error": "login failed - user not found"}) + return + } + + hash := sha512.Sum512([]byte(password + user.Salt)) + userSHA512 := hex.EncodeToString(hash[:]) + + if userSHA512 != user.EncryptedPassword { + c.JSON(http.StatusBadRequest, fmt.Sprintf("storedChecksum: %s, calculatedChecksum: %s", user.EncryptedPassword, userSHA512)) + return + } + + if !user.CanAccessAPI { + c.JSON(http.StatusUnauthorized, "login failed -- user not authorized to access api") + return + } + + token := controllers.GenerateStringRunes(24) + tkHash := sha512.Sum512([]byte(token)) + token = hex.EncodeToString(tkHash[:]) + + user.EncryptedPassword = "####" + user.Salt = "####" + + apiToken := models.Token{ + Token: token, + UserID: user.ID, + IsValid: true, + Expires: time.Now().Add(time.Hour * 3), + User: user, + Type: "api", + } + + //expire users other tokens + if err := database.ExpireAPITokensByUserID(user.ID); err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + //add token to api db + if err := database.InsertToken(&apiToken); err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + return + } + + c.JSON(200, apiToken) +} + +func APILogout(c *gin.Context) { + token, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, ACCESS_DENIED) + return + } + + if err := database.DeleteToken(token); err != nil { + c.JSON(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, fmt.Sprintf("Logged Out")) +} + +func GetV0Root(c *gin.Context) { + medialogInfo := models.MedialogInfo{ + Version: medialogVersion, + GolangVersion: runtime.Version(), + GinVersion: gin.Version, + APIVersion: apiVersion, + } + + c.JSON(http.StatusOK, medialogInfo) +} + +func DeleteSessionsV0(c *gin.Context) { + _, err := checkToken(c) + if err != nil { + c.JSON(http.StatusUnauthorized, err.Error()) + return + } + + if err := database.DeleteSessions(); err != nil { + c.JSON(http.StatusInternalServerError, err.Error()) + } + + c.JSON(http.StatusOK, "sessions deleted") +} + +func checkToken(c *gin.Context) (string, error) { + controllers.ExpireTokens() + token := c.Request.Header.Get("X-Medialog-Token") + + if token == "" { + return "", fmt.Errorf("no `X-Medialog-Token` set in request header") + } + + apiToken, err := database.FindToken(token) + if err != nil { + return "", fmt.Errorf("could not find supplied token: %s", token) + } + + if !apiToken.IsValid { + return "", fmt.Errorf("invalid token - please reauthenticate") + } + + return token, nil +} diff --git a/api/v0/apiV0Controller.go b/api/v0/apiV0Controller.go deleted file mode 100644 index c29f25c..0000000 --- a/api/v0/apiV0Controller.go +++ /dev/null @@ -1,1061 +0,0 @@ -package api - -import ( - "crypto/sha512" - "encoding/hex" - "fmt" - "log" - "net/http" - "runtime" - "strconv" - "time" - - "github.com/gin-gonic/gin" - "github.com/google/uuid" - "github.com/nyudlts/go-medialog/controllers" - "github.com/nyudlts/go-medialog/database" - "github.com/nyudlts/go-medialog/models" -) - -type EntryResultSet struct { - FirstPage int `json:"first_page"` - LastPage int `json:"last_page"` - ThisPage int `json:"this_page"` - Total int64 `json:"total"` - Results []models.Entry `json:"results"` -} - -type SummaryTotalsRepo struct { - Repository string `json:"repository"` - Totals database.Totals `json:"totals"` - Summaries []database.Summary `json:"summaries"` -} - -type SummaryTotalsResource struct { - ResourceIdentifier string `json:"resource_identifier"` - ResourceTitle string `json:"resource_title"` - Totals database.Totals `json:"totals"` - Summaries []database.Summary `json:"summaries"` -} - -type SummaryTotalsAccession struct { - AccessionIdentifier string `json:"accession_identifier"` - Totals database.Totals `json:"totals"` - Summaries []database.Summary `json:"summaries"` -} - -const UNAUTHORIZED = "Please authenticate to access this service" -const apiVersion = "v0.1.3" -const medialogVersion = "v1.0.6" - -var ACCESS_DENIED = map[string]string{"error": "access denied"} - -type APIError struct { - Message map[string][]string `json:"error"` -} - -func APILogin(c *gin.Context) { - controllers.ExpireTokens() - email := c.Param("user") - password := c.Query("password") - - if password == "" { - apiError := APIError{} - e := map[string][]string{"password": []string{"Parameter required but no value provided"}} - apiError.Message = e - c.JSON(http.StatusBadRequest, apiError) - return - } - - user, err := database.FindUserByEmail(email) - if err != nil { - c.JSON(http.StatusUnauthorized, map[string]string{"error": "login failed - user not found"}) - return - } - - hash := sha512.Sum512([]byte(password + user.Salt)) - userSHA512 := hex.EncodeToString(hash[:]) - - if userSHA512 != user.EncryptedPassword { - c.JSON(http.StatusBadRequest, fmt.Sprintf("storedChecksum: %s, calculatedChecksum: %s", user.EncryptedPassword, userSHA512)) - return - } - - if !user.CanAccessAPI { - c.JSON(http.StatusUnauthorized, "login failed -- user not authorized to access api") - return - } - - token := controllers.GenerateStringRunes(24) - tkHash := sha512.Sum512([]byte(token)) - token = hex.EncodeToString(tkHash[:]) - - user.EncryptedPassword = "####" - user.Salt = "####" - - apiToken := models.Token{ - Token: token, - UserID: user.ID, - IsValid: true, - Expires: time.Now().Add(time.Hour * 3), - User: user, - Type: "api", - } - - //expire users other tokens - if err := database.ExpireAPITokensByUserID(user.ID); err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - //add token to api db - if err := database.InsertToken(&apiToken); err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - c.JSON(200, apiToken) -} - -func APILogout(c *gin.Context) { - token, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - if err := database.DeleteToken(token); err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - c.JSON(http.StatusOK, fmt.Sprintf("Logged Out")) -} - -func GetV0Index(c *gin.Context) { - medialogInfo := models.MedialogInfo{ - Version: medialogVersion, - GolangVersion: runtime.Version(), - GinVersion: gin.Version, - APIVersion: apiVersion, - } - - c.JSON(http.StatusOK, medialogInfo) -} - -/* Repository Functions */ - -func GetRepositoriesV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - repositories, err := database.FindRepositories() - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error) - return - } - - c.JSON(http.StatusOK, repositories) -} - -func GetRepositoryV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error) - } - - repository, err := database.FindRepository(uint(id)) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error) - return - } - - c.JSON(http.StatusOK, repository) -} - -func CreateRepositoryV0(c *gin.Context) { - token, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - repo := models.Repository{} - if err := c.Bind(&repo); err != nil { - c.JSON(http.StatusBadRequest, err) - return - } - - userID, err := database.FindUserIDByToken(token) - if err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - repo.CreatedBy = int(userID) - repo.UpdatedBy = int(userID) - repo.CreatedAt = time.Now() - repo.UpdatedAt = time.Now() - - _, err = database.CreateRepository(&repo) - if err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - c.JSON(http.StatusOK, repo) -} - -func DeleteRepositoryV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - repositoryIDParam := c.Param("id") - repositoryID, err := strconv.Atoi(repositoryIDParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - if err := database.DeleteRepository(uint(repositoryID)); err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - c.JSON(http.StatusOK, fmt.Sprintf("Repository %d deleted", repositoryID)) - -} - -//repository functions - -func GetRepositoryEntriesV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - repositoryIDParam := c.Param("id") - repositoryID, err := strconv.Atoi(repositoryIDParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - } - - allIDsParam := c.Query("all_ids") - pageParam := c.Query("page") - pageSizeParam := c.Query("page_size") - log.Println(allIDsParam) - var allIds bool - if allIDsParam != "" { - var err error - allIds, err = strconv.ParseBool(allIDsParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - } - - if allIds { - entries, err := database.FindEntryIDsByRepositoryID(uint(repositoryID)) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - c.JSON(http.StatusOK, entries) - return - } else { - page, err := strconv.Atoi(pageParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - pagination := database.Pagination{} - pagination.Offset = page - - pageSize, err := strconv.Atoi(pageSizeParam) - if err != nil { - pagination.Limit = 25 - } else { - pagination.Limit = pageSize - } - - entries, err := database.FindEntriesByRepositoryIDPaginated(uint(repositoryID), pagination) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - e := EntryResultSet{} - e.Total = database.GetCountOfEntriesInRepository(uint(repositoryID)) - e.FirstPage = 1 - e.ThisPage = page - e.Results = entries - r := int(e.Total / int64(pagination.Limit)) - m := int(e.Total % int64(pagination.Limit)) - var t int - if m > 0 { - t = r + 1 - } - e.LastPage = t - c.JSON(http.StatusOK, e) - } -} - -func GetRepositorySummaryV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - idParam := c.Param("id") - id, err := strconv.Atoi(idParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - } - - repository, err := database.FindRepository(uint(id)) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - summaryMap, err := database.GetSummaryByRepository(uint(id)) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - summaryTotals := SummaryTotalsRepo{ - Repository: repository.Title, - Totals: summaryMap.GetTotals(), - Summaries: summaryMap.GetSlice(), - } - - c.JSON(http.StatusOK, summaryTotals) -} - -/* Resource Functions */ -func CreateResourceV0(c *gin.Context) { - token, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - resource := models.Resource{} - if err := c.Bind(&resource); err != nil { - c.JSON(http.StatusBadRequest, err) - return - } - - userID, err := database.FindUserIDByToken(token) - if err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - repository, err := database.FindRepository(resource.RepositoryID) - if err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - resource.CreatedBy = int(userID) - resource.UpdatedBy = int(userID) - resource.CreatedAt = time.Now() - resource.UpdatedAt = time.Now() - resource.Repository = repository - - _, err = database.InsertResource(&resource) - if err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - c.JSON(http.StatusOK, resource) -} - -func DeleteResourceV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - resourceIDParam := c.Param("id") - resourceID, err := strconv.Atoi(resourceIDParam) - if err != nil { - c.JSON(http.StatusBadRequest, err) - return - } - - if err := database.DeleteResource(uint(resourceID)); err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - c.JSON(http.StatusOK, fmt.Sprintf("Resource %d deleted", resourceID)) - -} - -func GetResourcesV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - resources, err := database.FindResources() - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error) - return - } - - c.JSON(http.StatusOK, resources) -} - -func GetResourceV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error) - } - - resource, err := database.FindResource(uint(id)) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error) - return - } - - c.JSON(http.StatusOK, resource) -} - -func GetResourceEntriesV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - resourceIDParam := c.Param("id") - resourceID, err := strconv.Atoi(resourceIDParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - } - - allIDsParam := c.Query("all_ids") - pageParam := c.Query("page") - pageSizeParam := c.Query("page_size") - - var allIds bool - if allIDsParam != "" { - var err error - allIds, err = strconv.ParseBool(allIDsParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - } - - if allIds { - entries, err := database.FindEntryIDsByResourceID(uint(resourceID)) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - c.JSON(http.StatusOK, entries) - } else { - page, err := strconv.Atoi(pageParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - pagination := database.Pagination{} - pagination.Offset = page - - pageSize, err := strconv.Atoi(pageSizeParam) - if err != nil { - pagination.Limit = 25 - } else { - pagination.Limit = pageSize - } - - entries, err := database.FindEntriesByResourceIDPaginated(uint(resourceID), pagination) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - e := EntryResultSet{} - e.Total = database.GetCountOfEntriesInResource(uint(resourceID)) - e.FirstPage = 1 - e.ThisPage = page - e.Results = entries - r := int(e.Total / int64(pagination.Limit)) - m := int(e.Total % int64(pagination.Limit)) - var t int - if m > 0 { - t = r + 1 - } - e.LastPage = t - c.JSON(http.StatusOK, e) - } -} - -func GetResourceSummaryV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - idParam := c.Param("id") - id, err := strconv.Atoi(idParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - resource, err := database.FindResource(uint(id)) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - summaries, err := database.GetSummaryByResource(uint(id)) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - resourceSummary := SummaryTotalsResource{} - resourceSummary.ResourceIdentifier = resource.CollectionCode - resourceSummary.ResourceTitle = resource.Title - resourceSummary.Totals = summaries.GetTotals() - resourceSummary.Summaries = summaries.GetSlice() - - c.JSON(http.StatusOK, resourceSummary) -} - -/* Accession Functions */ - -func CreateAccessionV0(c *gin.Context) { - token, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - accession := models.Accession{} - if err := c.Bind(&accession); err != nil { - c.JSON(http.StatusBadRequest, err) - return - } - - userId, err := database.FindUserIDByToken(token) - if err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - resource, err := database.FindResource(accession.ResourceID) - if err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - accession.CreatedBy = int(userId) - accession.UpdatedBy = int(userId) - accession.CreatedAt = time.Now() - accession.UpdatedAt = time.Now() - accession.Resource = resource - - _, err = database.InsertAccession(&accession) - if err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - c.JSON(http.StatusOK, accession) - -} - -func GetAccessionsV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - accessions, err := database.FindAccessions() - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error) - return - } - - c.JSON(http.StatusOK, accessions) -} - -func GetAccessionV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, err.Error()) - return - } - - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error) - } - - accession, err := database.FindAccession(uint(id)) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error) - return - } - - repository, err := database.FindRepository(accession.Resource.RepositoryID) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error) - return - } - - accession.Resource.Repository = repository - - c.JSON(http.StatusOK, accession) -} - -func DeleteAccessionV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, err.Error()) - return - } - - accessionIDParam := c.Param("id") - accessionID, err := strconv.Atoi(accessionIDParam) - if err != nil { - c.JSON(http.StatusBadRequest, err) - return - } - - if err := database.DeleteAccession(uint(accessionID)); err != nil { - c.JSON(http.StatusInternalServerError, err) - return - } - - c.JSON(http.StatusOK, fmt.Sprintf("Resource %d deleted", accessionID)) - -} - -func GetAccessionEntriesV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - accessionIDParam := c.Param("id") - accessionID, err := strconv.Atoi(accessionIDParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - } - - allIDsParam := c.Query("all_ids") - pageParam := c.Query("page") - pageSizeParam := c.Query("page_size") - var allIds bool - - if allIDsParam != "" { - var err error - allIds, err = strconv.ParseBool(allIDsParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - } - - if allIds { - entries, err := database.FindEntryIDsByAccessionID(uint(accessionID)) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - c.JSON(http.StatusOK, entries) - } else { - page, err := strconv.Atoi(pageParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - pagination := database.Pagination{} - pagination.Offset = page - - pageSize, err := strconv.Atoi(pageSizeParam) - if err != nil { - pagination.Limit = 25 - } else { - pagination.Limit = pageSize - } - - entries, err := database.FindEntriesByAccessionIDPaginated(uint(accessionID), pagination) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - e := EntryResultSet{} - e.Total = database.GetCountOfEntriesInAccession(uint(accessionID)) - e.FirstPage = 1 - e.ThisPage = page - e.Results = entries - r := int(e.Total / int64(pagination.Limit)) - m := int(e.Total % int64(pagination.Limit)) - var t int - if m > 0 { - t = r + 1 - } - e.LastPage = t - - c.JSON(http.StatusOK, e) - } - -} - -func GetAccessionSummaryV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - idParam := c.Param("id") - accessionID, err := strconv.Atoi(idParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - accession, err := database.FindAccession(uint(accessionID)) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - summaries, err := database.GetSummaryByAccession(uint(accessionID)) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - summaryAccession := SummaryTotalsAccession{} - summaryAccession.AccessionIdentifier = accession.AccessionNum - summaryAccession.Totals = summaries.GetTotals() - summaryAccession.Summaries = summaries.GetSlice() - - c.JSON(http.StatusOK, summaryAccession) - -} - -/* Entry Functions */ -func CreateEntryV0(c *gin.Context) { - token, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, err.Error()) - return - } - - userID, err := database.FindUserIDByToken(token) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - entry := models.Entry{} - if err := c.Bind(&entry); err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - entry.CreatedBy = int(userID) - entry.UpdatedBy = int(userID) - entry.CreatedAt = time.Now() - entry.UpdatedAt = time.Now() - entry.ID, _ = uuid.NewUUID() - - accession, err := database.FindAccession(entry.AccessionID) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - entry.Accession = accession - - resource, err := database.FindResource(accession.ResourceID) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - entry.Resource = resource - - repository, err := database.FindRepository(resource.RepositoryID) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - entry.Repository = repository - - _, err = database.InsertEntry(&entry) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - c.JSON(http.StatusOK, entry) -} - -func DeleteEntryV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, err.Error()) - return - } - - entryID := c.Param("id") - entryUUID, err := uuid.Parse(entryID) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - if err := database.DeleteEntry(entryUUID); err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - c.JSON(http.StatusOK, fmt.Sprintf("Entry %s deleted", entryUUID)) -} - -func GetEntryV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, err.Error()) - return - } - - id := c.Param("id") - - uId, err := uuid.Parse(id) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - entry, err := database.FindEntry(uId) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - c.JSON(http.StatusOK, entry) -} - -func GetEntriesV0(c *gin.Context) { - - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, ACCESS_DENIED) - return - } - - allIDsParam := c.Query("all_ids") - - var allIds bool - if allIDsParam != "" { - var err error - allIds, err = strconv.ParseBool(allIDsParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - } - - if allIds { - ids, err := database.GetEntryIDs() - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } else { - c.JSON(http.StatusOK, ids) - return - } - } else { - - pageSizeParam := c.Query("page_size") - var pageSize int - if pageSizeParam != "" { - var err error - pageSize, err = strconv.Atoi(pageSizeParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - } else { - pageSize = 25 - } - - pageParam := c.Query("page") - var entries []models.Entry - var page int - if pageParam != "" { - var err error - page, err = strconv.Atoi(pageParam) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - pagination := database.Pagination{Offset: page, Limit: pageSize} - fmt.Println(pagination) - entries, err = database.FindEntriesPaginated(pagination) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - } else { - page = 1 - } - - results := EntryResultSet{} - results.Total = database.GetCountOfEntriesInDB() - r := int(results.Total / int64(pageSize)) - m := int(results.Total % int64(pageSize)) - var t int - if m > 0 { - t = r + 1 - } - results.Results = entries - results.FirstPage = 1 - results.ThisPage = page - results.LastPage = t - - c.JSON(http.StatusOK, results) - return - } -} - -func UpdateEntryLocationV0(c *gin.Context) { - token, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, err.Error()) - return - } - - id := c.Param("id") - if id == "" { - c.JSON(http.StatusBadRequest, "no id provided") - return - } - - uid, err := uuid.Parse(id) - if err != nil { - c.JSON(http.StatusBadRequest, "provided id is not a valid uuid") - return - } - - location := c.Query("location") - if location == "" { - c.JSON(http.StatusBadRequest, "no location provided") - return - } - - storageLocation := controllers.GetStorageLocation(location) - - if storageLocation == "No Match" { - c.JSON(http.StatusBadRequest, fmt.Sprintf("`%s` is not a valid location", location)) - return - } - - entry, err := database.FindEntry(uid) - if err != nil { - c.JSON(http.StatusBadRequest, err.Error()) - return - } - - userID, err := database.FindUserIDByToken(token) - if err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - entry.Location = location - entry.UpdatedAt = time.Now() - entry.UpdatedBy = int(userID) - - if err := database.UpdateEntry(&entry); err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - return - } - - c.JSON(http.StatusOK, fmt.Sprintf("id: %s, location: %s, storage location: %s", id, location, storageLocation)) - -} - -func DeleteSessionsV0(c *gin.Context) { - _, err := checkToken(c) - if err != nil { - c.JSON(http.StatusUnauthorized, err.Error()) - return - } - - if err := database.DeleteSessions(); err != nil { - c.JSON(http.StatusInternalServerError, err.Error()) - } - - c.JSON(http.StatusOK, "sessions deleted") -} - -func checkToken(c *gin.Context) (string, error) { - controllers.ExpireTokens() - token := c.Request.Header.Get("X-Medialog-Token") - - if token == "" { - return "", fmt.Errorf("no `X-Medialog-Token` set in request header") - } - - apiToken, err := database.FindToken(token) - if err != nil { - return "", fmt.Errorf("could not find supplied token: %s", token) - } - - if !apiToken.IsValid { - return "", fmt.Errorf("invalid token - please reauthenticate") - } - - return token, nil -} diff --git a/controllers/errorController.go b/controllers/ErrorsController.go similarity index 100% rename from controllers/errorController.go rename to controllers/ErrorsController.go diff --git a/controllers/sessionController.go b/controllers/SessionsController.go similarity index 100% rename from controllers/sessionController.go rename to controllers/SessionsController.go diff --git a/controllers/userController.go b/controllers/UsersController.go similarity index 100% rename from controllers/userController.go rename to controllers/UsersController.go diff --git a/controllers/vocabularyController.go b/controllers/VocabulariesController.go similarity index 100% rename from controllers/vocabularyController.go rename to controllers/VocabulariesController.go diff --git a/database/accessions.go b/database/Database-Accessions.go similarity index 100% rename from database/accessions.go rename to database/Database-Accessions.go diff --git a/database/entries.go b/database/Database-Entries.go similarity index 100% rename from database/entries.go rename to database/Database-Entries.go diff --git a/database/migrations.go b/database/Database-Migrations.go similarity index 100% rename from database/migrations.go rename to database/Database-Migrations.go diff --git a/database/repositories.go b/database/Database-Repositories.go similarity index 100% rename from database/repositories.go rename to database/Database-Repositories.go diff --git a/database/resources.go b/database/Database-Resources.go similarity index 100% rename from database/resources.go rename to database/Database-Resources.go diff --git a/database/sessions.go b/database/Database-Sessions.go similarity index 100% rename from database/sessions.go rename to database/Database-Sessions.go diff --git a/database/Tokens.go b/database/Database-Tokens.go similarity index 100% rename from database/Tokens.go rename to database/Database-Tokens.go diff --git a/database/users.go b/database/Database-Users.go similarity index 100% rename from database/users.go rename to database/Database-Users.go diff --git a/router/routes.go b/router/routes.go index 4539489..81ea4cf 100644 --- a/router/routes.go +++ b/router/routes.go @@ -110,7 +110,7 @@ func LoadAPI(router *gin.Engine) { apiV0Routes := router.Group("/api/v0") //index - apiV0Routes.GET("", func(c *gin.Context) { api.GetV0Index(c) }) + apiV0Routes.GET("", func(c *gin.Context) { api.GetV0Root(c) }) //users apiV0Routes.POST("users/:user/login", func(c *gin.Context) { api.APILogin(c) }) From b53d6dd2db911f89b3bda82948fc59869bf42468 Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Fri, 13 Sep 2024 14:08:42 -0400 Subject: [PATCH 6/9] removing any hardcoded repo codes --- controllers/VocabulariesController.go | 14 -------- controllers/reportsController.go | 14 ++++++-- medialog_test.go | 42 ++++++++++++++--------- templates/accessions/accessions-show.html | 6 ++-- templates/resources/resources-show.html | 6 ++-- 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/controllers/VocabulariesController.go b/controllers/VocabulariesController.go index 3014465..420d5f3 100644 --- a/controllers/VocabulariesController.go +++ b/controllers/VocabulariesController.go @@ -2,20 +2,6 @@ package controllers var is_refreshed = map[bool]string{true: "yes", false: "no"} -var PartnerCodes = map[string]string{ - "": "", - "fales": "Fales Library & Special Collections", - "nyuarchives": "NYU Archives", - "tamwag": "Tamiment Library and Robert F. Wagner Labor Archives", - "abudhabi": "Abu Dhabi", -} - -var filename_partner_codes = map[string]string{ - "fa": "fales", - "tw": "tamwag", - "ua": "nyuarchives", -} - var storageLocations = map[string]string{ "sl_rsw_acm_born_digital": "RW ACM Born Digital", "sl_rsw_spec_coll": "RW Special Collections", diff --git a/controllers/reportsController.go b/controllers/reportsController.go index 0880704..8be66d3 100644 --- a/controllers/reportsController.go +++ b/controllers/reportsController.go @@ -7,8 +7,6 @@ import ( "github.com/nyudlts/go-medialog/database" ) -var partnerCodes = map[int]string{0: "", 2: "tamwag", 3: "fales", 6: "nyu archives"} - func ReportsIndex(c *gin.Context) { if err := isLoggedIn(c); err != nil { @@ -18,6 +16,12 @@ func ReportsIndex(c *gin.Context) { isLoggedIn := true + partnerCodes, err := database.GetRepositoryMap() + if err != nil { + ThrowError(http.StatusInternalServerError, err.Error(), c, isLoggedIn) + return + } + sessionCookies, err := getSessionCookies(c) if err != nil { ThrowError(http.StatusInternalServerError, err.Error(), c, isLoggedIn) @@ -74,6 +78,12 @@ func ReportRange(c *gin.Context) { return } + partnerCodes, err := database.GetRepositoryMap() + if err != nil { + ThrowError(http.StatusInternalServerError, err.Error(), c, isLoggedIn) + return + } + c.HTML(http.StatusOK, "reports-range.html", gin.H{ "summary": summary, "totals": summary.GetTotals(), diff --git a/medialog_test.go b/medialog_test.go index 6d32e9b..f461c9a 100644 --- a/medialog_test.go +++ b/medialog_test.go @@ -1,9 +1,12 @@ package main import ( + "bufio" + "fmt" "net/http" "net/http/httptest" "net/url" + "os" "strings" "testing" @@ -40,25 +43,32 @@ func TestApplication(t *testing.T) { r.ServeHTTP(recorder, req) assert.Equal(t, http.StatusFound, recorder.Code) - t.Log(recorder.Result().Header.Get("Set-Cookie")) + outFile, _ := os.Create("headers.txt") + defer outFile.Close() + writer := bufio.NewWriter(outFile) + writer.WriteString(fmt.Sprintf("%v", recorder.Result().Header)) + writer.Flush() + }) - t.Run("test get index authenticated", func(t *testing.T) { - recorder := httptest.NewRecorder() - c, _ := gin.CreateTestContext(recorder) - c.SetCookie("medialog-sessions", - "MTcyNTk5NzI2MHxOd3dBTkZkRVFUZEhRazFKU1VWVldqVlRSRlpZUkVWSVYxQkRRMUpHTjAxTFdsVk9OME5HTWpWTVdqSkhURnBPUkVsVVNGWmFWVkU9fGYXoOEZhC7V7FyNzW3NZd0xiPTGNjOqHJg2LMMM5iex", - 2592000, "/", "", false, true, - ) + /* + t.Run("test get index authenticated", func(t *testing.T) { + recorder := httptest.NewRecorder() + c, _ := gin.CreateTestContext(recorder) + c.SetCookie("medialog-sessions", + "MTcyNTk5NzI2MHxOd3dBTkZkRVFUZEhRazFKU1VWVldqVlRSRlpZUkVWSVYxQkRRMUpHTjAxTFdsVk9OME5HTWpWTVdqSkhURnBPUkVsVVNGWmFWVkU9fGYXoOEZhC7V7FyNzW3NZd0xiPTGNjOqHJg2LMMM5iex", + 2592000, "/", "", false, true, + ) - req, err := http.NewRequestWithContext(c, "GET", "/", nil) - if err != nil { - t.Error(err) - } - r.ServeHTTP(recorder, req) - assert.Equal(t, 200, recorder.Code) - assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("content-type")) + req, err := http.NewRequestWithContext(c, "GET", "/", nil) + if err != nil { + t.Error(err) + } + r.ServeHTTP(recorder, req) + assert.Equal(t, 200, recorder.Code) + assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("content-type")) - }) + }) + */ } diff --git a/templates/accessions/accessions-show.html b/templates/accessions/accessions-show.html index a279cd8..4302193 100644 --- a/templates/accessions/accessions-show.html +++ b/templates/accessions/accessions-show.html @@ -37,13 +37,13 @@
{{ .accession.AccessionNum }}
Entries
-
+
CSV
-
+ - diff --git a/templates/resources/resources-show.html b/templates/resources/resources-show.html index c8af7d6..be677bb 100644 --- a/templates/resources/resources-show.html +++ b/templates/resources/resources-show.html @@ -66,13 +66,13 @@
Accessions
Entries
-
+
CSV
-
+ - From 6c8cf3f6935b564be867d7b52098865a50ed0842 Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Tue, 24 Sep 2024 11:45:20 -0400 Subject: [PATCH 7/9] updating csv template and entry.create func --- .gitignore | 4 +--- api/v0/API-Entries.go | 3 +-- controllers/accessionsController.go | 2 +- controllers/entriesController.go | 4 ++-- database/Database-Entries.go | 7 +++---- models/models.go | 4 +++- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 5192871..071a894 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,4 @@ bin/* .vscode/* .idea/* *.log -*.conf -sys/* -/public/csv/*.csv \ No newline at end of file +*.conf \ No newline at end of file diff --git a/api/v0/API-Entries.go b/api/v0/API-Entries.go index 4ebdf3d..74c4345 100644 --- a/api/v0/API-Entries.go +++ b/api/v0/API-Entries.go @@ -59,8 +59,7 @@ func CreateEntryV0(c *gin.Context) { } entry.Repository = repository - _, err = database.InsertEntry(&entry) - if err != nil { + if err = database.InsertEntry(&entry); err != nil { c.JSON(http.StatusInternalServerError, err.Error()) return } diff --git a/controllers/accessionsController.go b/controllers/accessionsController.go index 9b4c9bd..f16d305 100644 --- a/controllers/accessionsController.go +++ b/controllers/accessionsController.go @@ -518,7 +518,7 @@ func createSlewEntry(slew Slew, accession models.Accession) error { entry.UpdatedBy = userID entry.UpdatedAt = time.Now() - if _, err := database.InsertEntry(&entry); err != nil { + if err := database.InsertEntry(&entry); err != nil { return err } } diff --git a/controllers/entriesController.go b/controllers/entriesController.go index 4dada4d..e326cd5 100644 --- a/controllers/entriesController.go +++ b/controllers/entriesController.go @@ -364,7 +364,7 @@ func CreateEntry(c *gin.Context) { createEntry.Repository = repository //insert the entry - if _, err := database.InsertEntry(&createEntry); err != nil { + if err := database.InsertEntry(&createEntry); err != nil { ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) return } @@ -603,7 +603,7 @@ func CloneEntry(c *gin.Context) { entry.RepositoryID = repository.ID entry.Repository = repository - if _, err := database.InsertEntry(&entry); err != nil { + if err := database.InsertEntry(&entry); err != nil { ThrowError(http.StatusBadRequest, err.Error(), c, isLoggedIn) return } diff --git a/database/Database-Entries.go b/database/Database-Entries.go index 2c794ae..138c0a9 100644 --- a/database/Database-Entries.go +++ b/database/Database-Entries.go @@ -9,12 +9,11 @@ import ( "gorm.io/gorm/clause" ) -func InsertEntry(entry *models.Entry) (uuid.UUID, error) { +func InsertEntry(entry *models.Entry) error { if err := db.Create(&entry).Error; err != nil { - fakeUUID, _ := uuid.NewUUID() - return fakeUUID, err + return err } - return entry.ID, nil + return nil } func DeleteEntry(id uuid.UUID) error { diff --git a/models/models.go b/models/models.go index c9d91e8..e668703 100644 --- a/models/models.go +++ b/models/models.go @@ -83,7 +83,7 @@ type Entry struct { Location string `json:"location" form:"location"` } -var CSVHeader = []string{"id", "media_id", "mediatype", "label_text", "is_refreshed", "repository", "resource", "accession", "storage_location"} +var CSVHeader = []string{"id", "media_id", "mediatype", "content_type", "label_text", "is_refreshed", "imaging_success", "repository", "resource", "accession", "storage_location"} func (e Entry) ToCSV() []string { re := regexp.MustCompile(`\r?\n`) @@ -93,8 +93,10 @@ func (e Entry) ToCSV() []string { e.ID.String(), fmt.Sprintf("%d", e.MediaID), e.Mediatype, + e.ContentType, labelText, boolToString(e.IsRefreshed), + e.ImagingSuccess, e.Repository.Slug, e.Resource.CollectionCode, e.Accession.AccessionNum, From 8bdc2455c11293de670ee433896c91d5a96b50ec Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Tue, 24 Sep 2024 13:36:17 -0400 Subject: [PATCH 8/9] updating version --- api/v0/API-V0.go | 4 ++-- medialog.go | 2 +- templates/global/footer.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v0/API-V0.go b/api/v0/API-V0.go index 309b654..6061b63 100644 --- a/api/v0/API-V0.go +++ b/api/v0/API-V0.go @@ -42,8 +42,8 @@ type SummaryTotalsAccession struct { } const UNAUTHORIZED = "Please authenticate to access this service" -const apiVersion = "v0.1.3" -const medialogVersion = "v1.0.6" +const apiVersion = "v0.1.4" +const medialogVersion = "v1.0.7" var ACCESS_DENIED = map[string]string{"error": "access denied"} diff --git a/medialog.go b/medialog.go index 48cedfc..d927885 100644 --- a/medialog.go +++ b/medialog.go @@ -25,7 +25,7 @@ var ( createAdmin bool ) -const version = "v1.0.6" +const version = "v1.0.7" func init() { flag.StringVar(&environment, "environment", "", "") diff --git a/templates/global/footer.html b/templates/global/footer.html index 27c02a0..a4fac7c 100644 --- a/templates/global/footer.html +++ b/templates/global/footer.html @@ -4,7 +4,7 @@ From e72d2dfb31671cb743fbc98d623004251ffb2375 Mon Sep 17 00:00:00 2001 From: Don Mennerich Date: Tue, 24 Sep 2024 13:47:22 -0400 Subject: [PATCH 9/9] type in accessions show template --- templates/accessions/accessions-show.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/accessions/accessions-show.html b/templates/accessions/accessions-show.html index 4302193..d12fd12 100644 --- a/templates/accessions/accessions-show.html +++ b/templates/accessions/accessions-show.html @@ -38,13 +38,13 @@
{{ .accession.AccessionNum }}
Entries
- CSV + CSV