diff --git a/docs/docs/migration/migration-from-v4-to-v5.md b/docs/docs/migration/migration-from-v4-to-v5.md index f82da2dbf4..0f30d24f5d 100644 --- a/docs/docs/migration/migration-from-v4-to-v5.md +++ b/docs/docs/migration/migration-from-v4-to-v5.md @@ -1,6 +1,6 @@ --- title: Migrating from v4 to v5 -sidebar_position: 1 +sidebar_position: 2 --- # Migrating from v4 to v5 diff --git a/docs/docs/migration/migration-from-v5-to-v6.md b/docs/docs/migration/migration-from-v5-to-v6.md new file mode 100644 index 0000000000..079f067095 --- /dev/null +++ b/docs/docs/migration/migration-from-v5-to-v6.md @@ -0,0 +1,288 @@ +--- +title: Migrating from v5 to v6 +sidebar_position: 1 +--- + +# Migrating from v5 to v6 + +First, execute `npx @comet/upgrade@latest v6` in the root of your project. +It automatically installs the new versions of all `@comet` libraries and handles some of the necessary renames. + +
+ +Renames handled by @comet/upgrade + +- `JobStatus` -> `KubernetesJobStatus` in API +- `@SubjectEntity` -> `@AffectedEntity` in API +- `BuildRuntime` -> `JobRuntime` in Admin + +
+ + + +## API + +### User Permissions + +1. _Prerequisites_: Manage or sync allowed users in project (not covered here) + +2. Remove custom `CurrentUser` and `CurrentUserLoader` + + ```diff + - declare module "@comet/cms-api" { + - interface CurrentUserInterface { + - ... + - } + - } + + - @ObjectType() + - export class CurrentUser implements CurrentUserInterface { + - ... + - } + + - export class CurrentUserLoader implements CurrentUserLoaderInterface { + - ... + - } + ``` + + Also remove usage + + ```diff + createAuthProxyJwtStrategy({ + jwksUri: config.auth.idpJwksUri, + - currentUserLoader: new CurrentUserLoader(), + }), + ``` + + Change imports of removed classes + + ```diff + - import { CurrentUser, CurrentUserLoader } from "@src/auth/current-user"; + + import { CurrentUser } from "@comet/cms-api"; + ``` + + It shouldn't be necessary to override these classes anymore. However, if you really need it, provide the CurrentUserLoader with `CURRENT_USER_LOADER`. + +3. Create interface for `availablePermissions` similar to the already existing interface `interface ContentScope` + + ```ts + declare module "@comet/cms-api" { + interface Permission { + // e.g. `products: string;` + } + } + export {}; + ``` + +4. Create necessary services for the `UserPermissionsModule` (either in a new module or where it fits best) + + ```ts + // Attention: might already being provided by the library which syncs the users + @Injectable() + export class UserService implements UserPermissionsUserServiceInterface { + getUser(id: string): User { + ... + } + findUsers(args: FindUsersArgs): Users { + ... + } + } + ``` + + ```ts + @Injectable() + export class AccessControlService extends AbstractAccessControlService { + getPermissionsForUser(user: User): PermissionsForUser { + // e.g. return `UserPermissions.allPermissions;` for certain users + } + getContentScopesForUser(user: User): ContentScopesForUser { + // e.g. return `UserPermissions.allContentScopes;` for certain users + } + } + ``` + +5. Replace `ContentScopeModule` with `UserPermissionsModule` + + Remove `ContentScopeModule`: + + ```diff + - ContentScopeModule.forRoot({ + - ... + - }), + ``` + + Add `UserPermissionsModule`: + + ```ts + UserPermissionsModule.forRootAsync({ + useFactory: (userService: UserService, accessControlService: AccessControlService) => ({ + availablePermissions: [/* Array of strings defined in interface Permission */], + availableContentScopes: [/* Array of content Scopes */], + userService, + accessControlService, + }), + inject: [UserService, AccessControlService], + imports: [/* Modules which provide the services injected in useFactory */], + }), + ``` + +6. Adapt decorators + + Add `@RequiredPermission` to resolvers and controllers + + ```diff + + @RequiredPermission(["pageTree"]) + export class PagesResolver { + ``` + + Remove `@AllowForRole` (replaced by `@RequiredPermission`) + + ```diff + - @AllowForRole(...) + ``` + +## Admin + +### User Permissions + +1. Add `` to App.tsx + + ```diff + + + + ``` + +2. Use `useCurrentUser()` hook instead requesting the current user from the API + + ```diff + - const { loading, data } = useQuery(gql` + - query CurrentUser { + - currentUser { + - ... + - } + - } + - `); + + const user = useCurrentUser(); + ``` + + Also access allowedContentScopes where necessary (e.g. in ContentScopeProvider): + + ```diff + - const allowedUserDomains = data.currentUser.domains; + + const allowedUserDomains = user.allowedContentScopes.map((contentScope) => contentScope.domain); + ``` + +3. Add the `UserPermissionsPage` + + ```tsx + } + to={`${match.url}/user-permissions`} + /> + ``` + + ```tsx + + ``` + +### Sites Config + +The `SitesConfigProvider` and `useSitesConfig` were made generic. + +You must make following changes in the application: + +1. Define the type of your sites config + + Preferably this should be done in `config.ts`: + + ```diff + export function createConfig() { + // ... + + return { + ...cometConfig, + apiUrl: environmentVariables.API_URL, + adminUrl: environmentVariables.ADMIN_URL, + + sitesConfig: JSON.parse(environmentVariables.SITES_CONFIG) as SitesConfig, + }; + } + + + export type SitesConfig = Record; + ``` + +2. Use the type when using `useSitesConfig` + + ```diff + - const sitesConfig = useSitesConfig(); + + const sitesConfig = useSitesConfig(); + ``` + +3. Optional: Remove type annotation from `ContentScopeProvider#resolveSiteConfigForScope` (as it's now inferred) + + ```diff + - resolveSiteConfigForScope: (configs: Record, scope: ContentScope) => configs[scope.domain], + + resolveSiteConfigForScope: (configs, scope: ContentScope) => configs[scope.domain], + ``` + +### @comet/admin + +#### FinalForm + +Previously, `FinalForm#onAfterSubmit()` automatically executed + +```ts +stackApi?.goBack(); +editDialog?.closeDialog({ delay: true }); +``` + +This was removed because it was often unwanted and overridden. + +**You need to:** + +1. Add following code if you still want the old behavior: + + ```tsx + const stackApi = React.useContext(StackApiContext); + const editDialog = React.useContext(EditDialogApiContext); + + // ... + + { + stackApi?.goBack(); + editDialog?.closeDialog({ delay: true }); + }} + > + ``` + +2. You can remove workarounds like + + ```diff + - onAfterSubmit={() => { + - //don't go back automatically + - }} + ``` + +### @comet/admin-icons + +The icons `Betrieb`, `LogischeFilter`, `Pool`, `Pool2`, `Vignette1`, `Vignette2`, `StateGreen`, `StateGreenRing`, `StateOrange`, `StateOrangeRing`, `StateRed` and `StateRedRing` were removed. + +If you used any of these icons in your app, you must add them to your project. You can download them [here](https://github.com/vivid-planet/comet/tree/76e50aa86fd69b1df79825967c6c5c50e2cb6df7/packages/admin/admin-icons/icons/deprecated). + +## ESLint + +**Both new rules are auto-fixable.** All errors can be fixed by executing `npm run lint:eslint -- --fix` in `/api`, `/admin` and `/site`. + +### @comet/no-other-module-relative-import + +The `@comet/no-other-module-relative-import` rule is now enabled by default. It enforces absolute imports when importing from other modules. + +```diff +- import { AThingInModuleA } from "../moduleA/AThingInModuleA" ++ import { AThingInModuleA } from "@src/moduleA/AThingInModuleA" +``` + +### import/newline-after-import + +The `import/newline-after-import` rule is now enabled by default. It enforces adding a blank line between imports and code.