diff --git a/auth.go b/auth.go new file mode 100644 index 0000000..5591381 --- /dev/null +++ b/auth.go @@ -0,0 +1,71 @@ +package main + +import ( + "crypto/rand" + "myproject/tools" + "net/http" + "strings" + + "github.com/gorilla/sessions" + "github.com/labstack/echo/v4" +) + +func NewAuthStore() *sessions.CookieStore { + auth := make([]byte, 32) + _, _ = rand.Read(auth) + enc := make([]byte, 16) + _, _ = rand.Read(enc) + s := sessions.NewCookieStore(auth, enc) + s.Options.Secure = false + s.Options.SameSite = http.SameSiteDefaultMode + s.MaxAge(3600) + return s +} + +func setAuth(onlyAdmin bool, g *echo.Group) *echo.Group { + g.Use( + func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + sess, err := c.Get("authStore").(*sessions.CookieStore).New(c.Request(), tools.SessionName) + if err != nil { + // journal.Debug(ctx, commerr.Trace(err).Error()) + } + + userName := sess.Values[tools.UserNameSessionKey] + if userName == nil { + return echo.ErrUnauthorized + } + + email, lp, domain := SplitEmail(userName.(string)) + c.Set(tools.UserCtxKey, email) + c.Set(tools.LpCtxKey, lp) + c.Set(tools.DomainCtxKey, domain) + + return next(c) + } + }, + func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if onlyAdmin && tools.GetUser(c) != "admin" { + return echo.ErrUnauthorized + } + + return next(c) + } + }, + ) + + return g +} + +func SplitEmail(toSplit string) (email, user, domain string) { + email = strings.TrimSpace(toSplit) + email = strings.ToLower(email) + parts := strings.Split(email, "@") + user = parts[0] + if len(parts) > 1 { + domain = parts[1] + } + + return +} diff --git a/echo.go b/echo.go new file mode 100644 index 0000000..ecfccde --- /dev/null +++ b/echo.go @@ -0,0 +1,98 @@ +package main + +import ( + "context" + "fmt" + "myproject/tools" + "net" + "net/http" + "strings" + "time" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" +) + +func NewEcho(ctx context.Context, restartMode *bool) *echo.Echo { + timeout := 5 * time.Minute + e := echo.New() + e.HideBanner = true + e.Server.ReadTimeout = timeout + e.Server.WriteTimeout = timeout + e.Server.BaseContext = func(listener net.Listener) context.Context { + return ctx + } + e.HTTPErrorHandler = func(err error, c echo.Context) { + httpError, ok := err.(*echo.HTTPError) + if ok { + errorCode := httpError.Code + switch errorCode { + case http.StatusServiceUnavailable: + tools.Serve503(c) + case http.StatusTooManyRequests: + tools.Serve429(c) + case http.StatusForbidden: + tools.Serve403(c) + case http.StatusUnauthorized: + tools.Serve401(c) + case http.StatusNotFound, http.StatusMethodNotAllowed: + if strings.HasPrefix(c.Request().RequestURI, "/backend") { + switch errorCode { + case http.StatusNotFound: + tools.Serve404(c) + case http.StatusMethodNotAllowed: + tools.Serve405(c) + } + return + } + c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/?redirect=%s", c.Request().RequestURI)) + default: + tools.Serve500(c) + } + } + } + + authStore := NewAuthStore() + + e.Use( + middleware.CORSWithConfig(middleware.CORSConfig{ + AllowOrigins: []string{"http://localhost:7777", "http://localhost:8808"}, + AllowHeaders: []string{ + echo.HeaderOrigin, + echo.HeaderContentType, + echo.HeaderAccept, + echo.HeaderAccessControlAllowOrigin, + echo.HeaderAccessControlAllowCredentials, + echo.HeaderAccessControlAllowHeaders, + echo.HeaderAccessControlRequestHeaders, + echo.HeaderAuthorization, + }, + AllowCredentials: true, + }), + middleware.GzipWithConfig(middleware.GzipConfig{ + Level: 6, + }), + func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + c.Set("authStore", authStore) + + return next(c) + } + }, + func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + + return next(c) + } + }, + func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + c.Set(tools.RootCtxKey, ctx) + + return next(c) + } + }, + ) + + return e +} diff --git a/frontend/.env.development b/frontend/.env.development new file mode 100644 index 0000000..1bb4252 --- /dev/null +++ b/frontend/.env.development @@ -0,0 +1 @@ +VITE_API_URL=http://localhost:8888 \ No newline at end of file diff --git a/frontend/.env.production b/frontend/.env.production new file mode 100644 index 0000000..3452b5c --- /dev/null +++ b/frontend/.env.production @@ -0,0 +1 @@ +VITE_API_URL= \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..a52d458 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,29 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/frontend/README.md b/frontend/README.md index 98f4a52..74e1fcc 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,23 +1,33 @@ -# Vue 3 + TypeScript + Vite +# js -This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue -3 ` -
+ + ++
+ + + +
+ +