DB & Route Organization

This commit is contained in:
Evan Reichard 2021-01-09 19:44:02 -05:00
parent 04924ead5c
commit 96b0c888ed
21 changed files with 430 additions and 192 deletions

View File

@ -1,14 +1,17 @@
package cmd package cmd
import ( import (
// "reichard.io/imagini/routes" "fmt"
"errors"
"reichard.io/imagini/routes"
"reichard.io/imagini/internal/db" "reichard.io/imagini/internal/db"
"reichard.io/imagini/internal/auth"
"reichard.io/imagini/internal/models"
"reichard.io/imagini/internal/config" "reichard.io/imagini/internal/config"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
// "net/http" "net/http"
// "log" log "github.com/sirupsen/logrus"
"fmt"
) )
var CmdServe = cli.Command{ var CmdServe = cli.Command{
@ -19,32 +22,66 @@ var CmdServe = cli.Command{
} }
var CmdDBTest = cli.Command{ var CmdDBTest = cli.Command{
Name: "db", Name: "test",
Aliases: []string{"d"}, Aliases: []string{"t"},
Usage: "test db.", Usage: "test db.",
Action: testDatabase, Action: testDatabase,
} }
func serveWeb(ctx *cli.Context) error { func serveWeb(ctx *cli.Context) error {
c := config.NewConfig() log.Info("Serving Web")
db.ConnectDB(c) routes.RegisterRoutes()
//db.PopulateTestData() if err := http.ListenAndServe(":8080", nil); err != nil {
newItems := db.ItemsFromAlbum(1, 2) log.Fatal(err)
}
fmt.Printf("%+v\n", newItems)
return nil return nil
// routes.RegisterRoutes()
// if err := http.ListenAndServe(":8080", nil); err != nil {
// log.Fatal(err)
// }
// return nil
} }
func testDatabase(ctx *cli.Context) error { func testDatabase(ctx *cli.Context) error {
resp := db.ItemsFromAlbum(1, 3) log.Info("Testing Database")
fmt.Printf("%v", resp) 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 return nil
} }

2
go.mod
View File

@ -6,8 +6,10 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/disintegration/imaging v1.6.2 // indirect github.com/disintegration/imaging v1.6.2 // indirect
github.com/mattn/go-sqlite3 v1.14.6 github.com/mattn/go-sqlite3 v1.14.6
github.com/sirupsen/logrus v1.7.0
github.com/tus/tusd v1.4.0 github.com/tus/tusd v1.4.0
github.com/urfave/cli/v2 v2.3.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 golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect
gorm.io/driver/sqlite v1.1.4 gorm.io/driver/sqlite v1.1.4
gorm.io/gorm v1.20.9 gorm.io/gorm v1.20.9

8
go.sum
View File

@ -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/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.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 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-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/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= 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/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 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-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-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 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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/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 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 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-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-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-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.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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=

Binary file not shown.

37
internal/auth/auth.go Normal file
View File

@ -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
}
}

View File

@ -0,0 +1,9 @@
package auth
import (
"reichard.io/imagini/internal/db"
)
func authenticateLDAPUser(user db.User, pw string) bool {
return false
}

View File

@ -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)
}

View File

@ -3,39 +3,41 @@ package db
import ( import (
"log" "log"
"path" "path"
"fmt" // "time"
"time"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"reichard.io/imagini/internal/config" "reichard.io/imagini/internal/config"
"reichard.io/imagini/internal/models"
) )
var db *gorm.DB var db *gorm.DB
func ConnectDB(c *config.Config) { 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" { if c.DBType == "SQLite" {
dbLocation := path.Join(c.ConfigPath, "imagini.db") dbLocation := path.Join(c.ConfigPath, "imagini.db")
db, _ = gorm.Open(sqlite.Open(dbLocation), &gorm.Config{ db, _ = gorm.Open(sqlite.Open(dbLocation), gormConfig)
PrepareStmt: true,
})
} else { } else {
log.Fatal("ERROR: Unsupported Database") log.Fatal("ERROR: Unsupported Database")
} }
// Initialize Database // Initialize Database
db.AutoMigrate(&ServerSetting{}) db.AutoMigrate(&models.ServerSetting{})
db.AutoMigrate(&User{}) db.AutoMigrate(&models.User{})
db.AutoMigrate(&MediaItem{}) db.AutoMigrate(&models.MediaItem{})
db.AutoMigrate(&Tag{}) db.AutoMigrate(&models.Tag{})
db.AutoMigrate(&Album{}) db.AutoMigrate(&models.Album{})
} }
func ItemsFromAlbum(user User, album Album) []MediaItem { func ItemsFromAlbum(user models.User, album models.Album) []models.MediaItem {
var mediaItems []MediaItem var mediaItems []models.MediaItem
// db.Table("media_albums"). // db.Table("media_albums").
// Select("media_item.*"). // Select("media_item.*").
// Joins("INNER JOIN media_items ON media_albums.ID = media_items.Albums"). // 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 IndexMediaItems(newItems []MediaItem) {
// } // }
func PopulateTestData() { // func PopulateTestData() {
user1 := User{Name: "Evan", Email: "evan@reichard.io", AuthType: "LDAP", Salt: "1234", HashedPWSalt: "1234"} // user1 := User{Username: "Evan", Email: "evan@reichard.io", FirstName: "Evan", LastName: "Reichard", AuthType: "LDAP", Salt: "1234", HashedPWSalt: "1234"}
user2 := User{Name: "Ryan", Email: "ryan@example.com", AuthType: "Local", Salt: "2345", HashedPWSalt: "2345"} // user2 := User{Username: "Ryan", Email: "ryan@example.com", FirstName: "Ryan", LastName: "Dunfrey", AuthType: "Local", Salt: "2345", HashedPWSalt: "2345"}
user3 := User{Name: "Bill", Email: "bill@example.com", AuthType: "LDAP", Salt: "3456", HashedPWSalt: "3456"} // user3 := User{Username: "Bill", Email: "bill@example.com", FirstName: "Bill", LastName: "Smith", AuthType: "LDAP", Salt: "3456", HashedPWSalt: "3456"}
//
mi1 := MediaItem{ // mi1 := MediaItem{
User: user1, // User: user1,
EXIFDate: time.Now(), // EXIFDate: time.Now(),
Latitude: "1234", // Latitude: "1234",
Longitude: "1234", // Longitude: "1234",
RelPath: "./1234.jpg", // RelPath: "./1234.jpg",
Tags: []Tag{ // Tags: []Tag{
{Name: "Tag1"}, // {Name: "Tag1"},
{Name: "Tag2"}, // {Name: "Tag2"},
}, // },
Albums: []Album{ // Albums: []Album{
{Name: "Album1"}, // {Name: "Album1"},
{Name: "Album2"}, // {Name: "Album2"},
}, // },
} // }
//
mi2 := MediaItem{ // mi2 := MediaItem{
User: user2, // User: user2,
EXIFDate: time.Now(), // EXIFDate: time.Now(),
Latitude: "1234", // Latitude: "1234",
Longitude: "1234", // Longitude: "1234",
RelPath: "./1234.jpg", // RelPath: "./1234.jpg",
Tags: []Tag{ // Tags: []Tag{
{Name: "Tag3"}, // {Name: "Tag3"},
{Name: "Tag4"}, // {Name: "Tag4"},
}, // },
Albums: []Album{ // Albums: []Album{
{Name: "Album3"}, // {Name: "Album3"},
{Name: "Album4"}, // {Name: "Album4"},
}, // },
} // }
//
mi3 := MediaItem{ // mi3 := MediaItem{
User: user3, // User: user3,
EXIFDate: time.Now(), // EXIFDate: time.Now(),
Latitude: "1234", // Latitude: "1234",
Longitude: "1234", // Longitude: "1234",
RelPath: "./1234.jpg", // RelPath: "./1234.jpg",
Tags: []Tag{ // Tags: []Tag{
{Name: "Tag4"}, // {Name: "Tag4"},
{Name: "Tag5"}, // {Name: "Tag5"},
}, // },
Albums: []Album{ // Albums: []Album{
{Name: "Album1"}, // {Name: "Album1"},
{Name: "Album7"}, // {Name: "Album7"},
}, // },
} // }
//
// db.Create(&user1) // // db.Create(&user1)
// db.Create(&user2) // // db.Create(&user2)
// db.Create(&user3) // // db.Create(&user3)
db.Create(&mi1) // db.Create(&mi1)
db.Create(&mi2) // db.Create(&mi2)
db.Create(&mi3) // db.Create(&mi3)
} // }

7
internal/db/errors.go Normal file
View File

@ -0,0 +1,7 @@
package db
import "errors"
var (
ErrUserAlreadyExists = errors.New("user already exists")
)

25
internal/db/users.go Normal file
View File

@ -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) {
}

View File

@ -1,4 +1,4 @@
package db package models
import ( import (
"gorm.io/gorm" "gorm.io/gorm"
@ -14,11 +14,12 @@ type ServerSetting struct {
type User struct { type User struct {
gorm.Model gorm.Model
Name string Email string `gorm:"unique;not null"`
Email string Username string `gorm:"unique;not null"`
FirstName string
LastName string
AuthType string AuthType string
Salt string HashedPassword string
HashedPWSalt string
} }
type MediaItem struct { type MediaItem struct {

16
main.go
View File

@ -2,9 +2,9 @@ package main
import ( import (
"os" "os"
"log"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
log "github.com/sirupsen/logrus"
"reichard.io/imagini/cmd" "reichard.io/imagini/cmd"
"reichard.io/imagini/internal/sessions" "reichard.io/imagini/internal/sessions"
@ -12,15 +12,27 @@ import (
var globalSessions *sessions.Manager 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() { func main() {
log.SetFormatter(UTCFormatter{&log.TextFormatter{FullTimestamp: true}})
log.Info("Starging Imagini")
app := &cli.App{ app := &cli.App{
Name: "Imagini", Name: "Imagini",
Usage: "A self hosted photo library.", Usage: "A self hosted photo library.",
Commands: []*cli.Command{ Commands: []*cli.Command{
&cmd.CmdServe, &cmd.CmdServe,
&cmd.CmdDBTest,
}, },
} }
err := app.Run(os.Args) err := app.Run(os.Args)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

9
routes/albums.go Normal file
View File

@ -0,0 +1,9 @@
package routes
import (
"net/http"
)
func albumsHandler(w http.ResponseWriter, r *http.Request) {
}

13
routes/auth.go Normal file
View File

@ -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) {
}

9
routes/info.go Normal file
View File

@ -0,0 +1,9 @@
package routes
import (
"net/http"
)
func infoHandler(w http.ResponseWriter, r *http.Request) {
}

9
routes/media_items.go Normal file
View File

@ -0,0 +1,9 @@
package routes
import (
"net/http"
)
func mediaItemsHandler(w http.ResponseWriter, r *http.Request) {
}

View File

@ -19,17 +19,17 @@ func MultipleMiddleware(h http.Handler, m ...Middleware) http.Handler {
return wrapped return wrapped
} }
func authMiddleware(h http.Handler) http.Handler { // func authMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, ok := ValidateUserToken(r) // _, ok := ValidateUserToken(r)
//
if ok { // if ok {
next.ServeHTTP(w, r) // next.ServeHTTP(w, r)
} else { // } else {
w.WriteHeader(http.StatusUnauthorized) // w.WriteHeader(http.StatusUnauthorized)
} // }
}) // })
} // }
func logMiddleware(h http.Handler) http.Handler { func logMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

View File

@ -2,84 +2,90 @@ package routes
import ( import (
"net/http" "net/http"
"fmt"
// "reichard.io/imagini/internal/db"
"github.com/tus/tusd/pkg/filestore"
tusd "github.com/tus/tusd/pkg/handler"
) )
func RegisterRoutes() { func RegisterRoutes() {
commonMiddleware := []Middleware{ http.HandleFunc("/MediaItems", mediaItemsHandler)
logMiddleware, http.HandleFunc("/Upload", uploadHandler)
authMiddleware, http.HandleFunc("/Albums", albumsHandler)
} http.HandleFunc("/Logout", logoutHandler)
http.Handle("/Users", MultipleMiddleware(usersHandler, commonMiddleware...)) http.HandleFunc("/Login", loginHandler)
http.Handle("/Uploads/", MultipleMiddleware(uploadsHandler, commonMiddleware...)) http.HandleFunc("/Users", usersHandler)
http.HandleFunc("/Tags", tagsHandler)
// http.HandleFunc("/uploads/", uploadsHandler()) http.HandleFunc("/Info", infoHandler)
http.Handle("/Uploads/", func(next http.Handler) http.Handler { http.HandleFunc("/Me", meHandler)
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)))
} }
// func tagsHandler(w http.ResponseWriter, r *http.Request) { // Examples:
// query := r.URL.Query() // [POST] /Login { user: <USER_OR_EMAIL>, password: <PASSWORD> }
// filters, present := query["filters"] // [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() { // func processMedia() {
// var mi db.MediaItem // var mi db.MediaItem
// //
@ -108,9 +114,3 @@ func uploadsHandler() http.Handler {
// img = imaging.Fit(img, 240, 160, imaging.Lanczos) // img = imaging.Fit(img, 240, 160, imaging.Lanczos)
// err = imaging.Save(img, "thumbnail.jpg") // err = imaging.Save(img, "thumbnail.jpg")
// } // }

9
routes/tags.go Normal file
View File

@ -0,0 +1,9 @@
package routes
import (
"net/http"
)
func tagsHandler(w http.ResponseWriter, r *http.Request) {
}

9
routes/upload.go Normal file
View File

@ -0,0 +1,9 @@
package routes
import (
"net/http"
)
func uploadHandler(w http.ResponseWriter, r *http.Request) {
}

View File

@ -5,6 +5,9 @@ import (
) )
func usersHandler(w http.ResponseWriter, r *http.Request) { func usersHandler(w http.ResponseWriter, r *http.Request) {
// TODO:
// - Get current UserID }
func meHandler(w http.ResponseWriter, r *http.Request) {
} }