kontor-echo: setup project to show homepage
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
Gitea Actions Demo / build-and-test (push) Failing after 11s

This commit is contained in:
Thomas Peetz
2026-11-09 17:02:59 +01:00
parent 074abd3c85
commit debdf3d0b0
63 changed files with 2411 additions and 485 deletions
+2 -2
View File
@@ -138,8 +138,8 @@ func InitConfig() error {
viper.SetDefault("db.user", "kontor")
viper.SetDefault("db.password", "kontor")
viper.SetDefault("db.path", "data/kontor.db")
viper.SetDefault("server.port", 8550)
viper.SetDefault("gin.mode", "release")
viper.SetDefault("server.host", "127.0.0.1")
viper.SetDefault("server.port", 8400)
// Read the config file
if err := viper.ReadInConfig(); err != nil {
// Handle the case where config file is not found
+114
View File
@@ -0,0 +1,114 @@
package handlers
import (
"kontor-api-echo/internal/config"
"kontor-api-echo/internal/globals"
"kontor-api-echo/internal/helpers"
"kontor-api-echo/internal/models"
"kontor-api-echo/internal/repository"
"kontor-api-echo/internal/service"
"net/http"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
type AuthHandler struct {
Service *service.AuthService
Secret []byte
}
func NewAuthHandler(db *bun.DB) *AuthHandler {
handler := &AuthHandler{Service: service.NewAuthService(repository.NewProfileRepository(db)), Secret: config.ServerConfig.ApiSecret}
return handler
}
func (handler *AuthHandler) Login(c *echo.Context) error {
var input models.LoginInput
if err := c.Bind(&input); err != nil {
return c.JSON(http.StatusBadRequest, map[string]any{"error": err.Error()})
}
profile_id, err := handler.Service.LoginCheck(input.Email, input.Password)
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]any{"error": "username or password is incorrect."})
}
token, err := helpers.GenerateToken(profile_id)
logger := c.Logger()
if err != nil {
logger.Info("Login", "GenerateToken error", err.Error())
}
return c.JSON(http.StatusOK, map[string]any{"token": token})
}
func (handler *AuthHandler) LoginPage(c *echo.Context) error {
cookie, _ := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
logger.Info("LoginPage", globals.UserKey, user)
data := globals.GetDefaultValues(user, "Please logout first")
if user != "" {
return c.Render(http.StatusBadRequest, "login", data)
}
data["message"] = ""
return c.Render(http.StatusOK, "login", data)
}
func (handler *AuthHandler) LoginPost(c *echo.Context) error {
cookie, _ := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
logger.Info("LoginPost", "user", user)
data := globals.GetDefaultValues(user, "Please logout first")
if user != "" {
return c.Render(http.StatusBadRequest, "login", data)
}
username := c.FormValue("username")
password := c.FormValue("password")
if helpers.EmptyUserPass(username, password) {
data["message"] = "Parameters can't be empty"
c.Render(http.StatusBadRequest, "login", data)
}
profile_id, err := handler.Service.LoginCheck(username, password)
if err != nil {
data["message"] = "Incorrect username or password"
c.Render(http.StatusUnauthorized, "login", data)
}
c.SetCookie(&http.Cookie{
Name: globals.UserKey,
Value: profile_id,
MaxAge: 3600,
Path: "/",
Domain: "",
HttpOnly: true,
})
logger.Info("LoginPost: redirect to index")
return c.Redirect(http.StatusMovedPermanently, "/")
}
func (handler *AuthHandler) LogoutPage(c *echo.Context) error {
cookie, _ := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
logger.Info("LogoutPage", globals.UserKey, user)
if user == "" {
logger.Info("Invalid session token")
return c.Redirect(http.StatusMovedPermanently, "/")
}
c.SetCookie(&http.Cookie{
Name: globals.UserKey,
Value: "",
MaxAge: -1, // Deletes the cookie immediately
Path: "/",
Domain: "",
HttpOnly: true,
})
logger.Info("LogoutPage: redirect to index page")
return c.Redirect(http.StatusMovedPermanently, "/")
}
+33
View File
@@ -0,0 +1,33 @@
package handlers
import (
"kontor-api-echo/internal/globals"
"net/http"
"time"
"github.com/labstack/echo/v5"
)
func Health(c *echo.Context) error {
return c.JSON(200, map[string]string{
"ok": "true",
"status": "healthy",
"version": globals.Version,
"time": time.Now().UTC().Format(time.RFC3339),
})
}
func Index(c *echo.Context) error {
logger := c.Logger()
cookie, err := c.Cookie(globals.UserKey)
user := ""
if err != nil {
logger.Info("error reading cookie", "error", err.Error())
} else {
user = cookie.Value
}
logger.Info("IndexGetHandler", globals.UserKey, user)
data := globals.GetDefaultValues(user, "This is an index page...")
return c.Render(http.StatusOK, "home", data)
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-echo/internal/models"
"kontor-api-echo/internal/repository"
"kontor-api-echo/internal/service"
"net/http"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
type MailHandler struct {
Service *service.MailService
}
func NewMailHandler(db *bun.DB) *MailHandler {
handler := &MailHandler{Service: service.NewMailService(repository.NewMailRepository(db))}
return handler
}
func (handler *MailHandler) List(c *echo.Context) {
mails, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
return
}
dtos := models.ConvertMailsToDtos(mails)
c.JSON(http.StatusOK, dtos)
}
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-echo/internal/models"
"kontor-api-echo/internal/repository"
"kontor-api-echo/internal/service"
"net/http"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
type MailAccountHandler struct {
Service *service.MailAccountService
}
func NewMailAccountHandler(db *bun.DB) *MailAccountHandler {
handler := &MailAccountHandler{Service: service.NewMailAccountService(repository.NewMailAccountRepository(db))}
return handler
}
func (handler *MailAccountHandler) List(c *echo.Context) {
mailaccounts, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
return
}
dtos := models.ConvertMailAccountsToDtos(mailaccounts)
c.JSON(http.StatusOK, dtos)
}
+13 -15
View File
@@ -67,35 +67,35 @@ func (handler *MediaActorHandler) Delete(c *echo.Context) {
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
func (handler *MediaActorHandler) ListPage(c *echo.Context) {
func (handler *MediaActorHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
actors, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return err
}
data := globals.GetDefaultValues(user, "MediaActors...")
data["actors"] = actors
c.Render(http.StatusOK, "media_actors", data)
return nil
}
func (handler *MediaActorHandler) EditPage(c *echo.Context) {
func (handler *MediaActorHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
//logger := slog.Get(c)
actor, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
data := globals.GetDefaultValues(user, "MediaActors...")
data["actor"] = actor
c.Render(http.StatusOK, "actor_detail", data)
return c.Render(http.StatusOK, "actor_detail", data)
}
func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
func (handler *MediaActorHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -103,8 +103,7 @@ func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
actor, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaActorHandler#UpdatePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaActorForm
if err := c.Bind(&form); err != nil {
@@ -113,15 +112,14 @@ func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
data["actor"] = actor
data["Form"] = form
data["Errors"] = err.Error()
c.Render(http.StatusBadRequest, "actor_detail", data)
return
return c.Render(http.StatusBadRequest, "actor_detail", data)
}
logger.Info("MediaActorHandler#UpdatePage", "actor", actor)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
c.Redirect(http.StatusFound, globals.MediaActorLink)
return c.Redirect(http.StatusFound, globals.MediaActorLink)
}
func (handler *MediaActorHandler) DeletePage(c *echo.Context) {
func (handler *MediaActorHandler) DeletePage(c *echo.Context) error {
//session := sessions.Default(c)
//user := session.Get(globals.UserKey)
id := c.Param("id")
@@ -129,9 +127,9 @@ func (handler *MediaActorHandler) DeletePage(c *echo.Context) {
//actor, err := handler.Service.Get(c.Request.Context(), id)
// if err != nil {
// logger.Info("MediaActorHandler#DeletePage", "error", err.Error())
// c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
// c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
// return
// }
logger.Info("MediaActorHandler#DeletePage", "actor", id)
c.Redirect(http.StatusFound, globals.MediaActorLink)
return c.Redirect(http.StatusFound, globals.MediaActorLink)
}
+19 -26
View File
@@ -22,44 +22,41 @@ func NewMediaArticleHandler(db *bun.DB) *MediaArticleHandler {
return mediaFileHandler
}
func (handler *MediaArticleHandler) List(c *echo.Context) {
func (handler *MediaArticleHandler) List(c *echo.Context) error {
logger := c.Logger()
logger.Info("MediaArticleHandler#List")
articles, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
dtos := models.ConvertMediaArticlesToDtos(articles)
c.JSON(http.StatusOK, dtos)
return c.JSON(http.StatusOK, dtos)
}
func (handler *MediaArticleHandler) Delete(c *echo.Context) {
func (handler *MediaArticleHandler) Delete(c *echo.Context) error {
id := c.Param("id")
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
return
return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
}
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
func (handler *MediaArticleHandler) ListPage(c *echo.Context) {
func (handler *MediaArticleHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
files, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
data := globals.GetDefaultValues(user, "MediaArticles...")
data["title"] = "Kontor MediaArticles"
data["media_links"] = files
data["MediaLinksUrl"] = globals.MediaArticleLink
c.Render(http.StatusOK, "media_links", data)
return c.Render(http.StatusOK, "media_links", data)
}
func (handler *MediaArticleHandler) EditPage(c *echo.Context) {
func (handler *MediaArticleHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -67,16 +64,15 @@ func (handler *MediaArticleHandler) EditPage(c *echo.Context) {
media_file, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaArticleHandler#EditPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaArticleHandler#EditPage", "media_file", media_file)
data := globals.GetDefaultValues(user, "MediaArticle Details...")
data["lofi"] = media_file
c.Render(http.StatusOK, "lofi_detail", data)
return c.Render(http.StatusOK, "lofi_detail", data)
}
func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -84,8 +80,7 @@ func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
media_article, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaArticleHandler#UpdatePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaArticleForm
if err := c.Bind(&form); err != nil {
@@ -93,23 +88,21 @@ func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
data := globals.GetDefaultValues(user, "MediaArticle Details...")
data["Form"] = form
data["Errors"] = err.Error()
c.Render(http.StatusBadRequest, "lofi_detail", data)
return
return c.Render(http.StatusBadRequest, "lofi_detail", data)
}
logger.Info("MediaArticleHandler#UpdatePage", "media_article", media_article)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO())
c.Redirect(http.StatusFound, globals.MediaArticleLink)
return c.Redirect(http.StatusFound, globals.MediaArticleLink)
}
func (handler *MediaArticleHandler) DeletePage(c *echo.Context) {
func (handler *MediaArticleHandler) DeletePage(c *echo.Context) error {
id := c.Param("id")
logger := c.Logger()
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
logger.Info("MediaArticleHandler#DeletePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaArticleHandler#DeletePage", "lofi", id)
c.Redirect(http.StatusFound, globals.MediaArticleLink)
return c.Redirect(http.StatusFound, globals.MediaArticleLink)
}
+23 -29
View File
@@ -22,59 +22,57 @@ func NewMediaFileHandler(db *bun.DB) *MediaFileHandler {
return mediaFileHandler
}
func (handler *MediaFileHandler) List(c *echo.Context) {
func (handler *MediaFileHandler) List(c *echo.Context) error {
logger := c.Logger()
logger.Info("MediaFileHandler#List")
files, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return err
}
dtos := models.ConvertMediaFilesToDtos(files)
c.JSON(http.StatusOK, dtos)
return c.JSON(http.StatusOK, dtos)
}
func (handler *MediaFileHandler) Add(c *echo.Context) {
func (handler *MediaFileHandler) Add(c *echo.Context) error {
var input models.MediaFileAdd
if err := c.Bind(&input); err != nil {
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
return
return err
}
lofi, err := handler.Service.Add(c.Request().Context(), input.Url)
if err != nil {
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not added"})
return
return err
}
c.JSON(http.StatusOK, lofi)
return c.JSON(http.StatusOK, lofi)
}
func (handler *MediaFileHandler) Delete(c *echo.Context) {
func (handler *MediaFileHandler) Delete(c *echo.Context) error {
id := c.Param("id")
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
return
return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
}
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
func (handler *MediaFileHandler) ListPage(c *echo.Context) {
func (handler *MediaFileHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
files, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
data := globals.GetDefaultValues(user, "MediaFiles...")
data["title"] = "Kontor MediaFiles"
data["media_links"] = files
data["MediaLinksUrl"] = globals.MediaVideoLink
c.Render(http.StatusOK, "media_links", data)
return c.Render(http.StatusOK, "media_links", data)
}
func (handler *MediaFileHandler) EditPage(c *echo.Context) {
func (handler *MediaFileHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -82,16 +80,15 @@ func (handler *MediaFileHandler) EditPage(c *echo.Context) {
media_file, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#EditPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaLoFiHandler#EditPage", "media_file", media_file)
data := globals.GetDefaultValues(user, "MediaFile Details...")
data["lofi"] = media_file
c.Render(http.StatusOK, "lofi_detail", data)
return c.Render(http.StatusOK, "lofi_detail", data)
}
func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
func (handler *MediaFileHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -99,8 +96,7 @@ func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
media_file, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaFileHandler#UpdatePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaFileForm
if err := c.Bind(&form); err != nil {
@@ -108,15 +104,14 @@ func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
data := globals.GetDefaultValues(user, "MediaFile Details...")
data["Form"] = form
data["Errors"] = err.Error()
c.Render(http.StatusBadRequest, "lofi_detail", data)
return
return c.Render(http.StatusBadRequest, "lofi_detail", data)
}
logger.Info("MediaFileHandler#UpdatePage", "media_file", media_file)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO())
c.Redirect(http.StatusFound, globals.MediaFileLink)
return c.Redirect(http.StatusFound, globals.MediaFileLink)
}
func (handler *MediaFileHandler) DeletePage(c *echo.Context) {
func (handler *MediaFileHandler) DeletePage(c *echo.Context) error {
//session := sessions.Default(c)
//user := session.Get(globals.UserKey)
id := c.Param("id")
@@ -124,9 +119,8 @@ func (handler *MediaFileHandler) DeletePage(c *echo.Context) {
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
logger.Info("MediaFileHandler#DeletePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaFileHandler#DeletePage", "lofi", id)
c.Redirect(http.StatusFound, globals.MediaFileLink)
return c.Redirect(http.StatusFound, globals.MediaFileLink)
}
+26 -35
View File
@@ -59,33 +59,31 @@ func (handler *MediaLoFiHandler) Add(c *echo.Context) {
c.JSON(http.StatusOK, lofi)
}
func (handler *MediaLoFiHandler) Update(c *echo.Context) {
func (handler *MediaLoFiHandler) Update(c *echo.Context) error {
var input models.MediaLoFiDTO
if err := c.Bind(&input); err != nil {
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
lofi, err := handler.Service.Update(c.Request().Context(), input)
if err != nil {
logger := c.Logger()
logger.Info("MediaLoFiHandler#Update", "error", err.Error())
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not updated"})
return
return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not updated"})
}
c.JSON(http.StatusOK, lofi)
return c.JSON(http.StatusOK, lofi)
}
func (handler *MediaLoFiHandler) Delete(c *echo.Context) {
func (handler *MediaLoFiHandler) Delete(c *echo.Context) error {
id := c.Param("id")
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
return
return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
}
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
func (handler *MediaLoFiHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
@@ -113,8 +111,7 @@ func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
lofis, err := handler.Service.List(c.Request().Context())
if err != nil {
logger.Info("MediaLoFiHandler#ListPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis))
data := globals.GetDefaultValues(user, "MediaFiles...")
@@ -122,10 +119,10 @@ func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
data["isReview"] = review
data["isDownload"] = download
data["MediaLinksUrl"] = globals.MediaLofiLink
c.Render(http.StatusOK, "media_links", data)
return c.Render(http.StatusOK, "media_links", data)
}
func (handler *MediaLoFiHandler) EditPage(c *echo.Context) {
func (handler *MediaLoFiHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -146,25 +143,23 @@ func (handler *MediaLoFiHandler) EditPage(c *echo.Context) {
lofi, err = handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#EditPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
}
logger.Info("MediaLoFiHandler#EditPage", "lofi", lofi)
data := globals.GetDefaultValues(user, "MediaLofis...")
data["media"] = lofi
data["MediaLinksUrl"] = globals.MediaLofiLink
c.Render(http.StatusOK, "media_detail", data)
return c.Render(http.StatusOK, "media_detail", data)
}
func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) {
func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) error {
id := c.Param("id")
logger := c.Logger()
lofi, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#ChangeReviewPage", "error", err.Error())
c.Redirect(http.StatusNotFound, globals.MediaLofiLink)
return
return c.Redirect(http.StatusNotFound, globals.MediaLofiLink)
}
lofi.Review = !lofi.Review
handler.Service.Update(c.Request().Context(), lofi.ConvertMediaLoFiToDTO())
@@ -174,17 +169,16 @@ func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) {
lofis, err := handler.Service.List(c.Request().Context())
if err != nil {
logger.Info("MediaLoFiHandler#ChangeReviewPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis))
data := globals.GetDefaultValues(user, "MediaLofis...")
data["lofis"] = lofis
//c.HTML(http.StatusOK, "lofi", data)
c.Redirect(http.StatusCreated, globals.MediaLofiLink)
//c.Render(http.StatusOK, "lofi", data)
return c.Redirect(http.StatusCreated, globals.MediaLofiLink)
}
func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) {
func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -192,25 +186,23 @@ func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) {
lofi, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#UpdatePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaLoFiForm
if err := c.Bind(&form); err != nil {
logger.Info("MediaLoFiHandler#UpdatePage", "error", err.Error())
c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
return c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
"Form": form,
"Errors": err.Error(),
"user": user,
})
return
}
logger.Info("MediaLoFiHandler#UpdatePage", "lofi", lofi)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
c.Redirect(http.StatusFound, globals.MediaLofiLink)
return c.Redirect(http.StatusFound, globals.MediaLofiLink)
}
func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) {
func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -218,11 +210,10 @@ func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) {
lofi, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#DeletePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaLoFiHandler#DeletePage", "lofi", id)
c.Render(http.StatusOK, "lofi_delete", map[string]any{
return c.Render(http.StatusOK, "lofi_delete", map[string]any{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
+31 -42
View File
@@ -22,68 +22,62 @@ func NewMediaMusicHandler(db *bun.DB) *MediaMusicHandler {
return mediaMusicHandler
}
func (handler *MediaMusicHandler) List(c *echo.Context) {
func (handler *MediaMusicHandler) List(c *echo.Context) error {
musics, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
dtos := models.ConvertMediaMusicsToDtos(musics)
c.JSON(http.StatusOK, dtos)
return c.JSON(http.StatusOK, dtos)
}
func (handler *MediaMusicHandler) Get(c *echo.Context) {
func (handler *MediaMusicHandler) Get(c *echo.Context) error {
id := c.Param("id")
music, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
return
return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
}
c.JSON(http.StatusOK, music)
return c.JSON(http.StatusOK, music)
}
func (handler *MediaMusicHandler) Add(c *echo.Context) {
func (handler *MediaMusicHandler) Add(c *echo.Context) error {
var input models.MediaLofiAdd
if err := c.Bind(&input); err != nil {
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
music, err := handler.Service.Add(c.Request().Context(), input.Url)
if err != nil {
c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not added"})
return
return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not added"})
}
c.JSON(http.StatusOK, music)
return c.JSON(http.StatusOK, music)
}
func (handler *MediaMusicHandler) Update(c *echo.Context) {
func (handler *MediaMusicHandler) Update(c *echo.Context) error {
var input models.MediaMusicDTO
if err := c.Bind(&input); err != nil {
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
music, err := handler.Service.Update(c.Request().Context(), input)
if err != nil {
logger := c.Logger()
logger.Info("MediaMusicHandler#Update", "error", err.Error())
c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not updated"})
return
return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not updated"})
}
c.JSON(http.StatusOK, music)
return c.JSON(http.StatusOK, music)
}
func (handler *MediaMusicHandler) Delete(c *echo.Context) {
func (handler *MediaMusicHandler) Delete(c *echo.Context) error {
id := c.Param("id")
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
return
return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
}
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
func (handler *MediaMusicHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
@@ -111,8 +105,7 @@ func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
musics, err := handler.Service.List(c.Request().Context())
if err != nil {
logger.Info("MediaMusicHandler#ListPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaMusicHandler#ListPage", "MediaMusic count", len(musics))
data := globals.GetDefaultValues(user, "MediaMusic...")
@@ -120,10 +113,10 @@ func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
data["MediaLinksUrl"] = globals.MediaMusicLink
data["isReview"] = review
data["isDownload"] = download
c.Render(http.StatusOK, "media_links", data)
return c.Render(http.StatusOK, "media_links", data)
}
func (handler *MediaMusicHandler) EditPage(c *echo.Context) {
func (handler *MediaMusicHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -131,16 +124,15 @@ func (handler *MediaMusicHandler) EditPage(c *echo.Context) {
music, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaMusicHandler#EditPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaMusicHandler#EditPage", "music", music)
data := globals.GetDefaultValues(user, "MediaMusic...")
data["lofi"] = music
c.Render(http.StatusOK, "lofi_detail", data)
return c.Render(http.StatusOK, "lofi_detail", data)
}
func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -148,8 +140,7 @@ func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
music, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaMusicHandler#UpdatePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaMusicForm
if err := c.Bind(&form); err != nil {
@@ -157,15 +148,14 @@ func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
data := globals.GetDefaultValues(user, "MediaMusic...")
data["Form"] = form
data["Errors"] = err.Error()
c.Render(http.StatusBadRequest, "lofi_detail", data)
return
return c.Render(http.StatusBadRequest, "lofi_detail", data)
}
logger.Info("MediaMusicHandler#UpdatePage", "music", music)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
c.Redirect(http.StatusFound, globals.MediaMusicLink)
return c.Redirect(http.StatusFound, globals.MediaMusicLink)
}
func (handler *MediaMusicHandler) DeletePage(c *echo.Context) {
func (handler *MediaMusicHandler) DeletePage(c *echo.Context) error {
// session := sessions.Default(c)
// user := session.Get(globals.UserKey)
id := c.Param("id")
@@ -173,9 +163,8 @@ func (handler *MediaMusicHandler) DeletePage(c *echo.Context) {
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
logger.Info("MediaMusicHandler#DeletePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaMusicHandler#DeletePage", "music", id)
c.Redirect(http.StatusFound, globals.MediaMusicLink)
return c.Redirect(http.StatusFound, globals.MediaMusicLink)
}
+16 -22
View File
@@ -20,36 +20,34 @@ func NewMediaVideoHandler(db *bun.DB) *MediaVideoHandler {
return handler
}
func (handler *MediaVideoHandler) List(c *echo.Context) {
func (handler *MediaVideoHandler) List(c *echo.Context) error {
logger := c.Logger()
logger.Info("MediaVideoHandler#List")
videos, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
dtos := models.ConvertMediaVideosToDtos(videos)
c.JSON(http.StatusOK, dtos)
return c.JSON(http.StatusOK, dtos)
}
func (handler *MediaVideoHandler) ListPage(c *echo.Context) {
func (handler *MediaVideoHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
videos, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaVideoHandler#ListPage", "videos count", len(videos))
data := globals.GetDefaultValues(user, "MediaVideos...")
data["title"] = "Kontor MediaVideos"
data["media_links"] = videos
data["MediaLinksUrl"] = globals.MediaVideoLink
c.Render(http.StatusOK, "media_links", data)
return c.Render(http.StatusOK, "media_links", data)
}
func (handler *MediaVideoHandler) EditPage(c *echo.Context) {
func (handler *MediaVideoHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -57,16 +55,15 @@ func (handler *MediaVideoHandler) EditPage(c *echo.Context) {
video, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaVideoHandler#EditPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaVideoHandler#EditPage", "lofi", video)
data := globals.GetDefaultValues(user, "MediaLofis...")
data["lofi"] = video
c.Render(http.StatusOK, "lofi_detail", data)
return c.Render(http.StatusOK, "lofi_detail", data)
}
func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) {
func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -74,25 +71,23 @@ func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) {
video, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaVideoHandler#UpdatePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaVideoForm
if err := c.Bind(&form); err != nil {
logger.Info("MediaVideoHandler#UpdatePage", "error", err.Error())
c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
return c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
"Form": form,
"Errors": err.Error(),
"user": user,
})
return
}
logger.Info("MediaVideoHandler#UpdatePage", "lofi", video)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
c.Redirect(http.StatusFound, globals.MediaVideoLink)
return c.Redirect(http.StatusFound, globals.MediaVideoLink)
}
func (handler *MediaVideoHandler) DeletePage(c *echo.Context) {
func (handler *MediaVideoHandler) DeletePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -100,11 +95,10 @@ func (handler *MediaVideoHandler) DeletePage(c *echo.Context) {
err = handler.Service.Delete(c.Request().Context(), id)
if err != nil {
logger.Info("MediaVideoHandler#DeletePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaVideoHandler#DeletePage", "video", id)
c.Render(http.StatusOK, "lofi_delete", map[string]string{
return c.Render(http.StatusOK, "lofi_delete", map[string]string{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-echo/internal/models"
"kontor-api-echo/internal/repository"
"kontor-api-echo/internal/service"
"net/http"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
type TokenHandler struct {
Service *service.TokenService
}
func NewTokenHandler(db *bun.DB) *TokenHandler {
handler := &TokenHandler{Service: service.NewTokenService(repository.NewTokenRepository(db))}
return handler
}
func (handler *TokenHandler) List(c *echo.Context) {
tokens, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
return
}
dtos := models.ConvertTokensToDtos(tokens)
c.JSON(http.StatusOK, dtos)
}
+7
View File
@@ -0,0 +1,7 @@
package helpers
import "strings"
func EmptyUserPass(username, password string) bool {
return strings.Trim(username, " ") == "" || strings.Trim(password, " ") == ""
}
+88
View File
@@ -0,0 +1,88 @@
package helpers
import (
"fmt"
"strings"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v5"
"github.com/spf13/viper"
)
func GenerateToken(profile_id string) (string, error) {
// token_lifespan := viper.GetInt("token_hour_lifespan")
claims := jwt.MapClaims{
"name": "Thomas Peetz",
"admin": true,
"authorized": true,
"sub": profile_id,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
// claims["authorized"] = true
// claims["profile_id"] = profile_id
// claims["exp"] = time.Now().Add(time.Hour * time.Duration(token_lifespan)).Unix()
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(viper.GetString("api_secret")))
}
func TokenValid(c *echo.Context) error {
logger := c.Logger()
tokenString := ExtractToken(c)
_, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
logger.Info("TokenValid", "Unexpected signing method", token.Header["alg"])
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(viper.GetString("api_secret")), nil
})
if err != nil {
return err
}
return nil
}
func ExtractToken(c *echo.Context) string {
logger := c.Logger()
token := c.QueryParam("token")
if token != "" {
logger.Info("ExtractToken", "token from query", token)
return token
}
bearerToken := c.Request().Header.Get("Authorization")
if len(strings.Split(bearerToken, " ")) == 2 {
logger.Info("ExtractToken", "token from query", token)
return strings.Split(bearerToken, " ")[1]
}
return ""
}
func ExtractTokenID(c *echo.Context) (string, error) {
tokenString := ExtractToken(c)
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(viper.GetString("api_secret")), nil
})
if err != nil {
return "", err
}
claims, ok := token.Claims.(jwt.MapClaims)
if ok && token.Valid {
uid, ok := claims["profile_id"].(string)
if !ok {
return "", err
}
return uid, nil
}
return "", nil
}
+69
View File
@@ -0,0 +1,69 @@
package helpers
import (
"encoding/json"
"fmt"
"io/ioutil"
"log/slog"
"net/http"
"net/url"
)
func StripUrl(webLink string, keepParam string) string {
u, err := url.Parse(webLink)
if err != nil {
slog.Info("StripUrl", "error", err)
return webLink
}
values := u.Query()
for key := range values {
if key != keepParam {
values.Del(key)
}
}
u.RawQuery = values.Encode()
return u.String()
}
func GetParam(webLink string, param string) string {
u, err := url.Parse(webLink)
if err != nil {
slog.Info("StripUrl", "error", err)
return webLink
}
values := u.Query()
for key := range values {
if key == param {
return values.Get(key)
}
}
return ""
}
type OEmbedResponse struct {
Title string `json:"title"`
}
func GetVideoTitle(videoUrl string) (string, error) {
videoID := GetParam(videoUrl, "v")
// Construct the oEmbed URL
url := fmt.Sprintf("https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=%s&format=json", videoID)
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
var data OEmbedResponse
if err := json.Unmarshal(body, &data); err != nil {
return "", err
}
return data.Title, nil
}
+73
View File
@@ -0,0 +1,73 @@
package models
import (
"kontor-api-echo/internal/helpers"
"time"
"github.com/uptrace/bun"
)
type Mail struct {
bun.BaseModel `bun:"table:mail"`
ID string `bun:"id,pk"`
CreatedAt time.Time `bun:"created_date,nullzero,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:"last_modified_date,nullzero,notnull,default:current_timestamp"`
DeletedAt *time.Time `bun:"deleted_date,nullzero"`
Version int `bun:"version,default:0"`
Folder string `bun:"folder"`
Subject string `bun:"subject"`
Body string `bun:"body"`
SendAt time.Time `bun:"sent_date"`
ReceivedAt time.Time `bun:"received_date"`
}
type MailDTO struct {
ID string `json:"id" binding:"required"`
CreatedAt helpers.KontorTime `json:"created_date"`
UpdatedAt helpers.KontorTime `json:"last_modified_date"`
DeletedAt *time.Time `json:"deleted_date.omitempty"`
Version int `json:"version"`
Folder string `json:"folder"`
Subject string `json:"subject"`
Body string `json:"body"`
SendAt time.Time `json:"sent_date"`
ReceivedAt time.Time `json:"received_date"`
}
func (dto MailDTO) ConvertDTOToModel() Mail {
model := Mail{
ID: dto.ID,
CreatedAt: dto.CreatedAt.Time,
UpdatedAt: dto.UpdatedAt.Time,
DeletedAt: dto.DeletedAt,
Version: dto.Version,
Folder: dto.Folder,
Subject: dto.Subject,
Body: dto.Body,
SendAt: dto.SendAt,
ReceivedAt: dto.ReceivedAt,
}
return model
}
func ConvertMailsToDtos(mails []Mail) []MailDTO {
dtos := make([]MailDTO, len(mails))
for i, mail := range mails {
dtos[i] = MailDTO{
ID: mail.ID,
CreatedAt: helpers.KontorTime{Time: mail.CreatedAt},
UpdatedAt: helpers.KontorTime{Time: mail.UpdatedAt},
DeletedAt: mail.DeletedAt,
Version: mail.Version,
Folder: mail.Folder,
Subject: mail.Subject,
Body: mail.Body,
SendAt: mail.SendAt,
ReceivedAt: mail.ReceivedAt,
}
}
return dtos
}
type MailDTOList []MailDTO
@@ -0,0 +1,77 @@
package models
import (
"kontor-api-echo/internal/helpers"
"time"
"github.com/uptrace/bun"
)
type MailAccount struct {
bun.BaseModel `bun:"table:mail_account"`
ID string `bun:"id,pk"`
CreatedAt time.Time `bun:"created_date,nullzero,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:"last_modified_date,nullzero,notnull,default:current_timestamp"`
DeletedAt *time.Time `bun:"deleted_date,nullzero"`
Version int `bun:"version,default:0"`
Host string `bun:"host"`
Port int `bun:"port"`
Protocol string `bun:"protocol"`
UserName string `bun:"user_name"`
Password string `bun:"password"`
StartTLS bool `bun:"start_tls"`
}
type MailAccountDTO struct {
ID string `json:"id" binding:"required"`
CreatedAt helpers.KontorTime `json:"created_date"`
UpdatedAt helpers.KontorTime `json:"last_modified_date"`
DeletedAt *time.Time `json:"deleted_date,omitempty"`
Version int `json:"version"`
Host string `json:"host"`
Port int `json:"port"`
Protocol string `json:"protocol"`
UserName string `json:"user_name"`
Password string `json:"password"`
StartTLS bool `json:"start_tls"`
}
func (dto MailAccountDTO) ConvertDTOToModel() MailAccount {
model := MailAccount{
ID: dto.ID,
CreatedAt: dto.CreatedAt.Time,
UpdatedAt: dto.UpdatedAt.Time,
DeletedAt: dto.DeletedAt,
Version: dto.Version,
Host: dto.Host,
Port: dto.Port,
Protocol: dto.Protocol,
UserName: dto.UserName,
Password: dto.Password,
StartTLS: dto.StartTLS,
}
return model
}
func ConvertMailAccountsToDtos(mailaccounts []MailAccount) []MailAccountDTO {
dtos := make([]MailAccountDTO, len(mailaccounts))
for i, mailaccount := range mailaccounts {
dtos[i] = MailAccountDTO{
ID: mailaccount.ID,
CreatedAt: helpers.KontorTime{Time: mailaccount.CreatedAt},
UpdatedAt: helpers.KontorTime{Time: mailaccount.UpdatedAt},
DeletedAt: mailaccount.DeletedAt,
Version: mailaccount.Version,
Host: mailaccount.Host,
Port: mailaccount.Port,
Protocol: mailaccount.Protocol,
UserName: mailaccount.UserName,
Password: mailaccount.Password,
StartTLS: mailaccount.StartTLS,
}
}
return dtos
}
type MailAccountDTOList []MailAccountDTO
+30 -21
View File
@@ -4,7 +4,9 @@ import (
"context"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -19,41 +21,48 @@ func NewAssignmentRepository(db *bun.DB) *AssignmentRepository {
func (repository *AssignmentRepository) FindAll(context context.Context) ([]models.Assignment, error) {
var assignments []models.Assignment
result := repository.db.Find(&assignments)
slog.Info("AssignmentRepository#FindAll", "count", result.RowsAffected)
err := repository.db.NewSelect().Model(&assignments).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("AssignmentRepository#FindAll", "count", len(assignments))
return assignments, nil
}
func (repository *AssignmentRepository) GetById(context context.Context, id string) (models.Assignment, error) {
func (repository *AssignmentRepository) GetById(context context.Context, id string) (*models.Assignment, error) {
var assignment = models.Assignment{ID: id}
slog.Info("AssignmentRepository#GetById", "id", id)
result := repository.db.First(&assignment)
if result.Error != nil {
slog.Info("AssignmentRepository#GetById", "error", result.Error.Error())
err := repository.db.NewSelect().Model(&assignment).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return assignment, result.Error
return &assignment, err
}
func (repository *AssignmentRepository) Import(assignments models.AssignmentDTOList) {
func (repository *AssignmentRepository) Import(dtos models.AssignmentDTOList) {
slog.Info("AssignmentRepository#Import")
for index, assignment := range assignments {
slog.Info("importing", "index", index, "profile", assignment)
model := assignment.ConvertDTOToModel()
existing_item := models.Assignment{ID: assignment.ID}
result_existing := repository.db.First(&existing_item)
if result_existing.Error != nil {
for index, dto := range dtos {
slog.Info("importing", "index", index, "assignment", dto)
model := dto.ConvertDTOToModel()
existing_item := models.Assignment{ID: dto.ID}
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
result := repository.db.Create(&model)
if result.Error != nil {
slog.Info("error during import", "error", result.Error.Error())
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
result := repository.db.Save(&model)
if result.Error != nil {
slog.Info("error during updating", "error", result.Error.Error())
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
+70
View File
@@ -0,0 +1,70 @@
package repository
import (
"context"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
type MailRepository struct {
db *bun.DB
}
func NewMailRepository(db *bun.DB) *MailRepository {
repository := &MailRepository{db: db}
return repository
}
func (repository *MailRepository) FindAll(context context.Context) ([]models.Mail, error) {
var models []models.Mail
err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("MailRepository#FindAll", "count", len(models))
return models, nil
}
func (repository *MailRepository) GetById(context context.Context, id string) (*models.Mail, error) {
var model = models.Mail{ID: id}
slog.Info("MailRepository#GetById", "id", id)
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return &model, err
}
func (repository *MailRepository) Import(dtos models.MailDTOList) {
slog.Info("MailRepository#Import")
for index, dto := range dtos {
slog.Info("importing", "index", index, "profile", dto)
model := dto.ConvertDTOToModel()
existing_item := models.Mail{ID: dto.ID}
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
}
@@ -0,0 +1,70 @@
package repository
import (
"context"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
type MailAccountRepository struct {
db *bun.DB
}
func (repository *MailAccountRepository) Import(dtos models.MailAccountDTOList) {
slog.Info("MailAccountRepository#Import")
for index, dto := range dtos {
slog.Info("importing", "index", index, "mailaccount", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MailAccount{ID: dto.ID}
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
}
func NewMailAccountRepository(db *bun.DB) *MailAccountRepository {
repository := &MailAccountRepository{db: db}
return repository
}
func (repository *MailAccountRepository) FindAll(context context.Context) ([]models.MailAccount, error) {
var models []models.MailAccount
err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("MailRepository#FindAll", "count", len(models))
return models, nil
}
func (repository *MailAccountRepository) GetById(context context.Context, id string) (*models.MailAccount, error) {
var model = models.MailAccount{ID: id}
slog.Info("MailAccountRepository#GetById", "id", id)
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return &model, err
}
+27 -17
View File
@@ -5,7 +5,9 @@ import (
"fmt"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -19,18 +21,21 @@ func (repository *MediaActorRepository) Import(dtos models.MediaActorDTOList) {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaActor{ID: dto.ID}
result_existing := repository.db.First(&existing_item)
if result_existing.Error != nil {
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
result := repository.db.Create(&model)
if result.Error != nil {
slog.Info("error during import", "error", result.Error.Error())
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
result := repository.db.Save(&model)
if result.Error != nil {
slog.Info("error during updating", "error", result.Error.Error())
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -42,22 +47,27 @@ func NewMediaActorRepository(db *bun.DB) *MediaActorRepository {
}
func (repository *MediaActorRepository) FindAll(context context.Context) ([]models.MediaActor, error) {
var actors []models.MediaActor
var models []models.MediaActor
result := repository.db.Find(&actors)
slog.Info("MediaActorRepository#FindAll", "count", result.RowsAffected)
err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("MailRepository#FindAll", "count", len(models))
return actors, nil
return models, nil
}
func (repository *MediaActorRepository) GetById(context context.Context, id string) (*models.MediaActor, error) {
var actor = models.MediaActor{ID: id}
var model = models.MediaActor{ID: id}
slog.Info("MediaActorRepository#GetById", "id", id)
result := repository.db.First(&actor)
if result.Error != nil {
slog.Info("SportRepository#GetById", "error", result.Error.Error())
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return &actor, result.Error
return &model, err
}
func (repository *MediaActorRepository) Add(context context.Context, url string) (*models.MediaActor, error) {
@@ -5,7 +5,9 @@ import (
"fmt"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -19,18 +21,21 @@ func (repository *MediaActorFileRepository) Import(dtos models.MediaActorFileDTO
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaActorFile{ID: dto.ID}
result_existing := repository.db.First(&existing_item)
if result_existing.Error != nil {
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
result := repository.db.Create(&model)
if result.Error != nil {
slog.Info("error during import", "error", result.Error.Error())
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
result := repository.db.Save(&model)
if result.Error != nil {
slog.Info("error during updating", "error", result.Error.Error())
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -42,23 +47,27 @@ func NewMediaActorFileRepository(db *bun.DB) *MediaActorFileRepository {
}
func (repository *MediaActorFileRepository) FindAll(context context.Context) ([]models.MediaActorFile, error) {
var actor_files []models.MediaActorFile
var models []models.MediaActorFile
result := repository.db.Find(&actor_files)
slog.Info("MediaActorFileRepository#FindAll", "count", result.RowsAffected)
err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("MailRepository#FindAll", "count", len(models))
return actor_files, nil
return models, nil
}
func (repository *MediaActorFileRepository) GetById(context context.Context, id string) (*models.MediaActorFile, error) {
var actorfile = models.MediaActorFile{ID: id}
var model = models.MediaActorFile{ID: id}
slog.Info("MediaActorFileRepository#GetById", "id", id)
result := repository.db.First(&actorfile)
if result.Error != nil {
slog.Info("MediaActorFileRepository#GetById", "error", result.Error.Error())
return nil, result.Error
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return &actorfile, result.Error
return &model, err
}
func (repository *MediaActorFileRepository) Add(context context.Context, media_actor_id, media_file_id string) (*models.MediaActorFile, error) {
+27 -18
View File
@@ -5,7 +5,9 @@ import (
"fmt"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -19,18 +21,21 @@ func (repository *MediaFileRepository) Import(dtos models.MediaFileDTOList) {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaFile{ID: dto.ID}
result_existing := repository.db.First(&existing_item)
if result_existing.Error != nil {
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
result := repository.db.Create(&model)
if result.Error != nil {
slog.Info("error during import", "error", result.Error.Error())
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
result := repository.db.Save(&model)
if result.Error != nil {
slog.Info("error during updating", "error", result.Error.Error())
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -42,23 +47,27 @@ func NewMediaFileRepository(db *bun.DB) *MediaFileRepository {
}
func (repository *MediaFileRepository) FindAll(context context.Context) ([]models.MediaFile, error) {
var files []models.MediaFile
var models []models.MediaFile
result := repository.db.Find(&files)
slog.Info("MediaFileRepository#FindAll", "count", result.RowsAffected)
err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("MailRepository#FindAll", "count", len(models))
return files, nil
return models, nil
}
func (repository *MediaFileRepository) GetById(context context.Context, id string) (*models.MediaFile, error) {
var file = models.MediaFile{ID: id}
var model = models.MediaFile{ID: id}
slog.Info("MediaFileRepository#GetById", "id", id)
result := repository.db.First(&file)
if result.Error != nil {
slog.Info("MediaFileRepository#GetById", "error", result.Error.Error())
return nil, result.Error
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return &file, result.Error
return &model, err
}
func (repository *MediaFileRepository) Add(context context.Context, url string) (*models.MediaFile, error) {
+39 -41
View File
@@ -4,7 +4,6 @@ import (
"context"
"database/sql"
"errors"
"fmt"
"kontor-api-echo/internal/helpers"
"kontor-api-echo/internal/models"
"log/slog"
@@ -25,18 +24,21 @@ func (repository *MediaLoFiRepository) Import(dtos models.MediaLoFiDTOList) {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaLoFi{ID: dto.ID}
result_existing := repository.db.First(&existing_item)
if result_existing.Error != nil {
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
result := repository.db.Create(&model)
if result.Error != nil {
slog.Info("error during import", "error", result.Error.Error())
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
result := repository.db.Save(&model)
if result.Error != nil {
slog.Info("error during updating", "error", result.Error.Error())
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -48,41 +50,37 @@ func NewMediaLoFiRepository(db *bun.DB) *MediaLoFiRepository {
}
func (repository *MediaLoFiRepository) FindAll(context context.Context) ([]models.MediaLoFi, error) {
var lofis []models.MediaLoFi
var models []models.MediaLoFi
err := repository.db.NewSelect().Model(&lofis).Scan(context)
err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("MediaLoFiRepository#FindAll", "count", len(lofis))
slog.Info("MailRepository#FindAll", "count", len(models))
return lofis, nil
return models, nil
}
func (repository *MediaLoFiRepository) GetById(context context.Context, id string) (*models.MediaLoFi, error) {
var lofi = models.MediaLoFi{ID: id}
var model = models.MediaLoFi{ID: id}
slog.Info("MediaLoFiRepository#GetById", "id", id)
err := repository.db.NewSelect().Model(&lofi).Where("id = ?", id).Scan(context)
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("MediaLoFiRepository#GetById", "error", err.Error())
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return &lofi, err
return &model, err
}
func (repository *MediaLoFiRepository) Add(context context.Context, url string) (*models.MediaLoFi, error) {
slog.Info("MediaLoFiRepository#Add", "url", url)
webLink := helpers.StripUrl(url, "v")
var lofi models.MediaLoFi
search_result := repository.db.Where("url = ?", webLink).First(&lofi)
if search_result.RowsAffected > 0 {
slog.Info("search for existing url", "result", search_result, "lofi", lofi)
return &lofi, nil
}
if errors.Is(search_result.Error, sql.ErrNoRows) {
var model models.MediaLoFi
err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
if errors.Is(err, sql.ErrNoRows) {
slog.Info("MediaLoFiRepository#Add URL not found", "url", webLink)
lofi = models.MediaLoFi{
lofi := models.MediaLoFi{
ID: uuid.NewString(),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
@@ -94,32 +92,32 @@ func (repository *MediaLoFiRepository) Add(context context.Context, url string)
Title: "",
FileName: "",
}
add_result := repository.db.Create(&lofi)
if add_result.Error != nil {
slog.Info("add new MediaLofi", "error", add_result.Error)
return nil, add_result.Error
_, add_error := repository.db.NewInsert().Model(&model).Exec(context)
if add_error != nil {
slog.Info("add new MediaLofi", "error", add_error)
return nil, add_error
}
slog.Info("add new MediaLofi", "lofi", lofi)
return &lofi, nil
} else {
slog.Info("search for existing url", "lofi", model)
return &model, nil
}
if search_result.Error != nil {
return nil, search_result.Error
}
return nil, fmt.Errorf("MediaLoFiRepository#Add unknown error")
}
func (repository *MediaLoFiRepository) Update(context context.Context, update models.MediaLoFiDTO) (*models.MediaLoFi, error) {
slog.Info("MediaLoFiRepository#Update", "lofi", update)
var lofi = models.MediaLoFi{ID: update.ID}
var model = models.MediaLoFi{ID: update.ID}
model.Update(update)
slog.Info("MediaLoFiRepository#Update", "id", update.ID)
result := repository.db.First(&lofi)
if result.Error != nil {
slog.Info("MediaLoFiRepository#Update", "error", result.Error.Error())
return nil, result.Error
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", update.ID).
Exec(context)
if err != nil {
slog.Info("MediaLoFiRepository#Update", "error", err.Error())
}
lofi.Update(update)
repository.db.Save(&lofi)
return &lofi, nil
return &model, nil
}
func (repository *MediaLoFiRepository) Delete(context context.Context, id string) error {
+48 -44
View File
@@ -4,13 +4,13 @@ import (
"context"
"database/sql"
"errors"
"fmt"
"kontor-api-echo/internal/helpers"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/google/uuid"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -24,18 +24,21 @@ func (repository *MediaMusicRepository) Import(dtos models.MediaMusicDTOList) {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaMusic{ID: dto.ID}
result_existing := repository.db.First(&existing_item)
if result_existing.Error != nil {
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
result := repository.db.Create(&model)
if result.Error != nil {
slog.Info("error during import", "error", result.Error.Error())
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
result := repository.db.Save(&model)
if result.Error != nil {
slog.Info("error during updating", "error", result.Error.Error())
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -47,36 +50,37 @@ func NewMediaMusicRepository(db *bun.DB) *MediaMusicRepository {
}
func (repository *MediaMusicRepository) FindAll(context context.Context) ([]models.MediaMusic, error) {
var musics []models.MediaMusic
var models []models.MediaMusic
result := repository.db.Find(&musics)
slog.Info("MediaMusicRepository#FindAll", "count", result.RowsAffected)
err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("MailRepository#FindAll", "count", len(models))
return musics, nil
return models, nil
}
func (repository *MediaMusicRepository) GetById(context context.Context, id string) (*models.MediaMusic, error) {
var music = models.MediaMusic{ID: id}
var model = models.MediaMusic{ID: id}
slog.Info("MediaMusicRepository#GetById", "id", id)
result := repository.db.First(&music)
if result.Error != nil {
slog.Info("MediaMusicRepository#GetById", "error", result.Error.Error())
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return &music, result.Error
return &model, err
}
func (repository *MediaMusicRepository) Add(context context.Context, url string) (*models.MediaMusic, error) {
slog.Info("MediaMusicRepository#Add", "url", url)
webLink := helpers.StripUrl(url, "v")
var music models.MediaMusic
search_result := repository.db.Where("url = ?", webLink).First(&music)
if search_result.RowsAffected > 0 {
slog.Info("search for existing url", "result", search_result, "music", music)
return &music, nil
}
if errors.Is(search_result.Error, sql.ErrNoRows) {
var model models.MediaMusic
err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
if errors.Is(err, sql.ErrNoRows) {
slog.Info("MediaMusicRepository#Add URL not found", "url", webLink)
music = models.MediaMusic{
music := models.MediaMusic{
ID: uuid.NewString(),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
@@ -88,32 +92,32 @@ func (repository *MediaMusicRepository) Add(context context.Context, url string)
Title: "",
FileName: "",
}
add_result := repository.db.Create(&music)
if add_result.Error != nil {
slog.Info("add new MediaMusic", "error", add_result.Error)
return nil, add_result.Error
_, add_error := repository.db.NewInsert().Model(&model).Exec(context)
if add_error != nil {
slog.Info("add new MediaMusic", "error", add_error)
return nil, add_error
}
slog.Info("add new MediaMusic", "music", music)
slog.Info("add new MediaMusic", "lofi", music)
return &music, nil
} else {
slog.Info("search for existing url", "lofi", model)
return &model, nil
}
if search_result.Error != nil {
return nil, search_result.Error
}
return nil, fmt.Errorf("MediaMusicRepository#Add unknown error")
}
func (repository *MediaMusicRepository) Update(context context.Context, update models.MediaMusicDTO) (*models.MediaMusic, error) {
slog.Info("MediaMusicRepository#Update", "music", update)
var music = models.MediaMusic{ID: update.ID}
slog.Info("MediaMusicRepository#Update", "id", update.ID)
result := repository.db.First(&music)
if result.Error != nil {
slog.Info("MediaMusicRepository#Update", "error", result.Error.Error())
return nil, result.Error
var model = models.MediaMusic{ID: update.ID}
model.Update(update)
slog.Info("MediaLoFiRepository#Update", "id", update.ID)
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", update.ID).
Exec(context)
if err != nil {
slog.Info("MediaLoFiRepository#Update", "error", err.Error())
}
music.Update(update)
repository.db.Save(&music)
return &music, nil
return &model, nil
}
func (repository *MediaMusicRepository) Delete(context context.Context, id string) error {
+35 -36
View File
@@ -2,10 +2,14 @@ package repository
import (
"context"
"database/sql"
"errors"
"kontor-api-echo/internal/helpers"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/google/uuid"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -68,42 +72,37 @@ func (repository *MediaVideoRepository) GetById(context context.Context, id stri
return &video, nil
}
// func (repository *MediaVideoRepository) Add(context context.Context, url string) (*models.MediaVideo, error) {
// slog.Info("MediaVideoRepository#Add", "url", url)
// webLink := helpers.StripUrl(url, "v")
// var video models.MediaVideo
// search_result := repository.db.Where("url = ?", webLink).First(&video)
// if search_result.RowsAffected > 0 {
// slog.Info("search for existing url", "result", search_result, "video", video)
// return &video, nil
// }
// if errors.Is(search_result.Error, sql.ErrNoRows) {
// slog.Info("MediaVideoRepository#Add URL not found", "url", webLink)
// video = models.MediaVideo{
// ID: uuid.NewString(),
// CreatedAt: time.Now(),
// UpdatedAt: time.Now(),
// DeletedAt: nil,
// Version: 0,
// WebLink: webLink,
// ShouldDownload: false,
// Review: true,
// Title: "",
// FileName: "",
// }
// add_result := repository.db.Create(&video)
// if add_result.Error != nil {
// slog.Info("add new MediaVideo", "error", add_result.Error)
// return nil, add_result.Error
// }
// slog.Info("add new MediaVideo", "music", video)
// return &video, nil
// }
// if search_result.Error != nil {
// return nil, search_result.Error
// }
// return nil, fmt.Errorf("MediaVideoRepository#Add unknown error")
// }
func (repository *MediaVideoRepository) Add(context context.Context, url string) (*models.MediaVideo, error) {
slog.Info("MediaVideoRepository#Add", "url", url)
webLink := helpers.StripUrl(url, "v")
var model models.MediaVideo
err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
if errors.Is(err, sql.ErrNoRows) {
slog.Info("MediaMusicRepository#Add URL not found", "url", webLink)
video := models.MediaVideo{
ID: uuid.NewString(),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
DeletedAt: nil,
Version: 0,
WebLink: webLink,
ShouldDownload: false,
Review: true,
Title: "",
FileName: "",
}
_, add_error := repository.db.NewInsert().Model(&model).Exec(context)
if add_error != nil {
slog.Info("add new MediaMusic", "error", add_error)
return nil, add_error
}
slog.Info("add new MediaMusic", "lofi", video)
return &video, nil
} else {
slog.Info("search for existing url", "lofi", model)
return &model, nil
}
}
func (repository *MediaVideoRepository) Update(context context.Context, update models.MediaVideoDTO) (*models.MediaVideo, error) {
slog.Info("MediaVideoRepository#Update", "video", update)
+2 -1
View File
@@ -31,9 +31,10 @@ func (repository *ProfileRepository) FindAll(context context.Context) ([]models.
return profiles, nil
}
func (repository *ProfileRepository) FindProfileByEmail(context context.Context, email string) (*models.Profile, error) {
func (repository *ProfileRepository) FindProfileByEmail(email string) (*models.Profile, error) {
var profile models.Profile
slog.Info("MediaArticleRepository#GetById", "email", email)
context := context.Background()
err := repository.db.NewSelect().Model(&profile).Where("email = ?", email).Scan(context)
if err != nil {
+70
View File
@@ -0,0 +1,70 @@
package repository
import (
"context"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
type TokenRepository struct {
db *bun.DB
}
func (repository *TokenRepository) Import(dtos models.TokenDTOList) {
slog.Info("TokenRepository#Import")
for index, dto := range dtos {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.Token{ID: dto.ID}
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
if err != nil {
slog.Info("check existing id: not found - inserting")
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
if err != nil {
slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
_, err := repository.db.NewUpdate().Model(&model).
Set("updated_at = ? ", time.Now).
Where("id = ?", model.ID).
Exec(context.Background())
if err != nil {
slog.Info("error during updating", "error", err.Error())
}
}
}
}
func NewTokenRepository(db *bun.DB) *TokenRepository {
repository := &TokenRepository{db: db}
return repository
}
func (repository *TokenRepository) FindAll(context context.Context) ([]models.Token, error) {
var models []models.Token
err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
slog.Info("MailRepository#FindAll", "count", len(models))
return models, nil
}
func (repository *TokenRepository) GetById(context context.Context, id string) (*models.Token, error) {
var model = models.Token{ID: id}
slog.Info("TokenRepository#GetById", "id", id)
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
return &model, err
}
+130 -10
View File
@@ -1,34 +1,154 @@
package router
import (
"html/template"
"io"
"kontor-api-echo/assets"
"kontor-api-echo/internal/config"
"kontor-api-echo/internal/handlers"
"kontor-api-echo/templates"
"log/slog"
"os"
echojwt "github.com/labstack/echo-jwt/v5"
"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
)
type Template struct {
templates *template.Template
}
func (t *Template) Render(c *echo.Context, w io.Writer, name string, data any) error {
return t.templates.ExecuteTemplate(w, name, data)
}
func New(admin *handlers.AdminHandler, media *handlers.MediaHandler) *echo.Echo {
e := echo.New()
skipper := func(c *echo.Context) bool {
// Skip health check endpoint
return c.Request().URL.Path == "/health"
}
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
e.Use(middleware.Recover())
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
LogStatus: true,
LogURI: true,
LogStatus: true,
HandleError: true,
Skipper: skipper,
Skipper: func(c *echo.Context) bool {
// Skip health check endpoint
return c.Path() == "/health"
},
LogValuesFunc: func(c *echo.Context, v middleware.RequestLoggerValues) error {
if v.Error == nil {
slog.Info("REQUEST", "uri", v.URI, "status", v.Status)
} else {
slog.Info("REQUEST-ERROR", "uri", v.URI, "status", v.Status, "err", v.Error.Error())
if v.Error != nil {
logger.Error("request failed", "uri", v.URI, "status", v.Status, "error", v.Error)
return nil
}
logger.Info("request", "uri", v.URI, "status", v.Status)
return nil
},
}))
e.StaticFS("/public", echo.MustSubFS(assets.StaticFiles, "assets"))
templ := template.Must(template.New("").ParseFS(templates.TemplateFiles, "layouts/*.html", "pages/*.html"))
t := &Template{
templates: templ,
}
e.Renderer = t
e.GET("/health", handlers.Health)
e.GET("/", handlers.Index)
e.GET("/login", admin.AuthHandler.LoginPage)
e.POST("/login", admin.AuthHandler.LoginPost)
e.GET("/logout", admin.AuthHandler.LogoutPage)
mediaGroup := e.Group("/media")
//mediaGroup.Use(middleware.AuthRequired())
mediaGroup.GET("/actors", media.MediaActorHandler.ListPage)
mediaGroup.GET("/actors/:id", media.MediaActorHandler.EditPage)
mediaGroup.POST("/actors/:id", media.MediaActorHandler.UpdatePage)
mediaGroup.GET("/articles", media.MediaArticleHandler.ListPage)
mediaGroup.GET("/files", media.MediaFileHandler.ListPage)
mediaGroup.GET("/files/edit/:id", media.MediaFileHandler.EditPage)
mediaGroup.POST("/files/edit/:id", media.MediaFileHandler.UpdatePage)
mediaGroup.GET("/files/delete/:id", media.MediaFileHandler.DeletePage)
mediaGroup.GET("/videos", media.MediaVideoHandler.ListPage)
mediaGroup.GET("/videos/edit/:id", media.MediaVideoHandler.EditPage)
mediaGroup.POST("/videos/edit/:id", media.MediaVideoHandler.UpdatePage)
mediaGroup.GET("/videos/delete/:id", media.MediaVideoHandler.DeletePage)
mediaGroup.GET("/lofis", media.MediaLoFiHandler.ListPage)
mediaGroup.GET("/lofis/edit", media.MediaLoFiHandler.EditPage)
mediaGroup.GET("/lofis/edit/:id", media.MediaLoFiHandler.EditPage)
mediaGroup.POST("/lofis/edit/:id", media.MediaLoFiHandler.UpdatePage)
mediaGroup.GET("/lofis/review/:id", media.MediaLoFiHandler.ChangeReviewPage)
mediaGroup.GET("/lofis/delete/:id", media.MediaLoFiHandler.DeletePage)
mediaGroup.GET("/musics", media.MediaMusicHandler.ListPage)
mediaGroup.GET("/musics/edit/:id", media.MediaMusicHandler.EditPage)
mediaGroup.POST("/musics/edit/:id", media.MediaMusicHandler.UpdatePage)
mediaGroup.GET("/musics/delete/:id", media.MediaMusicHandler.DeletePage)
api := e.Group("/api")
api.POST("/login", admin.AuthHandler.Login)
v1 := api.Group("/v1")
{
secured := v1.Group("")
secured.Use(echojwt.WithConfig(echojwt.Config{SigningKey: config.ServerConfig.ApiSecret}))
//secured.Use(middleware.JWT(admin.Secret))
// secured.GET("admin/mailaccounts", admin.MailAccountHandler.List)
// secured.GET("user/profiles", admin.ProfileHandler.List)
// secured.GET("user/permissions", admin.PermissionHandler.List)
// secured.GET("user/assignments", admin.AssignmentHandler.List)
// secured.GET("user/mails", admin.MailHandler.List)
// secured.GET("user/tokens", admin.TokenHandler.List)
// secured.GET("tysc/sports", tysc.SportHandler.List)
// secured.GET("tysc/sports/:id", tysc.SportHandler.Get)
// secured.GET("tysc/players", tysc.PlayerHandler.List)
// secured.GET("tysc/teams", tysc.TeamHandler.List)
// secured.GET("tysc/positions", tysc.PositionHandler.List)
// secured.GET("tysc/roosters", tysc.RoosterHandler.List)
// secured.GET("tysc/vendors", tysc.VendorHandler.List)
// secured.GET("tysc/cardsets", tysc.CardSetHandler.List)
// secured.GET("tysc/cards", tysc.CardHandler.List)
// secured.GET("bookshelf/articles", bookshelf.ArticleHandler.List)
// secured.GET("bookshelf/publishers", bookshelf.BookshelfPublisherHandler.List)
// secured.GET("bookshelf/books", bookshelf.BookHandler.List)
// secured.GET("bookshelf/authors", bookshelf.AuthorHandler.List)
// secured.GET("bookshelf/articleauthors", bookshelf.ArticleAuthorHandler.List)
// secured.GET("bookshelf/bookauthors", bookshelf.BookAuthorHandler.List)
// secured.GET("comics/comics", comics.ComicHandler.List)
// secured.GET("comics/publishers", comics.PublisherHandler.List)
// secured.GET("comics/artists", comics.ArtistHandler.List)
// secured.GET("comics/issues", comics.IssueHandler.List)
// secured.GET("comics/tradepaperbacks", comics.TradePaperbackHandler.List)
// secured.GET("comics/worktypes", comics.WorkTypeHandler.List)
// secured.GET("comics/volumes", comics.VolumeHandler.List)
// secured.GET("comics/storyarcs", comics.StoryArcHandler.List)
// secured.GET("comics/comicworks", comics.ComicworkHandler.List)
// secured.GET("comics/issueworks", comics.IssueworkHandler.List)
mediaGroup := secured.Group("media")
mediaGroup.GET("/files", media.MediaFileHandler.List)
mediaGroup.POST("/files", media.MediaFileHandler.Add)
// mediaGroup.GET("/videos", media.MediaVideoHandler.List)
// mediaGroup.GET("/lofis", media.MediaLoFiHandler.List)
// mediaGroup.POST("/lofis", media.MediaLoFiHandler.Add)
// mediaGroup.GET("/lofis/:id", media.MediaLoFiHandler.Get)
// mediaGroup.POST("/lofis/:id", media.MediaLoFiHandler.Update)
// mediaGroup.DELETE("/lofis/:id", media.MediaLoFiHandler.Delete)
// mediaGroup.POST("/musics", media.MediaMusicHandler.Add)
// mediaGroup.GET("/musics/:id", media.MediaMusicHandler.Get)
// mediaGroup.POST("/musics/:id", media.MediaMusicHandler.Update)
// mediaGroup.DELETE("/musics/:id", media.MediaMusicHandler.Delete)
// mediaGroup.GET("/actors", media.MediaActorHandler.List)
// mediaGroup.POST("/actors", media.MediaActorHandler.Add)
// mediaGroup.GET("/actors/:id", media.MediaActorHandler.Get)
// mediaGroup.DELETE("/actors/:id", media.MediaActorHandler.Delete)
// mediaGroup.GET("/actorfiles", media.MediaActorFileHandler.List)
// mediaGroup.POST("/actorfiles", media.MediaActorFileHandler.Add)
// mediaGroup.DELETE("/actorfiles", media.MediaActorFileHandler.Delete)
}
return e
}
+1 -1
View File
@@ -21,7 +21,7 @@ func (service *AssignmentService) List(context context.Context) ([]models.Assign
return service.repository.FindAll(context)
}
func (service *AssignmentService) Get(context context.Context, id string) (models.Assignment, error) {
func (service *AssignmentService) Get(context context.Context, id string) (*models.Assignment, error) {
slog.Info("AssignmentService#Get")
return service.repository.GetById(context, id)
}
+47
View File
@@ -0,0 +1,47 @@
package service
import (
"kontor-api-echo/internal/helpers"
"kontor-api-echo/internal/repository"
"golang.org/x/crypto/bcrypt"
)
type AuthService struct {
repository *repository.ProfileRepository
}
func NewAuthService(repository *repository.ProfileRepository) *AuthService {
service := &AuthService{repository: repository}
return service
}
func VerifyPassword(password, hashedPassword string) error {
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
}
func (service *AuthService) LoginCheck(email string, password string) (string, error) {
var err error
profile, err := service.repository.FindProfileByEmail(email)
if err != nil {
return "", err
}
err = VerifyPassword(password, profile.Password)
if err != nil && err == bcrypt.ErrMismatchedHashAndPassword {
return "", err
}
token, err := helpers.GenerateToken(profile.ID)
if err != nil {
return "", err
}
return token, nil
}
+27
View File
@@ -0,0 +1,27 @@
package service
import (
"context"
"kontor-api-echo/internal/models"
"kontor-api-echo/internal/repository"
"log/slog"
)
type MailService struct {
repository *repository.MailRepository
}
func NewMailService(repo *repository.MailRepository) *MailService {
service := &MailService{repository: repo}
return service
}
func (service *MailService) List(context context.Context) ([]models.Mail, error) {
slog.Info("MailService#List")
return service.repository.FindAll(context)
}
func (service *MailService) Get(context context.Context, id string) (*models.Mail, error) {
slog.Info("MailService#Get")
return service.repository.GetById(context, id)
}
@@ -0,0 +1,27 @@
package service
import (
"context"
"kontor-api-echo/internal/models"
"kontor-api-echo/internal/repository"
"log/slog"
)
type MailAccountService struct {
repository *repository.MailAccountRepository
}
func NewMailAccountService(repo *repository.MailAccountRepository) *MailAccountService {
service := &MailAccountService{repository: repo}
return service
}
func (service *MailAccountService) List(context context.Context) ([]models.MailAccount, error) {
slog.Info("MailAccountService#List")
return service.repository.FindAll(context)
}
func (service *MailAccountService) Get(context context.Context, id string) (*models.MailAccount, error) {
slog.Info("MailAccountService#Get")
return service.repository.GetById(context, id)
}
+27
View File
@@ -0,0 +1,27 @@
package service
import (
"context"
"kontor-api-echo/internal/models"
"kontor-api-echo/internal/repository"
"log/slog"
)
type TokenService struct {
repository *repository.TokenRepository
}
func NewTokenService(repo *repository.TokenRepository) *TokenService {
service := &TokenService{repository: repo}
return service
}
func (service *TokenService) List(context context.Context) ([]models.Token, error) {
slog.Info("TokenService#List")
return service.repository.FindAll(context)
}
func (service *TokenService) Get(context context.Context, id string) (*models.Token, error) {
slog.Info("TokenService#Get")
return service.repository.GetById(context, id)
}