83 lines
2.0 KiB
Go
83 lines
2.0 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
|
|
grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
|
|
"github.com/hhhapz/codequest/models"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
type ContextKey string
|
|
|
|
const (
|
|
UserKey ContextKey = "ctxUser"
|
|
TokenKey ContextKey = "ctxToken"
|
|
)
|
|
|
|
func AuthInterceptor(authFunc grpc_auth.AuthFunc) grpc.UnaryServerInterceptor {
|
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
|
var err error
|
|
if overrideSrv, ok := info.Server.(grpc_auth.ServiceAuthFuncOverride); ok {
|
|
method := strings.LastIndex(info.FullMethod, "/")
|
|
ctx, err = overrideSrv.AuthFuncOverride(ctx, info.FullMethod[method+1:])
|
|
} else {
|
|
ctx, err = authFunc(ctx)
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return handler(ctx, req)
|
|
}
|
|
}
|
|
|
|
func (as AuthService) defaultAuthFunc(ctx context.Context) (context.Context, error) {
|
|
return BearerAuth(ctx, as.userStore)
|
|
}
|
|
|
|
func BearerAuth(ctx context.Context, us UserStore) (context.Context, error) {
|
|
token, err := grpc_auth.AuthFromMD(ctx, "Bearer")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
u, err := us.UserByToken(ctx, token)
|
|
if err != nil {
|
|
if errors.As(err, &models.UserError{}) {
|
|
return nil, status.Error(codes.Unauthenticated, err.Error())
|
|
}
|
|
return nil, status.Errorf(codes.Internal, "could not authenticate your request")
|
|
}
|
|
|
|
ctx = context.WithValue(ctx, UserKey, u)
|
|
ctx = context.WithValue(ctx, TokenKey, token)
|
|
|
|
return ctx, nil
|
|
}
|
|
|
|
func AdminOnly(ctx context.Context) (context.Context, error) {
|
|
u := User(ctx)
|
|
if u == nil {
|
|
return nil, status.Errorf(codes.Unauthenticated, "user not found")
|
|
}
|
|
|
|
if !u.Admin {
|
|
return nil, status.Errorf(codes.PermissionDenied, "access denied: user is not admin")
|
|
}
|
|
return ctx, nil
|
|
}
|
|
|
|
func User(ctx context.Context) *models.User {
|
|
u, _ := ctx.Value(UserKey).(*models.User)
|
|
return u
|
|
}
|
|
|
|
func Token(ctx context.Context) string {
|
|
t, _ := ctx.Value(TokenKey).(string)
|
|
return t
|
|
}
|