Skip to content

feat: Community Translation v1 - #3765

Merged
Anty0 merged 8 commits into
mainfrom
jirikuchynka/public-projects
Jul 16, 2026
Merged

feat: Community Translation v1#3765
Anty0 merged 8 commits into
mainfrom
jirikuchynka/public-projects

Conversation

@Anty0

@Anty0 Anty0 commented Jun 24, 2026

Copy link
Copy Markdown
Member

Integration branch for Community Translation v1.0 (#3763). Individual lanes are reviewed as sub-PRs that target this branch and squash-merge into it; this PR merges to main once the v1.0 must-haves have landed.

Landed lanes

  • Public project togglepublic flag on Project (is_public column + Liquibase migration), exposed on ProjectModel/ProjectDto; owner-only PUT /v2/projects/{projectId}/publishing (gated by PROJECT_EDIT + checkUserIsOwnerOrServerAdmin, activity-logged, cache-evicting); confirmation-guarded "Public project" switch in advanced settings.

  • Community permission (feat: community permissions for public projects #3770) — authenticated users on a public project get a computed community floor (read subset of VIEW + translations.suggest + translation-comments.add, all languages; origin COMMUNITY) without a stored Permission row, so they contribute without taking a paid seat. Direct/org permissions and admin/supporter elevation layer on top, so no authenticated user is below a non-member; anonymous users get nothing. Member emails + member count are redacted behind MEMBERS_VIEW (REST + websocket); out-of-surface endpoints are gated (MT credits → ORGANIZATION_QUOTAS_VIEW, import-settings → TRANSLATIONS_EDIT (mirrors the import menu gate translations.edit + keys.view), branch-merge → BRANCH_MANAGEMENT, blocking-tasks → task-view-or-assigned).

  • List-row public indicator (feat: public badge + organization on project list rows #3771) — public projects show a second line under the project name in the shared list row (DashboardProjectListItem): an outlined public badge + organization name. Adds public to ProjectWithStatsModel + assembler. Sole indicator (no project-detail icon).

  • Suggestion resolution split (feat: split suggestion accept into "accept only" and "accept and decline others" #3776) — splits the single suggestion Accept into "Accept only" (declineOther=false, leaves the competing suggestions active) and "Accept and decline others" (declineOther=true, prior behavior). Inline row actions are ✓ Accept-only and ✕ Decline; an overflow menu holds Accept-and-decline-others and Delete (own suggestions only). Frontend-only — the backend already supported declineOther. Optimistic cache keeps the surviving sibling visible until refetch (vitest-covered). Two new i18n keys created in "Tolgee itself".

  • Suggestion moderation (feat: add translation-suggestions.manage permission scope #3785) — new translation-suggestions.manage scope lets project members delete suggestions authored by other users (previously author-only). Own per-language dimension (suggestManageLanguages, new join table + Liquibase migration); Suggest and Manage are grouped under a new "Suggestions" permission category, each with its own language selector. Granted to the EDIT/MANAGE presets; the suggestion list endpoint accepts suggest OR manage so moderators see what they can act on. Deletion is language-restricted like the sibling suggestion actions; decline/accept stay on translations.state-edit. New i18n keys in "Tolgee itself".

  • Suggestion display (feat: show up to 3 translation suggestions per cell by default #3774) — translations read view embeds up to 3 active suggestions per cell (was 1), newest-first via a windowed top-N query (cap MAX_DISPLAYED_SUGGESTIONS=3, created_at desc, id desc); the existing +N overflow badge is the "more" affordance (no separate button). Stays capped at 3 across the editor open/close, mutate, and suggest-create paths; +N restyled as an inline circle on the last suggestion row.

  • Public projects view (feat: public projects view (Community Translation v1.0) #3775) — logged-out-capable /public-projects page listing all public projects (stats, paged + search) via anonymous GET /v2/public/projects/with-stats (@Transactional(readOnly=true), filters guard the anonymous read so it is side-effect-free; the community-permission floor from feat: community permissions for public projects #3770 applies for logged-in visitors). Reuses the projects-list UI (shared ProjectsList extracted from ProjectListView); community-translation banner (Figma-matched gradient + dev-mouse mascot + Suggest/Comment bullets, no Vote), left-anchored search shown only above a >5 project threshold, LOG IN/SIGN UP top bar, no org switcher. DashboardProjectListItem gains variant='public': member affordances (⋮ menu / QA / translations) suppressed, whole-row click opens the project when logged-in (community VIEW) else routes to login.

  • Projects-page redesign (feat: community projects page and switcher navigation entry #3777) — projects list header redesigned: centered "Projects" title with the org switcher relocated beside it (standaloneTitle hides the separator, adds top spacing, stacks search on its own row); every non-list page keeps the top-left switcher. Synthetic "Community translation" switcher entry navigates to /community-projects (does not switch org) — implemented but temporarily disabled pending contributor tracking (its e2e tests are skipped with a re-enable TODO). /community-projects page reuses the projects-list shell, ignores the selected org, lists all public projects, email-verification gated, with the community-translation banner on top (diverges from the pitch's "no banner" — designer request). DashboardProjectListItem gains a public grid variant that drops the controls column entirely — no reserved space (default title width 150→180px, smaller breakpoints unchanged). New i18n keys in "Tolgee itself".

  • Community access to public-project orgs (feat: community access to public-project organizations #3792) — opening a public project auto-switches the preferred org; for non-members this previously 403'd because org access only recognized stored membership/permission rows. Extends the org view floor (canUserViewStrictOrPublic = direct permission / stored org role OR the org owns a publicly visible project) so community and direct-permission users can view the org and set it as preferred — without a dedicated role (an earlier GUEST-role iteration was removed; below-member users hold no role). Anything beyond viewing still requires MEMBER+. Reduced preferred-org model below MEMBER (activeCloudSubscription hidden; new PrivateOrganizationModel.limitedView drives the community project-list view). Guest-visible surface scoped to accessible projects — org GETs (role null), project listings, languages/base-languages, glossary reads incl. CSV export (one canonical ProjectRepository.BELOW_MEMBER_ACCESSIBLE_PROJECT predicate), llm-providers (name/type/token-credit pricing only), /leave. Preference healing writes on stale/missing preference; below-member viewers excluded from member listings, seat stats, and assignee search. Billing repo should audit its org-scoped @UseDefaultPermissions endpoints for the widened floor.

Pending lanes (this branch)

  • Contributors (~ optional) + docs

⚠️ Breaking changes

  • GET /v2/projects/{id}/machine-translation-credit-balance now requires ORGANIZATION_QUOTAS_VIEW; granular permissions / API keys without it get 403 and must be re-granted.
  • Branch-merge session endpoints now require BRANCH_MANAGEMENT.

Notes

  • On merge, existing EDIT/MANAGE project members gain the ability to delete other users' suggestions (additive permission change; decline/accept are unchanged).
  • No billing impact — community access is never a project membership / paid seat.

Deliberate inline style literals (no matching MUI theme token)

These Figma-exact values are kept inline on purpose — single-use surfaces with no matching
theme token; not folded into theme.typography/theme.spacing:

  • CommunityTranslationBanner (one-off marketing surface): eyebrow 24px/600/lh1.235/ls0.25px;
    heading 40px/700/lh1.167/-1.5px (rendered as h1 for semantics, visual is the Figma override);
    subtext max-width 561px; mascot-zone reserve padding-right 260px; mouse height 190px / bottom -15px;
    bullet icons 21×22px; gradient stop 69%.
  • SuggestionsFirst show-all button: 13px / letter-spacing 0.46px (matches TrialChip.tsx) / 6px vertical padding.
  • DashboardProjectListItem StyledPublicChip label: 13px.

Summary by CodeRabbit

Summary

  • New Features

    • Added public/community projects listing with search, pagination, and stats.
    • Added project publishing toggle to mark projects public/private.
    • Extended permissions with translation-suggestions.manage (per-language suggestion management) and organization-quotas.view.
  • Bug Fixes

    • Improved privacy redaction for usernames/emails across REST responses and realtime activity.
    • Refined public/community permission behavior and member visibility (e.g., hidden member counts when not allowed).
  • Tests

    • Expanded API, UI, and permissions test coverage for public/community access, publishing, masking, and suggestion-permission rules.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

This PR adds public project publishing/listing, community permission flooring and member masking, new suggestion-management scopes and language fields, and updated suggestion preview/moderation flows across backend, webapp, and tests.

Changes

Public projects and community permissions

Layer / File(s) Summary
Public project state and APIs
backend/data/.../Project.kt, ProjectDto.kt, ProjectView.kt, ProjectWithLanguagesView.kt, ProjectWithStatsView.kt, ProjectRepository.kt, ProjectService.kt, schema.xml, backend/api/.../ProjectsPublishingController.kt, PublicProjectsController.kt, SetProjectPublicRequest.kt, ProjectModel*.kt, ProjectWithStatsModel*.kt, backend/app/.../ProjectStatsController.kt, webapp/src/service/apiSchema*.ts
Adds project public-state storage, publishing/listing endpoints, and public fields in API models and generated schema.
Community permission computation and member visibility
ComputedPermissionOrigin.kt, ComputedPermissionDto.kt, PermissionService.kt, SecurityService.kt, ProjectModelAssembler.kt, ProjectWithStatsModelAssembler.kt, ProjectStatsController.kt, ActivityWebsocketListener.kt, SimpleUserAccountModelAssembler.kt, TranslationHistoryModelAssembler.kt, TrashedKey*Assembler.kt, ProjectActivityModelAssembler.kt
Adds community permission flooring and request-aware member-field masking, then wires masked usernames into REST and websocket payloads.
Suggestion-management scopes and language plumbing
Scope.kt, ProjectPermissionType.kt, Permission.kt, PermissionRepository.kt, LanguagePermissions.kt, SetPermissionLanguageParams.kt, RequestWithLanguagePermissions.kt, ProjectInviteUserDto.kt, LanguageDeletedPermissionUpdater.kt, ProjectPermissionFacade.kt, LanguagePermissionsSummary.tsx, hierarchyTools.ts, usePermissionsStructure.ts, useScopeTranslations.tsx, webapp/src/fixtures/permissions.ts
Adds TRANSLATION_SUGGESTIONS_MANAGE and ORGANIZATION_QUOTAS_VIEW, plus language-scoped permission propagation and UI mapping.
Public/community UI and routing
RootRouter.tsx, links.tsx, CommunityProjectsView.tsx, PublicProjectListView.tsx, PublicTopBar.tsx, CommunityTranslationBanner.tsx, CommunityTranslationItem.tsx, OrganizationSwitch*.tsx, HeaderBar.tsx, BaseView.tsx, ProjectsList.tsx, DashboardProjectListItem.tsx, ProjectListView.tsx, ProjectSettingsAdvanced.tsx, ProjectTotals.tsx, SwitchPopover.tsx
Adds public/community project browsing surfaces, navigation, and a public-visibility toggle in settings.
Backend/UI validation
*Test.kt, *cy.ts, dataCyType.d.ts, *TestData.kt
Covers the new public/community flows, publishing toggle, masking behavior, and suggestion-management rules.
Miscellaneous permission/controller updates
ImportSettingsController.kt, MtCreditsController.kt, BranchController.kt, TaskController.kt, SuggestionController.kt
Switches several endpoints to explicit project permissions and new suggestion/task authorization helpers.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is related to the PR theme, but "Community Translation v1" is too generic to clearly convey the main change. Use a more specific title that highlights the primary change, such as public projects, community permissions, and project publishing.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jirikuchynka/public-projects

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

@Anty0 Anty0 changed the title feat: public project toggle (Community Translation v1.0) feat: Community Translation v1.0 Jun 30, 2026
@Anty0
Anty0 force-pushed the jirikuchynka/public-projects branch 3 times, most recently from d9ca48a to ec88b34 Compare July 2, 2026 21:37
@Anty0
Anty0 marked this pull request as ready for review July 2, 2026 21:38

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 18

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
webapp/src/views/projects/translations/context/services/useEditService.tsx (1)

191-206: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Dedupe by id when merging the new suggestion into value.suggestions.

Without a dedup check, a subsequent update to value.suggestions (e.g. from a refetch or another local update path) that also contains this suggestion could leave the array with a duplicate entry for the same id, breaking the key={s.id} React key contract in SuggestionsFirst/TranslationSuggestion.

🐛 Suggested fix
-            suggestions: [result, ...(value.suggestions ?? [])].slice(
-              0,
-              MAX_DISPLAYED_SUGGESTIONS
-            ),
+            suggestions: [
+              result,
+              ...(value.suggestions ?? []).filter((s) => s.id !== result.id),
+            ].slice(0, MAX_DISPLAYED_SUGGESTIONS),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webapp/src/views/projects/translations/context/services/useEditService.tsx`
around lines 191 - 206, The suggestion merge in useEditService’s
updateTranslation data callback should dedupe by id before prepending the new
result, since value.suggestions may already contain the same suggestion from
another update path. Update the logic around result, value.suggestions, and
MAX_DISPLAYED_SUGGESTIONS so the merged array keeps only one entry per s.id
while preserving the existing count updates.
backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt (1)

41-52: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Restore sul.id is not null in findAllByPermittedLanguage()

PermissionService.removeLanguageFromPermissions() uses this query, but LanguageDeletedPermissionUpdater never removes suggestLanguages. Without sul.id is not null, permissions that only reference the deleted language through suggestLanguages are skipped and keep a stale relation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt`
around lines 41 - 52, `findAllByPermittedLanguage()` is missing the
`suggestLanguages` check, so permissions linked only through that relation are
not returned. Update the query in
`PermissionRepository.findAllByPermittedLanguage` to include `sul.id is not
null` alongside the existing `tl`, `vl`, `scl`, and `sml` conditions so
`PermissionService.removeLanguageFromPermissions()` can remove stale
`suggestLanguages` references.
webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx (1)

198-212: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Tooltip can render blank when name is unset and username is masked to "".

suggestion.author.name ?? suggestion.author.username only falls back on nullish name; it doesn't handle username being masked to an empty string (confirmed by the updated assertions in SuggestionControllerTest.kt expecting author.username == ""). If an author has no name set, the tooltip (and the AvatarImg avatar, which spreads the same author) would show blank.

🐛 Proposed fix
             params={{
-              user: suggestion.author.name ?? suggestion.author.username,
+              user: suggestion.author.name || suggestion.author.username || t('global_unknown_user'),
               b: <b />,
             }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx`
around lines 198 - 212, The tooltip and avatar author lookup in
TranslationSuggestion should not rely on suggestion.author.name ??
suggestion.author.username alone, since username may be an empty masked string.
Update the author label logic used by the Tooltip title and the AvatarImg owner
in TranslationSuggestion to fall back to a non-blank display value when name is
missing and username is empty, using the suggestion.author object as the source
of truth.
🧹 Nitpick comments (10)
backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt (1)

9-23: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Silent truncation when count > 6.

take(count) on a 6-element list silently caps output at 6 regardless of a larger count argument, which could mislead future callers into thinking more projects were seeded.

🛡️ Guard against an out-of-range count
 class PublicProjectsE2eData(
   count: Int = 6,
 ) : BaseTestData("publicProjectsUser", "Private project") {
   init {
+    require(count in 1..6) { "count must be between 1 and 6" }
     root.apply {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt`
around lines 9 - 23, `PublicProjectsE2eData` silently caps seeded projects at 6
because the `listOf(...).take(count)` source is fixed-length; update the `init`
block to validate or constrain `count` explicitly so callers can’t request more
than the available suffixes without being told. If `count` should be limited,
guard it up front in `PublicProjectsE2eData` and fail fast or clamp with an
intentional message; if more than 6 projects should be supported, replace the
hardcoded suffix list with a generator that can produce enough unique names
before calling `addProject`.
webapp/src/views/projects/translations/context/services/useEditService.tsx (1)

20-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use tg.views alias instead of a cross-directory relative import.

As per coding guidelines, "Use Tolgee custom TypeScript path aliases (tg.component, tg.service, tg.hooks, tg.views, tg.globalContext) instead of relative imports".

♻️ Suggested fix
-import { MAX_DISPLAYED_SUGGESTIONS } from '../../Suggestions/SuggestionsFirst';
+import { MAX_DISPLAYED_SUGGESTIONS } from 'tg.views/projects/translations/Suggestions/SuggestionsFirst';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webapp/src/views/projects/translations/context/services/useEditService.tsx`
at line 20, The import in useEditService should use the tg.views alias instead
of a cross-directory relative path. Update the MAX_DISPLAYED_SUGGESTIONS import
to point through the views alias so it follows the project’s Tolgee path-alias
convention and avoids relative imports across directories.

Source: Coding guidelines

backend/data/src/main/kotlin/io/tolgee/model/Project.kt (1)

175-175: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider a less keyword-adjacent property name.

var public: Boolean shadows the readability of the public visibility modifier elsewhere in the class. isPublic would be more idiomatic Kotlin and self-documenting, while @Column(name = "is_public") keeps the DB mapping intact.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/data/src/main/kotlin/io/tolgee/model/Project.kt` at line 175, Rename
the Project property currently named public to a more idiomatic boolean name
like isPublic so it does not read like the Kotlin visibility keyword and is
clearer at call sites. Update the Project class property definition and any
usages/accessors in the diff to match the new name, while keeping the existing
database mapping intact via the current column annotation.
e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts (2)

195-209: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Text-content selectors used instead of data-cy.

cy.contains('Community Alpha'), cy.contains('Community Zeta'), and cy.contains('Private project') select/assert purely on rendered text, which breaks on copy/i18n changes.

As per coding guidelines, "STRICTLY use data-cy attributes for E2E selectors, never rely on text content; use typed helpers gcy() or cy.gcy()."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts` around lines 195
- 209, The community projects navigation spec is using text-based assertions
instead of stable E2E selectors. Update the checks in
communityProjectsNavigation.cy.ts to use data-cy via gcy()/cy.gcy() for the
project items and badge visibility, and avoid cy.contains for “Community Alpha”,
“Community Zeta”, and “Private project”. Keep the existing test intent in the
affected it blocks, but reference the same selector helpers already used in this
file such as gcy('dashboard-projects-list-item'),
gcy('project-list-public-badge'), and gcy('global-list-search').

Source: Coding guidelines


78-106: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Text-content chained on gcy selectors.

gcy('organization-switch').contains('Microsoft') and gcy('global-base-view-title').contains('Projects') still rely on text content for the final assertion/target rather than a nested data-cy element.

As per coding guidelines, "STRICTLY use data-cy attributes for E2E selectors, never rely on text content."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts` around lines 78 -
106, The Cypress assertions in communityProjectsNavigation.cy.ts are still using
text-based chaining on gcy selectors, which violates the data-cy-only selector
rule. Update the affected checks in the community switcher and Projects title
tests to target nested data-cy elements instead of contains text, using the
existing gcy and findDcy patterns around organization-switch and
global-base-view-title so the assertions rely only on data-cy attributes.

Source: Coding guidelines

e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts (1)

268-291: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Row lookup relies on text content instead of a distinguishing data-cy attribute.

acceptOnly and openRowMenu locate the target suggestion via .contains(text) against translated suggestion copy. This pattern is reused across nearly every test in this file, so any change in suggestion phrasing/i18n breaks the whole suite.

As per coding guidelines, "STRICTLY use data-cy attributes for E2E selectors, never rely on text content; use typed helpers gcy() or cy.gcy()." Consider exposing a stable per-row identifier (e.g. data-cy-value keyed to suggestion id/index) so rows can be targeted without text matching.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts` around lines
268 - 291, The row-targeting helpers acceptOnly and openRowMenu rely on
translated text via .contains(text), which makes the tests fragile. Update these
helpers and the related callers in suggestions.reviewer.cy.ts to target each
translation-suggestion row using a stable data-cy-based identifier instead of
visible copy, ideally by adding a per-row value such as a suggestion id/index
and selecting it through cy.gcy() or gcyAdvanced(). Keep the action clicks the
same, but remove text matching so the suite no longer depends on suggestion
phrasing or i18n.

Source: Coding guidelines

webapp/src/component/SwitchPopover/SwitchPopover.tsx (1)

88-93: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make footerAction.dataCy required to guarantee E2E testability.

dataCy is optional, so a future caller could add a footerAction without a data-cy selector, making it unreachable from Cypress tests. As per coding guidelines, "STRICTLY use data-cy attributes for E2E selectors, never rely on text content."

♻️ Proposed fix
   footerAction?: {
     content: React.ReactNode;
     onClick: () => void;
-    dataCy?: string;
+    dataCy: string;
   };

Also applies to: 236-247

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webapp/src/component/SwitchPopover/SwitchPopover.tsx` around lines 88 - 93,
Make footerAction.dataCy required in SwitchPopover’s footerAction type so every
action has a Cypress selector. Update the footerAction interface and any related
props/usage in SwitchPopover and the affected call sites so they always pass a
dataCy value. Use the footerAction symbol and any rendering logic that wires the
selector to the footer action button to keep E2E testability guaranteed.

Source: Coding guidelines

webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx (1)

131-172: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add defaultValue for the new translation keys.

translation_suggestion_accept_only and translation_suggestion_accept_and_decline_others appear to be new keys introduced by this PR's suggestion-split feature. As per coding guidelines, always provide defaultValue for new keys so the UI shows meaningful text before they're uploaded to Tolgee.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx`
around lines 131 - 172, The new translation keys used in TranslationSuggestion
are missing required default text. Update the calls in TranslationSuggestion so
the t() lookups for translation_suggestion_accept_only and
translation_suggestion_accept_and_decline_others include defaultValue strings,
alongside the existing translation_suggestion_accept_tooltip and
translation_suggestion_reverse_tooltip usages, so the labels remain meaningful
before Tolgee sync.

Source: Coding guidelines

backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt (1)

138-146: 🔒 Security & Privacy | 🔵 Trivial

Consider enforcing this invariant with a test, not just a comment.

The comment correctly flags a real risk: any future /v2/public/** controller using {projectId}/{organizationId} path vars with @RequiresProjectPermissions would silently bypass authorization since these interceptors aren't registered for public endpoints. Comments can't catch regressions; consider adding an architecture test (e.g. ArchUnit rule scanning for @RequiresProjectPermissions on handlers mapped under /v2/public/**) to fail the build if this invariant is ever violated.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt`
around lines 138 - 146, Add a regression test that enforces the public-route
authorization invariant in WebSecurityConfig by scanning controllers/handlers
under /v2/public/** for any use of `@RequiresProjectPermissions` together with
{projectId}/{organizationId} path vars and failing the build if found. Use a
test such as an ArchUnit rule or equivalent around the relevant annotations and
mappings so future public endpoints cannot silently bypass the
organizationAuthorizationInterceptor/projectAuthorizationInterceptor
restriction.
ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionController.kt (1)

142-150: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Preserve the original cause when rewrapping PermissionException.
PermissionException has no cause-taking constructor, so this catch block drops the root exception. Add a cause-aware overload (via ExceptionWithMessage) or avoid rewrapping here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionController.kt`
around lines 142 - 150, The PermissionException handling in
SuggestionController.checkLanguageSuggestionsManagePermission currently rethrows
a new exception and loses the original cause; update this catch block to
preserve the underlying exception by using a cause-aware path (for example via
ExceptionWithMessage) or by avoiding the rewrap entirely. Keep the existing
special handling for LanguageNotPermittedException, and adjust the
PermissionException branch so the original throwable is carried forward while
still mapping to Message.USER_CAN_ONLY_DELETE_HIS_SUGGESTIONS.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionTest.kt`:
- Around line 20-25: `CommunityPermissionTest.setup()` creates and saves
`ProjectPublishingTestData` but never cleans it up, so add an `@AfterEach`
cleanup that removes the saved `testData` using the same test data lifecycle
pattern used elsewhere. Keep `testData` as the instance to clean, and ensure the
cleanup runs after every test so state does not leak between runs.

In
`@backend/app/src/test/kotlin/io/tolgee/service/ProjectPublishingCachingTest.kt`:
- Around line 20-28: `ProjectPublishingCachingTest` sets up persistent
`BaseTestData` in `setup()` but never cleans it up, leaving test data behind
between runs. Add an `@AfterEach` cleanup method in
`ProjectPublishingCachingTest` that removes the saved `testData` using the
existing test-data cleanup pattern, and keep the `BaseTestData` lifecycle
symmetrical with `testDataService.saveTestData(testData.root)` so the test setup
is created and torn down within the same class.

In `@backend/data/src/main/kotlin/io/tolgee/model/Permission.kt`:
- Around line 107-113: The organization base-permission check in
Permission.prePersist is missing the suggest language sets, so update that
invariant to include both suggestLanguages and suggestManageLanguages alongside
viewLanguages, translateLanguages, and stateChangeLanguages. Make sure the guard
rejects any non-empty language restriction on an organization base Permission,
and keep the existing logic centralized in Permission so the new
suggestManageLanguages field is covered too.

In `@e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts`:
- Line 26: The test data setup in the communityProjectsNavigation Cypress spec
is using the outdated organizationTestData.generate() pattern; replace it with
organizationTestData.generateStandard() in the affected test flow, including the
other matching occurrence noted in the same spec, so the E2E test follows the
standard data generation approach.

In `@e2e/cypress/e2e/projects/publicProjects.cy.ts`:
- Line 22: Replace the outdated test data generation calls in
publicProjects.cy.ts by using publicProjectsData.generateStandard() instead of
publicProjectsData.generate() wherever the current generate() pattern appears.
Update each affected test setup to call the standard generator consistently so
the publicProjectsData fixture follows the E2E coding guideline.
- Around line 37-39: Replace the text-based Cypress assertions in the public
projects test with `data-cy`-driven selectors using `gcy()` or `cy.gcy()`. In
the `publicProjects.cy.ts` spec, update the checks around the `Community Alpha`,
`Community Zeta`, and `Private project` assertions so they target the relevant
elements by their stable `data-cy` attributes instead of `cy.contains(...)`,
keeping the same visibility/existence expectations.

In `@e2e/cypress/e2e/projects/suggestions/suggestions.translator.cy.ts`:
- Around line 71-89: The suggestion deletion test is using translated text via
.contains('Navržený překlad 0-1') instead of stable E2E hooks. Update the
selector chain in the translator spec to scope the target card using
data-cy-based helpers only, ideally through cy.gcy()/gcyAdvanced on the
translation-suggestion element and its child action menu. Keep the same delete
flow, but remove all text-content matching so the test relies on stable
identifiers rather than localized copy.

In `@e2e/cypress/e2e/projects/suggestions/suggestions.unprotected.cy.ts`:
- Around line 48-53: The suggestion selection in the Cypress spec is still using
translated text and a raw closest selector, which bypasses the data-cy-only E2E
standard. Update the test to target the suggestion card via a stable data-cy
identifier using the existing gcy/cy.gcy helpers, and avoid .contains() on
“Navržený překlad 0-1” and the manual
closest('[data-cy="translation-suggestion"]'). If needed, add a unique data-cy
on the suggestion item in the UI and use that stable selector in the test around
gcyAdvanced and the translation-suggestion card.

In
`@ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionControllerTest.kt`:
- Around line 32-53: The `@AfterEach` cleanup in resetClock only clears the forced
date, so persisted SuggestionsTestData from initTestData can leak into later
tests. Update resetClock in SuggestionControllerTest to also invoke
testDataService.cleanTestData(testData.root) after clearForcedDate, using the
existing testDataService and testData symbols so all saved projects and
suggestions are removed after each test.

In `@webapp/src/component/organizationSwitch/CommunityTranslationItem.tsx`:
- Line 19: The CommunityTranslationItem component is calling
t('community_translation_switch_item') without a defaultValue, which can leave
the UI blank before the translation exists in Tolgee. Update the t() usage in
CommunityTranslationItem to include a meaningful defaultValue so the label
always renders readable text, following the existing i18n pattern used elsewhere
in the app.

In `@webapp/src/component/PermissionsSettings/LanguagePermissionsSummary.tsx`:
- Around line 20-21: The LanguagePermissionsSummary component is omitting
suggest-manage-only languages because languagesUnion and the derived
hintNeeded/tooltip logic in the summary do not include suggestManageLanguageIds
even though it is already present in categories. Update the union construction
in LanguagePermissionsSummary so suggestManageLanguageIds participates alongside
viewLanguageIds, translateLanguageIds, and stateChangeLanguageIds, and ensure
the chip/tooltip rendering paths still use that same union-derived set.

In `@webapp/src/views/projects/CommunityProjectsView.tsx`:
- Line 56: The new translation keys in CommunityProjectsView are missing
defaultValue, so the UI can render raw key names before Tolgee syncs. Update the
t() usage for community_projects_window_title and the T component/string for
public_projects_empty to include meaningful defaultValue text, following the
project guideline that all new translation keys must provide a fallback.

In `@webapp/src/views/projects/DashboardProjectListItem.tsx`:
- Around line 201-207: The new translation key used in DashboardProjectListItem
via t('project_list_public_badge') is missing a defaultValue, so the badge can
render blank before Tolgee updates. Update the translation call in
StyledPublicChip to include a meaningful defaultValue for
project_list_public_badge, following the same pattern used elsewhere in the
project for new T/t() keys.
- Around line 178-186: The onClick handler in DashboardProjectListItem currently
sends unauthenticated users directly to LINKS.LOGIN.build() without preserving
the project they clicked, so the post-login redirect cannot return them to that
project. Update the isPublicVariant && !allowPrivate branch to save the intended
project destination as the afterLoginLink before navigating to login, using the
same project URL that LINKS.PROJECT_DASHBOARD.build creates for p.id, while
keeping the existing history.push flow intact.

In `@webapp/src/views/projects/project/ProjectSettingsAdvanced.tsx`:
- Around line 62-77: The new public-project translation keys are used in
ProjectSettingsAdvanced without fallback text, so add defaultValue to each T
usage involved in the public/private section and the make-public/make-private
dialog content. Update the relevant T components in ProjectSettingsAdvanced so
the title and message (and the public section labels/hint in the same component)
all provide meaningful default text for project_settings_public_section_title,
project_settings_public_label, project_settings_public_hint,
project_settings_make_public_dialog_title,
project_settings_make_private_dialog_title,
project_settings_make_public_confirmation, and
project_settings_make_private_confirmation.

In `@webapp/src/views/projects/ProjectListView.tsx`:
- Around line 60-68: The ProjectListView search handler only updates search text
and does not reset pagination, which can leave the view on an invalid page after
filtering. Update the search flow in ProjectListView so the handler passed to
BaseView.onSearch also resets page to 0 when a new search is entered, matching
the behavior used in CommunityProjectsView.tsx. Keep the change localized to the
search state update path and use the existing setSearch and setPage state
setters.

In `@webapp/src/views/projects/translations/Suggestions/SuggestionsFirst.tsx`:
- Line 74: The new translation lookup in SuggestionsFirst using
t('translation_tools_suggestions_show_all_label') is missing a defaultValue, so
add a meaningful fallback string to this call. Update the t() usage in
SuggestionsFirst to include defaultValue so the UI shows readable text before
the translation is available in Tolgee.

In `@webapp/src/views/projects/translations/Suggestions/SuggestionsList.tsx`:
- Around line 140-150: The mapping in SuggestionsList uses inconsistent optional
chaining for firstPage: the suggestions slice is guarded, but
activeSuggestionCount still reads firstPage.page?.totalElements directly and can
throw if firstPage is undefined. Update the onSuccess transformation in
SuggestionsList to safely handle a missing firstPage by using the same optional
chaining pattern for activeSuggestionCount, falling back to 0 when
suggestions.pages is empty.

---

Outside diff comments:
In `@backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt`:
- Around line 41-52: `findAllByPermittedLanguage()` is missing the
`suggestLanguages` check, so permissions linked only through that relation are
not returned. Update the query in
`PermissionRepository.findAllByPermittedLanguage` to include `sul.id is not
null` alongside the existing `tl`, `vl`, `scl`, and `sml` conditions so
`PermissionService.removeLanguageFromPermissions()` can remove stale
`suggestLanguages` references.

In `@webapp/src/views/projects/translations/context/services/useEditService.tsx`:
- Around line 191-206: The suggestion merge in useEditService’s
updateTranslation data callback should dedupe by id before prepending the new
result, since value.suggestions may already contain the same suggestion from
another update path. Update the logic around result, value.suggestions, and
MAX_DISPLAYED_SUGGESTIONS so the merged array keeps only one entry per s.id
while preserving the existing count updates.

In
`@webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx`:
- Around line 198-212: The tooltip and avatar author lookup in
TranslationSuggestion should not rely on suggestion.author.name ??
suggestion.author.username alone, since username may be an empty masked string.
Update the author label logic used by the Tooltip title and the AvatarImg owner
in TranslationSuggestion to fall back to a non-blank display value when name is
missing and username is empty, using the suggestion.author object as the source
of truth.

---

Nitpick comments:
In `@backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt`:
- Around line 138-146: Add a regression test that enforces the public-route
authorization invariant in WebSecurityConfig by scanning controllers/handlers
under /v2/public/** for any use of `@RequiresProjectPermissions` together with
{projectId}/{organizationId} path vars and failing the build if found. Use a
test such as an ArchUnit rule or equivalent around the relevant annotations and
mappings so future public endpoints cannot silently bypass the
organizationAuthorizationInterceptor/projectAuthorizationInterceptor
restriction.

In
`@backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt`:
- Around line 9-23: `PublicProjectsE2eData` silently caps seeded projects at 6
because the `listOf(...).take(count)` source is fixed-length; update the `init`
block to validate or constrain `count` explicitly so callers can’t request more
than the available suffixes without being told. If `count` should be limited,
guard it up front in `PublicProjectsE2eData` and fail fast or clamp with an
intentional message; if more than 6 projects should be supported, replace the
hardcoded suffix list with a generator that can produce enough unique names
before calling `addProject`.

In `@backend/data/src/main/kotlin/io/tolgee/model/Project.kt`:
- Line 175: Rename the Project property currently named public to a more
idiomatic boolean name like isPublic so it does not read like the Kotlin
visibility keyword and is clearer at call sites. Update the Project class
property definition and any usages/accessors in the diff to match the new name,
while keeping the existing database mapping intact via the current column
annotation.

In `@e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts`:
- Around line 195-209: The community projects navigation spec is using
text-based assertions instead of stable E2E selectors. Update the checks in
communityProjectsNavigation.cy.ts to use data-cy via gcy()/cy.gcy() for the
project items and badge visibility, and avoid cy.contains for “Community Alpha”,
“Community Zeta”, and “Private project”. Keep the existing test intent in the
affected it blocks, but reference the same selector helpers already used in this
file such as gcy('dashboard-projects-list-item'),
gcy('project-list-public-badge'), and gcy('global-list-search').
- Around line 78-106: The Cypress assertions in
communityProjectsNavigation.cy.ts are still using text-based chaining on gcy
selectors, which violates the data-cy-only selector rule. Update the affected
checks in the community switcher and Projects title tests to target nested
data-cy elements instead of contains text, using the existing gcy and findDcy
patterns around organization-switch and global-base-view-title so the assertions
rely only on data-cy attributes.

In `@e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts`:
- Around line 268-291: The row-targeting helpers acceptOnly and openRowMenu rely
on translated text via .contains(text), which makes the tests fragile. Update
these helpers and the related callers in suggestions.reviewer.cy.ts to target
each translation-suggestion row using a stable data-cy-based identifier instead
of visible copy, ideally by adding a per-row value such as a suggestion id/index
and selecting it through cy.gcy() or gcyAdvanced(). Keep the action clicks the
same, but remove text matching so the suite no longer depends on suggestion
phrasing or i18n.

In
`@ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionController.kt`:
- Around line 142-150: The PermissionException handling in
SuggestionController.checkLanguageSuggestionsManagePermission currently rethrows
a new exception and loses the original cause; update this catch block to
preserve the underlying exception by using a cause-aware path (for example via
ExceptionWithMessage) or by avoiding the rewrap entirely. Keep the existing
special handling for LanguageNotPermittedException, and adjust the
PermissionException branch so the original throwable is carried forward while
still mapping to Message.USER_CAN_ONLY_DELETE_HIS_SUGGESTIONS.

In `@webapp/src/component/SwitchPopover/SwitchPopover.tsx`:
- Around line 88-93: Make footerAction.dataCy required in SwitchPopover’s
footerAction type so every action has a Cypress selector. Update the
footerAction interface and any related props/usage in SwitchPopover and the
affected call sites so they always pass a dataCy value. Use the footerAction
symbol and any rendering logic that wires the selector to the footer action
button to keep E2E testability guaranteed.

In `@webapp/src/views/projects/translations/context/services/useEditService.tsx`:
- Line 20: The import in useEditService should use the tg.views alias instead of
a cross-directory relative path. Update the MAX_DISPLAYED_SUGGESTIONS import to
point through the views alias so it follows the project’s Tolgee path-alias
convention and avoids relative imports across directories.

In
`@webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx`:
- Around line 131-172: The new translation keys used in TranslationSuggestion
are missing required default text. Update the calls in TranslationSuggestion so
the t() lookups for translation_suggestion_accept_only and
translation_suggestion_accept_and_decline_others include defaultValue strings,
alongside the existing translation_suggestion_accept_tooltip and
translation_suggestion_reverse_tooltip usages, so the labels remain meaningful
before Tolgee sync.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 26edd629-e21a-4c7b-8ccd-f005a3082d26

📥 Commits

Reviewing files that changed from the base of the PR and between aff9d7a and ec88b34.

⛔ Files ignored due to path filters (1)
  • webapp/public/images/communityMouse.svg is excluded by !**/*.svg
📒 Files selected for processing (132)
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/dataImport/ImportSettingsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/machineTranslation/MtCreditsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsPublishingController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/PublicProjectsController.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyWithTranslationsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/suggestions/TranslationSuggestionSimpleModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt
  • backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionComputationTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PublicProjectsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/notification/NotificationControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/ProjectsControllerPublishingTest.kt
  • backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/service/ProjectPublishingCachingTest.kt
  • backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt
  • backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectPublishingTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsListDashboardTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsControllerTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsStatsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/IPermission.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/organization/BasePermissionView.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/RequestWithLanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetPermissionLanguageParams.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetProjectPublicRequest.kt
  • backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Permission.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Project.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectView.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt
  • backend/data/src/main/resources/db/changelog/schema.xml
  • backend/data/src/test/kotlin/io/tolgee/unit/CommunityPermissionScopesTest.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/MemberInfoMaskingTest.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PublicProjectsE2eDataController.kt
  • e2e/cypress/common/apiCalls/testData/testData.ts
  • e2e/cypress/e2e/administration/base.cy.ts
  • e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts
  • e2e/cypress/e2e/projects/projectsListDashboard.cy.ts
  • e2e/cypress/e2e/projects/publicProjects.cy.ts
  • e2e/cypress/e2e/projects/settings.public.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.translator.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.unprotected.cy.ts
  • e2e/cypress/e2e/translations/translationFilters.suggestions.cy.ts
  • e2e/cypress/support/dataCyType.d.ts
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/TaskController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/branching/BranchController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/repository/TranslationSuggestionRepository.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/service/TranslationSuggestionServiceEeImpl.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/CommunitySuggestionTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerPermissionsTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerTest.kt
  • webapp/src/component/PermissionsSettings/LanguagePermissionsSummary.tsx
  • webapp/src/component/PermissionsSettings/PermissionsSettings.tsx
  • webapp/src/component/PermissionsSettings/hierarchyTools.ts
  • webapp/src/component/PermissionsSettings/usePermissionsStructure.ts
  • webapp/src/component/PermissionsSettings/useScopeTranslations.tsx
  • webapp/src/component/RootRouter.tsx
  • webapp/src/component/SwitchPopover/SwitchPopover.tsx
  • webapp/src/component/layout/BaseView.tsx
  • webapp/src/component/layout/HeaderBar.tsx
  • webapp/src/component/organizationSwitch/CommunityTranslationItem.tsx
  • webapp/src/component/organizationSwitch/OrganizationPopover.tsx
  • webapp/src/component/organizationSwitch/OrganizationSwitch.tsx
  • webapp/src/constants/links.tsx
  • webapp/src/fixtures/permissions.ts
  • webapp/src/service/apiSchema.generated.ts
  • webapp/src/service/apiSchemaTypes.generated.ts
  • webapp/src/views/projects/CommunityProjectsView.tsx
  • webapp/src/views/projects/DashboardProjectListItem.tsx
  • webapp/src/views/projects/ProjectListView.tsx
  • webapp/src/views/projects/ProjectsList.tsx
  • webapp/src/views/projects/dashboard/ProjectTotals.tsx
  • webapp/src/views/projects/project/ProjectSettingsAdvanced.tsx
  • webapp/src/views/projects/public/CommunityTranslationBanner.tsx
  • webapp/src/views/projects/public/PublicProjectListView.tsx
  • webapp/src/views/projects/public/PublicTopBar.tsx
  • webapp/src/views/projects/public/publicProjectsLayout.ts
  • webapp/src/views/projects/translations/Suggestions/SuggestionsFirst.tsx
  • webapp/src/views/projects/translations/Suggestions/SuggestionsList.tsx
  • webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx
  • webapp/src/views/projects/translations/Suggestions/__tests__/utils.test.ts
  • webapp/src/views/projects/translations/Suggestions/useInfiniteSuggestions.ts
  • webapp/src/views/projects/translations/Suggestions/utils.ts
  • webapp/src/views/projects/translations/TranslationsList/TranslationRead.tsx
  • webapp/src/views/projects/translations/TranslationsTable/TranslationRead.tsx
  • webapp/src/views/projects/translations/context/services/useEditService.tsx
  • webapp/src/views/projects/useLatchedSearchVisibility.ts

Comment thread backend/data/src/main/kotlin/io/tolgee/model/Permission.kt
Comment thread e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts
Comment thread e2e/cypress/e2e/projects/publicProjects.cy.ts Outdated
Comment thread webapp/src/views/projects/DashboardProjectListItem.tsx
Comment thread webapp/src/views/projects/project/ProjectSettingsAdvanced.tsx
Comment thread webapp/src/views/projects/ProjectListView.tsx
@Anty0
Anty0 force-pushed the jirikuchynka/public-projects branch from ec88b34 to 5153a35 Compare July 3, 2026 08:35

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsPublishingController.kt`:
- Around line 21-29: The publishing controller currently applies wildcard CORS
at the class level, which is too broad for the authenticated project-visibility
update endpoint. Remove the `@CrossOrigin(origins = ["*"])` from
`ProjectsPublishingController` and rely on the app’s shared CORS configuration,
or replace it with a narrowly scoped origin list if this endpoint truly needs
its own setting. Keep the change localized to `ProjectsPublishingController` so
the `PUT` publishing action remains protected by trusted-origin rules.

In
`@ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionController.kt`:
- Around line 117-119: The OpenAPI description for
SuggestionController.deleteSuggestion is missing the updated delete
authorization rule, so the docs are now ambiguous. Update the `@Operation`
summary/description on deleteSuggestion in SuggestionController to explicitly
state that deletion is allowed either by the suggestion author or by users with
suggestion-management permission, keeping the API docs aligned with the actual
authorization behavior.
- Around line 148-149: The PermissionException handling in
SuggestionController’s delete flow is dropping the original cause by rethrowing
only a new message. Update the catch block to preserve the caught
PermissionException as the cause, either by using an existing cause-aware
constructor or by adding one to PermissionException, so the original failure is
retained when rethrown.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea2f1c9a-9973-4756-8e38-8d202a37539b

📥 Commits

Reviewing files that changed from the base of the PR and between ec88b34 and 5153a35.

⛔ Files ignored due to path filters (1)
  • webapp/public/images/communityMouse.svg is excluded by !**/*.svg
📒 Files selected for processing (133)
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/dataImport/ImportSettingsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/machineTranslation/MtCreditsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsPublishingController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/PublicProjectsController.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyWithTranslationsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/suggestions/TranslationSuggestionSimpleModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt
  • backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionComputationTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PublicProjectsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/notification/NotificationControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/ProjectsControllerPublishingTest.kt
  • backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/service/ProjectPublishingCachingTest.kt
  • backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt
  • backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectPublishingTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsListDashboardTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsControllerTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsStatsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/IPermission.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/organization/BasePermissionView.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/RequestWithLanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetPermissionLanguageParams.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetProjectPublicRequest.kt
  • backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Permission.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Project.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectView.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt
  • backend/data/src/main/resources/db/changelog/schema.xml
  • backend/data/src/test/kotlin/io/tolgee/unit/CommunityPermissionScopesTest.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/MemberInfoMaskingTest.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/PermissionOrgBaseLanguageGuardTest.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PublicProjectsE2eDataController.kt
  • e2e/cypress/common/apiCalls/testData/testData.ts
  • e2e/cypress/e2e/administration/base.cy.ts
  • e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts
  • e2e/cypress/e2e/projects/projectsListDashboard.cy.ts
  • e2e/cypress/e2e/projects/publicProjects.cy.ts
  • e2e/cypress/e2e/projects/settings.public.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.translator.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.unprotected.cy.ts
  • e2e/cypress/e2e/translations/translationFilters.suggestions.cy.ts
  • e2e/cypress/support/dataCyType.d.ts
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/TaskController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/branching/BranchController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/repository/TranslationSuggestionRepository.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/service/TranslationSuggestionServiceEeImpl.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/CommunitySuggestionTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerPermissionsTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerTest.kt
  • webapp/src/component/PermissionsSettings/LanguagePermissionsSummary.tsx
  • webapp/src/component/PermissionsSettings/PermissionsSettings.tsx
  • webapp/src/component/PermissionsSettings/hierarchyTools.ts
  • webapp/src/component/PermissionsSettings/usePermissionsStructure.ts
  • webapp/src/component/PermissionsSettings/useScopeTranslations.tsx
  • webapp/src/component/RootRouter.tsx
  • webapp/src/component/SwitchPopover/SwitchPopover.tsx
  • webapp/src/component/layout/BaseView.tsx
  • webapp/src/component/layout/HeaderBar.tsx
  • webapp/src/component/organizationSwitch/CommunityTranslationItem.tsx
  • webapp/src/component/organizationSwitch/OrganizationPopover.tsx
  • webapp/src/component/organizationSwitch/OrganizationSwitch.tsx
  • webapp/src/constants/links.tsx
  • webapp/src/fixtures/permissions.ts
  • webapp/src/service/apiSchema.generated.ts
  • webapp/src/service/apiSchemaTypes.generated.ts
  • webapp/src/views/projects/CommunityProjectsView.tsx
  • webapp/src/views/projects/DashboardProjectListItem.tsx
  • webapp/src/views/projects/ProjectListView.tsx
  • webapp/src/views/projects/ProjectsList.tsx
  • webapp/src/views/projects/dashboard/ProjectTotals.tsx
  • webapp/src/views/projects/project/ProjectSettingsAdvanced.tsx
  • webapp/src/views/projects/public/CommunityTranslationBanner.tsx
  • webapp/src/views/projects/public/PublicProjectListView.tsx
  • webapp/src/views/projects/public/PublicTopBar.tsx
  • webapp/src/views/projects/public/publicProjectsLayout.ts
  • webapp/src/views/projects/translations/Suggestions/SuggestionsFirst.tsx
  • webapp/src/views/projects/translations/Suggestions/SuggestionsList.tsx
  • webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx
  • webapp/src/views/projects/translations/Suggestions/__tests__/utils.test.ts
  • webapp/src/views/projects/translations/Suggestions/useInfiniteSuggestions.ts
  • webapp/src/views/projects/translations/Suggestions/utils.ts
  • webapp/src/views/projects/translations/TranslationsList/TranslationRead.tsx
  • webapp/src/views/projects/translations/TranslationsTable/TranslationRead.tsx
  • webapp/src/views/projects/translations/context/services/useEditService.tsx
  • webapp/src/views/projects/useLatchedSearchVisibility.ts
✅ Files skipped from review due to trivial changes (9)
  • webapp/src/views/projects/public/publicProjectsLayout.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsListDashboardTestData.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt
  • webapp/src/component/layout/BaseView.tsx
  • backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerPermissionsTest.kt
  • webapp/src/service/apiSchemaTypes.generated.ts
  • e2e/cypress/support/dataCyType.d.ts
🚧 Files skipped from review as they are similar to previous changes (116)
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/IPermission.kt
  • webapp/src/views/projects/translations/Suggestions/useInfiniteSuggestions.ts
  • webapp/src/component/organizationSwitch/CommunityTranslationItem.tsx
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetProjectPublicRequest.kt
  • webapp/src/component/PermissionsSettings/useScopeTranslations.tsx
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectView.kt
  • webapp/src/views/projects/useLatchedSearchVisibility.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModel.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt
  • e2e/cypress/e2e/projects/suggestions/suggestions.unprotected.cy.ts
  • backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt
  • backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsStatsTestData.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt
  • backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetPermissionLanguageParams.kt
  • webapp/src/component/PermissionsSettings/LanguagePermissionsSummary.tsx
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/machineTranslation/MtCreditsController.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerTest.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt
  • webapp/src/fixtures/permissions.ts
  • webapp/src/views/projects/public/PublicTopBar.tsx
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt
  • webapp/src/constants/links.tsx
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/RequestWithLanguagePermissions.kt
  • webapp/src/component/RootRouter.tsx
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt
  • webapp/src/views/projects/ProjectsList.tsx
  • backend/data/src/main/kotlin/io/tolgee/model/Project.kt
  • webapp/src/component/PermissionsSettings/usePermissionsStructure.ts
  • backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/suggestions/TranslationSuggestionSimpleModelAssembler.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectPublishingTestData.kt
  • webapp/src/views/projects/dashboard/ProjectTotals.tsx
  • backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyWithTranslationsModelAssembler.kt
  • webapp/src/views/projects/translations/Suggestions/utils.ts
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsControllerTestData.kt
  • webapp/src/views/projects/translations/TranslationsList/TranslationRead.tsx
  • backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt
  • backend/app/src/test/kotlin/io/tolgee/service/ProjectPublishingCachingTest.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt
  • e2e/cypress/e2e/translations/translationFilters.suggestions.cy.ts
  • webapp/src/views/projects/translations/TranslationsTable/TranslationRead.tsx
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/notification/NotificationControllerTest.kt
  • e2e/cypress/e2e/projects/projectsListDashboard.cy.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyModelAssembler.kt
  • e2e/cypress/e2e/administration/base.cy.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt
  • webapp/src/views/projects/ProjectListView.tsx
  • webapp/src/views/projects/translations/Suggestions/SuggestionsFirst.tsx
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt
  • e2e/cypress/e2e/projects/suggestions/suggestions.translator.cy.ts
  • webapp/src/views/projects/translations/context/services/useEditService.tsx
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt
  • backend/data/src/main/resources/db/changelog/schema.xml
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/ProjectsControllerPublishingTest.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt
  • webapp/src/views/projects/translations/Suggestions/tests/utils.test.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt
  • webapp/src/views/projects/public/CommunityTranslationBanner.tsx
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/branching/BranchController.kt
  • e2e/cypress/e2e/projects/settings.public.cy.ts
  • e2e/cypress/common/apiCalls/testData/testData.ts
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/CommunitySuggestionTest.kt
  • webapp/src/views/projects/project/ProjectSettingsAdvanced.tsx
  • webapp/src/component/PermissionsSettings/hierarchyTools.ts
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionComputationTest.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/organization/BasePermissionView.kt
  • webapp/src/component/SwitchPopover/SwitchPopover.tsx
  • webapp/src/component/PermissionsSettings/PermissionsSettings.tsx
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/repository/TranslationSuggestionRepository.kt
  • webapp/src/views/projects/public/PublicProjectListView.tsx
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/PublicProjectsController.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/TaskController.kt
  • webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx
  • webapp/src/component/organizationSwitch/OrganizationPopover.tsx
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt
  • e2e/cypress/e2e/projects/publicProjects.cy.ts
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PublicProjectsControllerTest.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/service/TranslationSuggestionServiceEeImpl.kt
  • e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts
  • webapp/src/component/organizationSwitch/OrganizationSwitch.tsx
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionsTestData.kt
  • e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts
  • webapp/src/views/projects/translations/Suggestions/SuggestionsList.tsx
  • backend/data/src/test/kotlin/io/tolgee/unit/CommunityPermissionScopesTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionTest.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/dataImport/ImportSettingsController.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt
  • webapp/src/component/layout/HeaderBar.tsx
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModelAssembler.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionControllerTest.kt
  • webapp/src/service/apiSchema.generated.ts
  • webapp/src/views/projects/CommunityProjectsView.tsx
  • backend/data/src/test/kotlin/io/tolgee/unit/MemberInfoMaskingTest.kt

@Anty0
Anty0 force-pushed the jirikuchynka/public-projects branch from 5153a35 to cb9efc5 Compare July 3, 2026 13:08

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@webapp/src/views/projects/public/PublicProjectListView.tsx`:
- Line 41: The translation calls in PublicProjectListView are missing
defaultValue, so add fallback text to the useWindowTitle(t(...)) call for
public_projects_window_title and to the T usage for public_projects_empty.
Update the existing i18n keys in PublicProjectListView so both the window title
and empty-state text render meaningful content before Tolgee translations are
available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7cf6cd31-290b-46ae-ba45-3052c7efc4b9

📥 Commits

Reviewing files that changed from the base of the PR and between 5153a35 and cb9efc5.

⛔ Files ignored due to path filters (1)
  • webapp/public/images/communityMouse.svg is excluded by !**/*.svg
📒 Files selected for processing (122)
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/dataImport/ImportSettingsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/machineTranslation/MtCreditsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsPublishingController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/PublicProjectsController.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyWithTranslationsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/suggestions/TranslationSuggestionSimpleModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt
  • backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionComputationTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PublicProjectsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/notification/NotificationControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt
  • backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt
  • backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectPublishingTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsListDashboardTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsControllerTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsStatsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/IPermission.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/organization/BasePermissionView.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/RequestWithLanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetPermissionLanguageParams.kt
  • backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Permission.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt
  • backend/data/src/main/resources/db/changelog/schema.xml
  • backend/data/src/test/kotlin/io/tolgee/unit/CommunityPermissionScopesTest.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/MemberInfoMaskingTest.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/PermissionOrgBaseLanguageGuardTest.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PublicProjectsE2eDataController.kt
  • e2e/cypress/common/apiCalls/testData/testData.ts
  • e2e/cypress/e2e/administration/base.cy.ts
  • e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts
  • e2e/cypress/e2e/projects/projectsListDashboard.cy.ts
  • e2e/cypress/e2e/projects/publicProjects.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.translator.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.unprotected.cy.ts
  • e2e/cypress/e2e/translations/translationFilters.suggestions.cy.ts
  • e2e/cypress/support/dataCyType.d.ts
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/TaskController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/branching/BranchController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/repository/TranslationSuggestionRepository.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/service/TranslationSuggestionServiceEeImpl.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/CommunitySuggestionTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerPermissionsTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerTest.kt
  • webapp/src/component/PermissionsSettings/LanguagePermissionsSummary.tsx
  • webapp/src/component/PermissionsSettings/PermissionsSettings.tsx
  • webapp/src/component/PermissionsSettings/hierarchyTools.ts
  • webapp/src/component/PermissionsSettings/usePermissionsStructure.ts
  • webapp/src/component/PermissionsSettings/useScopeTranslations.tsx
  • webapp/src/component/RootRouter.tsx
  • webapp/src/component/SwitchPopover/SwitchPopover.tsx
  • webapp/src/component/layout/BaseView.tsx
  • webapp/src/component/layout/HeaderBar.tsx
  • webapp/src/component/organizationSwitch/CommunityTranslationItem.tsx
  • webapp/src/component/organizationSwitch/OrganizationPopover.tsx
  • webapp/src/component/organizationSwitch/OrganizationSwitch.tsx
  • webapp/src/constants/links.tsx
  • webapp/src/fixtures/permissions.ts
  • webapp/src/service/apiSchema.generated.ts
  • webapp/src/views/projects/CommunityProjectsView.tsx
  • webapp/src/views/projects/DashboardProjectListItem.tsx
  • webapp/src/views/projects/ProjectListView.tsx
  • webapp/src/views/projects/ProjectsList.tsx
  • webapp/src/views/projects/dashboard/ProjectTotals.tsx
  • webapp/src/views/projects/public/CommunityTranslationBanner.tsx
  • webapp/src/views/projects/public/PublicProjectListView.tsx
  • webapp/src/views/projects/public/PublicTopBar.tsx
  • webapp/src/views/projects/public/publicProjectsLayout.ts
  • webapp/src/views/projects/translations/Suggestions/SuggestionsFirst.tsx
  • webapp/src/views/projects/translations/Suggestions/SuggestionsList.tsx
  • webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx
  • webapp/src/views/projects/translations/Suggestions/__tests__/utils.test.ts
  • webapp/src/views/projects/translations/Suggestions/useInfiniteSuggestions.ts
  • webapp/src/views/projects/translations/Suggestions/utils.ts
  • webapp/src/views/projects/translations/TranslationsList/TranslationRead.tsx
  • webapp/src/views/projects/translations/TranslationsTable/TranslationRead.tsx
  • webapp/src/views/projects/translations/context/services/useEditService.tsx
  • webapp/src/views/projects/useLatchedSearchVisibility.ts
  • webapp/src/views/projects/usePublicProjectsList.ts
✅ Files skipped from review due to trivial changes (7)
  • webapp/src/views/projects/public/publicProjectsLayout.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModelAssembler.kt
  • backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/suggestions/TranslationSuggestionSimpleModelAssembler.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt
  • e2e/cypress/support/dataCyType.d.ts
🚧 Files skipped from review as they are similar to previous changes (108)
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsListDashboardTestData.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/notification/NotificationControllerTest.kt
  • e2e/cypress/e2e/projects/projectsListDashboard.cy.ts
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsStatsTestData.kt
  • webapp/src/component/layout/BaseView.tsx
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/machineTranslation/MtCreditsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsPublishingController.kt
  • webapp/src/views/projects/translations/Suggestions/useInfiniteSuggestions.ts
  • webapp/src/views/projects/translations/TranslationsList/TranslationRead.tsx
  • backend/data/src/test/kotlin/io/tolgee/unit/PermissionOrgBaseLanguageGuardTest.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsControllerTestData.kt
  • e2e/cypress/e2e/projects/suggestions/suggestions.unprotected.cy.ts
  • webapp/src/component/PermissionsSettings/LanguagePermissionsSummary.tsx
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetPermissionLanguageParams.kt
  • e2e/cypress/e2e/administration/base.cy.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyWithTranslationsModelAssembler.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectPublishingTestData.kt
  • webapp/src/views/projects/translations/TranslationsTable/TranslationRead.tsx
  • backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt
  • webapp/src/views/projects/useLatchedSearchVisibility.ts
  • backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt
  • webapp/src/views/projects/translations/context/services/useEditService.tsx
  • backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/organization/BasePermissionView.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt
  • webapp/src/component/PermissionsSettings/hierarchyTools.ts
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModel.kt
  • backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt
  • webapp/src/views/projects/public/PublicTopBar.tsx
  • webapp/src/fixtures/permissions.ts
  • webapp/src/component/organizationSwitch/CommunityTranslationItem.tsx
  • e2e/cypress/common/apiCalls/testData/testData.ts
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PublicProjectsE2eDataController.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/IPermission.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/MemberInfoMaskingTest.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt
  • backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt
  • webapp/src/component/organizationSwitch/OrganizationPopover.tsx
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionComputationTest.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt
  • webapp/src/constants/links.tsx
  • webapp/src/component/PermissionsSettings/PermissionsSettings.tsx
  • webapp/src/views/projects/public/CommunityTranslationBanner.tsx
  • webapp/src/component/PermissionsSettings/usePermissionsStructure.ts
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerTest.kt
  • webapp/src/views/projects/translations/Suggestions/SuggestionsFirst.tsx
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerPermissionsTest.kt
  • backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/branching/BranchController.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Permission.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt
  • webapp/src/component/layout/HeaderBar.tsx
  • webapp/src/component/SwitchPopover/SwitchPopover.tsx
  • backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt
  • webapp/src/views/projects/dashboard/ProjectTotals.tsx
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/CommunitySuggestionTest.kt
  • webapp/src/views/projects/ProjectListView.tsx
  • webapp/src/component/RootRouter.tsx
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/repository/TranslationSuggestionRepository.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/dataImport/ImportSettingsController.kt
  • backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/TaskController.kt
  • webapp/src/views/projects/translations/Suggestions/SuggestionsList.tsx
  • webapp/src/component/PermissionsSettings/useScopeTranslations.tsx
  • e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts
  • webapp/src/views/projects/DashboardProjectListItem.tsx
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/RequestWithLanguagePermissions.kt
  • webapp/src/component/organizationSwitch/OrganizationSwitch.tsx
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt
  • webapp/src/views/projects/ProjectsList.tsx
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionControllerTest.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionsTestData.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/service/TranslationSuggestionServiceEeImpl.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt
  • e2e/cypress/e2e/projects/publicProjects.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.translator.cy.ts
  • e2e/cypress/e2e/translations/translationFilters.suggestions.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts
  • backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt
  • webapp/src/views/projects/translations/Suggestions/TranslationSuggestion.tsx
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyModelAssembler.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/CommunityPermissionScopesTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionTest.kt
  • backend/data/src/main/resources/db/changelog/schema.xml
  • webapp/src/service/apiSchema.generated.ts
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PublicProjectsControllerTest.kt

Comment thread webapp/src/views/projects/public/PublicProjectListView.tsx
@Anty0
Anty0 force-pushed the jirikuchynka/public-projects branch 2 times, most recently from 5d8a325 to 43c0984 Compare July 3, 2026 14:24
@Anty0
Anty0 requested a review from dkrizan July 3, 2026 14:25
Comment thread e2e/cypress/e2e/projects/settings.public.cy.ts Outdated
const value = !project.public;
confirmation({
title: value ? (
<T keyName="project_settings_make_public_dialog_title" />

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I believe we all started to use a defaultValue for all new translation keys. Do you intentionally miss them? Tbh, I’m fine with both options, as long as you don't forget to add translations.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yee, it is intentional ^^
We need to sit down to discuss this. I think it's a bad idea because it masks problems. When a translation is missing, we won't notice because the default value is used. Plus, the default value could become outdated since no one will update it when the translation changes in Tolgee UI/in-context.

I plan to remove the rule in PR #3574, but I haven't finished it yet. The main difference would be that the agent adds the default value only temporarily.

I used to tell myself that at least we have the test checking for missing translations, so the default values can't break anything. Then I found out the test had been broken for half a year (#3787) and nobody had noticed. :D

Either way, I can add them if we decide to go that route, but yes, it's intentional. ^^

@dkrizan

dkrizan commented Jul 13, 2026

Copy link
Copy Markdown
Member

Good job @Anty0. I haven't found anything critical.

@Anty0 Anty0 changed the title feat: Community Translation v1.0 feat: Community Translation v1 Jul 14, 2026
Anty0 and others added 4 commits July 14, 2026 21:10
Add a `public` flag to projects, flippable only by the organization
owner (or a server admin) via a dedicated endpoint
(PUT /v2/projects/{id}/publishing). Surfaced as a confirmation-guarded
switch in advanced project settings.

First sub-task of Community Translation v1.0 (#3763). The public-projects
discovery page, community permission, and the public/private indicator
(pending design) follow as separate sub-tasks merged into this branch.
Authenticated users on a public project get a computed community permission (read subset of VIEW + translations-suggest + translation-comments-add, all languages; origin COMMUNITY) without a stored Permission row — they contribute translations without taking a paid seat. Direct/org permissions and admin/supporter elevation layer on top, so no authenticated user is below a non-member; anonymous users get nothing.

- Member emails and the project member count are redacted behind MEMBERS_VIEW across project-scoped REST surfaces; the realtime websocket never carries the author email.
- Out-of-surface endpoints reachable by the community scope set are gated: MT credit balance -> ORGANIZATION_QUOTAS_VIEW, import-settings store -> KEYS_CREATE, branch-merge sessions -> BRANCH_MANAGEMENT, blocking-tasks -> task-view-or-assigned.

BREAKING CHANGE: GET project machine-translation-credit-balance now requires ORGANIZATION_QUOTAS_VIEW; granular permissions and API keys without it get 403 and must be re-granted. Branch-merge session endpoints now require BRANCH_MANAGEMENT.
Part of the Community Translation v1.0 pitch (#3763), PR 1 — Public
projects. Targets the `jirikuchynka/public-projects` branch.

## What

Public projects now show a **second line** under the project name in the
project list row: an outlined lowercase **`public`** badge followed by
the **organization name**. Per the shaped pitch, this list-row badge is
the *only* public indicator — there is no separate icon in the project
detail view.

## Changes

- **Backend**: add `public: Boolean` to `ProjectWithStatsModel` + map it
in `ProjectWithStatsModelAssembler`; regenerate the frontend API schema.
- **Frontend**: `DashboardProjectListItem` renders the badge
(`TransparentChip`, i18n key `project_list_public_badge`) + organization
name when the project is public.
- **Tests**: backend `OrganizationProjectsControllerTest` asserts the
`public` flag is serialized (public + private); cypress
`projectsListDashboard.cy.ts` asserts the badge + org name render on a
public row and are absent on a private row.

## Verification

- Backend test green; ktlint green.
- webapp + e2e eslint + tsc green.
- Cypress `projectsListDashboard.cy.ts` — all 5 tests pass (incl. the 2
new badge tests) against a live dev stack.

## Notes

- i18n key `project_list_public_badge` ("public") created in the Tolgee
project; no inline default in code (matches sibling keys).
- In the normal org list the title column is 150px, so very long org
names ellipsize (consistent with the existing project-name layout). Full
names show in the wider community/public list layouts (later PRs in this
pitch).
…ine others" (#3776)

Part of the Community Translation v1.0 pitch (suggestion resolution
split). Stacked on top of `jirikuchynka/public-projects` — merge that
first.

## What

Splits the single suggestion **Accept** action into two:

- **Accept only** — accepts this suggestion and leaves the competing
suggestions active (`declineOther=false`).
- **Accept and decline others** — accepts this one and declines the rest
(`declineOther=true`, the previous behavior).

### UI (decided with design)

- Inline row actions: **✓ Accept only** and **✕ Decline** (inactive rows
show **↺ Reactivate**).
- Overflow **⋮** menu holds the secondary actions: **Accept and decline
others** and **Delete** (the latter only on your own suggestion). The
menu only renders when at least one of those applies.

## Scope

Frontend-only — the backend already supported `declineOther` on the
accept endpoint (`SuggestionController.acceptSuggestion`), so no
backend, migration, or API-schema changes.

## Notable details

- Optimistic cache fix in `applyAcceptedSuggestion`: on accept-only it
decrements `activeSuggestionCount` but leaves the single-item preview
for the `invalidatePrefix` refetch to reconcile — so the surviving
sibling stays visible and no stale count / phantom `+N` chip flashes.
Covered by a vitest unit test.
- `accept-and-decline-others` is gated on the row being **active** (so
it never appears on declined rows in show-all view).

## i18n

Two new keys created in the **Tolgee itself** project via the Tolgee API
(tagged `draft: suggestion-resolution-split`):
`translation_suggestion_accept_only`,
`translation_suggestion_accept_and_decline_others`. The
previously-unused `translation_suggestion_show_more_tooltip` is
referenced again by the kebab.

## Tests

- Vitest: `applyAcceptedSuggestion` (6 cases).
- Cypress: reworked the suggestion specs for the inline/kebab split
(accept-only keeps the sibling, accept-and-decline-others clears it,
kebab delete, single-suggestion has no kebab, translator can't accept).

### Known follow-ups
- The `active &&` guard's show-all false-branch is not e2e-covered (a
3-active fixture would break the backend `filters by suggestion` test
and key-0 count assertions; the cheap route later is a pure
action-builder helper unit-tested in vitest).
- In-flight `disabled` on menu items not e2e-asserted (flaky to test
deterministically).
@Anty0
Anty0 force-pushed the jirikuchynka/public-projects branch from 93e6fd9 to 1db65f9 Compare July 14, 2026 19:14
@Anty0
Anty0 requested a review from dkrizan July 15, 2026 06:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
webapp/src/component/organizationSwitch/OrganizationPopover.tsx (1)

5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use tg.component for both new component imports. These sibling-relative imports bypass the repository’s required TypeScript alias convention.

  • webapp/src/component/organizationSwitch/OrganizationPopover.tsx#L5-L5: import CommunityTranslationItem through tg.component.
  • webapp/src/component/organizationSwitch/OrganizationSwitch.tsx#L7-L7: import CommunityTranslationItem through tg.component.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webapp/src/component/organizationSwitch/OrganizationPopover.tsx` at line 5,
Replace the relative CommunityTranslationItem imports with the
repository-standard tg.component alias in both OrganizationPopover.tsx (line 5)
and OrganizationSwitch.tsx (line 7).

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@webapp/src/component/organizationSwitch/OrganizationSwitch.tsx`:
- Around line 81-90: Update OrganizationSwitch to accept an onCommunityNavigate
callback and forward it to OrganizationPopover alongside the existing
communitySelected prop, preserving the current organization selection and
navigation behavior.

In `@webapp/src/component/PermissionsSettings/useScopeTranslations.tsx`:
- Around line 12-14: Add meaningful defaultValue fallbacks to both new
translation calls in useScopeTranslations:
permissions_item_translations_suggestions_manage at
webapp/src/component/PermissionsSettings/useScopeTranslations.tsx lines 12-14
and permissions_item_organization_quotas_view at line 59. Keep the existing
translation keys and use fallback text matching each permission label.

---

Nitpick comments:
In `@webapp/src/component/organizationSwitch/OrganizationPopover.tsx`:
- Line 5: Replace the relative CommunityTranslationItem imports with the
repository-standard tg.component alias in both OrganizationPopover.tsx (line 5)
and OrganizationSwitch.tsx (line 7).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 958286d2-2665-484e-893c-b371a5f14621

📥 Commits

Reviewing files that changed from the base of the PR and between 5d8a325 and e20b538.

⛔ Files ignored due to path filters (1)
  • webapp/public/images/communityMouse.svg is excluded by !**/*.svg
📒 Files selected for processing (110)
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/dataImport/ImportSettingsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/machineTranslation/MtCreditsController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsPublishingController.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/PublicProjectsController.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyWithTranslationsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/suggestions/TranslationSuggestionSimpleModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt
  • backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionComputationTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PublicProjectsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/notification/NotificationControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/ProjectsControllerPublishingTest.kt
  • backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/service/ProjectPublishingCachingTest.kt
  • backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt
  • backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectPublishingTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsListDashboardTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsControllerTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsStatsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/IPermission.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/organization/BasePermissionView.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/RequestWithLanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetPermissionLanguageParams.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetProjectPublicRequest.kt
  • backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Permission.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Project.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectView.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt
  • backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt
  • backend/data/src/main/resources/db/changelog/schema.xml
  • backend/data/src/test/kotlin/io/tolgee/unit/CommunityPermissionScopesTest.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/MemberInfoMaskingTest.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/PermissionOrgBaseLanguageGuardTest.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PublicProjectsE2eDataController.kt
  • e2e/cypress/common/apiCalls/testData/testData.ts
  • e2e/cypress/common/shared.ts
  • e2e/cypress/e2e/administration/base.cy.ts
  • e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts
  • e2e/cypress/e2e/projects/projectsListDashboard.cy.ts
  • e2e/cypress/e2e/projects/publicProjects.cy.ts
  • e2e/cypress/e2e/projects/settings.public.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.translator.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.unprotected.cy.ts
  • e2e/cypress/e2e/translations/translationFilters.suggestions.cy.ts
  • e2e/cypress/support/dataCyType.d.ts
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/TaskController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/branching/BranchController.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/repository/TranslationSuggestionRepository.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/service/TranslationSuggestionServiceEeImpl.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/CommunitySuggestionTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerPermissionsTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerTest.kt
  • webapp/src/component/PermissionsSettings/LanguagePermissionsSummary.tsx
  • webapp/src/component/PermissionsSettings/PermissionsSettings.tsx
  • webapp/src/component/PermissionsSettings/hierarchyTools.ts
  • webapp/src/component/PermissionsSettings/usePermissionsStructure.ts
  • webapp/src/component/PermissionsSettings/useScopeTranslations.tsx
  • webapp/src/component/RootRouter.tsx
  • webapp/src/component/SwitchPopover/SwitchPopover.tsx
  • webapp/src/component/layout/BaseView.tsx
  • webapp/src/component/layout/HeaderBar.tsx
  • webapp/src/component/organizationSwitch/CommunityTranslationItem.tsx
  • webapp/src/component/organizationSwitch/OrganizationPopover.tsx
  • webapp/src/component/organizationSwitch/OrganizationSwitch.tsx
🚧 Files skipped from review as they are similar to previous changes (94)
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsListDashboardTestData.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/MemberInfoMaskingTest.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetProjectPublicRequest.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/IPermission.kt
  • e2e/cypress/e2e/projects/suggestions/suggestions.unprotected.cy.ts
  • backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectView.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModel.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/RequestWithLanguagePermissions.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/SetPermissionLanguageParams.kt
  • webapp/src/component/organizationSwitch/CommunityTranslationItem.tsx
  • e2e/cypress/e2e/administration/base.cy.ts
  • webapp/src/component/PermissionsSettings/hierarchyTools.ts
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt
  • backend/data/src/main/kotlin/io/tolgee/model/Project.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModel.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsStatsTestData.kt
  • backend/data/src/test/kotlin/io/tolgee/unit/PermissionOrgBaseLanguageGuardTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt
  • webapp/src/component/PermissionsSettings/PermissionsSettings.tsx
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PublicProjectsE2eDataController.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerPermissionsTest.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/key/trash/TrashedKeyWithTranslationsModelAssembler.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/repository/TranslationSuggestionRepository.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt
  • backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt
  • e2e/cypress/e2e/translations/translationFilters.suggestions.cy.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionWithAgencyModelAssembler.kt
  • backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt
  • webapp/src/component/PermissionsSettings/LanguagePermissionsSummary.tsx
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt
  • backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt
  • backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt
  • backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt
  • backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsControllerTestData.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/notification/NotificationControllerTest.kt
  • backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt
  • webapp/src/component/PermissionsSettings/usePermissionsStructure.ts
  • e2e/cypress/e2e/projects/projectsListDashboard.cy.ts
  • backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/ProjectsControllerPublishingTest.kt
  • backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt
  • e2e/cypress/e2e/projects/communityProjectsNavigation.cy.ts
  • backend/data/src/main/kotlin/io/tolgee/model/Permission.kt
  • backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/TaskController.kt
  • backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt
  • backend/app/src/test/kotlin/io/tolgee/service/ProjectPublishingCachingTest.kt
  • e2e/cypress/common/apiCalls/testData/testData.ts
  • backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/task/TaskControllerTest.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PublicProjectsE2eData.kt
  • e2e/cypress/support/dataCyType.d.ts
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/CommunityPermissionComputationTest.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/CommunitySuggestionTest.kt
  • backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PublicProjectsControllerTest.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt
  • webapp/src/component/SwitchPopover/SwitchPopover.tsx
  • e2e/cypress/e2e/projects/publicProjects.cy.ts
  • webapp/src/component/RootRouter.tsx
  • backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt
  • backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/dataImport/ImportSettingsController.kt
  • backend/data/src/main/resources/db/changelog/schema.xml
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionsTestData.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/branching/BranchController.kt
  • e2e/cypress/e2e/projects/suggestions/suggestions.translator.cy.ts
  • e2e/cypress/e2e/projects/suggestions/suggestions.reviewer.cy.ts
  • backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt
  • backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt
  • ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/SuggestionControllerTest.kt
  • e2e/cypress/e2e/projects/settings.public.cy.ts
  • backend/data/src/test/kotlin/io/tolgee/unit/CommunityPermissionScopesTest.kt
  • ee/backend/app/src/main/kotlin/io/tolgee/ee/service/TranslationSuggestionServiceEeImpl.kt
  • backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/organization/BasePermissionView.kt
  • backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt
  • backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt

Comment thread webapp/src/component/organizationSwitch/OrganizationSwitch.tsx
Comment thread webapp/src/component/PermissionsSettings/useScopeTranslations.tsx
dkrizan
dkrizan previously approved these changes Jul 15, 2026
Anty0 added 2 commits July 15, 2026 16:36
## What

Part of the Community Translation v1.0 pitch (suggestion behavior
changes). The translations list read view showed a single suggestion per
cell; it now shows **up to 3** by default, keeping the existing **`+N`**
overflow badge as the indicator (no new control).

Targets `jirikuchynka/public-projects` to be folded into that PR.

## Changes

**Backend**
- `TranslationSuggestionRepository.getByKeyId` swaps `DISTINCT ON` (1
row/group) for a `row_number()` windowed top-N (`rn <= :maxPerKey`) with
an explicit outer `ORDER BY` — the window `OVER(...)` order only assigns
`row_number()`, not the delivery order. Ordering is `created_at desc, id
desc`.
- `MAX_DISPLAYED_SUGGESTIONS = 3` constant in
`TranslationSuggestionServiceEeImpl` drives the cap.
- No new index: the `WHERE` predicate is unchanged from the previous
query and the existing `(project_id, language_id, key_id)` composite
index covers it.

**Frontend**
- The read view (`SuggestionsFirst`) renders up to 3 and self-caps in
render; the `+N` badge is guarded non-negative.
- The cell cache stays at 3 across the editor **open/close**,
**mutate**, and **suggest-create** paths (the suggest path previously
collapsed the stack to 1).
- The editor suggestion query gains an `id,desc` sort tiebreaker so its
order matches the embed.

## Tests
- Backend: embed cap (3) + `activeSuggestionCount`, per-`(key,
language)` partition isolation, cap-by-constant, and a dedicated
`created_at desc` primary-sort test (created via API at non-id-monotonic
timestamps so id-order and createdAt-order disagree).
- Cypress: read-cell 3-stack + `+N`, open/close, suggest-keeps-3,
decline-then-resync, and a table-view check.

Backend test suite green; frontend `eslint`/`tsc` green for `webapp` and
`e2e`.
Adds a logged-out-capable /public-projects page listing all public projects (stats, search, paging) via a new anonymous GET /v2/public/projects/with-stats endpoint, reusing the project-list UI with a community-translation onboarding banner.

- Backend: PublicProjectsController (anonymous, @OpenApiHideFromPublicDocs, @transactional(readOnly=true)); ProjectService.findAllPublicPaged (NO_USER_ID sentinel); ProjectRepository.findAllPublic (reuses BASE_VIEW_QUERY; guards public/deleted/org-owner/base-language to keep the anonymous read side-effect-free + community-permission floor via #3770).
- Frontend: /public-projects route, PublicProjectListView + PublicTopBar + community-translation banner (Figma-matched gradient, dev-mouse mascot, left-anchored gated search); shared ProjectsList extracted from ProjectListView; DashboardProjectListItem variant='public' (member affordances suppressed, row click -> project when logged-in, else login).
- Tests: PublicProjectsControllerTest (anonymous/member/community/direct-permission joins, guard filters, case-insensitive search) + publicProjects.cy.ts E2E.
Anty0 added 2 commits July 15, 2026 16:36
Projects-page redesign lane of Community Translation v1.0 (#3763).

- Projects list header: centered "Projects" title with the org switcher
  relocated next to it (standaloneTitle: hides the separator, adds top
  spacing, stacks search on its own row). Every non-list page keeps the
  top-left switcher.
- Synthetic "Community translation" switcher entry navigating to
  /community-projects (does not switch org). Implemented but temporarily
  disabled pending contributor tracking; its e2e tests are skipped with a
  re-enable TODO.
- /community-projects page: projects-list shell that ignores the selected
  org and lists all public projects, email-verification gated, with the
  community-translation banner on top (per designer).
- DashboardProjectListItem gains a public grid variant that drops the
  controls column entirely (no reserved space); default layout title width
  150px -> 180px, smaller breakpoints unchanged.
- New i18n keys created in "Tolgee itself"; default values stripped.
## What

Adds a new permission scope **`translation-suggestions.manage`** that
lets project members delete translation suggestions authored by **other
users**. Previously a community suggestion could be deleted only by its
author, so there was no way for project members to clean up spam / bad
suggestions.

Part of Community Translation v1.0 (#3763). Targets the
`jirikuchynka/public-projects` integration branch.

## Details

- **New scope** `translation-suggestions.manage` (enum
`TRANSLATION_SUGGESTIONS_MANAGE`), following the
`translation-labels.manage` sub-entity naming convention. Granted to the
**EDIT** preset (and MANAGE via ADMIN).
- **Own per-language dimension** `suggestManageLanguages` (new
`@ManyToMany` join table `permission_suggest_manage_languages` +
migration with FK constraints), so a moderator can be restricted to
specific languages — wired end-to-end incl. the language-deletion
cleanup + de-escalation path.
- **Granular editor:** `Suggest` and `Manage` are grouped under a new
**"Suggestions"** category, each with its own language selector.
- **Enforcement:** deleting another user's suggestion is gated on the
scope + language (like the sibling suggestion actions); the author
fast-path (delete your own) is unchanged. The list endpoint now accepts
`suggest` **OR** `manage` so moderators can see the suggestions they can
act on.

## Behavior changes to note

- **Permission change:** on merge, existing **EDIT/MANAGE** project
members gain the ability to delete other users' suggestions.
- **Delete-only:** the scope gates deletion only;
`decline`/`accept`/`set-active` intentionally remain on
`translations.state-edit`.
- i18n keys created in the Tolgee project
(`permissions_item_translations_suggestions`,
`permissions_item_translations_suggestions_manage`,
`permission_type_suggest_manage`), tagged `draft:
suggestion-moderation`.

## Follow-up / not in this PR

- Consolidating the 5 parallel language dimensions into one
scope-discriminated table (accepted architecture debt).
- Deferred tests: PAK/API-key delete, community-boundary integration, FE
Cypress e2e.
@Anty0
Anty0 force-pushed the jirikuchynka/public-projects branch from e20b538 to d42feb8 Compare July 15, 2026 14:37
@Anty0
Anty0 requested a review from dkrizan July 15, 2026 16:16
@Anty0
Anty0 merged commit 4a4ea3f into main Jul 16, 2026
71 of 74 checks passed
@Anty0
Anty0 deleted the jirikuchynka/public-projects branch July 16, 2026 10:30
TolgeeMachine added a commit that referenced this pull request Jul 16, 2026
# [3.213.0](v3.212.1...v3.213.0) (2026-07-16)

### Features

* Community Translation v1 ([#3765](#3765)) ([4a4ea3f](4a4ea3f)), closes [#3770](#3770) [#3771](#3771) [#3776](#3776) [#3785](#3785) [#3774](#3774) [#3775](#3775) [#3770](#3770) [#3777](#3777) [#3792](#3792)
Anty0 added a commit that referenced this pull request Jul 20, 2026
Re-lands the organization-permissions lane of Community Translation v1,
which is missing from `main`.

## The problem

Opening a public project partially fails. The frontend sets the
preferred organization to the project's owner org on every project open
(`ProjectContext.tsx` → `PUT
/v2/user-preferences/set-preferred-organization/{id}`), and that call is
rejected for community users.

`main` still has the strict check in `UserPreferencesController`:

```kotlin
organizationRoleService.checkUserCanView(organization.id)
```

which resolves to `OrganizationRepository.canUserView`, whose predicate
is `(perm is not null or mr is not null)` — it requires a **stored**
`Permission` or `OrganizationRole` row. The community floor from #3770
is *computed* by design, so contributors don't consume a paid seat. No
row → `PermissionException(USER_CANNOT_VIEW_THIS_ORGANIZATION)` → 403.

## How it went missing

#3792 was merged into `jirikuchynka/public-projects` on 2026-07-13
(merge commit `93e6fd9cc`). That branch was subsequently rebased and
force-pushed; the rebase dropped the merge commit along with its two
payload commits. #3765 then squash-merged the rebased branch into `main`
as `4a4ea3f55`, shipping v1 without this lane. GitHub still reports
#3792 as MERGED, which is why it went unnoticed.

## This PR

`git cherry-pick -m 1 93e6fd9` onto `main` — applied with no
conflicts, and the resulting diff against `main` is identical to the
original payload (55 files, 2197+/129-).

Contents (unchanged from #3792):

- `OrganizationRoleService.canUserViewStrictOrPublic` /
`checkUserCanViewOrPublic` — the org view floor: strict check OR
`projectService.hasPublicProjects(organizationId)`
- Applied at `UserPreferencesController:61` and
`OrganizationAuthorizationInterceptor:75`
- `PreferredOrganizationFacade` heals stale/missing preferences in place
and emits `PrivateOrganizationModel.limitedView` for below-member
viewers
- Scoping of org language reads to accessible projects for below-member
viewers
- Glossary guest access, member-listing and usage exclusions for floor
viewers

## Verification

- `:data:`/`:api:`/`:security:`/`:development:compileKotlin` — BUILD
SUCCESSFUL
- `UserPreferencesSetPreferredOrganizationTest` — 7/7 passed
- `OrganizationFloorAccessTest` — 29/29 passed
- webapp + e2e `eslint --fix` and `tsc` — clean, no files changed


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Community and below-member viewers now receive organization models
tailored to public-project access, including a new `limitedView` flag
and safer subscription-related visibility behavior.
* **Bug Fixes**
* Preferred-organization and “managed-by” responses now respect updated
viewability rules and permission filtering, with stronger
stale-preference healing when the stored organization becomes
unavailable.
* Organization language/project listing queries are now restricted to
only the projects accessible to the current caller.
* Authorization “view floor” enforcement was tightened to allow the
correct default endpoints while keeping role-required routes protected.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
TolgeeMachine added a commit that referenced this pull request Jul 20, 2026
## [3.213.1](v3.213.0...v3.213.1) (2026-07-20)

### Bug Fixes

* community access to public-project organizations ([#3808](#3808)) ([6a7f73f](6a7f73f)), closes [#3770](#3770) [#3792](#3792) [#3765](#3765) [#3792](#3792) [#3792](#3792)
* keep websocket connection alive when a subscription is denied ([#3809](#3809)) ([1235ad1](1235ad1)), closes [#3529](#3529) [#3621](#3621) [#3621](#3621)
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.

2 participants