Do more things through main web stuff instead of API
This commit is contained in:
@@ -14,7 +14,7 @@ type IDStruct interface {
|
||||
}
|
||||
|
||||
type Table[T IDStruct] interface {
|
||||
Get(ctx context.Context, ID string) (data *T, err error)
|
||||
Get(ctx context.Context, ID string) (data T, err error)
|
||||
Find(ctx context.Context, values map[string]any) ([]T, error)
|
||||
Insert(ctx context.Context, data T) error
|
||||
Remove(ctx context.Context, ID string) error
|
||||
|
||||
@@ -18,16 +18,16 @@ func NewMongoTable[T backend.IDStruct](col *mongo.Collection) *MongoTable[T] {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MongoTable[T]) Get(ctx context.Context, ID string) (data *T, err error) {
|
||||
func (m *MongoTable[T]) Get(ctx context.Context, ID string) (data T, err error) {
|
||||
res := m.col.FindOne(ctx, bson.M{"_id": ID})
|
||||
if res.Err() == mongo.ErrNoDocuments {
|
||||
return nil, backend.ErrNotFound
|
||||
return data, backend.ErrNotFound
|
||||
} else if res.Err() != nil {
|
||||
return nil, res.Err()
|
||||
return data, res.Err()
|
||||
}
|
||||
var out T
|
||||
err = res.Decode(&out)
|
||||
return &out, err
|
||||
return out, err
|
||||
}
|
||||
|
||||
func (m *MongoTable[T]) Find(ctx context.Context, values map[string]any) ([]T, error) {
|
||||
|
||||
+11
-36
@@ -7,8 +7,6 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -64,41 +62,18 @@ func (b *Backend) ParseHeader(r *http.Request) (*ParsedHeader, error) {
|
||||
}
|
||||
out.Key = &keys[0]
|
||||
}
|
||||
token := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
|
||||
if token != "" && b.userTable != nil {
|
||||
t, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
|
||||
return b.jwtPub, nil
|
||||
}, jwt.WithIssuer("darkstorm.tech"), jwt.WithExpirationRequired(), jwt.WithValidMethods([]string{"EdDSA"}))
|
||||
if err != nil {
|
||||
return out, errors.Join(ErrTokenUnauthorized, err)
|
||||
}
|
||||
exp, _ := t.Claims.GetExpirationTime()
|
||||
if exp.Time.Before(time.Now()) {
|
||||
return out, ErrTokenUnauthorized
|
||||
}
|
||||
sub, err := t.Claims.GetSubject()
|
||||
if err == jwt.ErrInvalidKey {
|
||||
return out, ErrTokenUnauthorized
|
||||
} else if err != nil {
|
||||
return out, errors.Join(ErrTokenUnauthorized, err)
|
||||
}
|
||||
usr, err := b.userTable.Get(r.Context(), sub)
|
||||
if err == jwt.ErrInvalidKey {
|
||||
return out, ErrTokenUnauthorized
|
||||
} else if err != nil {
|
||||
return out, errors.Join(ErrTokenUnauthorized, err)
|
||||
}
|
||||
iss, err := t.Claims.GetIssuedAt()
|
||||
if err == jwt.ErrInvalidKey {
|
||||
return out, ErrTokenUnauthorized
|
||||
} else if err != nil {
|
||||
return out, errors.Join(ErrTokenUnauthorized, err)
|
||||
}
|
||||
if usr.PasswordChange > 0 && iss.Time.Before(time.Unix(usr.PasswordChange, 0)) {
|
||||
return out, ErrTokenUnauthorized
|
||||
}
|
||||
out.User = usr.toReqUser()
|
||||
if b.userTable == nil || r.Header.Get("Authorization") == "" {
|
||||
return out, nil
|
||||
}
|
||||
token := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
|
||||
if token == "" {
|
||||
return out, nil
|
||||
}
|
||||
usr, err := b.VerifyUser(r.Context(), token)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
out.User = usr.ToReqUser()
|
||||
return out, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,41 @@ func (b *Backend) TryLogin(ctx context.Context, username, password string) (User
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (b *Backend) VerifyUser(ctx context.Context, token string) (*User, error) {
|
||||
t, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
|
||||
return b.jwtPub, nil
|
||||
}, jwt.WithIssuer("darkstorm.tech"), jwt.WithExpirationRequired(), jwt.WithValidMethods([]string{"EdDSA"}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exp, _ := t.Claims.GetExpirationTime()
|
||||
if exp.Time.Before(time.Now()) {
|
||||
return nil, ErrTokenUnauthorized
|
||||
}
|
||||
sub, err := t.Claims.GetSubject()
|
||||
if err == jwt.ErrInvalidKey {
|
||||
return nil, ErrTokenUnauthorized
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
usr, err := b.userTable.Get(ctx, sub)
|
||||
if err == jwt.ErrInvalidKey {
|
||||
return nil, ErrTokenUnauthorized
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iss, err := t.Claims.GetIssuedAt()
|
||||
if err == jwt.ErrInvalidKey {
|
||||
return nil, ErrTokenUnauthorized
|
||||
} else if err != nil {
|
||||
return nil, errors.Join(ErrTokenUnauthorized, err)
|
||||
}
|
||||
if usr.PasswordChange > 0 && iss.Time.Before(time.Unix(usr.PasswordChange, 0)) {
|
||||
return nil, ErrTokenUnauthorized
|
||||
}
|
||||
return usr, nil
|
||||
}
|
||||
|
||||
func NewUser(username, password, email string) (User, error) {
|
||||
id, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
@@ -115,7 +150,7 @@ func (u User) GetID() string {
|
||||
return u.ID
|
||||
}
|
||||
|
||||
func (u User) toReqUser() *ReqestUser {
|
||||
func (u User) ToReqUser() *ReqestUser {
|
||||
return &ReqestUser{
|
||||
Perm: u.Perm,
|
||||
ID: u.ID,
|
||||
@@ -205,7 +240,7 @@ func (b *Backend) createUser(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
var ret createUserReturn
|
||||
ret.Username = u.Username
|
||||
ret.Token, err = b.GenerateJWT(u.toReqUser())
|
||||
ret.Token, err = b.GenerateJWT(u.ToReqUser())
|
||||
if err != nil {
|
||||
log.Println("error generating token:", err)
|
||||
ReturnError(w, http.StatusInternalServerError, "internal", "Server error")
|
||||
@@ -264,7 +299,7 @@ func (b *Backend) login(w http.ResponseWriter, r *http.Request) {
|
||||
var ret loginReturn
|
||||
u, err := b.TryLogin(r.Context(), req.Username, req.Password)
|
||||
if err == nil {
|
||||
ret.Token, err = b.GenerateJWT(u.toReqUser())
|
||||
ret.Token, err = b.GenerateJWT(u.ToReqUser())
|
||||
if err != nil {
|
||||
ReturnError(w, http.StatusInternalServerError, "internal", "Server error")
|
||||
return
|
||||
@@ -272,7 +307,7 @@ func (b *Backend) login(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
if err == ErrLoginTimeout {
|
||||
ret.Error = "timeout"
|
||||
ret.ErrorMsg = fmt.Sprint("Timed out for", u.Timeout, "seconds")
|
||||
ret.ErrorMsg = fmt.Sprint("Timed out for", time.Unix(u.Timeout, 0).Sub(time.Now()), "seconds")
|
||||
ret.Timeout = u.Timeout
|
||||
} else {
|
||||
ret.Error = "incorrect"
|
||||
|
||||
Reference in New Issue
Block a user