Skip to content

Stage#9591

Merged
evereq merged 13 commits intostagefrom
develop
Mar 12, 2026
Merged

Stage#9591
evereq merged 13 commits intostagefrom
develop

Conversation

@evereq
Copy link
Member

@evereq evereq commented Mar 12, 2026

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

    • Manage plugin tenant users: allow, deny, unassign, bulk enable/disable; new counts and Smart Table UI with per-row actions.
    • Sync local plugin access with server; deactivate plugins when access is revoked; honor tenant-level tenantEnabled flag; new IPC plugins::update-tenant-enabled.
    • Desktop Setup: add JWT secret and refresh token fields; pass to local API via JWT_SECRET and JWT_REFRESH_TOKEN_SECRET; new env keys DESKTOP_JWT_SECRET, DESKTOP_JWT_REFRESH_TOKEN_SECRET.
    • Default admin permissions: admins get manual/modify/delete time enabled on creation and in seeds.
    • Angular init cleanup: replace APP_INITIALIZER with provideAppInitializer; provide plugin effects at module level; adjust overlay defaults to avoid top-layer popovers; add @ngneat/effects-ng.
  • Migration

    • Desktop app: run the new offline DB migration for plugin user scope (added automatically via the desktop DB migrations).
    • Configure secrets: in Setup → Server API, set JWT Secret and JWT Refresh Token Secret (or provide via env DESKTOP_JWT_SECRET / DESKTOP_JWT_REFRESH_TOKEN_SECRET). Restart desktop/server to apply.

Written for commit 4392c16. Summary will update on new commits.

dependabot bot and others added 13 commits March 10, 2026 19:28
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>
@cursor
Copy link

cursor bot commented Mar 12, 2026

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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 12, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 007cdff2-96d3-4bb3-b08c-6ab0832b0929

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@socket-security
Copy link

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​types/​fs-extra@​5.0.21001007380100
Addedbcryptjs@​3.0.310010010081100

View full report

@cla-assistant
Copy link

cla-assistant bot commented Mar 12, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
4 out of 5 committers have signed the CLA.

✅ evereq
✅ rahul-rocket
✅ adkif
✅ syns2191
❌ dependabot[bot]
You have signed the CLA already but the status is still pending? Let us recheck it.

@sonarqubecloud
Copy link

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 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".

Comment on lines +72 to +73
return from(this.pluginElectronService.updateTenantEnabled(plugin.marketplaceId, false)).pipe(
catchError(() => of(void 0))

Choose a reason for hiding this comment

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

P1 Badge 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 })),

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@evereq evereq merged commit 8f48977 into stage Mar 12, 2026
30 of 45 checks passed
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

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 || ''}',
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

@NgModule({
imports: [
CommonModule,
NbMenuModule.forRoot(),
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

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(
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

Comment on lines +89 to +91
async (_, { marketplaceId, tenantEnabled }: { marketplaceId: ID; tenantEnabled: boolean }) => {
try {
await this.pluginManager.updateTenantEnabled(marketplaceId, tenantEnabled);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Suggested change
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);
Fix with Cubic

import { PluginAssignedUsersTableService } from '../../../plugin-user-management/services/plugin-assigned-users-table.service';

/** Row data representing a user toggle action */
export interface PluginUserRow {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

<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
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

<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"
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

Comment on lines +621 to +625
public onChangeSecretConfig(config: IDesktopSecret) {
this.electronService.ipcRenderer.send('update_server_config', {
secret: config.secret
});
}
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Suggested change
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
});
}
Fix with Cubic

<nb-user [picture]="picture()" [name]="name()" [title]="email()" size="small"></nb-user>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NbUserModule]
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

return this.actions$.pipe(
ofType(PluginUserAssignmentActions.assignUsers),
tap(() => this.store.setLoading(true)),
tap(() => this.store.setOperation({ assigning: true })),
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 12, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

@nx-cloud
Copy link

nx-cloud bot commented Mar 12, 2026

View your CI Pipeline Execution ↗ for commit 4392c16

Command Status Duration Result
nx build desktop --configuration=production --b... ✅ Succeeded 1m 33s View ↗
nx build desktop-api --configuration=production... ✅ Succeeded 25s View ↗
nx run api:desktop-api ✅ Succeeded 49s View ↗
nx build gauzy -c=production --prod --verbose ✅ Succeeded 4m 17s View ↗
nx run gauzy:desktop-ui --base-href ./ ✅ Succeeded 3m 52s View ↗
nx run-many -t build -c development -p constant... ✅ Succeeded 3m 15s View ↗
nx run-many -t build -c production -p constants... ✅ Succeeded 3m 17s View ↗
nx build api -c=production --prod ✅ Succeeded 2m 8s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-12 11:21:40 UTC

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.

4 participants