hackathon/api/interceptors.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
}