Skip to content

Conversation

@rajdip-b
Copy link
Member

@rajdip-b rajdip-b commented Oct 19, 2025

PR Type

Enhancement


Description

  • Add comprehensive CLI commands to manage personal access tokens (PAT)

    • Create, list, update, delete, and regenerate PAT operations
  • Improve PAT expiry handling to support tokens that never expire

    • Allow expiresAfterDays value of 0 for non-expiring tokens
  • Refactor session and token response types for nullable fields

    • Make lastUsedOn and expiresOn nullable across session and token models
  • Extract common PAT utilities into reusable helper module

    • Centralize PAT selection menu and input prompts in PatUtils
  • Clean up user service by removing bootstrap initialization methods

    • Remove dummy user and admin user creation from application startup

Diagram Walkthrough

flowchart LR
  A["CLI PAT Commands"] -->|create| B["Create PAT"]
  A -->|list| C["List PAT"]
  A -->|update| D["Update PAT"]
  A -->|delete| E["Delete PAT"]
  A -->|regenerate| F["Regenerate PAT"]
  B -->|uses| G["PatUtils"]
  D -->|uses| G
  E -->|uses| G
  F -->|uses| G
  G -->|calls| H["PersonalAccessTokenController"]
  H -->|manages| I["PAT API Endpoints"]
  I -->|supports| J["Never-expire tokens"]
Loading

File Walkthrough

Relevant files
Enhancement
20 files
pat.command.ts
New PAT command with subcommands                                                 
+26/-0   
create.pat.ts
Implement interactive PAT creation command                             
+15/-7   
list.pat.ts
Add PAT listing with verbose option                                           
+56/-16 
update.pat.ts
Implement PAT update with interactive mode                             
+125/-0 
delete.pat.ts
Add PAT deletion with confirmation prompt                               
+17/-44 
regenerate.pat.ts
Implement PAT regeneration with confirmation                         
+78/-0   
pat.ts
Create PAT utility functions for reuse                                     
+76/-0   
controller-instance.ts
Add PersonalAccessTokenController instance                             
+14/-0   
index.ts
Register PAT command and reorder commands                               
+5/-3     
create.pat.ts
Allow zero expiry days for non-expiring tokens                     
+1/-1     
personal-access-token.service.ts
Handle zero expiry for never-expiring tokens                         
+10/-3   
user.types.ts
Update PAT response type with nullable fields                       
+3/-2     
session.types.ts
Make lastUsedOn nullable in session responses                       
+2/-2     
personal-access-token.ts
Create PersonalAccessTokenController for API                         
+79/-0   
index.ts
Export PersonalAccessTokenController                                         
+3/-1     
index.ts
Define PAT request and response schemas                                   
+50/-0   
index.types.ts
Export PAT TypeScript type definitions                                     
+56/-0   
index.ts
Export personal access token schemas                                         
+1/-0     
index.types.ts
Export personal access token types                                             
+1/-0     
schema.prisma
Make lastUsedOn nullable in token models                                 
+12/-12 
Bug fix
1 files
token.service.ts
Validate expiry days greater than zero                                     
+4/-3     
Miscellaneous
1 files
user.service.ts
Remove bootstrap initialization methods                                   
+0/-78   
Documentation
1 files
CHANGELOG.md
Document new PAT command features                                               
+12/-1   
Configuration changes
1 files
package.json
Bump version to 3.6.0-stage.1                                                       
+1/-1     
Formatting
2 files
init.command.ts
Sort imports and simplify variable assignment                       
+2/-3     
date-formatter.ts
Improve function signature formatting                                       
+3/-1     
Additional files
1 files
index.ts +2/-2     

@codiumai-pr-agent-free
Copy link
Contributor

codiumai-pr-agent-free bot commented Oct 19, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
- [ ] Create ticket/issue <!-- /create_ticket --create_ticket=true -->

</details></td></tr>
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
No custom compliance provided

Follow the guide to enable custom compliance check.

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@codiumai-pr-agent-free
Copy link
Contributor

codiumai-pr-agent-free bot commented Oct 19, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Remove environment-specific logic from application code

Instead of deleting the environment-specific user creation logic
(checkIfAdminExistsOrCreate, createDummyUser), move it from UserService to a
dedicated seeding script or test setup fixture.

Examples:

apps/api/src/user/service/user.service.ts [31-555]
export class UserService {
  private readonly log = new Logger(UserService.name)

  constructor(
    private readonly prisma: PrismaService,
    private readonly cache: UserCacheService,
    @Inject(MAIL_SERVICE) private readonly mailService: IMailService,
    private readonly slugGenerator: SlugGenerator,
    private readonly hydrationService: HydrationService,
    private readonly workspaceCacheService: WorkspaceCacheService

 ... (clipped 515 lines)

Solution Walkthrough:

Before:

// apps/api/src/user/service/user.service.ts
@Injectable()
export class UserService {
  constructor(...) {}

  async onApplicationBootstrap() {
    await this.checkIfAdminExistsOrCreate()
    await this.createDummyUser()
  }

  // ... other methods

  private async createDummyUser() {
    if (process.env.NODE_ENV === 'e2e') {
      // ... logic to create a dummy user
    }
  }

  private async checkIfAdminExistsOrCreate() {
    // ... logic to create an admin user if one doesn't exist
  }
}

After:

// apps/api/src/user/service/user.service.ts
@Injectable()
export class UserService {
  constructor(...) {}

  // onApplicationBootstrap and helper methods are removed.
  
  async getSelf(...) { ... }
  // ... other business logic methods
}

// prisma/seed.ts (conceptual new file)
async function main() {
  if (process.env.NODE_ENV === 'development') {
    await createAdminUserIfNotExists();
  }
  if (process.env.NODE_ENV === 'test') {
    await createDummyUser();
  }
}
Suggestion importance[1-10]: 8

__

Why: This is a strong architectural suggestion that improves maintainability by separating environment-specific setup from core application logic, which is a best practice.

Medium
Possible issue
Improve token expiration update logic

Refactor the token expiration logic by changing the type of expiresOn to Date |
null | undefined and using typeof to check dto.expiresAfterDays to prevent
potential runtime errors and fix a type mismatch.

apps/api/src/user/service/personal-access-token.service.ts [68-75]

-let expiresOn: Date | undefined
-if (dto.expiresAfterDays !== undefined) {
+let expiresOn: Date | null | undefined
+if (typeof dto.expiresAfterDays === 'number') {
   if (dto.expiresAfterDays === 0) {
     expiresOn = null // Never expires
   } else {
     expiresOn = dayjs().add(dto.expiresAfterDays, 'days').toDate()
   }
 }
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a type error and a potential runtime error if dto.expiresAfterDays is null, providing a robust fix for the newly added logic.

Medium
General
Handle non-numeric input for expiry

In readExpiresAfterDays, add a check for NaN after parsing the user input for
the expiry duration. Return undefined for invalid non-numeric input to prevent
sending NaN to the API.

apps/cli/src/util/pat.ts [66-75]

 readExpiresAfterDays: async (): Promise<number | undefined> => {
     const expiry = await text({
-      message: 'Enter the new expiry for the token',
+      message: 'Enter the new expiry for the token (in days, 0 for no expiry)',
       placeholder: '30'
     })
 
     handleSIGINT(expiry, 'Update cancelled!')
 
-    return expiry ? parseInt((expiry as string).trim()) : undefined
+    if (!expiry) {
+      return undefined
+    }
+
+    const parsedExpiry = parseInt((expiry as string).trim())
+    return !isNaN(parsedExpiry) ? parsedExpiry : undefined
   }
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly points out that parseInt can return NaN for non-numeric input, and provides a good improvement to handle this case gracefully, enhancing the robustness of the CLI's interactive mode.

Low
Handle invalid expiration input gracefully

In the parseOptions method, add a check to handle NaN results from parseInt on
the expiresAfterDays option. Return null if the input is non-numeric to prevent
API validation errors.

apps/cli/src/commands/pat/create.pat.ts [114-117]

+const parsedExpiresAfterDays = expiresAfterDays
+  ? parseInt(expiresAfterDays)
+  : null
+
 return {
   name,
-  expiresAfterDays: expiresAfterDays ? parseInt(expiresAfterDays) : null
+  expiresAfterDays:
+    parsedExpiresAfterDays === null || isNaN(parsedExpiresAfterDays)
+      ? null
+      : parsedExpiresAfterDays
 }
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that parseInt can return NaN from command-line arguments, which would cause an API error. The proposed change adds necessary validation to handle this case.

Low
  • Update

@rajdip-b rajdip-b merged commit 0473463 into develop Oct 19, 2025
9 of 10 checks passed
@rajdip-b rajdip-b deleted the feat/pat branch October 19, 2025 14:36
rajdip-b pushed a commit that referenced this pull request Oct 19, 2025
## [2.41.0-stage.1](v2.40.1-stage.1...v2.41.0-stage.1) (2025-10-19)

### 🚀 Features

* **cli:** ability to manage pat ([#1213](#1213)) ([0473463](0473463))
@rajdip-b
Copy link
Member Author

🎉 This PR is included in version 2.41.0-stage.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

rajdip-b pushed a commit that referenced this pull request Oct 23, 2025
## [2.41.0](v2.40.0...v2.41.0) (2025-10-23)

### 🚀 Features

* **cli:** ability to manage pat ([#1213](#1213)) ([0473463](0473463))
* **cli:** add `keyshade reset` command to wipe local profiles ([#1206](#1206)) ([229557a](229557a))
* **cli:** improved keyshade import flow ([#1219](#1219)) ([5affb52](5affb52))
* **platform:** add search functionality to integrations page ([#1184](#1184)) ([83b0374](83b0374))

### 🐛 Bug Fixes

* resolve hero image overlap with [secure] section text ([#1161](#1161)) ([3b1d4b6](3b1d4b6))

### 📚 Documentation

* add new internals pages for [secure], variable and env creation + cli docs for [secure] and variables ([#1208](#1208)) ([2bd595d](2bd595d))
* revamp getting started ([#1221](#1221)) ([e683fd6](e683fd6))
* Update image link in README.md ([adf7761](adf7761))

### 🔧 Miscellaneous Chores

* **cli:** bump CLI to v3.6.0 ([267469a](267469a))
* **release:** 2.36.0-stage.2 [skip ci] ([14aedf9](14aedf9))
* **release:** 2.40.1-stage.1 [skip ci] ([f0c296d](f0c296d))
* **release:** 2.41.0-stage.1 [skip ci] ([59fdbe3](59fdbe3))
* **release:** 2.41.0-stage.2 [skip ci] ([4d5ee50](4d5ee50))
* **release:** 2.41.0-stage.3 [skip ci] ([f2ca012](f2ca012))
* **release:** 2.41.0-stage.4 [skip ci] ([7a4e1fb](7a4e1fb))
@rajdip-b
Copy link
Member Author

🎉 This PR is included in version 2.41.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant