Conversation
Bumps [simple-git](https://github.com/steveukx/git-js/tree/HEAD/simple-git) from 3.31.1 to 3.32.3. - [Release notes](https://github.com/steveukx/git-js/releases) - [Changelog](https://github.com/steveukx/git-js/blob/main/simple-git/CHANGELOG.md) - [Commits](https://github.com/steveukx/git-js/commits/[email protected]/simple-git) --- updated-dependencies: - dependency-name: simple-git dependency-version: 3.32.3 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <[email protected]>
…git-3.32.3 chore(deps-dev): bump simple-git from 3.31.1 to 3.32.3
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.10 to 7.5.11. - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](isaacs/node-tar@v7.5.10...v7.5.11) --- updated-dependencies: - dependency-name: tar dependency-version: 7.5.11 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]>
Bumps [hono](https://github.com/honojs/hono) from 4.12.5 to 4.12.7. - [Release notes](https://github.com/honojs/hono/releases) - [Commits](honojs/hono@v4.12.5...v4.12.7) --- updated-dependencies: - dependency-name: hono dependency-version: 4.12.7 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]>
Bumps [sequelize](https://github.com/sequelize/sequelize) from 6.37.7 to 6.37.8. - [Release notes](https://github.com/sequelize/sequelize/releases) - [Changelog](https://github.com/sequelize/sequelize/blob/main/CHANGELOG.md) - [Commits](sequelize/sequelize@v6.37.7...v6.37.8) --- updated-dependencies: - dependency-name: sequelize dependency-version: 6.37.8 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]>
…rofile images (#9588) * fix(core): resolve expired S3 presigned URLs for employee time slot profile images * Update packages/core/src/lib/user/user.service.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update packages/core/src/lib/time-tracking/statistic/statistic.service.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Apply suggestion from @greptile-apps[bot] * Apply suggestion from @greptile-apps[bot] * fix(core): resolve expired S3 presigned URLs for employee time slot profile images * Apply suggestion from @greptile-apps[bot] * Apply suggestion from @greptile-apps[bot] * Apply suggestion from @greptile-apps[bot] * Apply suggestion from @greptile-apps[bot] --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: desktop start server * fix: missing env key in desktop local server * fix: missing env key in desktop server * fix: remove unused imported binding module * fix: add jwt secret to the setup configuration * fix: typo component * fix: translate module at secret module * fix: add translate jwt secret key to all lang * fix: i18n value * fix: remove unused method
Bumps [sequelize](https://github.com/sequelize/sequelize) from 6.37.7 to 6.37.8. - [Release notes](https://github.com/sequelize/sequelize/releases) - [Changelog](https://github.com/sequelize/sequelize/blob/main/CHANGELOG.md) - [Commits](sequelize/sequelize@v6.37.7...v6.37.8) --- updated-dependencies: - dependency-name: sequelize dependency-version: 6.37.8 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…12.7 chore(deps): bump hono from 4.12.5 to 4.12.7
chore(deps): bump tar from 7.5.10 to 7.5.11
* fix(ui): update plugin category effects to use forkJoin for bulk updates and deletions
* fix: Use Number.isNaN for robust date validation
This commit addresses a minor bug by using the more reliable `Number.isNaN()` method, which is the recommended global function for checking `NaN`. It's a small, self-contained change that can be safely committed and reverted independently.
* refactor: Migrate plugin user management UI to Smart Tables
Replaces the custom list rendering and infinite scroll logic with `angular2-smart-table` and `ga-pagination` components for both available and assigned users.
This refactoring includes:
- Removing manual list iteration, user display, and pagination/scroll logic from the template.
- Introducing `angular2-smart-table` components and their data sources (`LocalDataSource`).
- Defining the smart table settings and custom render components for displaying user and assignment details.
- Updating the component's lifecycle hooks and data binding to work with the new table structure.
- Removing associated styling for the old list components and adding styles for the new table containers.
This is a major UI overhaul, replacing a significant portion of the component's template, styling, and TypeScript logic. Grouping these changes into a single commit ensures the entire UI migration is self-contained. The smart table settings, including columns like `_access` (for the upcoming feature), are fully defined here to provide a complete and functional (though not yet fully interactive for the new feature) table UI.
* feat: Integrate Plugin Tenant User Access Management UI
Wires up the user interface for managing plugin tenant user access.
This includes:
- Adding bulk access control buttons ('Enable All', 'Disable All') to the 'Current Assignments' tab in the HTML.
- Implementing `onToggleUserAccess`, `onEnableAllUsers`, and `onDisableAllUsers` methods in the component to dispatch actions to the facade.
- Adding the `NbToggleModule` and `AccessToggleCellComponent` imports, as well as necessary logic to `bindSourcesToStreams` for handling the access toggle within the Smart Table.
This commit completes the implementation of the new user access management feature by integrating the UI components with the facade methods introduced in the previous commit.
* feat: Integrate effects manager and update dependencies across multiple modules
* feat: user management tab with bulk actions and smart table integration
* feat(desktop): add plugin access verification
◦ add user assignment flows and services
◦ sync plugin access on assignment changes
◦ update plugin system interfaces, events, and channels
◦ include migration for plugin user scope table
* feat(plugin-tenant): add unassign operation for users
Introduce a new 'unassign' operation to manage plugin tenant users.
This operation removes a user from both the allowed and denied lists
for a specific plugin tenant. It updates the command handler, command DTO,
and the enum for available operations.
Fix a bug in the 'get-plugin-tenant-users' query handler where denied users
were incorrectly fetched from the allowed users table. The query now
correctly retrieves denied users from the dedicated denied users table.
* feat(plugin-user-management): add unassign user functionality
Introduce a new 'unassign' operation to completely remove users from plugin tenants, rather than just changing their active/inactive status.
Refactor user assignment loading to fetch all users (allowed and denied) by default, providing a comprehensive view of plugin assignments.
Implement optimistic UI updates for allow, deny, and unassign actions, reducing server reloads and improving responsiveness.
Enhance the user management UI with:
* A dedicated 'Disabled Users' count.
* Improved empty states for both overall plugin assignments and specific tabs.
* Confirmation dialogs for bulk enable/disable and individual unassign actions.
* Clearer status badges and tooltips.
* Add translation keys for various user management components.
* feat(plugin-user-assignment): enhance operation state management and UI feedback
* feat(plugin-user-assignment): add translations
* feat(plugin-subscription): improve error handling and response structure in subscription management
* fix: false promise validate
* feat(cspell): add new words to the spell checker dictionary
* fix(plugin-electron): correct channel name for updateTenantEnabled method
* feat: add ai fixes for user management in plugin marketplace
- Updated user management tab styles to use CSS variables for colors and shadows.
- Refactored user management component to utilize Angular's dependency injection for services.
- Improved loading states in user management component templates with skeleton loaders.
- Introduced new interfaces for user row data to enhance type safety.
- Replaced direct property access with computed properties in user cell components for better reactivity.
- Enhanced the plugin access sync service to handle timeout errors gracefully.
- Updated internationalization strings for clarity and consistency.
- Removed unused effects from the plugin routing module to streamline the codebase.
* fix(plugin-subscription): improve error handling when fetching updated subscriptions
* fix: bulk enable/disable actions are not permission-gated, so users without assign rights can trigger access changes.
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* fix: the new table styles are scoped to .available-users, but the assign tab uses .assign-users-section, so Assign Users table styling is not applied.
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* fix: replace skeleton loaders with spinner for loading states in user management tab
* refactor(integrations): move plugin effects provider to module level
Previously, `providePluginsEffects()` was declared directly within the route configuration for the 'plugins' path.
This change moves the provider to the `IntegrationsModule`'s main `providers` array.
Elevating the provider's scope ensures that plugin-related effects are available consistently across the entire integrations feature area, not just limited to the lazy-loaded 'plugins' route.
---------
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
…opovers (#9590) * fix: override default overlay config to disable use of top-layered popovers * refactor(angular): replace `APP_INITIALIZER` with `provideAppInitializer` * Update app.module.ts * Update app.module.ts * Update packages/plugins/posthog-ui/src/lib/posthog.module.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update apps/gauzy/src/app/app.module.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update packages/plugins/posthog-ui/src/lib/posthog.module.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update apps/gauzy/src/app/app.module.ts * Update apps/gauzy/src/app/app.module.ts --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* fix(timesheet): allow manual time for admins by default * Apply suggestion from @greptile-apps[bot] * Update packages/ui-core/shared/src/lib/directives/read-more.directive.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update packages/ui-core/shared/src/lib/directives/read-more.directive.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update apps/gauzy/src/app/pages/employees/timesheet/daily/daily/daily.component.html Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update packages/core/src/lib/employee/commands/handlers/employee.create.handler.ts Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Apply suggestion from @greptile-apps[bot] * Update apps/gauzy/src/app/pages/employees/timesheet/daily/daily/daily.component.html Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Update packages/ui-core/shared/src/lib/directives/read-more.directive.ts Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Apply suggestion from @greptile-apps[bot] * Apply suggestion from @greptile-apps[bot] * Update packages/ui-core/shared/src/lib/directives/read-more.directive.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Apply suggestion from @greptile-apps[bot] * Apply suggestion from @coderabbitai[bot] Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Revert "Apply suggestion from @coderabbitai[bot]" This reverts commit f59b7a4. * Update read-more.directive.ts --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
|
You have run out of free Bugbot PR reviews for this billing cycle. This will reset on April 7. To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
|
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4392c164b8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return from(this.pluginElectronService.updateTenantEnabled(plugin.marketplaceId, false)).pipe( | ||
| catchError(() => of(void 0)) |
There was a problem hiding this comment.
Avoid persisting user revocation as tenant-wide disable
In syncActivePlugins, a single failed access check deactivates the plugin locally and writes tenantEnabled = false via updateTenantEnabled. PluginManager.loadPlugins() uses that flag to skip activation entirely, so one user's revoked access can leave the plugin permanently disabled for later sessions/users on the same installation even when tenant-level access is still valid. This should remain a local user/session deactivation, not a tenant-wide persisted disable.
Useful? React with 👍 / 👎.
| return this.actions$.pipe( | ||
| ofType(PluginUserAssignmentActions.assignUsers), | ||
| tap(() => this.store.setLoading(true)), | ||
| tap(() => this.store.setOperation({ assigning: true })), |
There was a problem hiding this comment.
Restore shared loading signal for assign flow completion
This effect now toggles only operations.assigning, but PluginUserManagementComponent.onAssignUsers() waits on loadingAssignedUsers$ (backed by query.loading$) to detect completion before clearing submitting and reloading assignments. Since loading is no longer set for this path, the completion branch can trigger immediately, allowing repeat submissions and racey reloads before the API finishes. Keep loading in sync for this flow or update the component to await the new operation flags.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
12 issues found across 103 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/desktop-lib/src/lib/plugin-system/events/plugin.event.ts">
<violation number="1" location="packages/desktop-lib/src/lib/plugin-system/events/plugin.event.ts:89">
P2: Destructuring the IPC payload in the function parameter can throw before `try/catch`, causing unhandled invocation failures for missing/malformed payloads.</violation>
</file>
<file name="packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/plugin-marketplace-item/tabs/user-management-tab/user-management-tab.component.ts">
<violation number="1" location="packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/plugin-marketplace-item/tabs/user-management-tab/user-management-tab.component.ts:31">
P2: Duplicate `PluginUserRow` interface — identical definition exists in `plugin-user-management.component.ts`. Extract it to a shared types file (e.g., alongside the table service or in a `models/` folder) and import from both components to avoid drift.</violation>
</file>
<file name=".scripts/electron-desktop-environment/concrete-environment-content/desktop-server-environment-content.ts">
<violation number="1" location=".scripts/electron-desktop-environment/concrete-environment-content/desktop-server-environment-content.ts:33">
P2: Serialize/escape JWT secret values before embedding them in the generated template; raw single-quoted interpolation can break generated config syntax for valid secret characters.</violation>
</file>
<file name="packages/desktop-ui-lib/src/lib/settings/secret/secret.component.ts">
<violation number="1" location="packages/desktop-ui-lib/src/lib/settings/secret/secret.component.ts:32">
P2: The IPC listener registered in ngOnInit is never removed. If this component is destroyed and recreated, listeners accumulate and can cause duplicate updates and memory leaks. Add teardown in ngOnDestroy (removeListener or use fromEvent with subscription cleanup).</violation>
</file>
<file name="packages/desktop-ui-lib/src/lib/settings/secret/secret.component.html">
<violation number="1" location="packages/desktop-ui-lib/src/lib/settings/secret/secret.component.html:6">
P2: JWT secret should use a masked password input and a matching `id` for the existing label `for` attribute.</violation>
<violation number="2" location="packages/desktop-ui-lib/src/lib/settings/secret/secret.component.html:13">
P2: Refresh token secret should use a masked password input and a matching `id` for the existing label `for` attribute.</violation>
</file>
<file name=".scripts/electron-desktop-environment/concrete-environment-content/desktop-environment-content.ts">
<violation number="1" location=".scripts/electron-desktop-environment/concrete-environment-content/desktop-environment-content.ts:33">
P0: Do not embed JWT signing secrets in desktop environment content; this exposes credentials in client-distributed configuration.</violation>
</file>
<file name="packages/desktop-ui-lib/src/lib/settings/secret/secret.module.ts">
<violation number="1" location="packages/desktop-ui-lib/src/lib/settings/secret/secret.module.ts:22">
P1: Use `NbMenuModule` (without `forRoot`) in this feature module to avoid re-initializing menu root providers.</violation>
</file>
<file name="packages/desktop-ui-lib/src/lib/setup/setup.component.ts">
<violation number="1" location="packages/desktop-ui-lib/src/lib/setup/setup.component.ts:621">
P2: Update `secretConfig` in `onChangeSecretConfig`; otherwise `saveAndRun()` may send stale/default secrets instead of the latest user-edited values.</violation>
</file>
<file name="packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/plugin-user-management/render/user-cell/user-cell.component.ts">
<violation number="1" location="packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/plugin-user-management/render/user-cell/user-cell.component.ts:19">
P2: `imports` is only valid on standalone components. Add `standalone: true` to this component metadata to avoid an Angular compilation error.</violation>
</file>
<file name="packages/desktop-ui-lib/src/lib/settings/plugins/services/plugin-access-sync.service.ts">
<violation number="1" location="packages/desktop-ui-lib/src/lib/settings/plugins/services/plugin-access-sync.service.ts:72">
P1: Do not persist `tenantEnabled = false` when a single user's access check fails. This is a tenant-wide activation flag used during plugin loading, so writing it here can keep the plugin disabled for subsequent sessions/users on the installation.</violation>
</file>
<file name="packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/+state/effects/plugin-user-assignment.effects.ts">
<violation number="1" location="packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/+state/effects/plugin-user-assignment.effects.ts:168">
P2: Keep the shared `loading` signal consistent for the assign-user flow, or migrate callers to wait on `operations.assigning`. With only operation flags toggled here, consumers that await `query.loading$` can treat the request as complete before the assignment API call finishes.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| IS_SERVER: ${false}, | ||
| IS_SERVER_API: ${false} | ||
| IS_SERVER_API: ${false}, | ||
| JWT_SECRET: '${variable.DESKTOP_JWT_SECRET || ''}', |
There was a problem hiding this comment.
P0: Do not embed JWT signing secrets in desktop environment content; this exposes credentials in client-distributed configuration.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .scripts/electron-desktop-environment/concrete-environment-content/desktop-environment-content.ts, line 33:
<comment>Do not embed JWT signing secrets in desktop environment content; this exposes credentials in client-distributed configuration.</comment>
<file context>
@@ -29,7 +29,9 @@ export class DesktopEnvironmentContent implements IContentGenerator {
IS_SERVER: ${false},
- IS_SERVER_API: ${false}
+ IS_SERVER_API: ${false},
+ JWT_SECRET: '${variable.DESKTOP_JWT_SECRET || ''}',
+ JWT_REFRESH_TOKEN_SECRET: '${variable.DESKTOP_JWT_REFRESH_TOKEN_SECRET || ''}'
`;
</file context>
| @NgModule({ | ||
| imports: [ | ||
| CommonModule, | ||
| NbMenuModule.forRoot(), |
There was a problem hiding this comment.
P1: Use NbMenuModule (without forRoot) in this feature module to avoid re-initializing menu root providers.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-ui-lib/src/lib/settings/secret/secret.module.ts, line 22:
<comment>Use `NbMenuModule` (without `forRoot`) in this feature module to avoid re-initializing menu root providers.</comment>
<file context>
@@ -0,0 +1,39 @@
+@NgModule({
+ imports: [
+ CommonModule,
+ NbMenuModule.forRoot(),
+ NbCardModule,
+ NbIconModule,
</file context>
| const deactivations$ = revoked.map(({ plugin }) => { | ||
| console.info(`Access revoked for plugin "${plugin.name}" — deactivating locally`); | ||
| this.pluginElectronService.deactivate(plugin); | ||
| return from(this.pluginElectronService.updateTenantEnabled(plugin.marketplaceId, false)).pipe( |
There was a problem hiding this comment.
P1: Do not persist tenantEnabled = false when a single user's access check fails. This is a tenant-wide activation flag used during plugin loading, so writing it here can keep the plugin disabled for subsequent sessions/users on the installation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-ui-lib/src/lib/settings/plugins/services/plugin-access-sync.service.ts, line 72:
<comment>Do not persist `tenantEnabled = false` when a single user's access check fails. This is a tenant-wide activation flag used during plugin loading, so writing it here can keep the plugin disabled for subsequent sessions/users on the installation.</comment>
<file context>
@@ -0,0 +1,83 @@
+ const deactivations$ = revoked.map(({ plugin }) => {
+ console.info(`Access revoked for plugin "${plugin.name}" — deactivating locally`);
+ this.pluginElectronService.deactivate(plugin);
+ return from(this.pluginElectronService.updateTenantEnabled(plugin.marketplaceId, false)).pipe(
+ catchError(() => of(void 0))
+ );
</file context>
| async (_, { marketplaceId, tenantEnabled }: { marketplaceId: ID; tenantEnabled: boolean }) => { | ||
| try { | ||
| await this.pluginManager.updateTenantEnabled(marketplaceId, tenantEnabled); |
There was a problem hiding this comment.
P2: Destructuring the IPC payload in the function parameter can throw before try/catch, causing unhandled invocation failures for missing/malformed payloads.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-lib/src/lib/plugin-system/events/plugin.event.ts, line 89:
<comment>Destructuring the IPC payload in the function parameter can throw before `try/catch`, causing unhandled invocation failures for missing/malformed payloads.</comment>
<file context>
@@ -84,6 +84,19 @@ class ElectronPluginListener {
+ ipcMain.handle(
+ PluginHandlerChannel.UPDATE_TENANT_ENABLED,
+ async (_, { marketplaceId, tenantEnabled }: { marketplaceId: ID; tenantEnabled: boolean }) => {
+ try {
+ await this.pluginManager.updateTenantEnabled(marketplaceId, tenantEnabled);
</file context>
| async (_, { marketplaceId, tenantEnabled }: { marketplaceId: ID; tenantEnabled: boolean }) => { | |
| try { | |
| await this.pluginManager.updateTenantEnabled(marketplaceId, tenantEnabled); | |
| async (_, payload: { marketplaceId: ID; tenantEnabled: boolean } | undefined) => { | |
| try { | |
| const { marketplaceId, tenantEnabled } = payload ?? ({} as { marketplaceId?: ID; tenantEnabled?: boolean }); | |
| if (!marketplaceId || typeof tenantEnabled !== 'boolean') { | |
| return { success: false, error: 'Invalid payload' }; | |
| } | |
| await this.pluginManager.updateTenantEnabled(marketplaceId, tenantEnabled); |
| import { PluginAssignedUsersTableService } from '../../../plugin-user-management/services/plugin-assigned-users-table.service'; | ||
|
|
||
| /** Row data representing a user toggle action */ | ||
| export interface PluginUserRow { |
There was a problem hiding this comment.
P2: Duplicate PluginUserRow interface — identical definition exists in plugin-user-management.component.ts. Extract it to a shared types file (e.g., alongside the table service or in a models/ folder) and import from both components to avoid drift.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/plugin-marketplace-item/tabs/user-management-tab/user-management-tab.component.ts, line 31:
<comment>Duplicate `PluginUserRow` interface — identical definition exists in `plugin-user-management.component.ts`. Extract it to a shared types file (e.g., alongside the table service or in a `models/` folder) and import from both components to avoid drift.</comment>
<file context>
@@ -1,18 +1,38 @@
+import { PluginAssignedUsersTableService } from '../../../plugin-user-management/services/plugin-assigned-users-table.service';
+
+/** Row data representing a user toggle action */
+export interface PluginUserRow {
+ userId?: string;
+ newState: boolean;
</file context>
| <label class="secret-label" for="refresh_secret">{{ | ||
| 'TIMER_TRACKER.SETUP.JWT_REFRESH_TOKEN_SECRET' | translate | ||
| }}</label> | ||
| <input [(ngModel)]="config.secret.refresh_token" (ngModelChange)="onUpdate()" type="text" nbInput fullWidth |
There was a problem hiding this comment.
P2: Refresh token secret should use a masked password input and a matching id for the existing label for attribute.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-ui-lib/src/lib/settings/secret/secret.component.html, line 13:
<comment>Refresh token secret should use a masked password input and a matching `id` for the existing label `for` attribute.</comment>
<file context>
@@ -0,0 +1,16 @@
+ <label class="secret-label" for="refresh_secret">{{
+ 'TIMER_TRACKER.SETUP.JWT_REFRESH_TOKEN_SECRET' | translate
+ }}</label>
+ <input [(ngModel)]="config.secret.refresh_token" (ngModelChange)="onUpdate()" type="text" nbInput fullWidth
+ status="basic" [placeholder]="'TIMER_TRACKER.SETUP.JWT_REFRESH_TOKEN_SECRET_PLACEHOLDER' | translate" />
+ </div>
</file context>
| <label class="secret-label" for="jwt-secret">{{ | ||
| 'TIMER_TRACKER.SETUP.JWT_SECRET' | translate | ||
| }}</label> | ||
| <input [(ngModel)]="config.secret.jwt" (ngModelChange)="onUpdate()" type="text" nbInput fullWidth status="basic" |
There was a problem hiding this comment.
P2: JWT secret should use a masked password input and a matching id for the existing label for attribute.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-ui-lib/src/lib/settings/secret/secret.component.html, line 6:
<comment>JWT secret should use a masked password input and a matching `id` for the existing label `for` attribute.</comment>
<file context>
@@ -0,0 +1,16 @@
+ <label class="secret-label" for="jwt-secret">{{
+ 'TIMER_TRACKER.SETUP.JWT_SECRET' | translate
+ }}</label>
+ <input [(ngModel)]="config.secret.jwt" (ngModelChange)="onUpdate()" type="text" nbInput fullWidth status="basic"
+ [placeholder]="'TIMER_TRACKER.SETUP.JWT_SECRET_PLACEHOLDER' | translate" />
+ </div>
</file context>
| public onChangeSecretConfig(config: IDesktopSecret) { | ||
| this.electronService.ipcRenderer.send('update_server_config', { | ||
| secret: config.secret | ||
| }); | ||
| } |
There was a problem hiding this comment.
P2: Update secretConfig in onChangeSecretConfig; otherwise saveAndRun() may send stale/default secrets instead of the latest user-edited values.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-ui-lib/src/lib/setup/setup.component.ts, line 621:
<comment>Update `secretConfig` in `onChangeSecretConfig`; otherwise `saveAndRun()` may send stale/default secrets instead of the latest user-edited values.</comment>
<file context>
@@ -597,4 +617,10 @@ export class SetupComponent implements OnInit, OnDestroy {
});
}
+
+ public onChangeSecretConfig(config: IDesktopSecret) {
+ this.electronService.ipcRenderer.send('update_server_config', {
+ secret: config.secret
</file context>
| public onChangeSecretConfig(config: IDesktopSecret) { | |
| this.electronService.ipcRenderer.send('update_server_config', { | |
| secret: config.secret | |
| }); | |
| } | |
| public onChangeSecretConfig(config: IDesktopSecret) { | |
| this.secretConfig = config; | |
| this.electronService.ipcRenderer.send('update_server_config', { | |
| secret: config.secret | |
| }); | |
| } |
| <nb-user [picture]="picture()" [name]="name()" [title]="email()" size="small"></nb-user> | ||
| `, | ||
| changeDetection: ChangeDetectionStrategy.OnPush, | ||
| imports: [NbUserModule] |
There was a problem hiding this comment.
P2: imports is only valid on standalone components. Add standalone: true to this component metadata to avoid an Angular compilation error.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/plugin-user-management/render/user-cell/user-cell.component.ts, line 19:
<comment>`imports` is only valid on standalone components. Add `standalone: true` to this component metadata to avoid an Angular compilation error.</comment>
<file context>
@@ -0,0 +1,38 @@
+ <nb-user [picture]="picture()" [name]="name()" [title]="email()" size="small"></nb-user>
+ `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ imports: [NbUserModule]
+})
+export class UserCellComponent {
</file context>
| return this.actions$.pipe( | ||
| ofType(PluginUserAssignmentActions.assignUsers), | ||
| tap(() => this.store.setLoading(true)), | ||
| tap(() => this.store.setOperation({ assigning: true })), |
There was a problem hiding this comment.
P2: Keep the shared loading signal consistent for the assign-user flow, or migrate callers to wait on operations.assigning. With only operation flags toggled here, consumers that await query.loading$ can treat the request as complete before the assignment API call finishes.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop-ui-lib/src/lib/settings/plugins/component/plugin-marketplace/+state/effects/plugin-user-assignment.effects.ts, line 168:
<comment>Keep the shared `loading` signal consistent for the assign-user flow, or migrate callers to wait on `operations.assigning`. With only operation flags toggled here, consumers that await `query.loading$` can treat the request as complete before the assignment API call finishes.</comment>
<file context>
@@ -165,7 +165,7 @@ export class PluginUserAssignmentEffects {
return this.actions$.pipe(
ofType(PluginUserAssignmentActions.assignUsers),
- tap(() => this.store.setLoading(true)),
+ tap(() => this.store.setOperation({ assigning: true })),
switchMap(({ pluginId, userIds, reason }) =>
// First, get or create the plugin tenant
</file context>
|
View your CI Pipeline Execution ↗ for commit 4392c16
☁️ Nx Cloud last updated this comment at |



PR
Please note: we will close your PR without comment if you do not check the boxes above and provide ALL requested information.
Summary by cubic
Adds plugin tenant user access management (allow/deny/unassign, bulk actions, smarter UI) and adds JWT secret setup for the desktop local server. Also fixes desktop server startup, refreshes expired avatar URLs in timesheet stats, and defaults admin users to allow manual/modify/delete time.
New Features
tenantEnabledflag; new IPCplugins::update-tenant-enabled.JWT_SECRETandJWT_REFRESH_TOKEN_SECRET; new env keysDESKTOP_JWT_SECRET,DESKTOP_JWT_REFRESH_TOKEN_SECRET.APP_INITIALIZERwithprovideAppInitializer; provide plugin effects at module level; adjust overlay defaults to avoid top-layer popovers; add@ngneat/effects-ng.Migration
DESKTOP_JWT_SECRET/DESKTOP_JWT_REFRESH_TOKEN_SECRET). Restart desktop/server to apply.Written for commit 4392c16. Summary will update on new commits.