From 96b0c888ed829146bf71256dfe8acee739e1aa24 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Sat, 9 Jan 2021 19:44:02 -0500 Subject: [PATCH] DB & Route Organization --- cmd/cmd.go | 81 +++++++++++----- go.mod | 2 + go.sum | 8 ++ imagini.db | Bin 61440 -> 69632 bytes internal/auth/auth.go | 37 +++++++ internal/auth/ldap.go | 9 ++ internal/auth/local.go | 37 +++++++ internal/db/db.go | 148 ++++++++++++++-------------- internal/db/errors.go | 7 ++ internal/db/users.go | 25 +++++ internal/{db => models}/models.go | 11 ++- main.go | 16 +++- routes/albums.go | 9 ++ routes/auth.go | 13 +++ routes/info.go | 9 ++ routes/media_items.go | 9 ++ routes/middlewares.go | 22 ++--- routes/routes.go | 154 +++++++++++++++--------------- routes/tags.go | 9 ++ routes/upload.go | 9 ++ routes/users.go | 7 +- 21 files changed, 430 insertions(+), 192 deletions(-) create mode 100644 internal/auth/auth.go create mode 100644 internal/db/errors.go create mode 100644 internal/db/users.go rename internal/{db => models}/models.go (76%) create mode 100644 routes/albums.go create mode 100644 routes/auth.go create mode 100644 routes/info.go create mode 100644 routes/media_items.go create mode 100644 routes/tags.go create mode 100644 routes/upload.go diff --git a/cmd/cmd.go b/cmd/cmd.go index 9c568de..c2a4761 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,14 +1,17 @@ package cmd import ( - // "reichard.io/imagini/routes" + "fmt" + "errors" + "reichard.io/imagini/routes" "reichard.io/imagini/internal/db" + "reichard.io/imagini/internal/auth" + "reichard.io/imagini/internal/models" "reichard.io/imagini/internal/config" "github.com/urfave/cli/v2" - // "net/http" - // "log" - "fmt" + "net/http" + log "github.com/sirupsen/logrus" ) var CmdServe = cli.Command{ @@ -19,32 +22,66 @@ var CmdServe = cli.Command{ } var CmdDBTest = cli.Command{ - Name: "db", - Aliases: []string{"d"}, + Name: "test", + Aliases: []string{"t"}, Usage: "test db.", Action: testDatabase, } func serveWeb(ctx *cli.Context) error { - c := config.NewConfig() - db.ConnectDB(c) - //db.PopulateTestData() - newItems := db.ItemsFromAlbum(1, 2) - - fmt.Printf("%+v\n", newItems) + log.Info("Serving Web") + routes.RegisterRoutes() + if err := http.ListenAndServe(":8080", nil); err != nil { + log.Fatal(err) + } return nil - - - // routes.RegisterRoutes() - - // if err := http.ListenAndServe(":8080", nil); err != nil { - // log.Fatal(err) - // } - // return nil } func testDatabase(ctx *cli.Context) error { - resp := db.ItemsFromAlbum(1, 3) - fmt.Printf("%v", resp) + log.Info("Testing Database") + c := config.NewConfig() + db.ConnectDB(c) + + err := auth.CreateUser(models.User{ + Username: "User12346", + Email: "user26@evan.pub", + FirstName: "User", + LastName: "Reichard", + AuthType: "Local", + }, "myPassword123") + + if err != nil { + fmt.Println(err) + } + + resp := auth.AuthenticateUser("User123", "myPassword123") + if resp == true { + log.Info("USER SUCCESSFULLY AUTHENTICATED BY USERNAME") + }else { + log.Info("USER NOT AUTHENTICATED") + } + + resp = auth.AuthenticateUser("user@evan.pub", "myPassword123") + if resp == true { + log.Info("USER SUCCESSFULLY AUTHENTICATED BY EMAIL") + }else { + log.Info("USER NOT AUTHENTICATED") + } + + resp = auth.AuthenticateUser("user@evan.pub", "myPassword12") + if resp == true { + log.Info("USER SUCCESSFULLY AUTHENTICATED BY EMAIL") + }else { + log.Info("USER NOT AUTHENTICATED") + } + + // foundUser, err := db.GetUser(db.User{Username: "User123"}) + + // if errors.Is(err, gorm.ErrRecordNotFound) { + // log.Warn("RECORD NOT FOUND") + // } else { + // log.Info("FOUND USER", foundUser) + // } + return nil } diff --git a/go.mod b/go.mod index 8af0f47..ea00570 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,10 @@ require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/disintegration/imaging v1.6.2 // indirect github.com/mattn/go-sqlite3 v1.14.6 + github.com/sirupsen/logrus v1.7.0 github.com/tus/tusd v1.4.0 github.com/urfave/cli/v2 v2.3.0 + golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect gorm.io/driver/sqlite v1.1.4 gorm.io/gorm v1.20.9 diff --git a/go.sum b/go.sum index 96f9dd4..2228345 100644 --- a/go.sum +++ b/go.sum @@ -99,6 +99,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= @@ -124,9 +126,12 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -160,6 +165,9 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/imagini.db b/imagini.db index 858c14376c196c116fc048f186395059818c9627..8efa76a66ca7ac230a68d25924b1087b50b18026 100644 GIT binary patch delta 1206 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 A5C8xG diff --git a/internal/auth/auth.go b/internal/auth/auth.go new file mode 100644 index 0000000..0cd271a --- /dev/null +++ b/internal/auth/auth.go @@ -0,0 +1,37 @@ +package auth + +import ( + "errors" + "gorm.io/gorm" + "reichard.io/imagini/internal/db" + log "github.com/sirupsen/logrus" +) + +func AuthenticateUser(userIdentifier string, userPassword string) bool { + // By Username + foundUser, err := db.GetUser(db.User{Username: userIdentifier}) + if errors.Is(err, gorm.ErrRecordNotFound) { + foundUser, err = db.GetUser(db.User{Email: userIdentifier}) + } + + // Error Checking + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Warn("[auth] User not found: ", userIdentifier) + return false + } else if err != nil { + log.Error(err) + return false + } + + log.Info("[auth] Authenticating user: ", foundUser.Username) + + // Determine Type + switch foundUser.AuthType { + case "Local": + return authenticateLocalUser(foundUser, userPassword) + case "LDAP": + return authenticateLDAPUser(foundUser, userPassword) + default: + return false + } +} diff --git a/internal/auth/ldap.go b/internal/auth/ldap.go index e69de29..505d5dc 100644 --- a/internal/auth/ldap.go +++ b/internal/auth/ldap.go @@ -0,0 +1,9 @@ +package auth + +import ( + "reichard.io/imagini/internal/db" +) + +func authenticateLDAPUser(user db.User, pw string) bool { + return false +} diff --git a/internal/auth/local.go b/internal/auth/local.go index e69de29..84b391e 100644 --- a/internal/auth/local.go +++ b/internal/auth/local.go @@ -0,0 +1,37 @@ +package auth + +import ( + "errors" + "gorm.io/gorm" + "golang.org/x/crypto/bcrypt" + log "github.com/sirupsen/logrus" + "reichard.io/imagini/internal/db" +) + +func authenticateLocalUser(user db.User, pw string) bool { + bPassword :=[]byte(pw) + err := bcrypt.CompareHashAndPassword([]byte(user.HashedPassword), bPassword) + if err == nil { + log.Info("[local] Authentication successfull: ", user.Username) + return true + } + log.Warn("[local] Authentication failed: ", user.Username) + return false +} + +func CreateUser(user db.User, pw string) error { + log.Info("[local] Creating user: ", user.Username) + _, err := db.GetUser(user) + if !errors.Is(err, gorm.ErrRecordNotFound) { + log.Warn("[auth] User already exists: ", user.Username) + return errors.New("User already exists") + } + + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost) + if err != nil { + log.Error(err) + return err + } + user.HashedPassword = string(hashedPassword) + return db.CreateUser(user) +} diff --git a/internal/db/db.go b/internal/db/db.go index eccd9ad..430a089 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -3,39 +3,41 @@ package db import ( "log" "path" - "fmt" - "time" + // "time" "gorm.io/gorm" + "gorm.io/gorm/logger" "gorm.io/driver/sqlite" "reichard.io/imagini/internal/config" + "reichard.io/imagini/internal/models" ) var db *gorm.DB func ConnectDB(c *config.Config) { - fmt.Printf("%+v\n", c) + gormConfig := &gorm.Config{ + PrepareStmt: true, + Logger: logger.Default.LogMode(logger.Silent), + } if c.DBType == "SQLite" { dbLocation := path.Join(c.ConfigPath, "imagini.db") - db, _ = gorm.Open(sqlite.Open(dbLocation), &gorm.Config{ - PrepareStmt: true, - }) + db, _ = gorm.Open(sqlite.Open(dbLocation), gormConfig) } else { log.Fatal("ERROR: Unsupported Database") } // Initialize Database - db.AutoMigrate(&ServerSetting{}) - db.AutoMigrate(&User{}) - db.AutoMigrate(&MediaItem{}) - db.AutoMigrate(&Tag{}) - db.AutoMigrate(&Album{}) + db.AutoMigrate(&models.ServerSetting{}) + db.AutoMigrate(&models.User{}) + db.AutoMigrate(&models.MediaItem{}) + db.AutoMigrate(&models.Tag{}) + db.AutoMigrate(&models.Album{}) } -func ItemsFromAlbum(user User, album Album) []MediaItem { - var mediaItems []MediaItem +func ItemsFromAlbum(user models.User, album models.Album) []models.MediaItem { + var mediaItems []models.MediaItem // db.Table("media_albums"). // Select("media_item.*"). // Joins("INNER JOIN media_items ON media_albums.ID = media_items.Albums"). @@ -63,63 +65,63 @@ func ItemsFromAlbum(user User, album Album) []MediaItem { // func IndexMediaItems(newItems []MediaItem) { // } -func PopulateTestData() { - user1 := User{Name: "Evan", Email: "evan@reichard.io", AuthType: "LDAP", Salt: "1234", HashedPWSalt: "1234"} - user2 := User{Name: "Ryan", Email: "ryan@example.com", AuthType: "Local", Salt: "2345", HashedPWSalt: "2345"} - user3 := User{Name: "Bill", Email: "bill@example.com", AuthType: "LDAP", Salt: "3456", HashedPWSalt: "3456"} - - mi1 := MediaItem{ - User: user1, - EXIFDate: time.Now(), - Latitude: "1234", - Longitude: "1234", - RelPath: "./1234.jpg", - Tags: []Tag{ - {Name: "Tag1"}, - {Name: "Tag2"}, - }, - Albums: []Album{ - {Name: "Album1"}, - {Name: "Album2"}, - }, - } - - mi2 := MediaItem{ - User: user2, - EXIFDate: time.Now(), - Latitude: "1234", - Longitude: "1234", - RelPath: "./1234.jpg", - Tags: []Tag{ - {Name: "Tag3"}, - {Name: "Tag4"}, - }, - Albums: []Album{ - {Name: "Album3"}, - {Name: "Album4"}, - }, - } - - mi3 := MediaItem{ - User: user3, - EXIFDate: time.Now(), - Latitude: "1234", - Longitude: "1234", - RelPath: "./1234.jpg", - Tags: []Tag{ - {Name: "Tag4"}, - {Name: "Tag5"}, - }, - Albums: []Album{ - {Name: "Album1"}, - {Name: "Album7"}, - }, - } - - // db.Create(&user1) - // db.Create(&user2) - // db.Create(&user3) - db.Create(&mi1) - db.Create(&mi2) - db.Create(&mi3) -} +// func PopulateTestData() { +// user1 := User{Username: "Evan", Email: "evan@reichard.io", FirstName: "Evan", LastName: "Reichard", AuthType: "LDAP", Salt: "1234", HashedPWSalt: "1234"} +// user2 := User{Username: "Ryan", Email: "ryan@example.com", FirstName: "Ryan", LastName: "Dunfrey", AuthType: "Local", Salt: "2345", HashedPWSalt: "2345"} +// user3 := User{Username: "Bill", Email: "bill@example.com", FirstName: "Bill", LastName: "Smith", AuthType: "LDAP", Salt: "3456", HashedPWSalt: "3456"} +// +// mi1 := MediaItem{ +// User: user1, +// EXIFDate: time.Now(), +// Latitude: "1234", +// Longitude: "1234", +// RelPath: "./1234.jpg", +// Tags: []Tag{ +// {Name: "Tag1"}, +// {Name: "Tag2"}, +// }, +// Albums: []Album{ +// {Name: "Album1"}, +// {Name: "Album2"}, +// }, +// } +// +// mi2 := MediaItem{ +// User: user2, +// EXIFDate: time.Now(), +// Latitude: "1234", +// Longitude: "1234", +// RelPath: "./1234.jpg", +// Tags: []Tag{ +// {Name: "Tag3"}, +// {Name: "Tag4"}, +// }, +// Albums: []Album{ +// {Name: "Album3"}, +// {Name: "Album4"}, +// }, +// } +// +// mi3 := MediaItem{ +// User: user3, +// EXIFDate: time.Now(), +// Latitude: "1234", +// Longitude: "1234", +// RelPath: "./1234.jpg", +// Tags: []Tag{ +// {Name: "Tag4"}, +// {Name: "Tag5"}, +// }, +// Albums: []Album{ +// {Name: "Album1"}, +// {Name: "Album7"}, +// }, +// } +// +// // db.Create(&user1) +// // db.Create(&user2) +// // db.Create(&user3) +// db.Create(&mi1) +// db.Create(&mi2) +// db.Create(&mi3) +// } diff --git a/internal/db/errors.go b/internal/db/errors.go new file mode 100644 index 0000000..035b3c1 --- /dev/null +++ b/internal/db/errors.go @@ -0,0 +1,7 @@ +package db + +import "errors" + +var ( + ErrUserAlreadyExists = errors.New("user already exists") +) diff --git a/internal/db/users.go b/internal/db/users.go new file mode 100644 index 0000000..d2d2557 --- /dev/null +++ b/internal/db/users.go @@ -0,0 +1,25 @@ +package db + +import ( + "reichard.io/imagini/internal/models" +) + +func CreateUser (user models.User) error { + err := db.Create(&user).Error + return err +} + +func User (user models.User) (models.User, error) { + var foundUser models.User + var count int64 + err := db.Where(&user).First(&foundUser).Count(&count).Error + return foundUser, err +} + +func DeleteUser (user models.User) error { + return nil +} + +func UpdatePassword (user models.User, pw string) { + +} diff --git a/internal/db/models.go b/internal/models/models.go similarity index 76% rename from internal/db/models.go rename to internal/models/models.go index 007fca5..98b3540 100644 --- a/internal/db/models.go +++ b/internal/models/models.go @@ -1,4 +1,4 @@ -package db +package models import ( "gorm.io/gorm" @@ -14,11 +14,12 @@ type ServerSetting struct { type User struct { gorm.Model - Name string - Email string + Email string `gorm:"unique;not null"` + Username string `gorm:"unique;not null"` + FirstName string + LastName string AuthType string - Salt string - HashedPWSalt string + HashedPassword string } type MediaItem struct { diff --git a/main.go b/main.go index eea1bef..f58013a 100644 --- a/main.go +++ b/main.go @@ -2,9 +2,9 @@ package main import ( "os" - "log" "github.com/urfave/cli/v2" + log "github.com/sirupsen/logrus" "reichard.io/imagini/cmd" "reichard.io/imagini/internal/sessions" @@ -12,15 +12,27 @@ import ( var globalSessions *sessions.Manager +type UTCFormatter struct { + log.Formatter +} + +func (u UTCFormatter) Format(e *log.Entry) ([]byte, error) { + e.Time = e.Time.UTC() + return u.Formatter.Format(e) +} + func main() { + log.SetFormatter(UTCFormatter{&log.TextFormatter{FullTimestamp: true}}) + + log.Info("Starging Imagini") app := &cli.App{ Name: "Imagini", Usage: "A self hosted photo library.", Commands: []*cli.Command{ &cmd.CmdServe, + &cmd.CmdDBTest, }, } - err := app.Run(os.Args) if err != nil { log.Fatal(err) diff --git a/routes/albums.go b/routes/albums.go new file mode 100644 index 0000000..ffc835b --- /dev/null +++ b/routes/albums.go @@ -0,0 +1,9 @@ +package routes + +import ( + "net/http" +) + +func albumsHandler(w http.ResponseWriter, r *http.Request) { + +} diff --git a/routes/auth.go b/routes/auth.go new file mode 100644 index 0000000..ab25e04 --- /dev/null +++ b/routes/auth.go @@ -0,0 +1,13 @@ +package routes + +import ( + "net/http" +) + +func loginHandler(w http.ResponseWriter, r *http.Request) { + +} + +func logoutHandler(w http.ResponseWriter, r *http.Request) { + +} diff --git a/routes/info.go b/routes/info.go new file mode 100644 index 0000000..2e3a759 --- /dev/null +++ b/routes/info.go @@ -0,0 +1,9 @@ +package routes + +import ( + "net/http" +) + +func infoHandler(w http.ResponseWriter, r *http.Request) { + +} diff --git a/routes/media_items.go b/routes/media_items.go new file mode 100644 index 0000000..6c7e572 --- /dev/null +++ b/routes/media_items.go @@ -0,0 +1,9 @@ +package routes + +import ( + "net/http" +) + +func mediaItemsHandler(w http.ResponseWriter, r *http.Request) { + +} diff --git a/routes/middlewares.go b/routes/middlewares.go index cf11ad1..a52593d 100644 --- a/routes/middlewares.go +++ b/routes/middlewares.go @@ -19,17 +19,17 @@ func MultipleMiddleware(h http.Handler, m ...Middleware) http.Handler { return wrapped } -func authMiddleware(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - _, ok := ValidateUserToken(r) - - if ok { - next.ServeHTTP(w, r) - } else { - w.WriteHeader(http.StatusUnauthorized) - } - }) -} +// func authMiddleware(h http.Handler) http.Handler { +// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +// _, ok := ValidateUserToken(r) +// +// if ok { +// next.ServeHTTP(w, r) +// } else { +// w.WriteHeader(http.StatusUnauthorized) +// } +// }) +// } func logMiddleware(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/routes/routes.go b/routes/routes.go index 618e557..21f0107 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -2,84 +2,90 @@ package routes import ( "net/http" - "fmt" - // "reichard.io/imagini/internal/db" - "github.com/tus/tusd/pkg/filestore" - tusd "github.com/tus/tusd/pkg/handler" ) func RegisterRoutes() { - commonMiddleware := []Middleware{ - logMiddleware, - authMiddleware, - } - http.Handle("/Users", MultipleMiddleware(usersHandler, commonMiddleware...)) - http.Handle("/Uploads/", MultipleMiddleware(uploadsHandler, commonMiddleware...)) - - // http.HandleFunc("/uploads/", uploadsHandler()) - http.Handle("/Uploads/", func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - _, ok := ValidateUserToken(r) - - if ok { - next.ServeHTTP(w, r) - } else { - w.WriteHeader(http.StatusUnauthorized) - } - }) - }(http.StripPrefix("/Uploads/", tusHandler))) + http.HandleFunc("/MediaItems", mediaItemsHandler) + http.HandleFunc("/Upload", uploadHandler) + http.HandleFunc("/Albums", albumsHandler) + http.HandleFunc("/Logout", logoutHandler) + http.HandleFunc("/Login", loginHandler) + http.HandleFunc("/Users", usersHandler) + http.HandleFunc("/Tags", tagsHandler) + http.HandleFunc("/Info", infoHandler) + http.HandleFunc("/Me", meHandler) } -// func tagsHandler(w http.ResponseWriter, r *http.Request) { -// query := r.URL.Query() -// filters, present := query["filters"] + // Examples: + // [POST] /Login { user: , password: } + // [POST] /Logout + // [GET] /MediaItems + + // commonMiddleware := []Middleware{ + // logMiddleware, + // authMiddleware, + // } + // http.Handle("/Users", MultipleMiddleware(usersHandler, commonMiddleware...)) + // http.Handle("/Uploads/", MultipleMiddleware(uploadsHandler, commonMiddleware...)) + + // // http.HandleFunc("/uploads/", uploadsHandler()) + // http.Handle("/Uploads/", func(next http.Handler) http.Handler { + // return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // _, ok := ValidateUserToken(r) + + // if ok { + // next.ServeHTTP(w, r) + // } else { + // w.WriteHeader(http.StatusUnauthorized) + // } + // }) + // }(http.StripPrefix("/Uploads/", tusHandler))) + +// Filter Example: +// query := r.URL.Query() +// filters, present := query["filters"] + +// HTTP Errors +// if r.Method != "GET" { +// http.Error(w, "Method is not supported.", http.StatusNotFound) +// return +// } +// if r.URL.Path != "/hello" { +// http.Error(w, "404 not found.", http.StatusNotFound) +// return +// } + +// func uploadsHandler() http.Handler { +// store := filestore.FileStore{ +// Path: "./Uploads", +// } +// composer := tusd.NewStoreComposer() +// store.UseIn(composer) +// +// handler, err := tusd.NewHandler(tusd.Config{ +// BasePath: "/uploads/", +// StoreComposer: composer, +// NotifyCompleteUploads: true, +// }) +// +// if err != nil { +// panic(fmt.Errorf("Unable to create handler: %s", err)) +// } +// +// go func() { +// for { +// event := <-handler.CompleteUploads +// fmt.Printf("Upload %s finished\n", event.Upload.ID) +// } +// }() +// +// // return func(w http.ResponseWriter, r *http.Request) { +// // http.StripPrefix("/Uploads/", handler).ServeHTTP(w, r) +// // }; +// +// return http.StripPrefix("/Uploads/", handler) // } -func helloHandler(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/hello" { - http.Error(w, "404 not found.", http.StatusNotFound) - return - } - - if r.Method != "GET" { - http.Error(w, "Method is not supported.", http.StatusNotFound) - return - } - - fmt.Fprintf(w, "Hello!") -} - -func uploadsHandler() http.Handler { - store := filestore.FileStore{ - Path: "./Uploads", - } - composer := tusd.NewStoreComposer() - store.UseIn(composer) - - handler, err := tusd.NewHandler(tusd.Config{ - BasePath: "/uploads/", - StoreComposer: composer, - NotifyCompleteUploads: true, - }) - - if err != nil { - panic(fmt.Errorf("Unable to create handler: %s", err)) - } - - go func() { - for { - event := <-handler.CompleteUploads - fmt.Printf("Upload %s finished\n", event.Upload.ID) - } - }() - - // return func(w http.ResponseWriter, r *http.Request) { - // http.StripPrefix("/Uploads/", handler).ServeHTTP(w, r) - // }; - - return http.StripPrefix("/Uploads/", handler) -} - // func processMedia() { // var mi db.MediaItem // @@ -108,9 +114,3 @@ func uploadsHandler() http.Handler { // img = imaging.Fit(img, 240, 160, imaging.Lanczos) // err = imaging.Save(img, "thumbnail.jpg") // } - - - - - - diff --git a/routes/tags.go b/routes/tags.go new file mode 100644 index 0000000..4e81579 --- /dev/null +++ b/routes/tags.go @@ -0,0 +1,9 @@ +package routes + +import ( + "net/http" +) + +func tagsHandler(w http.ResponseWriter, r *http.Request) { + +} diff --git a/routes/upload.go b/routes/upload.go new file mode 100644 index 0000000..85fd2a6 --- /dev/null +++ b/routes/upload.go @@ -0,0 +1,9 @@ +package routes + +import ( + "net/http" +) + +func uploadHandler(w http.ResponseWriter, r *http.Request) { + +} diff --git a/routes/users.go b/routes/users.go index 6dcd6bd..96de876 100644 --- a/routes/users.go +++ b/routes/users.go @@ -5,6 +5,9 @@ import ( ) func usersHandler(w http.ResponseWriter, r *http.Request) { - // TODO: - // - Get current UserID + +} + +func meHandler(w http.ResponseWriter, r *http.Request) { + }