refactor, sketch SSE implementation
This commit is contained in:
@@ -1,12 +1,34 @@
|
||||
package handlers
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
import (
|
||||
"ytdlp-site/config"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var log *logrus.Logger
|
||||
var store *sessions.CookieStore
|
||||
|
||||
func Init(logger *logrus.Logger) error {
|
||||
log = logger.WithFields(logrus.Fields{
|
||||
"component": "handlers",
|
||||
}).Logger
|
||||
|
||||
// create the cookie store
|
||||
key, err := config.GetSessionAuthKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
store = sessions.NewCookieStore(key)
|
||||
store.Options = &sessions.Options{
|
||||
Path: "/",
|
||||
MaxAge: 30 * 24 * 60 * 60, // seconds
|
||||
HttpOnly: true,
|
||||
Secure: config.GetSecure(),
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Fini() {}
|
||||
|
58
handlers/login.go
Normal file
58
handlers/login.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"ytdlp-site/database"
|
||||
"ytdlp-site/users"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func LoginPost(c echo.Context) error {
|
||||
username := c.FormValue("username")
|
||||
password := c.FormValue("password")
|
||||
|
||||
db := database.Get()
|
||||
|
||||
var user users.User
|
||||
if err := db.Where("username = ?", username).First(&user).Error; err != nil {
|
||||
return c.String(http.StatusUnauthorized, "Invalid credentials")
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
||||
return c.String(http.StatusUnauthorized, "Invalid credentials")
|
||||
}
|
||||
|
||||
session, err := store.Get(c.Request(), "session")
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, "Unable to retrieve session")
|
||||
}
|
||||
session.Values["user_id"] = user.ID
|
||||
err = session.Save(c.Request(), c.Response().Writer)
|
||||
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, "Unable to save session")
|
||||
}
|
||||
|
||||
session, _ = store.Get(c.Request(), "session")
|
||||
_, ok := session.Values["user_id"]
|
||||
if !ok {
|
||||
return c.String(http.StatusInternalServerError, "user_id was not saved as expected")
|
||||
}
|
||||
|
||||
fmt.Println("loginPostHandler: redirect to /download")
|
||||
return c.Redirect(http.StatusSeeOther, "/download")
|
||||
}
|
||||
|
||||
func LoginGet(c echo.Context) error {
|
||||
return c.Render(http.StatusOK, "login.html", nil)
|
||||
}
|
||||
|
||||
func LogoutGet(c echo.Context) error {
|
||||
session, _ := store.Get(c.Request(), "session")
|
||||
delete(session.Values, "user_id")
|
||||
session.Save(c.Request(), c.Response().Writer)
|
||||
return c.Redirect(http.StatusSeeOther, "/login")
|
||||
}
|
25
handlers/middleware.go
Normal file
25
handlers/middleware.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func AuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
session, err := store.Get(c.Request(), "session")
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, "Error: Unable to retrieve session")
|
||||
}
|
||||
userID, ok := session.Values["user_id"]
|
||||
if !ok {
|
||||
fmt.Println("authMiddleware: session does not contain user_id. Redirect to /login")
|
||||
// return c.String(http.StatusForbidden, "not logged in")
|
||||
return c.Redirect(http.StatusSeeOther, "/login")
|
||||
}
|
||||
c.Set("user_id", userID)
|
||||
return next(c)
|
||||
}
|
||||
}
|
26
handlers/session.go
Normal file
26
handlers/session.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Id uint
|
||||
}
|
||||
|
||||
func GetUser(c echo.Context) (User, error) {
|
||||
session, err := store.Get(c.Request(), "session")
|
||||
if err == nil {
|
||||
val, ok := session.Values["user_id"]
|
||||
if ok {
|
||||
return User{Id: val.(uint)}, nil
|
||||
} else {
|
||||
return User{}, fmt.Errorf("user_id not in session")
|
||||
}
|
||||
} else {
|
||||
return User{}, fmt.Errorf("couldn't retureve session from store")
|
||||
}
|
||||
|
||||
}
|
53
handlers/videos.go
Normal file
53
handlers/videos.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"ytdlp-site/originals"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func VideosEvents(c echo.Context) error {
|
||||
|
||||
user, err := GetUser(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := c.Request()
|
||||
res := c.Response()
|
||||
|
||||
// Set headers for SSE
|
||||
res.Header().Set(echo.HeaderContentType, "text/event-stream")
|
||||
res.Header().Set("Cache-Control", "no-cache")
|
||||
res.Header().Set("Connection", "keep-alive")
|
||||
|
||||
// Create a channel to signal client disconnect
|
||||
done := req.Context().Done()
|
||||
|
||||
q := originals.Subscribe(user.Id)
|
||||
defer originals.Unsubscribe(user.Id, q)
|
||||
|
||||
// Send SSE messages
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return nil
|
||||
default:
|
||||
event := <-q.Ch
|
||||
|
||||
jsonData, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("data: %s\n\n", jsonData)
|
||||
_, err = res.Write([]byte(msg))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.Flush()
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user