This commit is contained in:
r8zavetr8v 2024-05-11 00:18:56 +03:00
parent 9f3b54ab51
commit b32bc780d6
3 changed files with 101 additions and 47 deletions
backend
README.md
internal
interface/rest
pkg/ctxmeta

View File

@ -109,39 +109,6 @@ Response:
}
```
## POST **/join**
### Request body:
name (string, optional)
credentals (object, optional)
credentals.email (string, optional)
credentals.phone (string, optional)
credentals.telegram (string, optional)
mnemonic (string, **required**)
### Example
Request:
``` bash
curl --location 'http://localhost:8081/login' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Bladee The Grand Drainer",
"credentals": {
"email": "bladeee@gmail.com",
"phone": "+79999999999",
"telegram": "@thebladee"
},
"mnemonic":"airport donate language disagree dumb access insect tribe ozone humor foot jealous much digital confirm"
}'
```
Response:
``` json
{
"token": "token-here"
}
```
## POST **/organization**
### Request body:
name (string, **required**)

View File

@ -6,13 +6,16 @@ import (
"fmt"
"log/slog"
"net/http"
"strings"
"sync"
"time"
"github.com/emochka2007/block-accounting/internal/interface/rest/controllers"
"github.com/emochka2007/block-accounting/internal/pkg/config"
"github.com/emochka2007/block-accounting/internal/pkg/ctxmeta"
"github.com/emochka2007/block-accounting/internal/pkg/logger"
"github.com/emochka2007/block-accounting/internal/pkg/metrics"
"github.com/emochka2007/block-accounting/internal/usecase/interactors/jwt"
"github.com/go-chi/chi/v5"
mw "github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/render"
@ -29,6 +32,8 @@ type Server struct {
tls bool
controllers *controllers.RootController
jwt jwt.JWTInteractor
closeMu sync.RWMutex
closed bool
}
@ -89,23 +94,27 @@ func (s *Server) buildRouter() {
router.Post("/join", s.handle(s.controllers.Auth.Join, "join"))
router.Post("/login", s.handle(s.controllers.Auth.Login, "login"))
router.Post("/organization", s.handle(s.controllers.Auth.Invite, "organization"))
router.Route("/organization", func(r chi.Router) {
r.With(s.withAuthorization)
router.Route("/organization/{organization_id}", func(r chi.Router) {
router.Route("/transactions", func(r chi.Router) {
r.Get("/", nil) // list
r.Post("/", nil) // add
r.Put("/{tx_id}", nil) // update / approve (or maybe body?)
r.Delete("/{tx_id}", nil) // remove
})
r.Get("/", s.handle(s.controllers.Auth.Invite, "organization"))
r.Post("/invite/{hash}", s.handle(s.controllers.Auth.Invite, "invite")) // create a new invite link
r.Route("/{organization_id}", func(r chi.Router) {
r.Route("/transactions", func(r chi.Router) {
r.Get("/", nil) // list
r.Post("/", nil) // add
r.Put("/{tx_id}", nil) // update / approve (or maybe body?)
r.Delete("/{tx_id}", nil) // remove
})
r.Route("/employees", func(r chi.Router) {
r.Get("/", nil) // list
r.Post("/", nil) // add
r.Put("/{employee_id}", nil) // update (or maybe body?)
r.Delete("/{employee_id}", nil) // remove
r.Post("/invite/{hash}", s.handle(s.controllers.Auth.Invite, "invite")) // create a new invite link
r.Route("/employees", func(r chi.Router) {
r.Get("/", nil) // list
r.Post("/", nil) // add
r.Put("/{employee_id}", nil) // update (or maybe body?)
r.Delete("/{employee_id}", nil) // remove
})
})
})
@ -173,3 +182,41 @@ func (s *Server) handleMw(next http.Handler) http.Handler {
return http.HandlerFunc(fn)
}
func (s *Server) withAuthorization(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
tokenStringRaw := r.Header.Get("Authorization")
if tokenStringRaw == "" {
s.log.Warn(
"unauthorized request",
slog.String("remote_addr", r.RemoteAddr),
slog.String("endpoint", r.RequestURI),
)
w.WriteHeader(401)
return
}
tokenString := strings.Split(tokenStringRaw, " ")[1]
user, err := s.jwt.User(tokenString)
if err != nil {
s.log.Warn(
"unauthorized request",
slog.String("remote_addr", r.RemoteAddr),
slog.String("endpoint", r.RequestURI),
logger.Err(err),
)
s.responseError(w, err)
return
}
next.ServeHTTP(w, r.WithContext(
ctxmeta.UserContext(r.Context(), user),
))
}
return http.HandlerFunc(fn)
}

View File

@ -0,0 +1,40 @@
package ctxmeta
import (
"context"
"fmt"
"github.com/emochka2007/block-accounting/internal/pkg/models"
"github.com/google/uuid"
)
type ContextKey string
var (
UserContextKey = ContextKey("user")
OrganizationIdContextKey = ContextKey("org-id")
)
func UserContext(parent context.Context, user *models.User) context.Context {
return context.WithValue(parent, UserContextKey, user)
}
func User(ctx context.Context) (*models.User, error) {
if user, ok := ctx.Value(UserContextKey).(*models.User); ok {
return user, nil
}
return nil, fmt.Errorf("error user not passed in context")
}
func OrganizationIdContext(parent context.Context, id uuid.UUID) context.Context {
return context.WithValue(parent, OrganizationIdContextKey, id)
}
func OrganizationId(ctx context.Context) (uuid.UUID, error) {
if id, ok := ctx.Value(OrganizationIdContextKey).(uuid.UUID); ok {
return id, nil
}
return uuid.Nil, fmt.Errorf("error organization id not passed in context")
}