Skip to content

Conversation

@IgorShadurin
Copy link
Member

Overview

This PR implements a daily limit of 10 AI usages per user for the "Fill with AI" feature. The system uses a cryptographic challenge-response mechanism to verify the user's identity and track usage accurately.

Features Implemented

  • Added database fields to track AI usage and challenges
  • Created backend endpoints for challenge generation and verification
  • Updated frontend to handle challenge signing and usage tracking
  • Added UI elements to display remaining usage and reset time
  • Implemented daily usage reset at midnight UTC

Technical Details

  • Added migration to add AI usage tracking fields to users table
  • Created AiUsageService to handle challenge generation and verification
  • Updated AI endpoints to require challenge verification
  • Added frontend API functions for challenge handling
  • Updated CreateAppModal to display usage information

Testing

  • Tested with manual verification of challenge signing
  • Verified usage limits are enforced correctly
  • Confirmed daily reset functionality works as expected

Closes #13

@IgorShadurin
Copy link
Member Author

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR introduces a daily limit for AI usages, incorporating a cryptographic challenge-response mechanism. The changes span database migrations, backend endpoints, and frontend updates. Overall, the implementation appears well-structured, but there are several areas that could benefit from closer scrutiny and refinement, particularly around error handling and security.

Summary of Findings

  • Error Handling in AI Routes: The error handling in the AI routes could be improved to provide more specific feedback to the user. Consider adding more context to the error messages to aid in debugging.
  • Inconsistent Error Responses: The AI routes have inconsistent error responses. Some routes return 401 for authentication failures, while others return 500 for internal server errors. Standardizing these responses would improve the API's usability.
  • Missing Input Validation: The AiUsageService lacks input validation for the address parameter in the generateChallenge and verifyChallenge methods. This could lead to unexpected behavior or security vulnerabilities.

Merge Readiness

The pull request introduces significant functionality and requires careful review before merging. Several comments highlight areas where error handling, input validation, and security measures could be improved. It is recommended that these issues be addressed before merging. I am unable to approve this pull request, and others should review and approve this code before merging.

Comment on lines +42 to +48
async generateChallenge(address: string): Promise<string> {
// Get user from database
const user = await this.db<UserWithAi>('users').where({ address }).first()

if (!user) {
throw new Error('User not found')
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Consider adding input validation for the address parameter to ensure it is a valid Ethereum address. This can help prevent unexpected behavior or security vulnerabilities.

    if (!address || !/^0x[a-fA-F0-9]{40}$/.test(address)) {
      throw new Error('Invalid wallet address')
    }

    // Get user from database

Comment on lines +76 to +80
const user = await this.db<UserWithAi>('users').where({ address }).first()

if (!user) {
throw new Error('User not found')
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Consider adding input validation for the address parameter to ensure it is a valid Ethereum address. This can help prevent unexpected behavior or security vulnerabilities.

    if (!address || !/^0x[a-fA-F0-9]{40}$/.test(address)) {
      throw new Error('Invalid wallet address')
    }

    // Get user from database

Comment on lines +61 to 65
console.error('Error generating AI challenge:', error instanceof Error ? error.message : 'Unknown error')
return res.status(500).json({
success: false,
error: 'Missing required fields: prompt and templateId are required',
error: 'Failed to generate challenge',
})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message here is a bit generic. Consider providing more specific feedback to the user about why the challenge generation failed. For example, you could check if the user exists before attempting to generate the challenge and return a more informative error message if the user is not found.

      console.error('Error generating AI challenge:', error instanceof Error ? error.message : 'Unknown error')
      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
      return res.status(500).json({
        success: false,
        error: `Failed to generate challenge: ${errorMessage}`, // More specific error message
      })

Comment on lines +88 to 92
console.error('Error verifying AI challenge:', error instanceof Error ? error.message : 'Unknown error')
return res.status(500).json({
success: false,
error: 'AI service is not available. OPENAI_API_KEY may be missing.',
error: 'Failed to verify challenge',
})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous comment, the error message here is also generic. Consider adding more context to the error message to help the user understand why the challenge verification failed. For example, you could check if the challenge is valid before attempting to verify it and return a more informative error message if the challenge is invalid.

      console.error('Error verifying AI challenge:', error instanceof Error ? error.message : 'Unknown error')
      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
      return res.status(500).json({
        success: false,
        error: `Failed to verify challenge: ${errorMessage}`, // More specific error message
      })

Comment on lines +119 to +123
console.error('Error getting remaining AI requests:', error instanceof Error ? error.message : 'Unknown error')
return res.status(500).json({
success: false,
error: 'Failed to get remaining requests',
})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message here is also generic. Consider adding more context to the error message to help the user understand why getting the remaining AI requests failed. For example, you could check if the user exists before attempting to get the remaining requests and return a more informative error message if the user is not found.

      console.error('Error getting remaining AI requests:', error instanceof Error ? error.message : 'Unknown error')
      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
      return res.status(500).json({
        success: false,
        error: `Failed to get remaining requests: ${errorMessage}`, // More specific error message
      })

Comment on lines +183 to +186
return res.status(403).json({
success: false,
error: 'Challenge verification failed',
})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Returning a 403 status code here might not be the most appropriate choice. A 403 status code typically indicates that the server understands the request but refuses to authorize it. In this case, the user is authorized, but they have exceeded their daily usage limit. A more appropriate status code might be 429 (Too Many Requests).

          return res.status(429).json({
            success: false,
            error: 'Daily AI usage limit reached',
            data: {
              remaining_attempts: verificationResult.remaining_attempts,
              max_attempts: verificationResult.max_attempts,
            },
          })

@DappyKit DappyKit deleted a comment from gemini-code-assist bot Mar 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Implement Daily AI Usage Limit with Cryptographic Challenge Verification

2 participants