Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PLA-1872] Beam packs #89

Closed
wants to merge 17 commits into from
Closed

Conversation

enjinabner
Copy link
Contributor

@enjinabner enjinabner commented Jul 29, 2024

PR Type

Enhancement, Tests


Description

  • Added BeamPack model with necessary attributes and relationships.
  • Created migrations for beam_packs table and updated existing tables to support BeamPack.
  • Added GraphQL mutations for creating, updating, adding tokens to, and removing tokens from BeamPack.
  • Updated validation rules and messages to support BeamPack.
  • Added tests for BeamPack related functionalities.
  • Updated BeamService to handle BeamPack operations.

Changes walkthrough 📝

Relevant files
Enhancement
27 files
BeamPackFactory.php
Add BeamPack factory with default state definition             

database/factories/BeamPackFactory.php

  • Added a factory for the BeamPack model.
  • Defined default state for BeamPack.
  • +28/-0   
    2024_07_01_011034_add_is_pack_column_to_beams_table.php
    Add `is_pack` column to beams table                                           

    database/migrations/2024_07_01_011034_add_is_pack_column_to_beams_table.php

  • Added migration to include is_pack column in beams table.
  • Defined up and down methods for migration.
  • +27/-0   
    2024_07_01_020155_create_beam_packs_table.php
    Create `beam_packs` table migration                                           

    database/migrations/2024_07_01_020155_create_beam_packs_table.php

  • Created migration for beam_packs table.
  • Defined columns and constraints for beam_packs.
  • +31/-0   
    2024_07_01_020426_add_beam_pack_id_to_beam_claims_table.php
    Add `beam_pack_id` column to beam_claims table                     

    database/migrations/2024_07_01_020426_add_beam_pack_id_to_beam_claims_table.php

  • Added migration to include beam_pack_id column in beam_claims table.
  • Updated indexes and constraints.
  • +30/-0   
    BeamServiceProvider.php
    Register migrations for beam packs                                             

    src/BeamServiceProvider.php

    • Registered new migrations for beam packs.
    +3/-0     
    AddTokensBeamPackMutation.php
    Add mutation for adding tokens to beam pack                           

    src/GraphQL/Mutations/AddTokensBeamPackMutation.php

  • Added mutation for adding tokens to a beam pack.
  • Defined attributes, arguments, and resolve method.
  • +95/-0   
    CreateBeamPackMutation.php
    Add mutation for creating beam pack                                           

    src/GraphQL/Mutations/CreateBeamPackMutation.php

  • Added mutation for creating a beam pack.
  • Defined attributes, arguments, and resolve method.
  • +102/-0 
    RemoveTokensBeamPackMutation.php
    Add mutation for removing tokens from beam pack                   

    src/GraphQL/Mutations/RemoveTokensBeamPackMutation.php

  • Added mutation for removing tokens from a beam pack.
  • Defined attributes, arguments, and resolve method.
  • +92/-0   
    UpdateBeamPackMutation.php
    Add mutation for updating beam pack                                           

    src/GraphQL/Mutations/UpdateBeamPackMutation.php

  • Added mutation for updating a beam pack.
  • Defined attributes, arguments, and resolve method.
  • +110/-0 
    GetSingleUseCodesQuery.php
    Update query to return union type for single use codes     

    src/GraphQL/Queries/GetSingleUseCodesQuery.php

  • Updated query to return a union type for single use codes.
  • Adjusted resolve method to handle beam packs.
  • +8/-2     
    HasBeamPackCommonRules.php
    Add common validation rules for beam packs                             

    src/GraphQL/Traits/HasBeamPackCommonRules.php

    • Added trait for common beam pack validation rules.
    +89/-0   
    BeamPackType.php
    Add GraphQL type for BeamPack                                                       

    src/GraphQL/Types/BeamPackType.php

    • Added GraphQL type for BeamPack.
    • Defined fields and attributes.
    +74/-0   
    BeamPackInputType.php
    Add input type for BeamPack                                                           

    src/GraphQL/Types/Input/BeamPackInputType.php

    • Added input type for BeamPack.
    • Defined fields and attributes.
    +36/-0   
    RemovesBeamPackInputType.php
    Add input type for removing BeamPack                                         

    src/GraphQL/Types/Input/RemovesBeamPackInputType.php

  • Added input type for removing BeamPack.
  • Defined fields and attributes.
  • +36/-0   
    ClaimUnion.php
    Add union type for claims                                                               

    src/GraphQL/Unions/ClaimUnion.php

  • Added union type for claims.
  • Defined possible types and resolve method.
  • +41/-0   
    ClaimBeam.php
    Update ClaimBeam job to handle beam packs                               

    src/Jobs/ClaimBeam.php

  • Updated job to handle beam packs.
  • Adjusted claim logic and attributes.
  • +32/-11 
    DispatchCreateBeamClaimsJobs.php
    Update DispatchCreateBeamClaimsJobs to handle beam packs 

    src/Jobs/DispatchCreateBeamClaimsJobs.php

  • Updated job to handle beam pack IDs.
  • Adjusted claim creation logic.
  • +7/-3     
    BeamPack.php
    Add BeamPack model with relationships                                       

    src/Models/BeamPack.php

    • Added BeamPack model.
    • Defined relationships and attributes.
    +7/-0     
    Beam.php
    Add `is_pack` attribute and BeamPack relationship to Beam model

    src/Models/Laravel/Beam.php

    • Added is_pack attribute and relationship to BeamPack.
    +9/-0     
    BeamClaim.php
    Add BeamPack relationship to BeamClaim model                         

    src/Models/Laravel/BeamClaim.php

    • Added relationship to BeamPack.
    • Removed redundant methods.
    +7/-40   
    BeamPack.php
    Add BeamPack model with relationships                                       

    src/Models/Laravel/BeamPack.php

    • Added BeamPack model with relationships and attributes.
    +136/-0 
    HasSingleUseCodeScope.php
    Add single use code scope methods                                               

    src/Models/Laravel/Traits/HasSingleUseCodeScope.php

    • Added single use code scope methods.
    +29/-0   
    BeamPackExistInBeam.php
    Add validation rule for BeamPack existence in Beam             

    src/Rules/BeamPackExistInBeam.php

    • Added validation rule to check if BeamPack exists in Beam.
    +43/-0   
    CanUseOnBeam.php
    Add validation rule for operations on Beam                             

    src/Rules/CanUseOnBeam.php

    • Added validation rule to check if operation can be used on Beam.
    +26/-0   
    CanUseOnBeamPack.php
    Add validation rule for operations on BeamPack                     

    src/Rules/CanUseOnBeamPack.php

  • Added validation rule to check if operation can be used on BeamPack.
  • +26/-0   
    SingleUseCodeExist.php
    Update SingleUseCodeExist rule for BeamPack                           

    src/Rules/SingleUseCodeExist.php

    • Updated rule to handle single use codes for BeamPack.
    +10/-6   
    BeamService.php
    Add BeamPack handling methods to BeamService                         

    src/Services/BeamService.php

  • Added methods to handle BeamPack creation, updates, and token
    management.
  • Updated existing methods to support BeamPack.
  • +185/-27
    Documentation
    3 files
    input_type.php
    Add descriptions for beam pack fields in input types         

    lang/en/input_type.php

  • Added descriptions for beam pack fields and remove beam pack input
    type.
  • +3/-0     
    mutation.php
    Add descriptions for beam pack mutations                                 

    lang/en/mutation.php

    • Added descriptions for beam pack related mutations.
    +4/-0     
    validation.php
    Add validation messages for beam pack rules                           

    lang/en/validation.php

    • Added validation messages for beam pack related rules.
    +3/-0     
    Tests
    9 files
    AddPackTokensTest.php
    Add tests for AddTokensBeamPack mutation                                 

    tests/Feature/GraphQL/Mutations/AddPackTokensTest.php

    • Added tests for adding tokens to BeamPack.
    +205/-0 
    CreateBeamPackTest.php
    Add tests for CreateBeamPack mutation                                       

    tests/Feature/GraphQL/Mutations/CreateBeamPackTest.php

    • Added tests for creating BeamPack.
    +402/-0 
    UpdateBeamPackTest.php
    Add tests for UpdateBeamPack mutation                                       

    tests/Feature/GraphQL/Mutations/UpdateBeamPackTest.php

    • Added tests for updating BeamPack.
    +504/-0 
    CreateBeamData.php
    Update CreateBeamData trait for BeamPack                                 

    tests/Feature/Traits/CreateBeamData.php

    • Updated trait to generate BeamPack data.
    +2/-2     
    SeedBeamData.php
    Update SeedBeamData trait for BeamPack                                     

    tests/Feature/Traits/SeedBeamData.php

    • Updated trait to seed BeamPack data.
    +30/-0   
    AddTokensBeamPack.graphql
    Add GraphQL mutation for AddTokensBeamPack                             

    tests/Feature/GraphQL/Resources/AddTokensBeamPack.graphql

    • Added GraphQL mutation for adding tokens to BeamPack.
    +3/-0     
    CreateBeamPack.graphql
    Add GraphQL mutation for CreateBeamPack                                   

    tests/Feature/GraphQL/Resources/CreateBeamPack.graphql

    • Added GraphQL mutation for creating BeamPack.
    +21/-0   
    GetSingleUseCodes.graphql
    Update GraphQL query for single use codes to include BeamPack

    tests/Feature/GraphQL/Resources/GetSingleUseCodes.graphql

    • Updated GraphQL query to include BeamPack in single use codes.
    +14/-4   
    UpdateBeamPack.graphql
    Add GraphQL mutation for UpdateBeamPack                                   

    tests/Feature/GraphQL/Resources/UpdateBeamPack.graphql

    • Added GraphQL mutation for updating BeamPack.
    +21/-0   

    💡 PR-Agent usage:
    Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    Copy link

    PR Reviewer Guide 🔍

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Key issues to review

    Code Complexity
    The BeamService class has multiple new methods added (createPack, updatePackByCode, removeBeamPack, etc.), increasing its responsibilities and complexity. Consider refactoring by splitting responsibilities into more specialized service classes or helpers.

    Validation Logic
    The mutation uses a direct DB transaction in the resolve method which might not handle all edge cases or validation errors effectively before attempting to write to the database. Consider moving or extending validation logic to service layers or using form request validation.

    Data Integrity
    The BeamPack model allows mass assignment on all fields ($guarded is empty). This could lead to mass assignment vulnerabilities. Consider defining $fillable properties explicitly.

    Test Coverage
    The test methods in UpdateBeamPackTest are extensive but might be testing multiple behaviors in single test methods. Consider breaking them down into more focused tests to improve test clarity and isolation.

    Copy link

    github-actions bot commented Jul 29, 2024

    PR Code Suggestions ✨

    CategorySuggestion                                                                                                                                    Score
    Performance
    Add an index to the 'is_pack' column to enhance query performance

    Consider adding an index to the 'is_pack' column to improve query performance,
    especially if you will be querying frequently based on this column.

    database/migrations/2024_07_01_011034_add_is_pack_column_to_beams_table.php [14]

    -$table->boolean('is_pack')->default(false);
    +$table->boolean('is_pack')->default(false)->index();
     
    Suggestion importance[1-10]: 9

    Why: Adding an index to the 'is_pack' column can significantly improve query performance, especially if queries frequently filter by this column. This is a valuable optimization.

    9
    Improve string replacement efficiency and readability

    Replace the string concatenation with a more efficient method using strtr for better
    readability and performance.

    src/GraphQL/Traits/HasBeamPackCommonRules.php [48]

    -str_replace('attributes', 'type', $attribute)
    +strtr($attribute, ['attributes' => 'type'])
     
    Suggestion importance[1-10]: 7

    Why: The suggestion to use strtr instead of str_replace is valid for improving readability and potentially performance. However, the improvement is minor and not critical to the functionality.

    7
    Simplify the array merging process to enhance readability and performance

    The method loadClaims uses a complex and potentially inefficient way to merge arrays
    and filter data. Simplifying this method can improve readability and performance.

    src/Models/Laravel/BeamPack.php [114-122]

    -$with = array_merge(
    -    $with,
    -    static::getRelationQuery(
    -        BeamPackType::class,
    -        $relation,
    -        $fields,
    -        $key,
    -        $with
    -    )
    +$with[] = static::getRelationQuery(
    +    BeamPackType::class,
    +    $relation,
    +    $fields,
    +    $key,
    +    $with
     );
     
    Suggestion importance[1-10]: 6

    Why: This suggestion improves code readability and performance by simplifying the array merging process. While beneficial, it addresses a minor issue compared to security concerns.

    6
    Enhancement
    Enhance validation by specifying a maximum value for token quantity per claim

    Use a more specific validation rule for tokenQuantityPerClaim to ensure the value is
    not only an integer but also within a reasonable range.

    src/GraphQL/Traits/HasBeamPackCommonRules.php [83-84]

     'integer',
    -'min:1'
    +'between:1,1000'
     
    Suggestion importance[1-10]: 9

    Why: Adding a maximum value for tokenQuantityPerClaim enhances validation and ensures that the value stays within a reasonable range, which is important for maintaining data integrity.

    9
    Improve the precision of response validation in test methods

    Consider using a more specific assertion than assertTrue for the $response in the
    test methods. This will help ensure that the response not only evaluates to true but
    also matches expected values or conditions more precisely.

    tests/Feature/GraphQL/Mutations/AddPackTokensTest.php [45]

    -$this->assertTrue($response);
    +$this->assertIsArray($response);
    +$this->assertNotEmpty($response);
     
    Suggestion importance[1-10]: 8

    Why: The suggestion improves the precision of the test assertions by ensuring that the response is not only true but also has the expected structure and content, enhancing test reliability and robustness.

    8
    Security
    Validate or sanitize input used in dynamic SQL query construction to prevent SQL injection

    The loadClaims method uses a dynamic query construction based on the $fields array,
    which includes a conditional spread operator for adding 'code' and 'nonce'. This can
    lead to unpredictable query behavior and potential SQL injection if not properly
    sanitized. It is recommended to validate or sanitize $fields before using them to
    construct SQL queries.

    src/Models/Laravel/BeamPack.php [84-90]

    +$validatedFields = array_intersect_key($fields, array_flip(['qr', 'nonce'])); // Only allow specific keys
     $select = array_filter([
         'id',
         'beam_id',
    -    ...(isset($fields['qr']) ? ['code'] : []),
    +    ...(isset($validatedFields['qr']) ? ['code'] : []),
         ...(static::$query == 'GetSingleUseCodes' ? ['code', 'nonce'] : ['nonce']),
    -    ...BeamPackType::getSelectFields($fieldKeys = array_keys($fields)),
    +    ...BeamPackType::getSelectFields($fieldKeys = array_keys($validatedFields)),
     ]);
     
    Suggestion importance[1-10]: 9

    Why: This suggestion addresses a significant security concern by validating or sanitizing input used in dynamic SQL query construction, which can prevent SQL injection attacks. The improved code correctly implements this validation.

    9
    Configure guarded attributes to prevent mass assignment vulnerabilities

    The guarded attribute is set to an empty array, which means all attributes are mass
    assignable. This can lead to mass assignment vulnerabilities. It is safer to
    explicitly define fillable attributes or properly configure guarded attributes.

    src/Models/Laravel/BeamPack.php [28]

    -public $guarded = [];
    +protected $guarded = ['id', 'created_at', 'updated_at']; // protect critical fields
     
    Suggestion importance[1-10]: 8

    Why: This suggestion improves security by configuring the guarded attributes to prevent mass assignment vulnerabilities. The improved code correctly protects critical fields.

    8
    Possible issue
    Ensure safe access to array keys in the response error handling

    Replace the direct array access with a method that checks if the key exists to
    prevent potential errors from undefined indexes when accessing the response error
    details.

    tests/Feature/GraphQL/Mutations/AddPackTokensTest.php [109-111]

    -$this->assertArraySubset([
    -    'packs.0.tokens.0.tokenIds' => ['The packs.0.tokens.0.tokenIds already exist in beam.'],
    -], $response['error']);
    +$this->assertArrayHasKey('error', $response);
    +$this->assertArrayHasKey('packs.0.tokens.0.tokenIds', $response['error']);
    +$this->assertEquals(['The packs.0.tokens.0.tokenIds already exist in beam.'], $response['error']['packs.0.tokens.0.tokenIds']);
     
    Suggestion importance[1-10]: 9

    Why: This suggestion addresses a potential issue with undefined indexes, making the code more robust and preventing possible runtime errors, which is crucial for reliable error handling in tests.

    9
    Data validation
    Validate that each token ID is an integer to ensure data integrity

    Validate the 'tokenIds' input to ensure each ID is a valid integer. This prevents
    invalid data types from being processed.

    src/GraphQL/Mutations/RemoveTokensBeamPackMutation.php [84-88]

     'tokenIds.*' => [
         'bail',
         'filled',
    +    'integer',
         'distinct',
         new TokensExistInBeam(),
     ],
     
    Suggestion importance[1-10]: 8

    Why: Ensuring that each token ID is an integer prevents invalid data types from being processed, which is crucial for maintaining data integrity.

    8
    Ensure the 'end' date is not set in the past to maintain logical consistency

    Add a check to ensure the 'end' date is not in the past, which would be logically
    incorrect for a beam pack update.

    src/GraphQL/Mutations/UpdateBeamPackMutation.php [106]

    -'end' => ['filled', 'date', new IsEndDateValid()],
    +'end' => ['filled', 'date', 'after_or_equal:today', new IsEndDateValid()],
     
    Suggestion importance[1-10]: 8

    Why: Adding a check to ensure the 'end' date is not in the past helps maintain logical consistency and prevents potential errors in the application.

    8
    Maintainability
    Simplify and clarify the conditional prohibition logic

    Use a direct comparison instead of using Rule::prohibitedIf for clarity and to avoid
    potential issues with enum comparisons.

    src/GraphQL/Traits/HasBeamPackCommonRules.php [48]

    -Rule::prohibitedIf(BeamType::getEnumCase(Arr::get($args, str_replace('attributes', 'type', $attribute))) == BeamType::TRANSFER_TOKEN)
    +'prohibited' => BeamType::getEnumCase(Arr::get($args, strtr($attribute, ['attributes' => 'type']))) === BeamType::TRANSFER_TOKEN
     
    Suggestion importance[1-10]: 8

    Why: This suggestion improves maintainability by simplifying the conditional logic and making the code more readable. It also avoids potential issues with enum comparisons.

    8
    Use class constants for column names to improve maintainability

    The method scopeClaimable uses a hard-coded column name 'is_claimed' which can lead
    to errors if the column name changes. Using a class constant for column names can
    make the code more maintainable.

    src/Models/Laravel/BeamPack.php [71]

    -return $query->where('is_claimed', false);
    +const IS_CLAIMED = 'is_claimed';
    +return $query->where(self::IS_CLAIMED, false);
     
    Suggestion importance[1-10]: 7

    Why: This suggestion enhances maintainability by using class constants for column names, reducing the risk of errors if column names change. The improved code correctly implements this change.

    7
    Refactor file upload handling in tests to a separate method to reduce duplication

    Refactor the repeated logic for faking and handling file uploads into a separate
    private method to reduce code duplication and improve maintainability.

    tests/Feature/GraphQL/Mutations/AddPackTokensTest.php [72-79]

    -$file = UploadedFile::fake()->createWithContent('tokens.txt', "1\n2..10");
    -$response = $this->graphql(
    -    $this->method,
    -    [
    -        'code' => $this->beam->code,
    -        'packs' => [['tokens' => [['tokenIdDataUpload' => $file, 'type' => BeamType::MINT_ON_DEMAND->name]]]],
    -    ]
    -);
    +$response = $this->handleFileUploadTest('tokens.txt', "1\n2..10", BeamType::MINT_ON_DEMAND->name);
     
    Suggestion importance[1-10]: 7

    Why: The suggestion enhances code maintainability by reducing duplication, making the test code cleaner and easier to manage. However, it is a minor improvement and does not address any critical issues.

    7
    Refactor complex inline function to a separate method for better code organization

    Refactor the nested Rule::forEach to a separate method to improve code readability
    and maintainability.

    src/GraphQL/Traits/HasBeamPackCommonRules.php [36-50]

    -'packs.*.tokens.*.attributes' => Rule::forEach(function ($value, $attribute) use ($args) {
    -            if (empty($value)) {
    -                return [];
    -            }
    -            return [
    -                'nullable',
    -                'bail',
    -                'array',
    -                'min:1',
    -                'max:10',
    -                new DistinctAttributes(),
    -                Rule::prohibitedIf(BeamType::getEnumCase(Arr::get($args, str_replace('attributes', 'type', $attribute))) == BeamType::TRANSFER_TOKEN),
    -            ];
    -        })
    +'packs.*.tokens.*.attributes' => $this->attributeRules($args)
     
    Suggestion importance[1-10]: 6

    Why: Refactoring the nested Rule::forEach to a separate method improves readability and maintainability. However, the suggestion does not address a critical issue, so the improvement is moderate.

    6
    Best practice
    Use a data provider for varying file upload test cases

    Use a data provider for the test cases that involve different input scenarios to
    streamline the test structure and enhance the reusability of the test setup.

    tests/Feature/GraphQL/Mutations/AddPackTokensTest.php [70-93]

    -public function test_it_can_update_beam_with_file_upload(): void
    +/**
    + * @dataProvider fileUploadProvider
    + */
    +public function test_it_can_update_beam_with_file_upload($fileName, $content, $type): void
     {
    -    $file = UploadedFile::fake()->createWithContent('tokens.txt', "1\n2..10");
    +    $file = UploadedFile::fake()->createWithContent($fileName, $content);
         $response = $this->graphql(
             $this->method,
             [
                 'code' => $this->beam->code,
    -            'packs' => [['tokens' => [['tokenIdDataUpload' => $file, 'type' => BeamType::MINT_ON_DEMAND->name]]]],
    +            'packs' => [['tokens' => [['tokenIdDataUpload' => $file, 'type' => $type]]]],
             ]
         );
         $this->assertTrue($response);
         Event::assertDispatched(TokensAdded::class);
     }
     
    +public function fileUploadProvider()
    +{
    +    return [
    +        ['tokens.txt', "1\n2..10", BeamType::MINT_ON_DEMAND->name],
    +        ['tokens.txt', "{$this->token->token_chain_id}\n{$this->token->token_chain_id}..{$this->token->token_chain_id}", BeamType::TRANSFER_TOKEN->name]
    +    ];
    +}
    +
    Suggestion importance[1-10]: 8

    Why: Using a data provider improves test structure and reusability, making it easier to add new test cases and maintain existing ones. This is a best practice for writing clean and efficient tests.

    8
    Error handling
    Handle exceptions when a beam is not found to improve error handling and user experience

    Add exception handling for the case where the 'Beam::where('code',
    $args['code'])->firstOrFail()' does not find a beam, to prevent server errors and
    provide a user-friendly message.

    src/GraphQL/Mutations/AddTokensBeamPackMutation.php [71]

    -Beam::where('code', $args['code'])->firstOrFail(),
    +Beam::where('code', $args['code'])->firstOrFail() ?? throw new \Exception("Beam not found"),
     
    Suggestion importance[1-10]: 7

    Why: Adding exception handling improves robustness and user experience by providing a clear error message when a beam is not found. However, the suggested code uses a non-standard way to throw an exception in PHP.

    7

    @enjinabner enjinabner closed this Aug 5, 2024
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Development

    Successfully merging this pull request may close these issues.

    1 participant