Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ACS-8694] Cleanup of visibility rules for extensions in ACA #4140

Open
wants to merge 25 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4c044df
[ACS-8694] Updated occurrences of visible in extensions.json to use a…
swapnil-verma-gl Sep 18, 2024
ad84694
[ACS-8694] Removed extra commas
swapnil-verma-gl Sep 18, 2024
c83af45
[ACS-8694] Broke down canDelete rule into seperate entities
swapnil-verma-gl Sep 18, 2024
7324aa3
[ACS-8694] Fixed typo for notEmpty rule
swapnil-verma-gl Sep 18, 2024
db27f56
[ACS-8694] Fixed rule for edit offline
swapnil-verma-gl Sep 18, 2024
5c5eda8
[ACS-8694] Updated extension.schema.json
swapnil-verma-gl Sep 18, 2024
b4cc744
[ACS-8694] Updated extension.schema.json
swapnil-verma-gl Sep 18, 2024
68416ae
[ACS-8694] Fixed rule for manage versions context menu item
swapnil-verma-gl Sep 19, 2024
0303332
[ACS-8694] Fixed rule for manage versions and manage permissions
swapnil-verma-gl Sep 19, 2024
9568dd7
[ACS-8694] Added rules.canManageFolderRules
swapnil-verma-gl Sep 19, 2024
1a25921
[ACS-8694] Fixed typo
swapnil-verma-gl Sep 19, 2024
f16aa54
[ACS-8694] Updated visibility rules for folder rules and AOS plugin
swapnil-verma-gl Sep 19, 2024
ab00283
[ACS-8694] Updated extension.schema.json
swapnil-verma-gl Sep 19, 2024
66c5f0e
[ACS-8694] Updated existing rules to use !isTrashcan() instead of isN…
swapnil-verma-gl Sep 20, 2024
bafbd16
[ACS-8694] folder-rules.plugin.json now uses arrays for controlling v…
swapnil-verma-gl Sep 20, 2024
dc8b2b5
[ACS-8694] Updated app.extensions.schema
swapnil-verma-gl Sep 20, 2024
fb140b4
[ACS-8694] Removed unused rules
swapnil-verma-gl Sep 20, 2024
f430cf4
[ACS-8694] Added unit tests for canToggleFileLock
swapnil-verma-gl Sep 20, 2024
8a9f3cb
[ACS-8694] Added rules-list.md
swapnil-verma-gl Sep 20, 2024
82b1929
[ACS-8694] Revert unneeded project.json change
swapnil-verma-gl Sep 26, 2024
75465ba
[ACS-8694] Fixed toggleEditOffline rule
swapnil-verma-gl Sep 26, 2024
ad392c7
[ACS-8694] Added migration guide (#4139)
swapnil-verma-gl Oct 11, 2024
104e438
[ACS-8694] Code review finding - Replaced instance of any
swapnil-verma-gl Oct 11, 2024
dab8da7
[ACS-8694] Code review finding - Updated rules.md. Removed duplicatio…
swapnil-verma-gl Oct 11, 2024
4ea6dfb
[ACS-8694] Fixed build issue
swapnil-verma-gl Nov 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions docs/extending/legacy-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
----
Title: Legacy Rules for ACA
----

# Legacy rules

Below is a list of all unused rules that were removed with ACA 5.1.1. You may use them as a reference in case your application/extension is still dependent on them,
however we do advise that you revisit those implementations and substitute them with a different approach, since these rules will no longer be supported.

```typescript
/**
* app.selection.file.canLock
* Checks if user can lock selected file.
*/
export const canLockFile = (context: RuleContext): boolean => !isWriteLocked(context) && canUpdateSelectedNode(context);

/**
* app.selection.file.canUnlock
* Checks if user can unlock selected file.
*/
export function canUnlockFile(context: RuleContext): boolean {
const { file } = context.selection;
return isWriteLocked(context) && (context.permissions.check(file?.entry, ['delete']) || isUserWriteLockOwner(context));
}

/**
* app.selection.file.isLockOwner
* Checks if the selected file has **write** or **read-only** locks specified,
* and that current user is the owner of the lock.
*/
export const isUserWriteLockOwner = (context: RuleContext): boolean =>
isWriteLocked(context) &&
context.selection.file?.entry.properties['cm:lockOwner'] &&
context.selection.file?.entry.properties['cm:lockOwner'].id === context.profile.id;

/**
* app.selection.file.canShare
* Checks if user can share selected file.
*/
export const canShareFile = (context: RuleContext): boolean =>
[context.selection.file, navigation.isNotTrashcan(context), repository.hasQuickShareEnabled(context), !isShared(context)].every(Boolean);

/**
* app.selection.canUnshare
* Checks if user can un-share selected nodes.
*/
export function canUnshareNodes(context: RuleContext): boolean {
if (hasSelection(context)) {
return context.permissions.check(context.selection.nodes, ['delete'], {
target: 'allowableOperationsOnTarget'
});
}
return false;
}

/**
* app.selection.file.isShared
* Checks if the selected file is already shared.
*/
export function isShared(context: RuleContext): boolean {
if (navigation.isSharedFiles(context) && context.selection.file) {
return true;
}

if (navigation.isNotTrashcan(context) && hasSelection(context) && context.selection.file) {
return !!context.selection.file.entry?.properties?.['qshare:sharedId'];
}

return false;
}

/**
* app.selection.isPrivateLibrary
* Checks if user has selected a **private** library (site)
*/
export function isPrivateLibrary(context: RuleContext): boolean {
return context.selection.library?.entry?.visibility === 'PRIVATE';
}

/**
* app.selection.hasNoLibraryRole
* Checks if the selected library has no **role** property defined.
*/
export const hasNoLibraryRole = (context: RuleContext): boolean => !hasLibraryRole(context);

/**
* app.navigation.isLibraryFiles
* Checks if a **Library Files** route is activated.
*/
export function isLibraryFiles(context: RuleContext): boolean {
const { url } = context.navigation;
return url?.startsWith('/libraries');
}

/**
* app.navigation.isPersonalFiles
* Checks if a **Personal Files** route is activated.
*/
export function isPersonalFiles(context: RuleContext): boolean {
const { url } = context.navigation;
return url?.startsWith('/personal-files');
}

/**
* app.navigation.isSharedPreview
* Checks if a **Shared Preview** route is activated.
*/
export function isSharedPreview(context: RuleContext): boolean {
const { url } = context.navigation;
return url?.startsWith('/shared/preview/') || (url?.startsWith('/shared') && url?.includes('viewer:view'));
}

/**
* app.navigation.isFavoritesPreview
* Checks if a **Favorites Preview** route is activated.
*/
export function isFavoritesPreview(context: RuleContext): boolean {
const { url } = context.navigation;
return url?.startsWith('/favorites/preview/') || (url?.startsWith('/favorites') && url?.includes('viewer:view'));
}

/**
* app.navigation.isSharedFileViewer
* Checks if a **Shared File Preview** route is activated.
*/
export function isSharedFileViewer(context: RuleContext): boolean {
const { url } = context.navigation;
return url?.startsWith('/preview/s/');
}

/**
* repository.isQuickShareEnabled
* Checks if the quick share repository option is enabled or not.
*/
export const hasQuickShareEnabled = (context: RuleContext): boolean => context.repository.status.isQuickShareEnabled;

/**
* user.isAdmin
* Checks if user is admin.
*/
export const isAdmin = (context: RuleContext): boolean => context.profile.isAdmin;
```
129 changes: 129 additions & 0 deletions docs/extending/rule-migration-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
Title: Rule Migration Guide
---

# Migrating rules to be ACA 5.1.1 compatible

As part of cleanup of the evaluators section in ACA 5.1.1, several rules from the application were removed and
replaced with their alternatives. The biggest change involves the preference to use array based visibility rules
instead of string based. What this means is that developers will now be able to provide a set of smaller visibility
rules via array, instead of having to provide one single rule, which would internally call multiple smaller rules
via code.

For e.g., for a rule `app.canManageFileVersions`, which was basically a combination of `hasFileSelection(app.selection.file)`,
`isNotTrashcan (app.navigation.isNotTrashcan)`, and `isNotLocked(app.selection.file.isNotLocked)`, earlier, the code
used to look something like -

app.extensions.json

```json
{
"rules": {
"visible": "canManageFileVersions"
}
}
```

aca-content.module.ts -

```ts
extensions.setEvaluators({
'app.canManageFileVersions': rules.canManageFileVersions,
'app.selection.file': rules.hasFileSelection,
'app.navigation.isNotTrashcan': rules.isNotTrashcan,
'app.navigation.isTrashcan': rules.isTrashcan,
'app.selection.file.isNotLocked': rules.isNotLocked
})

```

app.rules.ts -

```ts
import { isTrashcan } from './navigation.rules';

export const rules = {
canManageFileVersions: () => hasFileSelection() && isNotTrashcan() && isNotLocked(),
hasFileSelection: (context) => !!context?.selection?.file,
isTrashcan: (context) => context.navigation.startsWith('/trashcan'),
isNotTrashcan: (context) => !isTrashcan(context),
isNotLocked: (context) => context.selection.file.entry.isLocked || context.selection.file.entry.properties?.['cm:lockType'] === 'READ_ONLY_LOCK'
}


```

Now, the visibility of this extension unit can be controlled in more compact way -

```json
{
"rules": {
"visible": [
"app.selection.file",
"!app.navigation.isTrashcan",
"!app.selection.file.isLocked"
]
}
}
```

No further changes in aca-content.module.ts, or app.rules.ts is required, apart from removing the unused rules and functions

**NOTE**: Notice the use of the rule negation `!` in the app.navigation.isTrashcan rule above, thereby removing another unneeded rule.

Below is a full list of rules that would need to be migrated, along with the corresponding set of rules that can be used in their place. Do note that the default OOTB ACA already has the migrations applied on extensions.json, and the changes would
only need to be done on any extensions configuration that is custom to you. All old migrated rules have been removed from the code base, so performing this migration is necessary in order to ensure a stable Alfresco Content Application experience

| Old rule | New Rule |
|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| app.navigation.isNotTrashcan | !app.navigation.isTrashcan |
| app.navigation.isNotFavorites | !app.navigation.isFavorites |
| app.navigation.isNotSharedFiles | !app.navigation.isSharedFiles |
| app.navigation.isNotLibraries | !app.navigation.isLibraries |
| app.navigation.isNotRecentFiles | !app.navigation.isRecentFiles |
| app.navigation.isNotSearchResults | !app.navigation.isSearchResults |
| canViewFile | app.selection.file<br/>!app.navigation.isTrashcan |
| app.canCreateLibrary | app.isContentServiceEnabled<br/>app.navigation.isLibraries |
| app.selection.canDownload | app.selection.notEmpty<br/>!app.navigation.isTrashcan<br/>app.selection.canDownload |
| isTrashcanItemSelected | app.navigation.isTrashcan<br/>app.selection.notEmpty |
| canLeaveLibrary | app.selection.library<br/>app.selection.hasLibraryRole |
| canShowInfoDrawer | app.selection.notEmpty<br/>!app.navigation.isLibraries<br/>!app.navigation.isTrashcan |
| app.toolbar.favorite.canEditMetadata | app.selection.library<br/>isLibraryManager |
| canToggleEditOffline | app.selection.file<br/>!app.navigation.isTrashcan<br/>canToggleFileLock |
| canEditFolder | app.selection.folder.canUpdate<br/>!app.navigation.isTrashcan |
| app.toolbar.favorite.canAdd | app.selection.notEmpty<br/>app.selection.canAddFavorite<br/>!app.navigation.isTrashcan<br/>!app.navigation.isRecentFiles<br/>!app.navigation.isSharedFiles<br/>!app.navigation.isSearchResults<br/>!app.navigation.isFavorites |
| app.toolbar.favorite.canRemove | app.selection.notEmpty<br/>app.selection.canRemoveFavorite<br/>!app.navigation.isTrashcan<br/>!app.navigation.isRecentFiles<br/>!app.navigation.isSharedFiles<br/>!app.navigation.isSearchResults<br/>!app.navigation.isFavorites |
| canCopyNode | app.selection.notEmpty<br/>!app.navigation.isTrashcan<br/>!app.navigation.isLibraries |
| canManageFileVersions | app.selection.file<br/>!app.navigation.isTrashcan<br/>!app.selection.file.isLocked |
| canManagePermissions | app.selection.first.canUpdate<br/>!app.navigation.isTrashcan<br/>!isSmartFolder<br/>!isMultiSelection |
| rules.canManageFolderRules | rules.isFolderRulesEnabled<br/>app.selection.folder.canUpdate<br/>!app.navigation.isTrashcan<br/>app.selection.folder<br/>!app.navigation.isFavorites<br/>!isSmartFolder |
| app.navigation.folder.canCreate | app.isContentServiceEnabled<br/>app.navigation.folder.canCreate |
| app.navigation.folder.canUpload | app.isContentServiceEnabled<br/>app.navigation.folder.canCreate |
| app.isUploadSupported | app.isContentServiceEnabled<br/>app.navigation.folder.canCreate |
| canToggleSharedLink | app.selection.file<br/>canToggleSharedLink |
| canToggleJoinLibrary | app.selection.library<br/>!app.selection.hasLibraryRole<br/>canToggleJoinLibrary |
| canShowExpand | !app.navigation.isLibraries<br/>!app.navigation.isDetails |
| canInfoPreview | app.navigation.isSearchResults<br/>!isMultiSelection<br/>!app.selection.folder<br/>!app.navigation.isPreview |
| app.selection.canDelete | !app.navigation.isTrashcan<br/>!app.navigation.isLibraries<br/>app.selection.notEmpty<br/>app.selection.canDelete |

In addition to the above-mentioned migrations, the following set of rules were removed from the ACA codebase, since they were not being used by the application. If you still need access to these rules however, the original implementation
can be found in [legacy-rules.md](./legacy-rules.md). However, do note that since these rules have been removed from the ACA codebase, no support will be provided for them in the future. We advise that you should only use the provided rules as reference,
and migrate your current implementation to use a different approach instead.

| Rule |
|-----------------------------------|
| app.selection.file.canLock |
| app.selection.file.canUnlock |
| app.selection.file.isLockOwner |
| app.selection.file.canShare |
| app.selection.file.isShared |
| app.selection.canUnshare |
| app.selection.isPrivateLibrary |
| app.selection.hasNoLibraryRole |
| app.navigation.isLibraryFiles |
| app.navigation.isPersonalFiles |
| app.navigation.isSharedPreview |
| app.navigation.isFavoritesPreview |
| app.navigation.isSharedFileViewer |
| repository.isQuickShareEnabled |
| user.isAdmin |
Loading
Loading