ERC721 NFT transfer controller in the receiving contract

Hey guys, I have a smart contract that is used to accept NFTs, but I'd like to ask the users to transfer their NFTs to this contract by calling a specific function, not directly or in any other way. I'm wondering if there is a controller on the receiving contract.

Here is my current approach. In this contract, in the onERC721Received function, I added a bool flag variable to control access. Only when the function that is desired to be called can set this variable true. A direct transfer by safeTransferFrom would fail since once the NFT contract calls onERC721Received, the transaction will revert.

   function DoSth() external {
          require(!flag, "not allowed");
          flag = true;
          INFT(contractAddr).safeTransferFrom(owner, address(this), tokenId);
    }

    function onERC721Received(address from, address to, uint256 tokenId, bytes memory data) external returns (bytes4) {
        require(flag, "Not allowed");
        flag = false;
        return IERC721Receiver.onERC721Received.selector;
    }

Besides, this approach is useful when the transfer is made through the safeTransferFrom function, I have not figured out a way of prevent a transfer made by calling the transferFrom function. Any idea about this?

There is no way to prevent transfers using transferFrom, so you can't rely on this mechanism to control the NFTs that you receive.

If you still want to do this, you could reject tokens transferred using safeTransferFrom, and in your DoSth function use transferFrom in order to bypass the check, without the need of any flags.