package v1 import ( "context" "errors" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers" tokens "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/tokens/v1" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" ) // var _ tokens.TokensServiceServer = (*TokensServer)(nil) type TokensServer struct { tokens.UnimplementedTokensServiceServer tokenCtrl *controllers.TokenController authorizationCtrl *controllers.AuthController } func NewTokensServer( tokenCtrl *controllers.TokenController, authorizationCtrl *controllers.AuthController, ) *TokensServer { return &TokensServer{ tokenCtrl: tokenCtrl, authorizationCtrl: authorizationCtrl, } } // CreateToken implements [v1.TokensServiceServer]. func (srv *TokensServer) CreateToken(ctx context.Context, in *tokens.CreateTokenRequest) (*tokens.CreateTokenResponse, error) { claims, err := srv.authorizationCtrl.ClaimsFromContext(ctx) if err != nil { return nil, status.Error(codes.Aborted, "Context is invalid") } if claims.UserID == "" { return nil, status.Error(codes.Aborted, "Context is invalid") } if in.TokenPermissions == nil { return nil, status.Error(codes.InvalidArgument, "Permissions must be set") } permissions := map[string][]string{} for service, methods := range in.TokenPermissions.Permissions { permissions[service] = methods.GetMethods() } tokenData := &controllers.TokenData{ Name: in.TokenMetadata.GetName(), UserID: claims.UserID, Scopes: permissions, } token, err := srv.tokenCtrl.Create(ctx, tokenData) if err != nil { if errors.Is(err, controllers.ErrServerError) { return nil, status.Error(codes.Internal, "Something is broken on our side") } return nil, status.Error(codes.Aborted, "Couldn't create a token") } return &tokens.CreateTokenResponse{ TokenValue: &tokens.TokenValue{Token: token}, }, nil } // ForceTokenExpiration implements [v1.TokensServiceServer]. func (t *TokensServer) ForceTokenExpiration(context.Context, *tokens.ForceTokenExpirationRequest) (*emptypb.Empty, error) { return nil, status.Error(codes.Unimplemented, "Method is not implemented") } // GetToken implements [v1.TokensServiceServer]. func (t *TokensServer) GetToken(context.Context, *tokens.GetTokenRequest) (*tokens.GetTokenResponse, error) { return nil, status.Error(codes.Unimplemented, "Method is not implemented") } // ListTokens implements [v1.TokensServiceServer]. func (srv *TokensServer) ListTokens(in *emptypb.Empty, stream grpc.ServerStreamingServer[tokens.ListTokensResponse]) error { claims, err := srv.authorizationCtrl.ClaimsFromContext(stream.Context()) if err != nil { return status.Error(codes.Aborted, "Context is invalid") } if claims.UserID == "" { return status.Error(codes.Aborted, "Context is invalid") } tokensRes, err := srv.tokenCtrl.List(stream.Context(), claims.UserID) if err != nil { if errors.Is(err, controllers.ErrServerError) { return status.Error(codes.Internal, "Something is broken on our side") } return status.Error(codes.Aborted, "Couldn't create a token") } for _, tokenRes := range tokensRes { stream.Send(&tokens.ListTokensResponse{ TokenUuid: &tokens.TokenUUID{ Uuid: tokenRes.UUID, }, TokenMetadata: &tokens.TokenMetadata{ Name: tokenRes.Name, ExpiresAt: timestamppb.New(tokenRes.ExpiresAt), }, }) } return status.Error(codes.Unimplemented, "Method is not implemented") } // RegenerateToken implements [v1.TokensServiceServer]. func (t *TokensServer) RegenerateToken(context.Context, *tokens.RegenerateTokenRequest) (*tokens.RegenerateTokenResponse, error) { return nil, status.Error(codes.Unimplemented, "Method is not implemented") } // UpdateToken implements [v1.TokensServiceServer]. func (t *TokensServer) UpdateToken(context.Context, *tokens.UpdateTokenRequest) (*tokens.UpdateTokenResponse, error) { return nil, status.Error(codes.Unimplemented, "Method is not implemented") } // ListPermissions implements [v1.TokensServiceServer]. func (srv *TokensServer) ListPermissions(in *emptypb.Empty, stream grpc.ServerStreamingServer[tokens.ListPermissionsResponse]) error { data := srv.tokenCtrl.ListPermissions(stream.Context()) for key, data := range data { result := &tokens.ListPermissionsResponse{ Permissions: &tokens.TokenPermissions{ Permissions: map[string]*tokens.MethodList{ key: {Methods: data}, }, }, } if err := stream.Send(result); err != nil { return status.Error(codes.Aborted, "Couldn't send data to the client") } } return nil }