@microsoft/windows-admin-center-sdk 4.52.0 → 4.123.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/angular/esm2020/src/controls/actions/containers/action-bar/action-bar.component.mjs +2 -2
  2. package/angular/esm2020/src/controls/master-view/master-view.component.mjs +8 -6
  3. package/angular/esm2020/src/controls/ux/sme-ux-footer/sme-ux-footer-template/sme-wizard-lite-footer-template/sme-wizard-lite-footer-template.component.mjs +56 -1
  4. package/angular/esm2020/src/service/navigation.service.mjs +3 -1
  5. package/angular/fesm2015/microsoft-windows-admin-center-sdk-angular.mjs +66 -6
  6. package/angular/fesm2015/microsoft-windows-admin-center-sdk-angular.mjs.map +1 -1
  7. package/angular/fesm2020/microsoft-windows-admin-center-sdk-angular.mjs +65 -6
  8. package/angular/fesm2020/microsoft-windows-admin-center-sdk-angular.mjs.map +1 -1
  9. package/angular/src/controls/master-view/master-view.component.d.ts +6 -2
  10. package/angular/src/controls/ux/sme-ux-footer/sme-ux-footer-template/sme-wizard-lite-footer-template/sme-wizard-lite-footer-template.component.d.ts +64 -0
  11. package/core/assets/strings/cs-CZ/strings.json +1 -1
  12. package/core/assets/strings/de-DE/strings.json +1 -1
  13. package/core/assets/strings/es-ES/strings.json +1 -1
  14. package/core/assets/strings/fr-FR/strings.json +1 -1
  15. package/core/assets/strings/hu-HU/strings.json +1 -1
  16. package/core/assets/strings/id-ID/strings.json +1 -1
  17. package/core/assets/strings/it-IT/strings.json +1 -1
  18. package/core/assets/strings/ja-JP/strings.json +1 -1
  19. package/core/assets/strings/ko-KR/strings.json +1 -1
  20. package/core/assets/strings/nl-NL/strings.json +1 -1
  21. package/core/assets/strings/pl-PL/strings.json +1 -1
  22. package/core/assets/strings/pt-BR/strings.json +1 -1
  23. package/core/assets/strings/pt-PT/strings.json +1 -1
  24. package/core/assets/strings/ru-RU/strings.json +1 -1
  25. package/core/assets/strings/strings.json +1 -1
  26. package/core/assets/strings/sv-SE/strings.json +1 -1
  27. package/core/assets/strings/tr-TR/strings.json +1 -1
  28. package/core/assets/strings/zh-CN/strings.json +1 -1
  29. package/core/assets/strings/zh-TW/strings.json +1 -1
  30. package/core/azure/azure-constants.d.ts +7 -3
  31. package/core/azure/azure-constants.d.ts.map +1 -1
  32. package/core/azure/azure-constants.js +8 -4
  33. package/core/azure/azure-constants.js.map +1 -1
  34. package/core/azure/models/azureArcStatusEnum.d.ts +4 -2
  35. package/core/azure/models/azureArcStatusEnum.d.ts.map +1 -1
  36. package/core/azure/models/azureArcStatusEnum.js +3 -1
  37. package/core/azure/models/azureArcStatusEnum.js.map +1 -1
  38. package/core/base/utilities.d.ts +3 -3
  39. package/core/base/utilities.d.ts.map +1 -1
  40. package/core/base/utilities.js +2 -2
  41. package/core/base/utilities.js.map +1 -1
  42. package/core/data/active-directory/active-directory.d.ts.map +1 -1
  43. package/core/data/active-directory/active-directory.js +1 -1
  44. package/core/data/active-directory/active-directory.js.map +1 -1
  45. package/core/data/cookie.d.ts.map +1 -1
  46. package/core/data/cookie.js +7 -0
  47. package/core/data/cookie.js.map +1 -1
  48. package/core/data/gateway-connection.d.ts +12 -0
  49. package/core/data/gateway-connection.d.ts.map +1 -1
  50. package/core/data/gateway-connection.js +16 -0
  51. package/core/data/gateway-connection.js.map +1 -1
  52. package/core/data/gateway-url-translator.d.ts +1 -0
  53. package/core/data/gateway-url-translator.d.ts.map +1 -1
  54. package/core/data/gateway-url-translator.js +15 -0
  55. package/core/data/gateway-url-translator.js.map +1 -1
  56. package/core/data/gateway-urls.d.ts +6 -0
  57. package/core/data/gateway-urls.d.ts.map +1 -1
  58. package/core/data/gateway-urls.js +8 -0
  59. package/core/data/gateway-urls.js.map +1 -1
  60. package/core/data/net.d.ts +1 -0
  61. package/core/data/net.d.ts.map +1 -1
  62. package/core/data/net.js +26 -1
  63. package/core/data/net.js.map +1 -1
  64. package/core/data/websocket-stream.d.ts.map +1 -1
  65. package/core/data/websocket-stream.js +2 -2
  66. package/core/data/websocket-stream.js.map +1 -1
  67. package/core/generated/powershell-scripts.d.ts.map +1 -1
  68. package/core/generated/powershell-scripts.js +1 -1
  69. package/core/generated/powershell-scripts.js.map +1 -1
  70. package/core/generated/strings.d.ts +3 -0
  71. package/core/generated/strings.d.ts.map +1 -1
  72. package/core/generated/strings.js.map +1 -1
  73. package/core/notification/notification.d.ts.map +1 -1
  74. package/core/notification/notification.js +1 -3
  75. package/core/notification/notification.js.map +1 -1
  76. package/core/resources/scripts/public/inventory/Get-ServerInventory.ps1 +8 -8
  77. package/core/security/tool-condition-validator.d.ts.map +1 -1
  78. package/core/security/tool-condition-validator.js +5 -5
  79. package/core/security/tool-condition-validator.js.map +1 -1
  80. package/core/shared/server-inventory/server-inventory-cache.d.ts.map +1 -1
  81. package/core/shared/server-inventory/server-inventory-cache.js +1 -2
  82. package/core/shared/server-inventory/server-inventory-cache.js.map +1 -1
  83. package/core/shared/server-inventory/server-inventory.d.ts +4 -4
  84. package/core/shared/server-inventory/server-inventory.d.ts.map +1 -1
  85. package/core/shared/server-inventory/server-inventory.js +2 -2
  86. package/core/shared/server-inventory/server-inventory.js.map +1 -1
  87. package/microsoft-windows-admin-center-sdk-4.123.0.tgz +0 -0
  88. package/package.json +4 -4
  89. package/styles/css/main-v2.css +1 -1
  90. package/tools/module-template/build/pipelines/ci-build.yml +2 -2
  91. package/tools/wac-cli/src/angular15/configs/angular-json-config.d.ts +2 -7
  92. package/tools/wac-cli/src/angular15/configs/angular-json-config.d.ts.map +1 -1
  93. package/tools/wac-cli/src/angular15/configs/angular-json-config.js +8 -1
  94. package/tools/wac-cli/src/angular15/configs/angular-json-config.js.map +1 -1
  95. package/tools/wac-cli/src/angular15/configs/package-json-config.d.ts +4 -0
  96. package/tools/wac-cli/src/angular15/configs/package-json-config.d.ts.map +1 -1
  97. package/tools/wac-cli/src/angular15/configs/package-json-config.js +13 -9
  98. package/tools/wac-cli/src/angular15/configs/package-json-config.js.map +1 -1
  99. package/tools/wac-cli/src/angular15/configs/ui-test-automation-lagacy-config.d.ts +14 -0
  100. package/tools/wac-cli/src/angular15/configs/ui-test-automation-lagacy-config.d.ts.map +1 -0
  101. package/tools/wac-cli/src/angular15/configs/ui-test-automation-lagacy-config.js +21 -0
  102. package/tools/wac-cli/src/angular15/configs/ui-test-automation-lagacy-config.js.map +1 -0
  103. package/tools/wac-cli/src/angular15/main.d.ts +33 -3
  104. package/tools/wac-cli/src/angular15/main.d.ts.map +1 -1
  105. package/tools/wac-cli/src/angular15/main.js +69 -7
  106. package/tools/wac-cli/src/angular15/main.js.map +1 -1
  107. package/tools/wac-cli/src/angular15/test/ui-test-automation-package.json/after.json +14 -0
  108. package/tools/wac-cli/src/angular15/test/ui-test-automation-package.json/before.json +13 -0
  109. package/tools/wac-cli/src/angular15/upgrader/ui-test-automation-legacy-upgrader.d.ts +15 -0
  110. package/tools/wac-cli/src/angular15/upgrader/ui-test-automation-legacy-upgrader.d.ts.map +1 -0
  111. package/tools/wac-cli/src/angular15/upgrader/ui-test-automation-legacy-upgrader.js +48 -0
  112. package/tools/wac-cli/src/angular15/upgrader/ui-test-automation-legacy-upgrader.js.map +1 -0
  113. package/tools/wac-cli/src/angular15/utils/main-debugger.d.ts.map +1 -1
  114. package/tools/wac-cli/src/angular15/utils/main-debugger.js +3 -0
  115. package/tools/wac-cli/src/angular15/utils/main-debugger.js.map +1 -1
  116. package/tools/wac-cli/src/angular15/utils/update-shell-references.d.ts +2 -0
  117. package/tools/wac-cli/src/angular15/utils/update-shell-references.d.ts.map +1 -0
  118. package/tools/wac-cli/src/angular15/utils/update-shell-references.js +69 -0
  119. package/tools/wac-cli/src/angular15/utils/update-shell-references.js.map +1 -0
  120. package/tools/wac-cli/src/common.d.ts +6 -0
  121. package/tools/wac-cli/src/common.d.ts.map +1 -1
  122. package/tools/wac-cli/src/common.js +13 -0
  123. package/tools/wac-cli/src/common.js.map +1 -1
  124. package/tools/wac-cli/src/create/main.d.ts.map +1 -1
  125. package/tools/wac-cli/src/create/main.js +3 -51
  126. package/tools/wac-cli/src/create/main.js.map +1 -1
  127. package/tools/wac-cli/src/eslint/main.d.ts +5 -1
  128. package/tools/wac-cli/src/eslint/main.d.ts.map +1 -1
  129. package/tools/wac-cli/src/eslint/main.js +17 -2
  130. package/tools/wac-cli/src/eslint/main.js.map +1 -1
  131. package/tools/wac-cli/src/index.d.ts.map +1 -1
  132. package/tools/wac-cli/src/index.js +2 -2
  133. package/tools/wac-cli/src/index.js.map +1 -1
  134. package/tools/wac-cli/templates/wac-template/package.json +3 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../packages/core/notification/notification.ts"],"names":[],"mappings":"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","file":"notification.d.ts","sourcesContent":["import { Globalization } from '../data/globalization';\r\nimport { Logging } from '../diagnostics/logging';\r\nimport { Strings } from '../generated/strings';\r\nimport { EnvironmentModule } from '../manifest/environment-modules';\r\nimport { RpcNotification } from '../rpc/notification/rpc-notification-model';\r\nimport { RpcWorkItem } from '../rpc/work-item/rpc-work-item-model';\r\nimport { NotificationLinkType } from './notification-link-type';\r\nimport { IFrameService } from './notification-manager';\r\nimport { NotificationMessage } from './notification-message';\r\nimport { NotificationState } from './notification-state';\r\nimport { PowerShellNotification, PowerShellWorkItemMessage } from './powershell-notification';\r\nimport { SocketMessage } from './socket-signalr';\r\nimport { RecoveredWorkItem } from './work-item-request';\r\n\r\n/**\r\n * Notification changed event type.\r\n */\r\nexport enum NotificationChangeEvent {\r\n Initialized,\r\n InitializationFailed,\r\n Add,\r\n Remove,\r\n Change\r\n}\r\n\r\n/**\r\n * Notification changed event packet.\r\n */\r\nexport interface NotificationEvent {\r\n changeEvent: NotificationChangeEvent;\r\n notification?: Notification;\r\n}\r\n\r\n/**\r\n * Internal notification object converted from ClientNotification object.\r\n * Contains data to track notifications.\r\n */\r\nexport class Notification {\r\n private strings: Strings = MsftSme.getStrings<Strings>();\r\n\r\n /**\r\n * Work item passed from RPC or client on shell.\r\n */\r\n private workItem: RpcWorkItem;\r\n\r\n /**\r\n * The type ID of work item.\r\n */\r\n public typeId: string;\r\n\r\n /**\r\n * The node name.\r\n */\r\n public nodeName: string;\r\n\r\n /**\r\n * The module name.\r\n */\r\n public moduleName: string;\r\n\r\n /**\r\n * The entry point name within the module\r\n */\r\n public entryPointName: string;\r\n\r\n /**\r\n * The module display name.\r\n */\r\n public moduleDisplayName: string;\r\n\r\n /**\r\n * Object included last response.\r\n */\r\n public object: any;\r\n\r\n /**\r\n * The state of notification.\r\n */\r\n public state: NotificationState;\r\n\r\n /**\r\n * The title of work item to display user. (localized)\r\n */\r\n public title: string;\r\n\r\n /**\r\n * @depracated\r\n * The description of work item to display user. (localized)\r\n */\r\n public description: string;\r\n\r\n /**\r\n * The message. (localized)\r\n */\r\n public message: string;\r\n\r\n /**\r\n * Possible solution message to address error. (localized)\r\n */\r\n public solutionMessage: string;\r\n\r\n /**\r\n * True if the notification was created from recover, updates from messages should be taken\r\n */\r\n public isFromRecover = false;\r\n\r\n /**\r\n * True if the notification is disabled and should not be shown to the user\r\n */\r\n public isDisabled = false;\r\n\r\n /**\r\n * The start timestamp as a formatted globalized string\r\n */\r\n public startTimestamp: string;\r\n\r\n /**\r\n * The last changed timestamp as a formatted globalized string\r\n */\r\n public changedTimestamp: string;\r\n\r\n /**\r\n * The last changed timestamp as a number\r\n */\r\n public changedTimestampValue: number;\r\n\r\n /**\r\n * The end timestamp as a formatted globalized string\r\n */\r\n public endTimestamp: string;\r\n\r\n /**\r\n * The progress percent.\r\n */\r\n public progressPercent: number;\r\n\r\n /**\r\n * The success link to navigate to the object view. (optional)\r\n * At default, it brings to the home page of the module.\r\n */\r\n public link: string;\r\n\r\n /**\r\n * the notification link type of the link\r\n */\r\n public linkType: NotificationLinkType;\r\n\r\n /**\r\n * True if we should show the link in the notification's alert\r\n * We will show the link if there is a custom link or it is a long running request\r\n */\r\n public showLinkInAlert = false;\r\n\r\n /**\r\n * Marked it's no longer display to include list of notifications.\r\n */\r\n public dismissed = false;\r\n\r\n /**\r\n * The parent URI window.location.pathname.\r\n */\r\n public locationPathname: string;\r\n\r\n /**\r\n * The parent URI window.location.search\r\n */\r\n public locationSearch: string;\r\n\r\n /**\r\n *\r\n * Tracks if the notification has been read.\r\n */\r\n public isUnread = true;\r\n\r\n /**\r\n * Create notification from WorkItem.\r\n *\r\n * @param id the notification ID.\r\n * @param workItem the RPC work item.\r\n * @param state the initial state.\r\n * @param object the object from query result.\r\n * @return notification the notification object.\r\n */\r\n public static createFromWorkItem(\r\n id: string, workItem: RpcWorkItem, state: NotificationState, iFrameService: IFrameService, object?: any): Notification {\r\n const notification = new Notification(id);\r\n notification.workItem = workItem;\r\n\r\n notification.state = state;\r\n notification.object = object;\r\n notification.initializeFromWorkItem(workItem, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Create notification from recovered work item.\r\n *\r\n * @param recoveredWorkItem the recovered work item.\r\n * @return notification the notification object.\r\n */\r\n public static createFromRecover(recoveredWorkItem: RecoveredWorkItem, iFrameService: IFrameService): Notification {\r\n const notification = new Notification(recoveredWorkItem.id);\r\n notification.workItem = recoveredWorkItem.metadata;\r\n notification.isFromRecover = true;\r\n\r\n if (recoveredWorkItem.failed) {\r\n notification.state = NotificationState.Error;\r\n notification.object = { errorType: 'WorkItemRecover', message: recoveredWorkItem.errorMessage };\r\n } else {\r\n notification.state = NotificationState.InProgress;\r\n notification.object = {};\r\n }\r\n\r\n notification.initializeFromWorkItem(recoveredWorkItem.metadata, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Create notification from instant request.\r\n *\r\n * @param client the RPC notification request.\r\n * @return notification the notification object.\r\n */\r\n public static createFromClient(client: RpcNotification, iFrameService: IFrameService): Notification {\r\n const notification = new Notification(client.id);\r\n notification.locationPathname = window.location.pathname;\r\n notification.locationSearch = window.location.search;\r\n notification.initializeFromInstant(client, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Initializes a new instance of the Notification class.\r\n *\r\n * @param id the notification ID.\r\n */\r\n constructor(public id: string) { }\r\n\r\n /**\r\n * Update a notification by work item from RPC.\r\n * @param id the notification id.\r\n * @param workItem the work item.\r\n * @param state the state of the notification.\r\n * @param object the object from query result.\r\n */\r\n public updateFromWorkItem(id: string, workItem: RpcWorkItem, state: NotificationState, object?: any) {\r\n let changed = false;\r\n\r\n if (this.updateState(state)) {\r\n changed = true;\r\n const now = Date.now();\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n if (this.object !== object) {\r\n changed = true;\r\n this.object = object;\r\n }\r\n\r\n this.updateMessageAndLinkAndTitle(workItem);\r\n return !this.isDisabled && changed;\r\n }\r\n\r\n /**\r\n * Update the notification by socket message from the gateway.\r\n *\r\n * @param item the socket message.\r\n * @return boolean the changed status.\r\n */\r\n public updateFromMessage(item: SocketMessage<PowerShellWorkItemMessage>): boolean {\r\n let changed = false;\r\n const now = Date.now();\r\n if (PowerShellNotification.hasError(item)) {\r\n Logging.logDebug('Notification', '{0}/Error/{1}'.format(this.id, JSON.stringify(item.message.errors)));\r\n if (this.updateState(NotificationState.Error)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = item.message.errors && MsftSme.first(item.message.errors);\r\n changed = true;\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled;\r\n }\r\n\r\n if (PowerShellNotification.hasException(item)) {\r\n Logging.logDebug('Notification', '{0}/Exception/{1}'.format(this.id, item.message.exception));\r\n if (this.updateState(NotificationState.Error)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = { message: item.message.exception };\r\n changed = true;\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled;\r\n }\r\n\r\n if (PowerShellNotification.hasProgress(item)) {\r\n Logging.logDebug('Notification', '{0}/Progress/{1}'.format(this.id, JSON.stringify(item.message.progress)));\r\n if (this.updateState(NotificationState.InProgress)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = item.message.progress && MsftSme.last(item.message.progress);\r\n if (this.object && this.object.hasOwnProperty('percentComplete')) {\r\n this.progressPercent = this.object && this.object.percentComplete;\r\n }\r\n\r\n if ((this.progressPercent == null || this.progressPercent < 0)\r\n && this.workItem.progressMessage && this.workItem.progressMessage.indexOf('{{percent}}') >= 0) {\r\n return false;\r\n }\r\n\r\n changed = true;\r\n }\r\n\r\n if (PowerShellNotification.hasData(item)) {\r\n Logging.logDebug('Notification', '{0}/Data/{1}'.format(this.id, JSON.stringify(item.message.results)));\r\n this.object = item.message.results && MsftSme.last(item.message.results);\r\n changed = true;\r\n }\r\n\r\n if (PowerShellNotification.hasCompleted(item)) {\r\n Logging.logDebug('Notification', '{0}/Completed'.format(this.id));\r\n if (this.updateState(NotificationState.Success)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n changed = true;\r\n }\r\n\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled && changed;\r\n }\r\n\r\n /**\r\n * Update the notification by socket message from the gateway.\r\n *\r\n * @param state the state of notification.\r\n * @param item the socket message.\r\n * @return boolean the changed status.\r\n */\r\n public updateFromNotificationMessage(state: NotificationState, item: NotificationMessage): boolean {\r\n const now = Date.now();\r\n this.title = item.title;\r\n this.message = item.message;\r\n this.state = state;\r\n this.changedTimestampValue = now;\r\n if (state === NotificationState.InProgress) {\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n } else {\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Update the notification by instant notification message from the client.\r\n *\r\n * @param client the instant notification object.\r\n * @param boolean the changed status.\r\n */\r\n public updateFromClient(client: RpcNotification): boolean {\r\n let changed = false;\r\n const title = client.title;\r\n if (this.title !== title) {\r\n changed = true;\r\n this.title = title;\r\n }\r\n\r\n if (this.updateState(client.state)) {\r\n const now = Date.now();\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n changed = true;\r\n if (this.state !== NotificationState.InProgress) {\r\n this.endTimestamp = this.changedTimestamp;\r\n }\r\n }\r\n\r\n const link = this.formatLink(client.link, client.linkType);\r\n if (this.link !== link) {\r\n changed = true;\r\n this.link = link;\r\n this.linkType = client.linkType;\r\n }\r\n\r\n if (this.message !== client.message) {\r\n changed = true;\r\n this.message = client.message;\r\n }\r\n\r\n if (this.solutionMessage !== client.solutionMessage) {\r\n changed = true;\r\n this.solutionMessage = client.solutionMessage;\r\n }\r\n\r\n return changed;\r\n }\r\n\r\n /**\r\n * Gets the module display name.\r\n */\r\n private getModuleDisplayName(iFrameService: IFrameService, sourceName: string, sourceSubName: string): string {\r\n const activeIFrame = iFrameService ? iFrameService.getActiveToolIFrameData() : null;\r\n if (activeIFrame && activeIFrame.entryPoint) {\r\n const entryPoint = activeIFrame.entryPoint;\r\n this.entryPointName = entryPoint.name;\r\n\r\n if (entryPoint.parentModule) {\r\n this.moduleName = entryPoint.parentModule.name;\r\n }\r\n } else {\r\n // fallback see if we can get any info from RPC\r\n this.moduleName = sourceName;\r\n if (sourceSubName) {\r\n this.entryPointName = MsftSme.first(sourceSubName.split('#'));\r\n }\r\n }\r\n\r\n const environment = MsftSme.self().Environment;\r\n\r\n // if moduleName === environment.name then the source is Shell. Return null to use generic module name\r\n if (this.moduleName && this.moduleName !== environment.name) {\r\n const module: EnvironmentModule = MsftSme.find(\r\n <EnvironmentModule[]>environment.modules,\r\n value => value.name === this.moduleName);\r\n if (module) {\r\n if (this.entryPointName) {\r\n const entryPoint = MsftSme.find(module.entryPoints, ep => ep.name === this.entryPointName);\r\n if (entryPoint) {\r\n return entryPoint.displayName;\r\n }\r\n }\r\n\r\n return module.displayName;\r\n }\r\n\r\n return this.moduleName;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Update the state.\r\n *\r\n * @param state the new state.\r\n * @return boolean the changed state.\r\n */\r\n private updateState(state: NotificationState): boolean {\r\n if (this.state !== state) {\r\n this.state = state;\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private initializeFromWorkItem(item: RpcWorkItem, iFrameService: IFrameService): void {\r\n this.nodeName = item.nodeName;\r\n this.moduleDisplayName = this.getModuleDisplayName(iFrameService, item.sourceName, item.sourceSubName);\r\n this.startTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n this.changedTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n this.changedTimestampValue = item.timestamp;\r\n this.typeId = item.typeId;\r\n this.updateMessageAndLinkAndTitle(item);\r\n }\r\n\r\n private updateMessageAndLinkAndTitle(item: RpcWorkItem): void {\r\n let template: string;\r\n this.isDisabled = !this.isFromRecover && item.disableAllNotifications;\r\n switch (this.state) {\r\n case NotificationState.Started:\r\n this.title = item.inProgressTitle;\r\n template = item.startedMessage;\r\n this.link = this.formatLink(null);\r\n break;\r\n case NotificationState.Error:\r\n this.title = item.errorTitle;\r\n this.isDisabled = !this.isFromRecover && item.disableErrorNotification;\r\n this.endTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n template = item.errorMessage;\r\n this.link = this.formatLink(item.errorLink, item.errorLinkType);\r\n this.linkType = item.errorLinkType;\r\n this.showLinkInAlert = true;\r\n this.moduleDisplayName = item.errorLinkText || this.moduleDisplayName;\r\n break;\r\n case NotificationState.InProgress:\r\n this.title = item.inProgressTitle;\r\n template = item.progressMessage;\r\n this.link = this.formatLink(null);\r\n break;\r\n case NotificationState.Success:\r\n this.title = item.successTitle;\r\n this.endTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n template = item.successMessage;\r\n this.link = this.formatLink(item.successLink, item.successLinkType);\r\n this.linkType = item.successLinkType;\r\n this.moduleDisplayName = item.successLinkText || this.moduleDisplayName;\r\n this.showLinkInAlert = true;\r\n break;\r\n default:\r\n const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.NotificationUnsupportedState.message;\r\n throw new Error(message);\r\n }\r\n\r\n this.message = this.formatMessage(template);\r\n }\r\n\r\n private initializeFromInstant(client: RpcNotification, iFrameService: IFrameService): void {\r\n this.nodeName = client.nodeName;\r\n this.moduleDisplayName = client.linkText ?\r\n client.linkText\r\n : this.getModuleDisplayName(iFrameService, client.sourceName, client.sourceSubName);\r\n this.startTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n this.changedTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n this.changedTimestampValue = client.timestamp;\r\n this.title = client.title;\r\n this.state = client.state;\r\n this.link = this.formatLink(client.link, client.linkType);\r\n this.linkType = client.linkType;\r\n this.message = client.message;\r\n this.solutionMessage = client.solutionMessage;\r\n if (this.state !== NotificationState.Started && this.state !== NotificationState.InProgress) {\r\n this.endTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n }\r\n }\r\n\r\n private getGlobalizedTimestamp(timestamp: number): string {\r\n return Globalization.timeOnly(new Date(timestamp));\r\n }\r\n\r\n private formatLink(link: string, linkType?: NotificationLinkType): string {\r\n // href example: \"http://localhost:4400/apps/msft.sme.server-manager!servers/tools/msft.sme.module-seed!main?connection=sme-full1.redmond.corp.microsoft.com\"\r\n if (linkType === NotificationLinkType.Absolute) {\r\n return link;\r\n }\r\n\r\n // null linkType behaves like NotificationLinkType.RelativeToTool\r\n const pathname = linkType === NotificationLinkType.RelativeToRoot ?\r\n '/'\r\n : this.locationPathname || this.workItem && this.workItem.locationPathname;\r\n\r\n if (link && pathname) {\r\n this.showLinkInAlert = true;\r\n return MsftSme.trimEnd(pathname, '/') + '/' + MsftSme.trimStart(link, '/');\r\n }\r\n\r\n this.showLinkInAlert = false;\r\n return pathname;\r\n }\r\n\r\n private formatMessage(template: string): string {\r\n const parameters = this.findParameters(template);\r\n const message = this.replaceParameters(template, parameters);\r\n return message;\r\n }\r\n\r\n private findParameters(template: string): string[] {\r\n const results: string[] = [];\r\n if (!template) {\r\n return results;\r\n }\r\n\r\n const segments = template.split('{{');\r\n for (const seg of segments) {\r\n const index = seg.indexOf('}}');\r\n if (index > 0) {\r\n results.push(seg.substring(0, index));\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n private replaceParameters(message: string, parameters: string[]): string {\r\n for (const param of parameters) {\r\n if (param === 'percent') {\r\n if (typeof this.progressPercent === 'number') {\r\n message = message.replaceAll('{{percent}}', '' + this.progressPercent);\r\n }\r\n } else if (param === 'objectName') {\r\n if (this.workItem && this.workItem.objectName) {\r\n message = message.replaceAll('{{objectName}}', this.workItem.objectName);\r\n }\r\n } else {\r\n if (this.object) {\r\n const segments = param.split('.');\r\n let target = this.object;\r\n for (const seg of segments) {\r\n if (target[seg]) {\r\n target = target[seg];\r\n } else {\r\n target = null;\r\n break;\r\n }\r\n }\r\n\r\n if (target) {\r\n message = message.replaceAll('{{' + param + '}}', '' + target);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return message;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../../packages/core/notification/notification.ts"],"names":[],"mappings":"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","file":"notification.d.ts","sourcesContent":["import { Globalization } from '../data/globalization';\r\nimport { Logging } from '../diagnostics/logging';\r\nimport { Strings } from '../generated/strings';\r\nimport { EnvironmentModule } from '../manifest/environment-modules';\r\nimport { RpcNotification } from '../rpc/notification/rpc-notification-model';\r\nimport { RpcWorkItem } from '../rpc/work-item/rpc-work-item-model';\r\nimport { NotificationLinkType } from './notification-link-type';\r\nimport { IFrameService } from './notification-manager';\r\nimport { NotificationMessage } from './notification-message';\r\nimport { NotificationState } from './notification-state';\r\nimport { PowerShellNotification, PowerShellWorkItemMessage } from './powershell-notification';\r\nimport { SocketMessage } from './socket-signalr';\r\nimport { RecoveredWorkItem } from './work-item-request';\r\n\r\n/**\r\n * Notification changed event type.\r\n */\r\nexport enum NotificationChangeEvent {\r\n Initialized,\r\n InitializationFailed,\r\n Add,\r\n Remove,\r\n Change\r\n}\r\n\r\n/**\r\n * Notification changed event packet.\r\n */\r\nexport interface NotificationEvent {\r\n changeEvent: NotificationChangeEvent;\r\n notification?: Notification;\r\n}\r\n\r\n/**\r\n * Internal notification object converted from ClientNotification object.\r\n * Contains data to track notifications.\r\n */\r\nexport class Notification {\r\n private strings: Strings = MsftSme.getStrings<Strings>();\r\n\r\n /**\r\n * Work item passed from RPC or client on shell.\r\n */\r\n private workItem: RpcWorkItem;\r\n\r\n /**\r\n * The type ID of work item.\r\n */\r\n public typeId: string;\r\n\r\n /**\r\n * The node name.\r\n */\r\n public nodeName: string;\r\n\r\n /**\r\n * The module name.\r\n */\r\n public moduleName: string;\r\n\r\n /**\r\n * The entry point name within the module\r\n */\r\n public entryPointName: string;\r\n\r\n /**\r\n * The module display name.\r\n */\r\n public moduleDisplayName: string;\r\n\r\n /**\r\n * Object included last response.\r\n */\r\n public object: any;\r\n\r\n /**\r\n * The state of notification.\r\n */\r\n public state: NotificationState;\r\n\r\n /**\r\n * The title of work item to display user. (localized)\r\n */\r\n public title: string;\r\n\r\n /**\r\n * @depracated\r\n * The description of work item to display user. (localized)\r\n */\r\n public description: string;\r\n\r\n /**\r\n * The message. (localized)\r\n */\r\n public message: string;\r\n\r\n /**\r\n * Possible solution message to address error. (localized)\r\n */\r\n public solutionMessage: string;\r\n\r\n /**\r\n * True if the notification was created from recover, updates from messages should be taken\r\n */\r\n public isFromRecover = false;\r\n\r\n /**\r\n * True if the notification is disabled and should not be shown to the user\r\n */\r\n public isDisabled = false;\r\n\r\n /**\r\n * The start timestamp as a formatted globalized string\r\n */\r\n public startTimestamp: string;\r\n\r\n /**\r\n * The last changed timestamp as a formatted globalized string\r\n */\r\n public changedTimestamp: string;\r\n\r\n /**\r\n * The last changed timestamp as a number\r\n */\r\n public changedTimestampValue: number;\r\n\r\n /**\r\n * The end timestamp as a formatted globalized string\r\n */\r\n public endTimestamp: string;\r\n\r\n /**\r\n * The progress percent.\r\n */\r\n public progressPercent: number;\r\n\r\n /**\r\n * The success link to navigate to the object view. (optional)\r\n * At default, it brings to the home page of the module.\r\n */\r\n public link: string;\r\n\r\n /**\r\n * the notification link type of the link\r\n */\r\n public linkType: NotificationLinkType;\r\n\r\n /**\r\n * True if we should show the link in the notification's alert\r\n * We will show the link if there is a custom link or it is a long running request\r\n */\r\n public showLinkInAlert = false;\r\n\r\n /**\r\n * Marked it's no longer display to include list of notifications.\r\n */\r\n public dismissed = false;\r\n\r\n /**\r\n * The parent URI window.location.pathname.\r\n */\r\n public locationPathname: string;\r\n\r\n /**\r\n * The parent URI window.location.search\r\n */\r\n public locationSearch: string;\r\n\r\n /**\r\n *\r\n * Tracks if the notification has been read.\r\n */\r\n public isUnread = true;\r\n\r\n /**\r\n * Create notification from WorkItem.\r\n *\r\n * @param id the notification ID.\r\n * @param workItem the RPC work item.\r\n * @param state the initial state.\r\n * @param object the object from query result.\r\n * @return notification the notification object.\r\n */\r\n public static createFromWorkItem(\r\n id: string, workItem: RpcWorkItem, state: NotificationState, iFrameService: IFrameService, object?: any): Notification {\r\n const notification = new Notification(id);\r\n notification.workItem = workItem;\r\n\r\n notification.state = state;\r\n notification.object = object;\r\n notification.initializeFromWorkItem(workItem, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Create notification from recovered work item.\r\n *\r\n * @param recoveredWorkItem the recovered work item.\r\n * @return notification the notification object.\r\n */\r\n public static createFromRecover(recoveredWorkItem: RecoveredWorkItem, iFrameService: IFrameService): Notification {\r\n const notification = new Notification(recoveredWorkItem.id);\r\n notification.workItem = recoveredWorkItem.metadata;\r\n notification.isFromRecover = true;\r\n\r\n if (recoveredWorkItem.failed) {\r\n notification.state = NotificationState.Error;\r\n notification.object = { errorType: 'WorkItemRecover', message: recoveredWorkItem.errorMessage };\r\n } else {\r\n notification.state = NotificationState.InProgress;\r\n notification.object = {};\r\n }\r\n\r\n notification.initializeFromWorkItem(recoveredWorkItem.metadata, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Create notification from instant request.\r\n *\r\n * @param client the RPC notification request.\r\n * @return notification the notification object.\r\n */\r\n public static createFromClient(client: RpcNotification, iFrameService: IFrameService): Notification {\r\n const notification = new Notification(client.id);\r\n notification.locationPathname = window.location.pathname;\r\n notification.locationSearch = window.location.search;\r\n notification.initializeFromInstant(client, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Initializes a new instance of the Notification class.\r\n *\r\n * @param id the notification ID.\r\n */\r\n constructor(public id: string) { }\r\n\r\n /**\r\n * Update a notification by work item from RPC.\r\n * @param id the notification id.\r\n * @param workItem the work item.\r\n * @param state the state of the notification.\r\n * @param object the object from query result.\r\n */\r\n public updateFromWorkItem(id: string, workItem: RpcWorkItem, state: NotificationState, object?: any) {\r\n let changed = false;\r\n\r\n if (this.updateState(state)) {\r\n changed = true;\r\n const now = Date.now();\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n if (this.object !== object) {\r\n changed = true;\r\n this.object = object;\r\n }\r\n\r\n this.updateMessageAndLinkAndTitle(workItem);\r\n return !this.isDisabled && changed;\r\n }\r\n\r\n /**\r\n * Update the notification by socket message from the gateway.\r\n *\r\n * @param item the socket message.\r\n * @return boolean the changed status.\r\n */\r\n public updateFromMessage(item: SocketMessage<PowerShellWorkItemMessage>): boolean {\r\n let changed = false;\r\n const now = Date.now();\r\n if (PowerShellNotification.hasError(item)) {\r\n Logging.logDebug('Notification', '{0}/Error/{1}'.format(this.id, JSON.stringify(item.message.errors)));\r\n if (this.updateState(NotificationState.Error)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = item.message.errors && MsftSme.first(item.message.errors);\r\n changed = true;\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled;\r\n }\r\n\r\n if (PowerShellNotification.hasException(item)) {\r\n Logging.logDebug('Notification', '{0}/Exception/{1}'.format(this.id, item.message.exception));\r\n if (this.updateState(NotificationState.Error)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = { message: item.message.exception };\r\n changed = true;\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled;\r\n }\r\n\r\n if (PowerShellNotification.hasProgress(item)) {\r\n Logging.logDebug('Notification', '{0}/Progress/{1}'.format(this.id, JSON.stringify(item.message.progress)));\r\n if (this.updateState(NotificationState.InProgress)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = item.message.progress && MsftSme.last(item.message.progress);\r\n this.progressPercent = this.object?.percentComplete ?? this.object?.percent;\r\n\r\n if ((this.progressPercent == null || this.progressPercent < 0)\r\n && this.workItem.progressMessage && this.workItem.progressMessage.indexOf('{{percent}}') >= 0) {\r\n return false;\r\n }\r\n\r\n changed = true;\r\n }\r\n\r\n if (PowerShellNotification.hasData(item)) {\r\n Logging.logDebug('Notification', '{0}/Data/{1}'.format(this.id, JSON.stringify(item.message.results)));\r\n this.object = item.message.results && MsftSme.last(item.message.results);\r\n changed = true;\r\n }\r\n\r\n if (PowerShellNotification.hasCompleted(item)) {\r\n Logging.logDebug('Notification', '{0}/Completed'.format(this.id));\r\n if (this.updateState(NotificationState.Success)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n changed = true;\r\n }\r\n\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled && changed;\r\n }\r\n\r\n /**\r\n * Update the notification by socket message from the gateway.\r\n *\r\n * @param state the state of notification.\r\n * @param item the socket message.\r\n * @return boolean the changed status.\r\n */\r\n public updateFromNotificationMessage(state: NotificationState, item: NotificationMessage): boolean {\r\n const now = Date.now();\r\n this.title = item.title;\r\n this.message = item.message;\r\n this.state = state;\r\n this.changedTimestampValue = now;\r\n if (state === NotificationState.InProgress) {\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n } else {\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Update the notification by instant notification message from the client.\r\n *\r\n * @param client the instant notification object.\r\n * @param boolean the changed status.\r\n */\r\n public updateFromClient(client: RpcNotification): boolean {\r\n let changed = false;\r\n const title = client.title;\r\n if (this.title !== title) {\r\n changed = true;\r\n this.title = title;\r\n }\r\n\r\n if (this.updateState(client.state)) {\r\n const now = Date.now();\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n changed = true;\r\n if (this.state !== NotificationState.InProgress) {\r\n this.endTimestamp = this.changedTimestamp;\r\n }\r\n }\r\n\r\n const link = this.formatLink(client.link, client.linkType);\r\n if (this.link !== link) {\r\n changed = true;\r\n this.link = link;\r\n this.linkType = client.linkType;\r\n }\r\n\r\n if (this.message !== client.message) {\r\n changed = true;\r\n this.message = client.message;\r\n }\r\n\r\n if (this.solutionMessage !== client.solutionMessage) {\r\n changed = true;\r\n this.solutionMessage = client.solutionMessage;\r\n }\r\n\r\n return changed;\r\n }\r\n\r\n /**\r\n * Gets the module display name.\r\n */\r\n private getModuleDisplayName(iFrameService: IFrameService, sourceName: string, sourceSubName: string): string {\r\n const activeIFrame = iFrameService ? iFrameService.getActiveToolIFrameData() : null;\r\n if (activeIFrame && activeIFrame.entryPoint) {\r\n const entryPoint = activeIFrame.entryPoint;\r\n this.entryPointName = entryPoint.name;\r\n\r\n if (entryPoint.parentModule) {\r\n this.moduleName = entryPoint.parentModule.name;\r\n }\r\n } else {\r\n // fallback see if we can get any info from RPC\r\n this.moduleName = sourceName;\r\n if (sourceSubName) {\r\n this.entryPointName = MsftSme.first(sourceSubName.split('#'));\r\n }\r\n }\r\n\r\n const environment = MsftSme.self().Environment;\r\n\r\n // if moduleName === environment.name then the source is Shell. Return null to use generic module name\r\n if (this.moduleName && this.moduleName !== environment.name) {\r\n const module: EnvironmentModule = MsftSme.find(\r\n <EnvironmentModule[]>environment.modules,\r\n value => value.name === this.moduleName);\r\n if (module) {\r\n if (this.entryPointName) {\r\n const entryPoint = MsftSme.find(module.entryPoints, ep => ep.name === this.entryPointName);\r\n if (entryPoint) {\r\n return entryPoint.displayName;\r\n }\r\n }\r\n\r\n return module.displayName;\r\n }\r\n\r\n return this.moduleName;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Update the state.\r\n *\r\n * @param state the new state.\r\n * @return boolean the changed state.\r\n */\r\n private updateState(state: NotificationState): boolean {\r\n if (this.state !== state) {\r\n this.state = state;\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private initializeFromWorkItem(item: RpcWorkItem, iFrameService: IFrameService): void {\r\n this.nodeName = item.nodeName;\r\n this.moduleDisplayName = this.getModuleDisplayName(iFrameService, item.sourceName, item.sourceSubName);\r\n this.startTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n this.changedTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n this.changedTimestampValue = item.timestamp;\r\n this.typeId = item.typeId;\r\n this.updateMessageAndLinkAndTitle(item);\r\n }\r\n\r\n private updateMessageAndLinkAndTitle(item: RpcWorkItem): void {\r\n let template: string;\r\n this.isDisabled = !this.isFromRecover && item.disableAllNotifications;\r\n switch (this.state) {\r\n case NotificationState.Started:\r\n this.title = item.inProgressTitle;\r\n template = item.startedMessage;\r\n this.link = this.formatLink(null);\r\n break;\r\n case NotificationState.Error:\r\n this.title = item.errorTitle;\r\n this.isDisabled = !this.isFromRecover && item.disableErrorNotification;\r\n this.endTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n template = item.errorMessage;\r\n this.link = this.formatLink(item.errorLink, item.errorLinkType);\r\n this.linkType = item.errorLinkType;\r\n this.showLinkInAlert = true;\r\n this.moduleDisplayName = item.errorLinkText || this.moduleDisplayName;\r\n break;\r\n case NotificationState.InProgress:\r\n this.title = item.inProgressTitle;\r\n template = item.progressMessage;\r\n this.link = this.formatLink(null);\r\n break;\r\n case NotificationState.Success:\r\n this.title = item.successTitle;\r\n this.endTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n template = item.successMessage;\r\n this.link = this.formatLink(item.successLink, item.successLinkType);\r\n this.linkType = item.successLinkType;\r\n this.moduleDisplayName = item.successLinkText || this.moduleDisplayName;\r\n this.showLinkInAlert = true;\r\n break;\r\n default:\r\n const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.NotificationUnsupportedState.message;\r\n throw new Error(message);\r\n }\r\n\r\n this.message = this.formatMessage(template);\r\n }\r\n\r\n private initializeFromInstant(client: RpcNotification, iFrameService: IFrameService): void {\r\n this.nodeName = client.nodeName;\r\n this.moduleDisplayName = client.linkText ?\r\n client.linkText\r\n : this.getModuleDisplayName(iFrameService, client.sourceName, client.sourceSubName);\r\n this.startTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n this.changedTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n this.changedTimestampValue = client.timestamp;\r\n this.title = client.title;\r\n this.state = client.state;\r\n this.link = this.formatLink(client.link, client.linkType);\r\n this.linkType = client.linkType;\r\n this.message = client.message;\r\n this.solutionMessage = client.solutionMessage;\r\n if (this.state !== NotificationState.Started && this.state !== NotificationState.InProgress) {\r\n this.endTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n }\r\n }\r\n\r\n private getGlobalizedTimestamp(timestamp: number): string {\r\n return Globalization.timeOnly(new Date(timestamp));\r\n }\r\n\r\n private formatLink(link: string, linkType?: NotificationLinkType): string {\r\n // href example: \"http://localhost:4400/apps/msft.sme.server-manager!servers/tools/msft.sme.module-seed!main?connection=sme-full1.redmond.corp.microsoft.com\"\r\n if (linkType === NotificationLinkType.Absolute) {\r\n return link;\r\n }\r\n\r\n // null linkType behaves like NotificationLinkType.RelativeToTool\r\n const pathname = linkType === NotificationLinkType.RelativeToRoot ?\r\n '/'\r\n : this.locationPathname || this.workItem && this.workItem.locationPathname;\r\n\r\n if (link && pathname) {\r\n this.showLinkInAlert = true;\r\n return MsftSme.trimEnd(pathname, '/') + '/' + MsftSme.trimStart(link, '/');\r\n }\r\n\r\n this.showLinkInAlert = false;\r\n return pathname;\r\n }\r\n\r\n private formatMessage(template: string): string {\r\n const parameters = this.findParameters(template);\r\n const message = this.replaceParameters(template, parameters);\r\n return message;\r\n }\r\n\r\n private findParameters(template: string): string[] {\r\n const results: string[] = [];\r\n if (!template) {\r\n return results;\r\n }\r\n\r\n const segments = template.split('{{');\r\n for (const seg of segments) {\r\n const index = seg.indexOf('}}');\r\n if (index > 0) {\r\n results.push(seg.substring(0, index));\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n private replaceParameters(message: string, parameters: string[]): string {\r\n for (const param of parameters) {\r\n if (param === 'percent') {\r\n if (typeof this.progressPercent === 'number') {\r\n message = message.replaceAll('{{percent}}', '' + this.progressPercent);\r\n }\r\n } else if (param === 'objectName') {\r\n if (this.workItem && this.workItem.objectName) {\r\n message = message.replaceAll('{{objectName}}', this.workItem.objectName);\r\n }\r\n } else {\r\n if (this.object) {\r\n const segments = param.split('.');\r\n let target = this.object;\r\n for (const seg of segments) {\r\n if (target[seg]) {\r\n target = target[seg];\r\n } else {\r\n target = null;\r\n break;\r\n }\r\n }\r\n\r\n if (target) {\r\n message = message.replaceAll('{{' + param + '}}', '' + target);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return message;\r\n }\r\n}\r\n"]}
@@ -248,9 +248,7 @@ export class Notification {
248
248
  this.changedTimestamp = this.getGlobalizedTimestamp(now);
249
249
  }
250
250
  this.object = item.message.progress && MsftSme.last(item.message.progress);
251
- if (this.object && this.object.hasOwnProperty('percentComplete')) {
252
- this.progressPercent = this.object && this.object.percentComplete;
253
- }
251
+ this.progressPercent = this.object?.percentComplete ?? this.object?.percent;
254
252
  if ((this.progressPercent == null || this.progressPercent < 0)
255
253
  && this.workItem.progressMessage && this.workItem.progressMessage.indexOf('{{percent}}') >= 0) {
256
254
  return false;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../packages/core/notification/notification.ts"],"names":[],"mappings":"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","file":"notification.js","sourcesContent":["import { Globalization } from '../data/globalization';\r\nimport { Logging } from '../diagnostics/logging';\r\nimport { Strings } from '../generated/strings';\r\nimport { EnvironmentModule } from '../manifest/environment-modules';\r\nimport { RpcNotification } from '../rpc/notification/rpc-notification-model';\r\nimport { RpcWorkItem } from '../rpc/work-item/rpc-work-item-model';\r\nimport { NotificationLinkType } from './notification-link-type';\r\nimport { IFrameService } from './notification-manager';\r\nimport { NotificationMessage } from './notification-message';\r\nimport { NotificationState } from './notification-state';\r\nimport { PowerShellNotification, PowerShellWorkItemMessage } from './powershell-notification';\r\nimport { SocketMessage } from './socket-signalr';\r\nimport { RecoveredWorkItem } from './work-item-request';\r\n\r\n/**\r\n * Notification changed event type.\r\n */\r\nexport enum NotificationChangeEvent {\r\n Initialized,\r\n InitializationFailed,\r\n Add,\r\n Remove,\r\n Change\r\n}\r\n\r\n/**\r\n * Notification changed event packet.\r\n */\r\nexport interface NotificationEvent {\r\n changeEvent: NotificationChangeEvent;\r\n notification?: Notification;\r\n}\r\n\r\n/**\r\n * Internal notification object converted from ClientNotification object.\r\n * Contains data to track notifications.\r\n */\r\nexport class Notification {\r\n private strings: Strings = MsftSme.getStrings<Strings>();\r\n\r\n /**\r\n * Work item passed from RPC or client on shell.\r\n */\r\n private workItem: RpcWorkItem;\r\n\r\n /**\r\n * The type ID of work item.\r\n */\r\n public typeId: string;\r\n\r\n /**\r\n * The node name.\r\n */\r\n public nodeName: string;\r\n\r\n /**\r\n * The module name.\r\n */\r\n public moduleName: string;\r\n\r\n /**\r\n * The entry point name within the module\r\n */\r\n public entryPointName: string;\r\n\r\n /**\r\n * The module display name.\r\n */\r\n public moduleDisplayName: string;\r\n\r\n /**\r\n * Object included last response.\r\n */\r\n public object: any;\r\n\r\n /**\r\n * The state of notification.\r\n */\r\n public state: NotificationState;\r\n\r\n /**\r\n * The title of work item to display user. (localized)\r\n */\r\n public title: string;\r\n\r\n /**\r\n * @depracated\r\n * The description of work item to display user. (localized)\r\n */\r\n public description: string;\r\n\r\n /**\r\n * The message. (localized)\r\n */\r\n public message: string;\r\n\r\n /**\r\n * Possible solution message to address error. (localized)\r\n */\r\n public solutionMessage: string;\r\n\r\n /**\r\n * True if the notification was created from recover, updates from messages should be taken\r\n */\r\n public isFromRecover = false;\r\n\r\n /**\r\n * True if the notification is disabled and should not be shown to the user\r\n */\r\n public isDisabled = false;\r\n\r\n /**\r\n * The start timestamp as a formatted globalized string\r\n */\r\n public startTimestamp: string;\r\n\r\n /**\r\n * The last changed timestamp as a formatted globalized string\r\n */\r\n public changedTimestamp: string;\r\n\r\n /**\r\n * The last changed timestamp as a number\r\n */\r\n public changedTimestampValue: number;\r\n\r\n /**\r\n * The end timestamp as a formatted globalized string\r\n */\r\n public endTimestamp: string;\r\n\r\n /**\r\n * The progress percent.\r\n */\r\n public progressPercent: number;\r\n\r\n /**\r\n * The success link to navigate to the object view. (optional)\r\n * At default, it brings to the home page of the module.\r\n */\r\n public link: string;\r\n\r\n /**\r\n * the notification link type of the link\r\n */\r\n public linkType: NotificationLinkType;\r\n\r\n /**\r\n * True if we should show the link in the notification's alert\r\n * We will show the link if there is a custom link or it is a long running request\r\n */\r\n public showLinkInAlert = false;\r\n\r\n /**\r\n * Marked it's no longer display to include list of notifications.\r\n */\r\n public dismissed = false;\r\n\r\n /**\r\n * The parent URI window.location.pathname.\r\n */\r\n public locationPathname: string;\r\n\r\n /**\r\n * The parent URI window.location.search\r\n */\r\n public locationSearch: string;\r\n\r\n /**\r\n *\r\n * Tracks if the notification has been read.\r\n */\r\n public isUnread = true;\r\n\r\n /**\r\n * Create notification from WorkItem.\r\n *\r\n * @param id the notification ID.\r\n * @param workItem the RPC work item.\r\n * @param state the initial state.\r\n * @param object the object from query result.\r\n * @return notification the notification object.\r\n */\r\n public static createFromWorkItem(\r\n id: string, workItem: RpcWorkItem, state: NotificationState, iFrameService: IFrameService, object?: any): Notification {\r\n const notification = new Notification(id);\r\n notification.workItem = workItem;\r\n\r\n notification.state = state;\r\n notification.object = object;\r\n notification.initializeFromWorkItem(workItem, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Create notification from recovered work item.\r\n *\r\n * @param recoveredWorkItem the recovered work item.\r\n * @return notification the notification object.\r\n */\r\n public static createFromRecover(recoveredWorkItem: RecoveredWorkItem, iFrameService: IFrameService): Notification {\r\n const notification = new Notification(recoveredWorkItem.id);\r\n notification.workItem = recoveredWorkItem.metadata;\r\n notification.isFromRecover = true;\r\n\r\n if (recoveredWorkItem.failed) {\r\n notification.state = NotificationState.Error;\r\n notification.object = { errorType: 'WorkItemRecover', message: recoveredWorkItem.errorMessage };\r\n } else {\r\n notification.state = NotificationState.InProgress;\r\n notification.object = {};\r\n }\r\n\r\n notification.initializeFromWorkItem(recoveredWorkItem.metadata, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Create notification from instant request.\r\n *\r\n * @param client the RPC notification request.\r\n * @return notification the notification object.\r\n */\r\n public static createFromClient(client: RpcNotification, iFrameService: IFrameService): Notification {\r\n const notification = new Notification(client.id);\r\n notification.locationPathname = window.location.pathname;\r\n notification.locationSearch = window.location.search;\r\n notification.initializeFromInstant(client, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Initializes a new instance of the Notification class.\r\n *\r\n * @param id the notification ID.\r\n */\r\n constructor(public id: string) { }\r\n\r\n /**\r\n * Update a notification by work item from RPC.\r\n * @param id the notification id.\r\n * @param workItem the work item.\r\n * @param state the state of the notification.\r\n * @param object the object from query result.\r\n */\r\n public updateFromWorkItem(id: string, workItem: RpcWorkItem, state: NotificationState, object?: any) {\r\n let changed = false;\r\n\r\n if (this.updateState(state)) {\r\n changed = true;\r\n const now = Date.now();\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n if (this.object !== object) {\r\n changed = true;\r\n this.object = object;\r\n }\r\n\r\n this.updateMessageAndLinkAndTitle(workItem);\r\n return !this.isDisabled && changed;\r\n }\r\n\r\n /**\r\n * Update the notification by socket message from the gateway.\r\n *\r\n * @param item the socket message.\r\n * @return boolean the changed status.\r\n */\r\n public updateFromMessage(item: SocketMessage<PowerShellWorkItemMessage>): boolean {\r\n let changed = false;\r\n const now = Date.now();\r\n if (PowerShellNotification.hasError(item)) {\r\n Logging.logDebug('Notification', '{0}/Error/{1}'.format(this.id, JSON.stringify(item.message.errors)));\r\n if (this.updateState(NotificationState.Error)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = item.message.errors && MsftSme.first(item.message.errors);\r\n changed = true;\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled;\r\n }\r\n\r\n if (PowerShellNotification.hasException(item)) {\r\n Logging.logDebug('Notification', '{0}/Exception/{1}'.format(this.id, item.message.exception));\r\n if (this.updateState(NotificationState.Error)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = { message: item.message.exception };\r\n changed = true;\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled;\r\n }\r\n\r\n if (PowerShellNotification.hasProgress(item)) {\r\n Logging.logDebug('Notification', '{0}/Progress/{1}'.format(this.id, JSON.stringify(item.message.progress)));\r\n if (this.updateState(NotificationState.InProgress)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = item.message.progress && MsftSme.last(item.message.progress);\r\n if (this.object && this.object.hasOwnProperty('percentComplete')) {\r\n this.progressPercent = this.object && this.object.percentComplete;\r\n }\r\n\r\n if ((this.progressPercent == null || this.progressPercent < 0)\r\n && this.workItem.progressMessage && this.workItem.progressMessage.indexOf('{{percent}}') >= 0) {\r\n return false;\r\n }\r\n\r\n changed = true;\r\n }\r\n\r\n if (PowerShellNotification.hasData(item)) {\r\n Logging.logDebug('Notification', '{0}/Data/{1}'.format(this.id, JSON.stringify(item.message.results)));\r\n this.object = item.message.results && MsftSme.last(item.message.results);\r\n changed = true;\r\n }\r\n\r\n if (PowerShellNotification.hasCompleted(item)) {\r\n Logging.logDebug('Notification', '{0}/Completed'.format(this.id));\r\n if (this.updateState(NotificationState.Success)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n changed = true;\r\n }\r\n\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled && changed;\r\n }\r\n\r\n /**\r\n * Update the notification by socket message from the gateway.\r\n *\r\n * @param state the state of notification.\r\n * @param item the socket message.\r\n * @return boolean the changed status.\r\n */\r\n public updateFromNotificationMessage(state: NotificationState, item: NotificationMessage): boolean {\r\n const now = Date.now();\r\n this.title = item.title;\r\n this.message = item.message;\r\n this.state = state;\r\n this.changedTimestampValue = now;\r\n if (state === NotificationState.InProgress) {\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n } else {\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Update the notification by instant notification message from the client.\r\n *\r\n * @param client the instant notification object.\r\n * @param boolean the changed status.\r\n */\r\n public updateFromClient(client: RpcNotification): boolean {\r\n let changed = false;\r\n const title = client.title;\r\n if (this.title !== title) {\r\n changed = true;\r\n this.title = title;\r\n }\r\n\r\n if (this.updateState(client.state)) {\r\n const now = Date.now();\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n changed = true;\r\n if (this.state !== NotificationState.InProgress) {\r\n this.endTimestamp = this.changedTimestamp;\r\n }\r\n }\r\n\r\n const link = this.formatLink(client.link, client.linkType);\r\n if (this.link !== link) {\r\n changed = true;\r\n this.link = link;\r\n this.linkType = client.linkType;\r\n }\r\n\r\n if (this.message !== client.message) {\r\n changed = true;\r\n this.message = client.message;\r\n }\r\n\r\n if (this.solutionMessage !== client.solutionMessage) {\r\n changed = true;\r\n this.solutionMessage = client.solutionMessage;\r\n }\r\n\r\n return changed;\r\n }\r\n\r\n /**\r\n * Gets the module display name.\r\n */\r\n private getModuleDisplayName(iFrameService: IFrameService, sourceName: string, sourceSubName: string): string {\r\n const activeIFrame = iFrameService ? iFrameService.getActiveToolIFrameData() : null;\r\n if (activeIFrame && activeIFrame.entryPoint) {\r\n const entryPoint = activeIFrame.entryPoint;\r\n this.entryPointName = entryPoint.name;\r\n\r\n if (entryPoint.parentModule) {\r\n this.moduleName = entryPoint.parentModule.name;\r\n }\r\n } else {\r\n // fallback see if we can get any info from RPC\r\n this.moduleName = sourceName;\r\n if (sourceSubName) {\r\n this.entryPointName = MsftSme.first(sourceSubName.split('#'));\r\n }\r\n }\r\n\r\n const environment = MsftSme.self().Environment;\r\n\r\n // if moduleName === environment.name then the source is Shell. Return null to use generic module name\r\n if (this.moduleName && this.moduleName !== environment.name) {\r\n const module: EnvironmentModule = MsftSme.find(\r\n <EnvironmentModule[]>environment.modules,\r\n value => value.name === this.moduleName);\r\n if (module) {\r\n if (this.entryPointName) {\r\n const entryPoint = MsftSme.find(module.entryPoints, ep => ep.name === this.entryPointName);\r\n if (entryPoint) {\r\n return entryPoint.displayName;\r\n }\r\n }\r\n\r\n return module.displayName;\r\n }\r\n\r\n return this.moduleName;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Update the state.\r\n *\r\n * @param state the new state.\r\n * @return boolean the changed state.\r\n */\r\n private updateState(state: NotificationState): boolean {\r\n if (this.state !== state) {\r\n this.state = state;\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private initializeFromWorkItem(item: RpcWorkItem, iFrameService: IFrameService): void {\r\n this.nodeName = item.nodeName;\r\n this.moduleDisplayName = this.getModuleDisplayName(iFrameService, item.sourceName, item.sourceSubName);\r\n this.startTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n this.changedTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n this.changedTimestampValue = item.timestamp;\r\n this.typeId = item.typeId;\r\n this.updateMessageAndLinkAndTitle(item);\r\n }\r\n\r\n private updateMessageAndLinkAndTitle(item: RpcWorkItem): void {\r\n let template: string;\r\n this.isDisabled = !this.isFromRecover && item.disableAllNotifications;\r\n switch (this.state) {\r\n case NotificationState.Started:\r\n this.title = item.inProgressTitle;\r\n template = item.startedMessage;\r\n this.link = this.formatLink(null);\r\n break;\r\n case NotificationState.Error:\r\n this.title = item.errorTitle;\r\n this.isDisabled = !this.isFromRecover && item.disableErrorNotification;\r\n this.endTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n template = item.errorMessage;\r\n this.link = this.formatLink(item.errorLink, item.errorLinkType);\r\n this.linkType = item.errorLinkType;\r\n this.showLinkInAlert = true;\r\n this.moduleDisplayName = item.errorLinkText || this.moduleDisplayName;\r\n break;\r\n case NotificationState.InProgress:\r\n this.title = item.inProgressTitle;\r\n template = item.progressMessage;\r\n this.link = this.formatLink(null);\r\n break;\r\n case NotificationState.Success:\r\n this.title = item.successTitle;\r\n this.endTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n template = item.successMessage;\r\n this.link = this.formatLink(item.successLink, item.successLinkType);\r\n this.linkType = item.successLinkType;\r\n this.moduleDisplayName = item.successLinkText || this.moduleDisplayName;\r\n this.showLinkInAlert = true;\r\n break;\r\n default:\r\n const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.NotificationUnsupportedState.message;\r\n throw new Error(message);\r\n }\r\n\r\n this.message = this.formatMessage(template);\r\n }\r\n\r\n private initializeFromInstant(client: RpcNotification, iFrameService: IFrameService): void {\r\n this.nodeName = client.nodeName;\r\n this.moduleDisplayName = client.linkText ?\r\n client.linkText\r\n : this.getModuleDisplayName(iFrameService, client.sourceName, client.sourceSubName);\r\n this.startTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n this.changedTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n this.changedTimestampValue = client.timestamp;\r\n this.title = client.title;\r\n this.state = client.state;\r\n this.link = this.formatLink(client.link, client.linkType);\r\n this.linkType = client.linkType;\r\n this.message = client.message;\r\n this.solutionMessage = client.solutionMessage;\r\n if (this.state !== NotificationState.Started && this.state !== NotificationState.InProgress) {\r\n this.endTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n }\r\n }\r\n\r\n private getGlobalizedTimestamp(timestamp: number): string {\r\n return Globalization.timeOnly(new Date(timestamp));\r\n }\r\n\r\n private formatLink(link: string, linkType?: NotificationLinkType): string {\r\n // href example: \"http://localhost:4400/apps/msft.sme.server-manager!servers/tools/msft.sme.module-seed!main?connection=sme-full1.redmond.corp.microsoft.com\"\r\n if (linkType === NotificationLinkType.Absolute) {\r\n return link;\r\n }\r\n\r\n // null linkType behaves like NotificationLinkType.RelativeToTool\r\n const pathname = linkType === NotificationLinkType.RelativeToRoot ?\r\n '/'\r\n : this.locationPathname || this.workItem && this.workItem.locationPathname;\r\n\r\n if (link && pathname) {\r\n this.showLinkInAlert = true;\r\n return MsftSme.trimEnd(pathname, '/') + '/' + MsftSme.trimStart(link, '/');\r\n }\r\n\r\n this.showLinkInAlert = false;\r\n return pathname;\r\n }\r\n\r\n private formatMessage(template: string): string {\r\n const parameters = this.findParameters(template);\r\n const message = this.replaceParameters(template, parameters);\r\n return message;\r\n }\r\n\r\n private findParameters(template: string): string[] {\r\n const results: string[] = [];\r\n if (!template) {\r\n return results;\r\n }\r\n\r\n const segments = template.split('{{');\r\n for (const seg of segments) {\r\n const index = seg.indexOf('}}');\r\n if (index > 0) {\r\n results.push(seg.substring(0, index));\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n private replaceParameters(message: string, parameters: string[]): string {\r\n for (const param of parameters) {\r\n if (param === 'percent') {\r\n if (typeof this.progressPercent === 'number') {\r\n message = message.replaceAll('{{percent}}', '' + this.progressPercent);\r\n }\r\n } else if (param === 'objectName') {\r\n if (this.workItem && this.workItem.objectName) {\r\n message = message.replaceAll('{{objectName}}', this.workItem.objectName);\r\n }\r\n } else {\r\n if (this.object) {\r\n const segments = param.split('.');\r\n let target = this.object;\r\n for (const seg of segments) {\r\n if (target[seg]) {\r\n target = target[seg];\r\n } else {\r\n target = null;\r\n break;\r\n }\r\n }\r\n\r\n if (target) {\r\n message = message.replaceAll('{{' + param + '}}', '' + target);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return message;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../../packages/core/notification/notification.ts"],"names":[],"mappings":"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","file":"notification.js","sourcesContent":["import { Globalization } from '../data/globalization';\r\nimport { Logging } from '../diagnostics/logging';\r\nimport { Strings } from '../generated/strings';\r\nimport { EnvironmentModule } from '../manifest/environment-modules';\r\nimport { RpcNotification } from '../rpc/notification/rpc-notification-model';\r\nimport { RpcWorkItem } from '../rpc/work-item/rpc-work-item-model';\r\nimport { NotificationLinkType } from './notification-link-type';\r\nimport { IFrameService } from './notification-manager';\r\nimport { NotificationMessage } from './notification-message';\r\nimport { NotificationState } from './notification-state';\r\nimport { PowerShellNotification, PowerShellWorkItemMessage } from './powershell-notification';\r\nimport { SocketMessage } from './socket-signalr';\r\nimport { RecoveredWorkItem } from './work-item-request';\r\n\r\n/**\r\n * Notification changed event type.\r\n */\r\nexport enum NotificationChangeEvent {\r\n Initialized,\r\n InitializationFailed,\r\n Add,\r\n Remove,\r\n Change\r\n}\r\n\r\n/**\r\n * Notification changed event packet.\r\n */\r\nexport interface NotificationEvent {\r\n changeEvent: NotificationChangeEvent;\r\n notification?: Notification;\r\n}\r\n\r\n/**\r\n * Internal notification object converted from ClientNotification object.\r\n * Contains data to track notifications.\r\n */\r\nexport class Notification {\r\n private strings: Strings = MsftSme.getStrings<Strings>();\r\n\r\n /**\r\n * Work item passed from RPC or client on shell.\r\n */\r\n private workItem: RpcWorkItem;\r\n\r\n /**\r\n * The type ID of work item.\r\n */\r\n public typeId: string;\r\n\r\n /**\r\n * The node name.\r\n */\r\n public nodeName: string;\r\n\r\n /**\r\n * The module name.\r\n */\r\n public moduleName: string;\r\n\r\n /**\r\n * The entry point name within the module\r\n */\r\n public entryPointName: string;\r\n\r\n /**\r\n * The module display name.\r\n */\r\n public moduleDisplayName: string;\r\n\r\n /**\r\n * Object included last response.\r\n */\r\n public object: any;\r\n\r\n /**\r\n * The state of notification.\r\n */\r\n public state: NotificationState;\r\n\r\n /**\r\n * The title of work item to display user. (localized)\r\n */\r\n public title: string;\r\n\r\n /**\r\n * @depracated\r\n * The description of work item to display user. (localized)\r\n */\r\n public description: string;\r\n\r\n /**\r\n * The message. (localized)\r\n */\r\n public message: string;\r\n\r\n /**\r\n * Possible solution message to address error. (localized)\r\n */\r\n public solutionMessage: string;\r\n\r\n /**\r\n * True if the notification was created from recover, updates from messages should be taken\r\n */\r\n public isFromRecover = false;\r\n\r\n /**\r\n * True if the notification is disabled and should not be shown to the user\r\n */\r\n public isDisabled = false;\r\n\r\n /**\r\n * The start timestamp as a formatted globalized string\r\n */\r\n public startTimestamp: string;\r\n\r\n /**\r\n * The last changed timestamp as a formatted globalized string\r\n */\r\n public changedTimestamp: string;\r\n\r\n /**\r\n * The last changed timestamp as a number\r\n */\r\n public changedTimestampValue: number;\r\n\r\n /**\r\n * The end timestamp as a formatted globalized string\r\n */\r\n public endTimestamp: string;\r\n\r\n /**\r\n * The progress percent.\r\n */\r\n public progressPercent: number;\r\n\r\n /**\r\n * The success link to navigate to the object view. (optional)\r\n * At default, it brings to the home page of the module.\r\n */\r\n public link: string;\r\n\r\n /**\r\n * the notification link type of the link\r\n */\r\n public linkType: NotificationLinkType;\r\n\r\n /**\r\n * True if we should show the link in the notification's alert\r\n * We will show the link if there is a custom link or it is a long running request\r\n */\r\n public showLinkInAlert = false;\r\n\r\n /**\r\n * Marked it's no longer display to include list of notifications.\r\n */\r\n public dismissed = false;\r\n\r\n /**\r\n * The parent URI window.location.pathname.\r\n */\r\n public locationPathname: string;\r\n\r\n /**\r\n * The parent URI window.location.search\r\n */\r\n public locationSearch: string;\r\n\r\n /**\r\n *\r\n * Tracks if the notification has been read.\r\n */\r\n public isUnread = true;\r\n\r\n /**\r\n * Create notification from WorkItem.\r\n *\r\n * @param id the notification ID.\r\n * @param workItem the RPC work item.\r\n * @param state the initial state.\r\n * @param object the object from query result.\r\n * @return notification the notification object.\r\n */\r\n public static createFromWorkItem(\r\n id: string, workItem: RpcWorkItem, state: NotificationState, iFrameService: IFrameService, object?: any): Notification {\r\n const notification = new Notification(id);\r\n notification.workItem = workItem;\r\n\r\n notification.state = state;\r\n notification.object = object;\r\n notification.initializeFromWorkItem(workItem, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Create notification from recovered work item.\r\n *\r\n * @param recoveredWorkItem the recovered work item.\r\n * @return notification the notification object.\r\n */\r\n public static createFromRecover(recoveredWorkItem: RecoveredWorkItem, iFrameService: IFrameService): Notification {\r\n const notification = new Notification(recoveredWorkItem.id);\r\n notification.workItem = recoveredWorkItem.metadata;\r\n notification.isFromRecover = true;\r\n\r\n if (recoveredWorkItem.failed) {\r\n notification.state = NotificationState.Error;\r\n notification.object = { errorType: 'WorkItemRecover', message: recoveredWorkItem.errorMessage };\r\n } else {\r\n notification.state = NotificationState.InProgress;\r\n notification.object = {};\r\n }\r\n\r\n notification.initializeFromWorkItem(recoveredWorkItem.metadata, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Create notification from instant request.\r\n *\r\n * @param client the RPC notification request.\r\n * @return notification the notification object.\r\n */\r\n public static createFromClient(client: RpcNotification, iFrameService: IFrameService): Notification {\r\n const notification = new Notification(client.id);\r\n notification.locationPathname = window.location.pathname;\r\n notification.locationSearch = window.location.search;\r\n notification.initializeFromInstant(client, iFrameService);\r\n return notification;\r\n }\r\n\r\n /**\r\n * Initializes a new instance of the Notification class.\r\n *\r\n * @param id the notification ID.\r\n */\r\n constructor(public id: string) { }\r\n\r\n /**\r\n * Update a notification by work item from RPC.\r\n * @param id the notification id.\r\n * @param workItem the work item.\r\n * @param state the state of the notification.\r\n * @param object the object from query result.\r\n */\r\n public updateFromWorkItem(id: string, workItem: RpcWorkItem, state: NotificationState, object?: any) {\r\n let changed = false;\r\n\r\n if (this.updateState(state)) {\r\n changed = true;\r\n const now = Date.now();\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n if (this.object !== object) {\r\n changed = true;\r\n this.object = object;\r\n }\r\n\r\n this.updateMessageAndLinkAndTitle(workItem);\r\n return !this.isDisabled && changed;\r\n }\r\n\r\n /**\r\n * Update the notification by socket message from the gateway.\r\n *\r\n * @param item the socket message.\r\n * @return boolean the changed status.\r\n */\r\n public updateFromMessage(item: SocketMessage<PowerShellWorkItemMessage>): boolean {\r\n let changed = false;\r\n const now = Date.now();\r\n if (PowerShellNotification.hasError(item)) {\r\n Logging.logDebug('Notification', '{0}/Error/{1}'.format(this.id, JSON.stringify(item.message.errors)));\r\n if (this.updateState(NotificationState.Error)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = item.message.errors && MsftSme.first(item.message.errors);\r\n changed = true;\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled;\r\n }\r\n\r\n if (PowerShellNotification.hasException(item)) {\r\n Logging.logDebug('Notification', '{0}/Exception/{1}'.format(this.id, item.message.exception));\r\n if (this.updateState(NotificationState.Error)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = { message: item.message.exception };\r\n changed = true;\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled;\r\n }\r\n\r\n if (PowerShellNotification.hasProgress(item)) {\r\n Logging.logDebug('Notification', '{0}/Progress/{1}'.format(this.id, JSON.stringify(item.message.progress)));\r\n if (this.updateState(NotificationState.InProgress)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n this.object = item.message.progress && MsftSme.last(item.message.progress);\r\n this.progressPercent = this.object?.percentComplete ?? this.object?.percent;\r\n\r\n if ((this.progressPercent == null || this.progressPercent < 0)\r\n && this.workItem.progressMessage && this.workItem.progressMessage.indexOf('{{percent}}') >= 0) {\r\n return false;\r\n }\r\n\r\n changed = true;\r\n }\r\n\r\n if (PowerShellNotification.hasData(item)) {\r\n Logging.logDebug('Notification', '{0}/Data/{1}'.format(this.id, JSON.stringify(item.message.results)));\r\n this.object = item.message.results && MsftSme.last(item.message.results);\r\n changed = true;\r\n }\r\n\r\n if (PowerShellNotification.hasCompleted(item)) {\r\n Logging.logDebug('Notification', '{0}/Completed'.format(this.id));\r\n if (this.updateState(NotificationState.Success)) {\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n changed = true;\r\n }\r\n\r\n this.updateMessageAndLinkAndTitle(this.workItem);\r\n return !this.isDisabled && changed;\r\n }\r\n\r\n /**\r\n * Update the notification by socket message from the gateway.\r\n *\r\n * @param state the state of notification.\r\n * @param item the socket message.\r\n * @return boolean the changed status.\r\n */\r\n public updateFromNotificationMessage(state: NotificationState, item: NotificationMessage): boolean {\r\n const now = Date.now();\r\n this.title = item.title;\r\n this.message = item.message;\r\n this.state = state;\r\n this.changedTimestampValue = now;\r\n if (state === NotificationState.InProgress) {\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n } else {\r\n this.changedTimestamp = this.endTimestamp = this.getGlobalizedTimestamp(now);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Update the notification by instant notification message from the client.\r\n *\r\n * @param client the instant notification object.\r\n * @param boolean the changed status.\r\n */\r\n public updateFromClient(client: RpcNotification): boolean {\r\n let changed = false;\r\n const title = client.title;\r\n if (this.title !== title) {\r\n changed = true;\r\n this.title = title;\r\n }\r\n\r\n if (this.updateState(client.state)) {\r\n const now = Date.now();\r\n this.changedTimestampValue = now;\r\n this.changedTimestamp = this.getGlobalizedTimestamp(now);\r\n changed = true;\r\n if (this.state !== NotificationState.InProgress) {\r\n this.endTimestamp = this.changedTimestamp;\r\n }\r\n }\r\n\r\n const link = this.formatLink(client.link, client.linkType);\r\n if (this.link !== link) {\r\n changed = true;\r\n this.link = link;\r\n this.linkType = client.linkType;\r\n }\r\n\r\n if (this.message !== client.message) {\r\n changed = true;\r\n this.message = client.message;\r\n }\r\n\r\n if (this.solutionMessage !== client.solutionMessage) {\r\n changed = true;\r\n this.solutionMessage = client.solutionMessage;\r\n }\r\n\r\n return changed;\r\n }\r\n\r\n /**\r\n * Gets the module display name.\r\n */\r\n private getModuleDisplayName(iFrameService: IFrameService, sourceName: string, sourceSubName: string): string {\r\n const activeIFrame = iFrameService ? iFrameService.getActiveToolIFrameData() : null;\r\n if (activeIFrame && activeIFrame.entryPoint) {\r\n const entryPoint = activeIFrame.entryPoint;\r\n this.entryPointName = entryPoint.name;\r\n\r\n if (entryPoint.parentModule) {\r\n this.moduleName = entryPoint.parentModule.name;\r\n }\r\n } else {\r\n // fallback see if we can get any info from RPC\r\n this.moduleName = sourceName;\r\n if (sourceSubName) {\r\n this.entryPointName = MsftSme.first(sourceSubName.split('#'));\r\n }\r\n }\r\n\r\n const environment = MsftSme.self().Environment;\r\n\r\n // if moduleName === environment.name then the source is Shell. Return null to use generic module name\r\n if (this.moduleName && this.moduleName !== environment.name) {\r\n const module: EnvironmentModule = MsftSme.find(\r\n <EnvironmentModule[]>environment.modules,\r\n value => value.name === this.moduleName);\r\n if (module) {\r\n if (this.entryPointName) {\r\n const entryPoint = MsftSme.find(module.entryPoints, ep => ep.name === this.entryPointName);\r\n if (entryPoint) {\r\n return entryPoint.displayName;\r\n }\r\n }\r\n\r\n return module.displayName;\r\n }\r\n\r\n return this.moduleName;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Update the state.\r\n *\r\n * @param state the new state.\r\n * @return boolean the changed state.\r\n */\r\n private updateState(state: NotificationState): boolean {\r\n if (this.state !== state) {\r\n this.state = state;\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private initializeFromWorkItem(item: RpcWorkItem, iFrameService: IFrameService): void {\r\n this.nodeName = item.nodeName;\r\n this.moduleDisplayName = this.getModuleDisplayName(iFrameService, item.sourceName, item.sourceSubName);\r\n this.startTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n this.changedTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n this.changedTimestampValue = item.timestamp;\r\n this.typeId = item.typeId;\r\n this.updateMessageAndLinkAndTitle(item);\r\n }\r\n\r\n private updateMessageAndLinkAndTitle(item: RpcWorkItem): void {\r\n let template: string;\r\n this.isDisabled = !this.isFromRecover && item.disableAllNotifications;\r\n switch (this.state) {\r\n case NotificationState.Started:\r\n this.title = item.inProgressTitle;\r\n template = item.startedMessage;\r\n this.link = this.formatLink(null);\r\n break;\r\n case NotificationState.Error:\r\n this.title = item.errorTitle;\r\n this.isDisabled = !this.isFromRecover && item.disableErrorNotification;\r\n this.endTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n template = item.errorMessage;\r\n this.link = this.formatLink(item.errorLink, item.errorLinkType);\r\n this.linkType = item.errorLinkType;\r\n this.showLinkInAlert = true;\r\n this.moduleDisplayName = item.errorLinkText || this.moduleDisplayName;\r\n break;\r\n case NotificationState.InProgress:\r\n this.title = item.inProgressTitle;\r\n template = item.progressMessage;\r\n this.link = this.formatLink(null);\r\n break;\r\n case NotificationState.Success:\r\n this.title = item.successTitle;\r\n this.endTimestamp = this.getGlobalizedTimestamp(item.timestamp);\r\n template = item.successMessage;\r\n this.link = this.formatLink(item.successLink, item.successLinkType);\r\n this.linkType = item.successLinkType;\r\n this.moduleDisplayName = item.successLinkText || this.moduleDisplayName;\r\n this.showLinkInAlert = true;\r\n break;\r\n default:\r\n const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.NotificationUnsupportedState.message;\r\n throw new Error(message);\r\n }\r\n\r\n this.message = this.formatMessage(template);\r\n }\r\n\r\n private initializeFromInstant(client: RpcNotification, iFrameService: IFrameService): void {\r\n this.nodeName = client.nodeName;\r\n this.moduleDisplayName = client.linkText ?\r\n client.linkText\r\n : this.getModuleDisplayName(iFrameService, client.sourceName, client.sourceSubName);\r\n this.startTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n this.changedTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n this.changedTimestampValue = client.timestamp;\r\n this.title = client.title;\r\n this.state = client.state;\r\n this.link = this.formatLink(client.link, client.linkType);\r\n this.linkType = client.linkType;\r\n this.message = client.message;\r\n this.solutionMessage = client.solutionMessage;\r\n if (this.state !== NotificationState.Started && this.state !== NotificationState.InProgress) {\r\n this.endTimestamp = this.getGlobalizedTimestamp(client.timestamp);\r\n }\r\n }\r\n\r\n private getGlobalizedTimestamp(timestamp: number): string {\r\n return Globalization.timeOnly(new Date(timestamp));\r\n }\r\n\r\n private formatLink(link: string, linkType?: NotificationLinkType): string {\r\n // href example: \"http://localhost:4400/apps/msft.sme.server-manager!servers/tools/msft.sme.module-seed!main?connection=sme-full1.redmond.corp.microsoft.com\"\r\n if (linkType === NotificationLinkType.Absolute) {\r\n return link;\r\n }\r\n\r\n // null linkType behaves like NotificationLinkType.RelativeToTool\r\n const pathname = linkType === NotificationLinkType.RelativeToRoot ?\r\n '/'\r\n : this.locationPathname || this.workItem && this.workItem.locationPathname;\r\n\r\n if (link && pathname) {\r\n this.showLinkInAlert = true;\r\n return MsftSme.trimEnd(pathname, '/') + '/' + MsftSme.trimStart(link, '/');\r\n }\r\n\r\n this.showLinkInAlert = false;\r\n return pathname;\r\n }\r\n\r\n private formatMessage(template: string): string {\r\n const parameters = this.findParameters(template);\r\n const message = this.replaceParameters(template, parameters);\r\n return message;\r\n }\r\n\r\n private findParameters(template: string): string[] {\r\n const results: string[] = [];\r\n if (!template) {\r\n return results;\r\n }\r\n\r\n const segments = template.split('{{');\r\n for (const seg of segments) {\r\n const index = seg.indexOf('}}');\r\n if (index > 0) {\r\n results.push(seg.substring(0, index));\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n private replaceParameters(message: string, parameters: string[]): string {\r\n for (const param of parameters) {\r\n if (param === 'percent') {\r\n if (typeof this.progressPercent === 'number') {\r\n message = message.replaceAll('{{percent}}', '' + this.progressPercent);\r\n }\r\n } else if (param === 'objectName') {\r\n if (this.workItem && this.workItem.objectName) {\r\n message = message.replaceAll('{{objectName}}', this.workItem.objectName);\r\n }\r\n } else {\r\n if (this.object) {\r\n const segments = param.split('.');\r\n let target = this.object;\r\n for (const seg of segments) {\r\n if (target[seg]) {\r\n target = target[seg];\r\n } else {\r\n target = null;\r\n break;\r\n }\r\n }\r\n\r\n if (target) {\r\n message = message.replaceAll('{{' + param + '}}', '' + target);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return message;\r\n }\r\n}\r\n"]}
@@ -446,16 +446,16 @@ function getAzureArcStatus() {
446
446
  <#
447
447
 
448
448
  .SYNOPSIS
449
- Checks if a system lockdown policy is enforced on this computer.
449
+ Gets an EnforcementMode that describes the system lockdown policy on this computer.
450
450
 
451
451
  .DESCRIPTION
452
- By checking the system lockdown policy, we can infer that PowerShell is in ConstrainedLanguage mode (WDAC).
453
- Note: $ExecutionContext.SessionState.LanguageMode should not be used within a script context as in the case of allowed scripts (by the WDAC policy),
454
- being executed locally, the language mode will always be FullLanguage and does NOT reflect the default system lockdown policy/language mode.
452
+ By checking the system lockdown policy, we can infer if PowerShell is in ConstrainedLanguage mode as a result of an enforced WDAC policy.
453
+ Note: $ExecutionContext.SessionState.LanguageMode should not be used within a trusted (by the WDAC policy) script context for this purpose because
454
+ the language mode returned would potentially not reflect the system-wide lockdown policy/language mode outside of the execution context.
455
455
 
456
456
  #>
457
- function isSystemLockdownPolicyEnforced() {
458
- return [System.Management.Automation.Security.SystemPolicy]::GetSystemLockdownPolicy() -eq [System.Management.Automation.Security.SystemEnforcementMode]::Enforce
457
+ function getSystemLockdownPolicy() {
458
+ return [System.Management.Automation.Security.SystemPolicy]::GetSystemLockdownPolicy().ToString()
459
459
  }
460
460
 
461
461
  <#
@@ -490,7 +490,7 @@ $isCredSSPEnabled = isCredSSPEnabled
490
490
  $isRemoteAppEnabled = isRemoteAppEnabled
491
491
  $smbiosData = getSmbiosData $computerSystem
492
492
  $azureArcStatus = getAzureArcStatus
493
- $isSystemLockdownPolicyEnforced = isSystemLockdownPolicyEnforced
493
+ $systemLockdownPolicy = getSystemLockdownPolicy
494
494
  $isHciServer = isServerOsHCI $operatingSystem.Caption
495
495
 
496
496
  $result = New-Object PSObject
@@ -514,7 +514,7 @@ $result | Add-Member -MemberType NoteProperty -Name 'IsCredSSPEnabled' -Value $i
514
514
  $result | Add-Member -MemberType NoteProperty -Name 'IsRemoteAppEnabled' -Value $isRemoteAppEnabled
515
515
  $result | Add-Member -MemberType NoteProperty -Name 'SmbiosData' -Value $smbiosData
516
516
  $result | Add-Member -MemberType NoteProperty -Name 'AzureArcStatus' -Value $azureArcStatus
517
- $result | Add-Member -MemberType NoteProperty -Name 'IsSystemLockdownPolicyEnforced' -Value $isSystemLockdownPolicyEnforced
517
+ $result | Add-Member -MemberType NoteProperty -Name 'SystemLockdownPolicy' -Value $systemLockdownPolicy
518
518
  $result | Add-Member -MemberType NoteProperty -Name 'IsHciServer' -Value $isHciServer
519
519
 
520
520
  $result
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../packages/core/security/tool-condition-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,UAAU,EAAM,MAAM,MAAM,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD,OAAO,EAIH,2BAA2B,EAC3B,kDAAkD,EAGrD,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAWxE;;GAEG;AACH,0BAAkB,mBAAmB;IACjC;;OAEG;IACH,aAAa,IAAA;IAEb;;OAEG;IACH,QAAQ,IAAA;IAER;;OAEG;IACH,OAAO,IAAA;IAEP;;OAEG;IACH,MAAM,IAAA;IAEN;;OAEG;IACH,MAAM,IAAA;CACT;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC1C;;OAEG;IACH,MAAM,EAAE,mBAAmB,CAAC;IAE5B;;OAEG;IACH,MAAM,EAAE,UAAU,CAAC,kDAAkD,CAAC,GAAG,kDAAkD,CAAC;CAC/H;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IA6MnB,OAAO,CAAC,UAAU;IA5M9B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB,CAgGtC;IAEF;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS,CAsEtB;IAEF,OAAO,CAAC,MAAM,CAAC,eAAe,CAAyB;IAEvD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,YAAY,CAAyD;IAE7E;;;;;OAKG;WACW,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,oBAAoB,GAAG,sBAAsB;IAQnG;;;;;OAKG;gBACiB,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,oBAAoB;IAMxE;;;;;;;;OAQG;IACI,iBAAiB,CACpB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,2BAA2B,EACrC,IAAI,EAAE,2BAA2B,GAAG,6BAA6B;IAuKrE,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,wBAAwB;IA0BhC,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,qBAAqB;IA0B7B,OAAO,CAAC,6BAA6B;IAWrC,OAAO,CAAC,cAAc;IAuKtB,OAAO,CAAC,cAAc;IAmDtB,OAAO,CAAC,eAAe;CAI1B","file":"tool-condition-validator.d.ts","sourcesContent":["import { EMPTY, Observable, of } from 'rxjs';\r\nimport { catchError, expand, filter, map, take } from 'rxjs/operators';\r\nimport { AppContext } from '../data/app-context';\r\nimport { Net } from '../data/net';\r\nimport { PowerShell, PowerShellCommand } from '../data/powershell';\r\nimport { LogLevel } from '../diagnostics/log-level';\r\nimport { Logging } from '../diagnostics/logging';\r\nimport { Strings } from '../generated/strings';\r\nimport {\r\n EnvironmentModule,\r\n EnvironmentModuleConditionMap,\r\n EnvironmentModuleConditionStatement,\r\n EnvironmentModuleEntryPoint,\r\n EnvironmentModuleEntryPointWithToolConditionResult,\r\n EnvironmentModuleToolConditionResult,\r\n EnvironmentModuleToolState\r\n} from '../manifest/environment-modules';\r\nimport { Connection } from '../security/connection';\r\nimport { GatewayMode } from '../shared/gateway-inventory/gateway-inventory';\r\nimport { InventoryQueryCaches } from '../shared/inventory-query-caches';\r\nimport { ServerInventory } from '../shared/server-inventory/server-inventory';\r\nimport { ToolInventoryCache } from '../shared/tool-inventory/tool-inventory-cache';\r\n\r\n/**\r\n * The interface object to be used by expand calculation.\r\n */\r\ninterface ToolConditionExpandResult extends EnvironmentModuleToolConditionResult {\r\n ends: boolean;\r\n}\r\n\r\n/**\r\n * The calculation weight ratio base on performance.\r\n */\r\nexport const enum ToolConditionWeight {\r\n /**\r\n * Not using any observable calculation.\r\n */\r\n NonObservable,\r\n\r\n /**\r\n * Using the connection property.\r\n */\r\n Property,\r\n\r\n /**\r\n * Using the gateway inventory data.\r\n */\r\n Gateway,\r\n\r\n /**\r\n * Using the server inventory data.\r\n */\r\n Server,\r\n\r\n /**\r\n * Using a custom PowerShell script.\r\n */\r\n Script\r\n}\r\n\r\n/**\r\n * The condition result with weight information.\r\n */\r\nexport interface ToolConditionResultWithWeight {\r\n /**\r\n * The calculation weight.\r\n */\r\n weight: ToolConditionWeight;\r\n\r\n /**\r\n * The result data.\r\n */\r\n result: Observable<EnvironmentModuleEntryPointWithToolConditionResult> | EnvironmentModuleEntryPointWithToolConditionResult;\r\n}\r\n\r\n/**\r\n * The class handles conditions of tools to be presented on tools' menu.\r\n * @dynamic\r\n */\r\nexport class ToolConditionValidator {\r\n /**\r\n * Support the following condition name.\r\n * It can be a string, number, boolean and version string.\r\n */\r\n private static serverInventoryProperties: { conditionName: string, dataName: string }[] = [\r\n // string\r\n {\r\n conditionName: 'computerManufacturer',\r\n dataName: 'computerManufacturer'\r\n },\r\n\r\n // string\r\n {\r\n conditionName: 'computerModel',\r\n dataName: 'computerModel'\r\n },\r\n\r\n // number\r\n {\r\n conditionName: 'operatingSystemSKU',\r\n dataName: 'operatingSystemSKU'\r\n },\r\n\r\n // version string\r\n {\r\n conditionName: 'operatingSystemVersion',\r\n dataName: 'operatingSystemVersion'\r\n },\r\n\r\n // number\r\n {\r\n conditionName: 'windowsProductType',\r\n dataName: 'productType'\r\n },\r\n\r\n // string\r\n {\r\n conditionName: 'clusterFqdn',\r\n dataName: 'clusterFqdn'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isHyperVRoleInstalled',\r\n dataName: 'isHyperVRoleInstalled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isHyperVPowershellInstalled',\r\n dataName: 'isHyperVPowershellInstalled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isManagementToolsAvailable',\r\n dataName: 'isManagementToolsAvailable'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isWmfInstalled',\r\n dataName: 'isWmfInstalled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isRemoteAppEnabled',\r\n dataName: 'isRemoteAppEnabled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isDomainController',\r\n dataName: 'isDomainController'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isS2dEnabled',\r\n dataName: 'isS2dEnabled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isBritannicaEnabled',\r\n dataName: 'isBritannicaEnabled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isSystemLockdownPolicyEnforced',\r\n dataName: 'isSystemLockdownPolicyEnforced'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isHciServer',\r\n dataName: 'isHciServer'\r\n }\r\n ];\r\n\r\n /**\r\n * The following operators are supported.\r\n * String comparison uses caseinsesitive pattern.\r\n */\r\n private static operators = {\r\n /**\r\n * Greater than: number, string (caseinsesitive), version\r\n */\r\n gt: 'gt',\r\n\r\n /**\r\n * Greater or equal: number, string (caseinsesitive), version\r\n */\r\n ge: 'ge',\r\n\r\n /**\r\n * Less than: number, string (caseinsesitive), version\r\n */\r\n lt: 'lt',\r\n\r\n /**\r\n * Less or equal: number, string (caseinsesitive), version\r\n */\r\n le: 'le',\r\n\r\n /**\r\n * Equal: number, string (caseinsesitive), version (Accept '*' like \"1.2.*\")\r\n */\r\n eq: 'eq',\r\n\r\n /**\r\n * Not equal: number, string (caseinsesitive), version (Accept '*' like \"1.2.*\")\r\n */\r\n ne: 'ne',\r\n\r\n /**\r\n * Test true: number, string, boolean\r\n */\r\n is: 'is',\r\n\r\n /**\r\n * Test false: number, string, boolean\r\n */\r\n not: 'not',\r\n\r\n /**\r\n * Contains a string: string (caseinsesitive)\r\n */\r\n contains: 'contains',\r\n\r\n /**\r\n * Not contains a string: string (caseinsesitive)\r\n */\r\n notContains: 'notContains',\r\n\r\n /**\r\n * Any one of value (number or string) equal: numberArray, stringArray\r\n */\r\n anyEq: 'anyEq',\r\n\r\n /**\r\n * Any one of value (number or string) not equal: numberArray, stringArray\r\n */\r\n anyNe: 'anyNe',\r\n\r\n /**\r\n * Any one of string contains: stringArray\r\n */\r\n anyContains: 'anyContains',\r\n\r\n /**\r\n * Any one of string not contains: stringArray\r\n */\r\n anyNotContains: 'anyNotContains'\r\n };\r\n\r\n private static internalCurrent: ToolConditionValidator;\r\n\r\n private caches: InventoryQueryCaches;\r\n private toolInventoryCache: ToolInventoryCache;\r\n private errorStrings = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error;\r\n\r\n /**\r\n * Gets the current object of the ToolConditionValidator class, and maintains as singleton.\r\n *\r\n * @param appContext the application context.\r\n * @param caches the instance of the inventory query caches to share the resource.\r\n */\r\n public static current(appContext: AppContext, caches: InventoryQueryCaches): ToolConditionValidator {\r\n if (!ToolConditionValidator.internalCurrent) {\r\n ToolConditionValidator.internalCurrent = new ToolConditionValidator(appContext, caches);\r\n }\r\n\r\n return ToolConditionValidator.internalCurrent;\r\n }\r\n\r\n /**\r\n * Initializes a new instance of the ToolConditionValidator class.\r\n *\r\n * @param appContext the application context.\r\n * @param caches the instance of the inventory query caches to share the resource.\r\n */\r\n constructor(private appContext: AppContext, caches: InventoryQueryCaches) {\r\n const statusExpiration = 4 * 60 * 1000; // 4 min\r\n this.caches = caches;\r\n this.toolInventoryCache = new ToolInventoryCache(appContext, { expiration: statusExpiration });\r\n }\r\n\r\n /**\r\n * Scan the tool condition to be present or not.\r\n *\r\n * @param connection the connection object.\r\n * @param solution The entry point object of solution.\r\n * @param tool The entry point object of tool.\r\n * @param scanMode The mode of scanning.\r\n * @return the result observable.\r\n */\r\n public scanToolCondition(\r\n connection: Connection,\r\n solution: EnvironmentModuleEntryPoint,\r\n tool: EnvironmentModuleEntryPoint): ToolConditionResultWithWeight {\r\n\r\n if (!tool.requirements) {\r\n // tool is missing requirements, never show.\r\n return {\r\n weight: ToolConditionWeight.NonObservable,\r\n result: {\r\n ...tool,\r\n ...<EnvironmentModuleToolConditionResult>{\r\n show: false,\r\n detail: EnvironmentModuleToolState.NotSupported\r\n }\r\n }\r\n };\r\n }\r\n\r\n const solutionId = EnvironmentModule.createFormattedEntrypoint(solution);\r\n const toolId = EnvironmentModule.createFormattedEntrypoint(tool);\r\n const checkersCollection = [];\r\n let weight = ToolConditionWeight.NonObservable;\r\n for (const requirement of tool.requirements) {\r\n const checkers: Observable<EnvironmentModuleToolConditionResult>[] = [];\r\n\r\n // tool must specify the solutions it can show in\r\n if (!requirement.solutionIds || requirement.solutionIds.every(id => id !== solutionId)) {\r\n continue;\r\n }\r\n\r\n // if ths solution is a connections type, then the tool must specify the connection type\r\n if (solution.rootNavigationBehavior === 'connections'\r\n && (!requirement.connectionTypes || requirement.connectionTypes.every(type => type !== connection.type))) {\r\n continue;\r\n }\r\n\r\n // if there are no conditions to check, then this tool has been satisfied.\r\n if (!requirement.conditions || requirement.conditions.length === 0) {\r\n checkers.push(this.installationTypeValidate(connection));\r\n weight = Math.max(weight, ToolConditionWeight.Gateway);\r\n } else {\r\n for (const condition of requirement.conditions) {\r\n\r\n checkers.push(this.installationTypeValidate(connection, condition.installationTypes));\r\n weight = Math.max(weight, ToolConditionWeight.Gateway);\r\n\r\n if (condition.localhost !== undefined && !condition.localhost) {\r\n // if connection is localhost and not supported.\r\n checkers.push(this.localhostValidate(connection));\r\n weight = Math.max(weight, ToolConditionWeight.Gateway);\r\n }\r\n\r\n if (condition.inventory) {\r\n checkers.push(this.inventoryValidate(connection, condition.inventory));\r\n weight = Math.max(weight, ToolConditionWeight.Server);\r\n }\r\n\r\n if (condition.properties) {\r\n checkers.push(this.propertyValidate(connection, condition.properties));\r\n weight = Math.max(weight, ToolConditionWeight.Property);\r\n }\r\n\r\n if (condition.powerShell) {\r\n // powerShell { command, script }\r\n checkers.push(this.toolInventoryValidate(connection, toolId, condition.powerShell));\r\n weight = Math.max(weight, ToolConditionWeight.Script);\r\n } else if (condition.script) {\r\n // deprecated\r\n checkers.push(this.toolInventoryValidate(connection, toolId, condition.script));\r\n weight = Math.max(weight, ToolConditionWeight.Script);\r\n }\r\n }\r\n }\r\n\r\n checkersCollection.push(checkers);\r\n }\r\n\r\n if (checkersCollection.length === 0) {\r\n return {\r\n weight: ToolConditionWeight.NonObservable,\r\n result: {\r\n ...tool,\r\n ...<EnvironmentModuleToolConditionResult>{\r\n show: false,\r\n detail: EnvironmentModuleToolState.NotSupported,\r\n connectionId: connection ? connection.id : null\r\n }\r\n }\r\n };\r\n }\r\n\r\n let collectionIndex = 0;\r\n let checkerIndex = 0;\r\n let lastDetail: EnvironmentModuleToolState = null;\r\n let lastMessage: string = null;\r\n return {\r\n weight: weight,\r\n result: this.runChecker(checkersCollection[collectionIndex][checkerIndex])\r\n .pipe(catchError(() => {\r\n Logging.log({\r\n level: LogLevel.Error,\r\n message: this.errorStrings.ToolValidationResult.message.format(\r\n tool.parentModule.name,\r\n tool.displayName),\r\n source: 'ToolConditionValidator'\r\n });\r\n return of(<ToolConditionExpandResult>{\r\n show: false,\r\n ends: true\r\n });\r\n }),\r\n expand((value) => {\r\n checkerIndex++;\r\n if (value.ends) {\r\n return EMPTY;\r\n }\r\n\r\n if (value.detail !== undefined && lastDetail == null) {\r\n lastDetail = value.detail;\r\n }\r\n\r\n if (value.message !== undefined && lastMessage == null) {\r\n lastMessage = value.message;\r\n }\r\n\r\n if (!value.show) {\r\n // failed result. increment collection index and reset checkerIndex.\r\n if (checkersCollection.length > ++collectionIndex) {\r\n // still has another condition, try next checker set.\r\n return this.runChecker(checkersCollection[collectionIndex][checkerIndex = 0]);\r\n } else {\r\n // no more condition, end to return 'false'.\r\n return of(<ToolConditionExpandResult>{\r\n show: false,\r\n detail: lastDetail,\r\n message: lastMessage,\r\n ends: true\r\n });\r\n }\r\n }\r\n\r\n if (checkersCollection[collectionIndex].length > checkerIndex) {\r\n // check next checker.\r\n return this.runChecker(checkersCollection[collectionIndex][checkerIndex]);\r\n } else {\r\n // all state/succeeded within the checker set.\r\n return of({\r\n show: true,\r\n detail: lastDetail,\r\n message: lastMessage,\r\n ends: true\r\n });\r\n }\r\n }),\r\n filter(combined => combined.ends),\r\n map(combined => {\r\n return {\r\n ...tool,\r\n ...<EnvironmentModuleToolConditionResult>{\r\n show: combined.show,\r\n detail: combined.detail,\r\n message: combined.message,\r\n connectionId: connection ? connection.id : null\r\n }\r\n };\r\n }))\r\n };\r\n }\r\n\r\n private runChecker(checker: Observable<EnvironmentModuleToolConditionResult>): Observable<ToolConditionExpandResult> {\r\n return checker.pipe(\r\n take(1),\r\n map(result => <ToolConditionExpandResult>{ ...result, ends: false }));\r\n }\r\n\r\n private localhostValidate(\r\n connection: Connection): Observable<EnvironmentModuleToolConditionResult> {\r\n return this.caches.gatewayCache.createObservable({})\r\n .pipe(\r\n map(instance => <EnvironmentModuleToolConditionResult>{\r\n show: !(instance.mode !== GatewayMode.Service\r\n && connection.properties\r\n && connection.properties.displayName === 'localhost')\r\n }));\r\n }\r\n\r\n private installationTypeValidate(\r\n connection: Connection, installationType?: String[]): Observable<EnvironmentModuleToolConditionResult> {\r\n if (MsftSme.getValue<boolean>(MsftSme.self().Environment.configuration, 'gateway.disabled')) {\r\n return of({ show: true });\r\n }\r\n\r\n if (!installationType || !Array.isArray(installationType) || installationType.length === 0) {\r\n // Default to standard if property doesnt exist in the manifest.\r\n installationType = ['Standard'];\r\n }\r\n\r\n return this.caches.gatewayCache.createObservable({ params: {} })\r\n .pipe(\r\n catchError((error) => {\r\n const errorStrings = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error;\r\n const notification = this.appContext.notification.create(connection.name);\r\n notification.showError(\r\n errorStrings.ToolValidationGatewayInventoryError.title,\r\n errorStrings.ToolValidationGatewayInventoryError.message.format(Net.getErrorMessage(error)));\r\n return of(null);\r\n }),\r\n map(instance => <EnvironmentModuleToolConditionResult>{\r\n show: installationType.some(t => instance.installationType === t)\r\n }));\r\n }\r\n\r\n private inventoryValidate(\r\n connection: Connection, condition: EnvironmentModuleConditionMap): Observable<EnvironmentModuleToolConditionResult> {\r\n const nodeName = connection.activeAlias ? connection.activeAlias : connection.name;\r\n return this.caches.serverCache.createObservable({ params: { name: nodeName } })\r\n .pipe(\r\n catchError((error) => {\r\n const errorStrings = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error;\r\n const notification = this.appContext.notification.create(connection.name);\r\n notification.showError(\r\n errorStrings.ToolValidationInventoryError.title,\r\n errorStrings.ToolValidationInventoryError.message.format(Net.getErrorMessage(error)));\r\n return of(null);\r\n }),\r\n filter((instance: ServerInventory) => instance.serverName === nodeName),\r\n map(instance => <EnvironmentModuleToolConditionResult>{\r\n show: this.checkServerInventoryCondition(condition, instance)\r\n }));\r\n }\r\n\r\n private propertyValidate(\r\n connection: Connection, condition: EnvironmentModuleConditionMap): Observable<EnvironmentModuleToolConditionResult> {\r\n const propertyNames = Object.keys(condition);\r\n let result = true;\r\n for (const propertyName of propertyNames) {\r\n const propertyValue = connection.properties && connection.properties[propertyName];\r\n const conditionItem = condition[propertyName];\r\n if (conditionItem && !this.checkCondition(propertyValue, conditionItem)) {\r\n result = false;\r\n break;\r\n }\r\n }\r\n\r\n return of(<EnvironmentModuleToolConditionResult>{ show: result });\r\n }\r\n\r\n private toolInventoryValidate(\r\n connection: Connection,\r\n id: string,\r\n scriptOrCommand: string | PowerShellCommand): Observable<EnvironmentModuleToolConditionResult> {\r\n const command = PowerShell.getPowerShellCommand(scriptOrCommand);\r\n return this.toolInventoryCache.query(\r\n { ...{ name: connection.activeAlias ? connection.activeAlias : connection.name, id: id }, ...command })\r\n .pipe(\r\n map(inventory => <EnvironmentModuleToolConditionResult>{\r\n show: inventory.instance.state === EnvironmentModuleToolState.Available\r\n || inventory.instance.state === EnvironmentModuleToolState.NotConfigured,\r\n detail: inventory.instance.state,\r\n message: inventory.instance.message\r\n }),\r\n catchError((error) => {\r\n const message = Net.getErrorMessage(error);\r\n Logging.logError('ToolConditionValidator', `${id}: ${message}`);\r\n return of(<EnvironmentModuleToolConditionResult>{\r\n show: false,\r\n detail: EnvironmentModuleToolState.NotSupported,\r\n message\r\n });\r\n })\r\n );\r\n }\r\n\r\n private checkServerInventoryCondition(condition: EnvironmentModuleConditionMap, instance: ServerInventory): boolean {\r\n for (const property of ToolConditionValidator.serverInventoryProperties) {\r\n const conditionItem = condition[property.conditionName];\r\n if (conditionItem && !this.checkCondition(instance[property.dataName], conditionItem)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private checkCondition(data: any, condition: EnvironmentModuleConditionStatement): boolean {\r\n switch (condition.type) {\r\n case 'number':\r\n const numberValue: number = this.getNumberOrZero(data);\r\n const numberTest: number = this.getNumberOrZero(condition.value);\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.gt:\r\n return numberValue > numberTest;\r\n case ToolConditionValidator.operators.ge:\r\n return numberValue >= numberTest;\r\n case ToolConditionValidator.operators.lt:\r\n return numberValue < numberTest;\r\n case ToolConditionValidator.operators.le:\r\n return numberValue <= numberTest;\r\n case ToolConditionValidator.operators.eq:\r\n return numberValue === numberTest;\r\n case ToolConditionValidator.operators.ne:\r\n return numberValue !== numberTest;\r\n case ToolConditionValidator.operators.is:\r\n return !!numberValue;\r\n case ToolConditionValidator.operators.not:\r\n return !numberValue;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n case 'string':\r\n const stringValue: string = '' + data;\r\n const stringTest: string = '' + condition.value;\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.gt:\r\n return stringValue.toLowerCase() > stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.ge:\r\n return stringValue.toLowerCase() >= stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.lt:\r\n return stringValue.toLowerCase() < stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.le:\r\n return stringValue.toLowerCase() <= stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.eq:\r\n return stringValue.toLowerCase() === stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.ne:\r\n return stringValue.toLowerCase() !== stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.is:\r\n return !!data;\r\n case ToolConditionValidator.operators.not:\r\n return !data;\r\n case ToolConditionValidator.operators.contains:\r\n return stringValue.toLowerCase().indexOf(stringTest.toLowerCase()) >= 0;\r\n case ToolConditionValidator.operators.notContains:\r\n return stringValue.toLowerCase().indexOf(stringTest.toLowerCase()) < 0;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n case 'boolean':\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.is:\r\n return !!data;\r\n case ToolConditionValidator.operators.not:\r\n return !data;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n case 'version':\r\n const versionValue: string = data;\r\n const versionTest: string = <string>condition.value;\r\n return this.compareVersion(versionValue, versionTest, condition.operator);\r\n\r\n case 'numberArray':\r\n const checkNumber: any = condition.value;\r\n if (!checkNumber\r\n || typeof checkNumber === 'string'\r\n || !checkNumber.length\r\n || typeof checkNumber[0] !== 'number') {\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedDataType.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n const numberArrayValue: number = this.getNumberOrZero(data);\r\n const numberArray: number[] = <number[]>condition.value;\r\n for (const numberItem of numberArray) {\r\n const numberArrayTest = this.getNumberOrZero(numberItem);\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.anyEq:\r\n if (numberArrayValue === numberArrayTest) {\r\n return true;\r\n }\r\n\r\n break;\r\n case ToolConditionValidator.operators.anyNe:\r\n if (numberArrayValue !== numberArrayTest) {\r\n return true;\r\n }\r\n\r\n break;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n }\r\n\r\n return false;\r\n\r\n case 'stringArray':\r\n const checkString: any = condition.value;\r\n if (!checkString\r\n || typeof checkString === 'string'\r\n || !checkString.length\r\n || typeof checkString[0] !== 'string') {\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedDataType.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n const stringArrayValue: string = '' + data;\r\n const stringArray: string[] = <string[]>condition.value;\r\n for (const stringArrayTest of stringArray) {\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.anyEq:\r\n if (stringArrayValue.toLowerCase() === stringArrayTest.toLowerCase()) {\r\n return true;\r\n }\r\n\r\n break;\r\n case ToolConditionValidator.operators.anyNe:\r\n if (stringArrayValue.toLowerCase() !== stringArrayTest.toLowerCase()) {\r\n return true;\r\n }\r\n\r\n break;\r\n case ToolConditionValidator.operators.anyContains:\r\n if (stringArrayValue.toLowerCase().indexOf(stringArrayTest.toLowerCase()) >= 0) {\r\n return true;\r\n }\r\n\r\n break;\r\n case ToolConditionValidator.operators.anyNotContains:\r\n if (stringArrayValue.toLowerCase().indexOf(stringArrayTest.toLowerCase()) < 0) {\r\n return true;\r\n }\r\n\r\n break;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n }\r\n\r\n return false;\r\n\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedDataType.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n }\r\n\r\n private compareVersion(left: string, right: string, operator: string): boolean {\r\n const leftSegments = left.split('.');\r\n const rightSegments = right.split('.');\r\n if (!leftSegments || leftSegments.length <= 0 || !rightSegments || rightSegments.length <= 0) {\r\n throw new Error(this.errorStrings.ToolValidationVersionFormat.message);\r\n }\r\n\r\n const count = Math.max(leftSegments.length, rightSegments.length);\r\n let status;\r\n for (let index = 0; index < count; index++) {\r\n if (rightSegments[index] === '*') {\r\n // quit comparison with wildcard.\r\n status = 0;\r\n break;\r\n }\r\n\r\n const leftSegment = this.getNumberOrZero(leftSegments[index]);\r\n const rightSegment = this.getNumberOrZero(rightSegments[index]);\r\n if (leftSegment === rightSegment) {\r\n // equal.\r\n status = 0;\r\n } else if (leftSegment > rightSegment) {\r\n // greater.\r\n status = 1;\r\n break;\r\n } else {\r\n // lesser.\r\n status = -1;\r\n break;\r\n }\r\n }\r\n\r\n switch (operator) {\r\n case ToolConditionValidator.operators.gt:\r\n return status > 0;\r\n case ToolConditionValidator.operators.ge:\r\n return status >= 0;\r\n case ToolConditionValidator.operators.lt:\r\n return status < 0;\r\n case ToolConditionValidator.operators.le:\r\n return status <= 0;\r\n case ToolConditionValidator.operators.eq:\r\n return status === 0;\r\n case ToolConditionValidator.operators.ne:\r\n return status !== 0;\r\n default:\r\n throw new Error(\r\n this.errorStrings.ToolValidationUnsupportedOperator.message.format(operator, left));\r\n }\r\n }\r\n\r\n private getNumberOrZero(data: any): number {\r\n const result = Number(data);\r\n return isNaN(result) ? 0 : result;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../../packages/core/security/tool-condition-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,UAAU,EAAM,MAAM,MAAM,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD,OAAO,EAIH,2BAA2B,EAC3B,kDAAkD,EAGrD,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAWxE;;GAEG;AACH,0BAAkB,mBAAmB;IACjC;;OAEG;IACH,aAAa,IAAA;IAEb;;OAEG;IACH,QAAQ,IAAA;IAER;;OAEG;IACH,OAAO,IAAA;IAEP;;OAEG;IACH,MAAM,IAAA;IAEN;;OAEG;IACH,MAAM,IAAA;CACT;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC1C;;OAEG;IACH,MAAM,EAAE,mBAAmB,CAAC;IAE5B;;OAEG;IACH,MAAM,EAAE,UAAU,CAAC,kDAAkD,CAAC,GAAG,kDAAkD,CAAC;CAC/H;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IA6MnB,OAAO,CAAC,UAAU;IA5M9B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB,CAgGtC;IAEF;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS,CAsEtB;IAEF,OAAO,CAAC,MAAM,CAAC,eAAe,CAAyB;IAEvD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,YAAY,CAAyD;IAE7E;;;;;OAKG;WACW,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,oBAAoB,GAAG,sBAAsB;IAQnG;;;;;OAKG;gBACiB,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,oBAAoB;IAMxE;;;;;;;;OAQG;IACI,iBAAiB,CACpB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,2BAA2B,EACrC,IAAI,EAAE,2BAA2B,GAAG,6BAA6B;IAuKrE,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,wBAAwB;IA0BhC,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,qBAAqB;IA0B7B,OAAO,CAAC,6BAA6B;IAWrC,OAAO,CAAC,cAAc;IAuKtB,OAAO,CAAC,cAAc;IAmDtB,OAAO,CAAC,eAAe;CAI1B","file":"tool-condition-validator.d.ts","sourcesContent":["import { EMPTY, Observable, of } from 'rxjs';\r\nimport { catchError, expand, filter, map, take } from 'rxjs/operators';\r\nimport { AppContext } from '../data/app-context';\r\nimport { Net } from '../data/net';\r\nimport { PowerShell, PowerShellCommand } from '../data/powershell';\r\nimport { LogLevel } from '../diagnostics/log-level';\r\nimport { Logging } from '../diagnostics/logging';\r\nimport { Strings } from '../generated/strings';\r\nimport {\r\n EnvironmentModule,\r\n EnvironmentModuleConditionMap,\r\n EnvironmentModuleConditionStatement,\r\n EnvironmentModuleEntryPoint,\r\n EnvironmentModuleEntryPointWithToolConditionResult,\r\n EnvironmentModuleToolConditionResult,\r\n EnvironmentModuleToolState\r\n} from '../manifest/environment-modules';\r\nimport { Connection } from '../security/connection';\r\nimport { GatewayMode } from '../shared/gateway-inventory/gateway-inventory';\r\nimport { InventoryQueryCaches } from '../shared/inventory-query-caches';\r\nimport { ServerInventory } from '../shared/server-inventory/server-inventory';\r\nimport { ToolInventoryCache } from '../shared/tool-inventory/tool-inventory-cache';\r\n\r\n/**\r\n * The interface object to be used by expand calculation.\r\n */\r\ninterface ToolConditionExpandResult extends EnvironmentModuleToolConditionResult {\r\n ends: boolean;\r\n}\r\n\r\n/**\r\n * The calculation weight ratio base on performance.\r\n */\r\nexport const enum ToolConditionWeight {\r\n /**\r\n * Not using any observable calculation.\r\n */\r\n NonObservable,\r\n\r\n /**\r\n * Using the connection property.\r\n */\r\n Property,\r\n\r\n /**\r\n * Using the gateway inventory data.\r\n */\r\n Gateway,\r\n\r\n /**\r\n * Using the server inventory data.\r\n */\r\n Server,\r\n\r\n /**\r\n * Using a custom PowerShell script.\r\n */\r\n Script\r\n}\r\n\r\n/**\r\n * The condition result with weight information.\r\n */\r\nexport interface ToolConditionResultWithWeight {\r\n /**\r\n * The calculation weight.\r\n */\r\n weight: ToolConditionWeight;\r\n\r\n /**\r\n * The result data.\r\n */\r\n result: Observable<EnvironmentModuleEntryPointWithToolConditionResult> | EnvironmentModuleEntryPointWithToolConditionResult;\r\n}\r\n\r\n/**\r\n * The class handles conditions of tools to be presented on tools' menu.\r\n * @dynamic\r\n */\r\nexport class ToolConditionValidator {\r\n /**\r\n * Support the following condition name.\r\n * It can be a string, number, boolean and version string.\r\n */\r\n private static serverInventoryProperties: { conditionName: string, dataName: string }[] = [\r\n // string\r\n {\r\n conditionName: 'computerManufacturer',\r\n dataName: 'computerManufacturer'\r\n },\r\n\r\n // string\r\n {\r\n conditionName: 'computerModel',\r\n dataName: 'computerModel'\r\n },\r\n\r\n // number\r\n {\r\n conditionName: 'operatingSystemSKU',\r\n dataName: 'operatingSystemSKU'\r\n },\r\n\r\n // version string\r\n {\r\n conditionName: 'operatingSystemVersion',\r\n dataName: 'operatingSystemVersion'\r\n },\r\n\r\n // number\r\n {\r\n conditionName: 'windowsProductType',\r\n dataName: 'productType'\r\n },\r\n\r\n // string\r\n {\r\n conditionName: 'clusterFqdn',\r\n dataName: 'clusterFqdn'\r\n },\r\n\r\n // string\r\n {\r\n conditionName: 'systemLockdownPolicy',\r\n dataName: 'systemLockdownPolicy'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isHyperVRoleInstalled',\r\n dataName: 'isHyperVRoleInstalled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isHyperVPowershellInstalled',\r\n dataName: 'isHyperVPowershellInstalled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isManagementToolsAvailable',\r\n dataName: 'isManagementToolsAvailable'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isWmfInstalled',\r\n dataName: 'isWmfInstalled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isRemoteAppEnabled',\r\n dataName: 'isRemoteAppEnabled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isDomainController',\r\n dataName: 'isDomainController'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isS2dEnabled',\r\n dataName: 'isS2dEnabled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isBritannicaEnabled',\r\n dataName: 'isBritannicaEnabled'\r\n },\r\n\r\n // boolean\r\n {\r\n conditionName: 'isHciServer',\r\n dataName: 'isHciServer'\r\n }\r\n ];\r\n\r\n /**\r\n * The following operators are supported.\r\n * String comparison uses caseinsesitive pattern.\r\n */\r\n private static operators = {\r\n /**\r\n * Greater than: number, string (caseinsesitive), version\r\n */\r\n gt: 'gt',\r\n\r\n /**\r\n * Greater or equal: number, string (caseinsesitive), version\r\n */\r\n ge: 'ge',\r\n\r\n /**\r\n * Less than: number, string (caseinsesitive), version\r\n */\r\n lt: 'lt',\r\n\r\n /**\r\n * Less or equal: number, string (caseinsesitive), version\r\n */\r\n le: 'le',\r\n\r\n /**\r\n * Equal: number, string (caseinsesitive), version (Accept '*' like \"1.2.*\")\r\n */\r\n eq: 'eq',\r\n\r\n /**\r\n * Not equal: number, string (caseinsesitive), version (Accept '*' like \"1.2.*\")\r\n */\r\n ne: 'ne',\r\n\r\n /**\r\n * Test true: number, string, boolean\r\n */\r\n is: 'is',\r\n\r\n /**\r\n * Test false: number, string, boolean\r\n */\r\n not: 'not',\r\n\r\n /**\r\n * Contains a string: string (caseinsesitive)\r\n */\r\n contains: 'contains',\r\n\r\n /**\r\n * Not contains a string: string (caseinsesitive)\r\n */\r\n notContains: 'notContains',\r\n\r\n /**\r\n * Any one of value (number or string) equal: numberArray, stringArray\r\n */\r\n anyEq: 'anyEq',\r\n\r\n /**\r\n * Any one of value (number or string) not equal: numberArray, stringArray\r\n */\r\n anyNe: 'anyNe',\r\n\r\n /**\r\n * Any one of string contains: stringArray\r\n */\r\n anyContains: 'anyContains',\r\n\r\n /**\r\n * Any one of string not contains: stringArray\r\n */\r\n anyNotContains: 'anyNotContains'\r\n };\r\n\r\n private static internalCurrent: ToolConditionValidator;\r\n\r\n private caches: InventoryQueryCaches;\r\n private toolInventoryCache: ToolInventoryCache;\r\n private errorStrings = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error;\r\n\r\n /**\r\n * Gets the current object of the ToolConditionValidator class, and maintains as singleton.\r\n *\r\n * @param appContext the application context.\r\n * @param caches the instance of the inventory query caches to share the resource.\r\n */\r\n public static current(appContext: AppContext, caches: InventoryQueryCaches): ToolConditionValidator {\r\n if (!ToolConditionValidator.internalCurrent) {\r\n ToolConditionValidator.internalCurrent = new ToolConditionValidator(appContext, caches);\r\n }\r\n\r\n return ToolConditionValidator.internalCurrent;\r\n }\r\n\r\n /**\r\n * Initializes a new instance of the ToolConditionValidator class.\r\n *\r\n * @param appContext the application context.\r\n * @param caches the instance of the inventory query caches to share the resource.\r\n */\r\n constructor(private appContext: AppContext, caches: InventoryQueryCaches) {\r\n const statusExpiration = 4 * 60 * 1000; // 4 min\r\n this.caches = caches;\r\n this.toolInventoryCache = new ToolInventoryCache(appContext, { expiration: statusExpiration });\r\n }\r\n\r\n /**\r\n * Scan the tool condition to be present or not.\r\n *\r\n * @param connection the connection object.\r\n * @param solution The entry point object of solution.\r\n * @param tool The entry point object of tool.\r\n * @param scanMode The mode of scanning.\r\n * @return the result observable.\r\n */\r\n public scanToolCondition(\r\n connection: Connection,\r\n solution: EnvironmentModuleEntryPoint,\r\n tool: EnvironmentModuleEntryPoint): ToolConditionResultWithWeight {\r\n\r\n if (!tool.requirements) {\r\n // tool is missing requirements, never show.\r\n return {\r\n weight: ToolConditionWeight.NonObservable,\r\n result: {\r\n ...tool,\r\n ...<EnvironmentModuleToolConditionResult>{\r\n show: false,\r\n detail: EnvironmentModuleToolState.NotSupported\r\n }\r\n }\r\n };\r\n }\r\n\r\n const solutionId = EnvironmentModule.createFormattedEntrypoint(solution);\r\n const toolId = EnvironmentModule.createFormattedEntrypoint(tool);\r\n const checkersCollection = [];\r\n let weight = ToolConditionWeight.NonObservable;\r\n for (const requirement of tool.requirements) {\r\n const checkers: Observable<EnvironmentModuleToolConditionResult>[] = [];\r\n\r\n // tool must specify the solutions it can show in\r\n if (!requirement.solutionIds || requirement.solutionIds.every(id => id !== solutionId)) {\r\n continue;\r\n }\r\n\r\n // if ths solution is a connections type, then the tool must specify the connection type\r\n if (solution.rootNavigationBehavior === 'connections'\r\n && (!requirement.connectionTypes || requirement.connectionTypes.every(type => type !== connection.type))) {\r\n continue;\r\n }\r\n\r\n // if there are no conditions to check, then this tool has been satisfied.\r\n if (!requirement.conditions || requirement.conditions.length === 0) {\r\n checkers.push(this.installationTypeValidate(connection));\r\n weight = Math.max(weight, ToolConditionWeight.Gateway);\r\n } else {\r\n for (const condition of requirement.conditions) {\r\n\r\n checkers.push(this.installationTypeValidate(connection, condition.installationTypes));\r\n weight = Math.max(weight, ToolConditionWeight.Gateway);\r\n\r\n if (condition.localhost !== undefined && !condition.localhost) {\r\n // if connection is localhost and not supported.\r\n checkers.push(this.localhostValidate(connection));\r\n weight = Math.max(weight, ToolConditionWeight.Gateway);\r\n }\r\n\r\n if (condition.inventory) {\r\n checkers.push(this.inventoryValidate(connection, condition.inventory));\r\n weight = Math.max(weight, ToolConditionWeight.Server);\r\n }\r\n\r\n if (condition.properties) {\r\n checkers.push(this.propertyValidate(connection, condition.properties));\r\n weight = Math.max(weight, ToolConditionWeight.Property);\r\n }\r\n\r\n if (condition.powerShell) {\r\n // powerShell { command, script }\r\n checkers.push(this.toolInventoryValidate(connection, toolId, condition.powerShell));\r\n weight = Math.max(weight, ToolConditionWeight.Script);\r\n } else if (condition.script) {\r\n // deprecated\r\n checkers.push(this.toolInventoryValidate(connection, toolId, condition.script));\r\n weight = Math.max(weight, ToolConditionWeight.Script);\r\n }\r\n }\r\n }\r\n\r\n checkersCollection.push(checkers);\r\n }\r\n\r\n if (checkersCollection.length === 0) {\r\n return {\r\n weight: ToolConditionWeight.NonObservable,\r\n result: {\r\n ...tool,\r\n ...<EnvironmentModuleToolConditionResult>{\r\n show: false,\r\n detail: EnvironmentModuleToolState.NotSupported,\r\n connectionId: connection ? connection.id : null\r\n }\r\n }\r\n };\r\n }\r\n\r\n let collectionIndex = 0;\r\n let checkerIndex = 0;\r\n let lastDetail: EnvironmentModuleToolState = null;\r\n let lastMessage: string = null;\r\n return {\r\n weight: weight,\r\n result: this.runChecker(checkersCollection[collectionIndex][checkerIndex])\r\n .pipe(catchError(() => {\r\n Logging.log({\r\n level: LogLevel.Error,\r\n message: this.errorStrings.ToolValidationResult.message.format(\r\n tool.parentModule.name,\r\n tool.displayName),\r\n source: 'ToolConditionValidator'\r\n });\r\n return of(<ToolConditionExpandResult>{\r\n show: false,\r\n ends: true\r\n });\r\n }),\r\n expand((value) => {\r\n checkerIndex++;\r\n if (value.ends) {\r\n return EMPTY;\r\n }\r\n\r\n if (value.detail !== undefined && lastDetail == null) {\r\n lastDetail = value.detail;\r\n }\r\n\r\n if (value.message !== undefined && lastMessage == null) {\r\n lastMessage = value.message;\r\n }\r\n\r\n if (!value.show) {\r\n // failed result. increment collection index and reset checkerIndex.\r\n if (checkersCollection.length > ++collectionIndex) {\r\n // still has another condition, try next checker set.\r\n return this.runChecker(checkersCollection[collectionIndex][checkerIndex = 0]);\r\n } else {\r\n // no more condition, end to return 'false'.\r\n return of(<ToolConditionExpandResult>{\r\n show: false,\r\n detail: lastDetail,\r\n message: lastMessage,\r\n ends: true\r\n });\r\n }\r\n }\r\n\r\n if (checkersCollection[collectionIndex].length > checkerIndex) {\r\n // check next checker.\r\n return this.runChecker(checkersCollection[collectionIndex][checkerIndex]);\r\n } else {\r\n // all state/succeeded within the checker set.\r\n return of({\r\n show: true,\r\n detail: lastDetail,\r\n message: lastMessage,\r\n ends: true\r\n });\r\n }\r\n }),\r\n filter(combined => combined.ends),\r\n map(combined => {\r\n return {\r\n ...tool,\r\n ...<EnvironmentModuleToolConditionResult>{\r\n show: combined.show,\r\n detail: combined.detail,\r\n message: combined.message,\r\n connectionId: connection ? connection.id : null\r\n }\r\n };\r\n }))\r\n };\r\n }\r\n\r\n private runChecker(checker: Observable<EnvironmentModuleToolConditionResult>): Observable<ToolConditionExpandResult> {\r\n return checker.pipe(\r\n take(1),\r\n map(result => <ToolConditionExpandResult>{ ...result, ends: false }));\r\n }\r\n\r\n private localhostValidate(\r\n connection: Connection): Observable<EnvironmentModuleToolConditionResult> {\r\n return this.caches.gatewayCache.createObservable({})\r\n .pipe(\r\n map(instance => <EnvironmentModuleToolConditionResult>{\r\n show: !(instance.mode !== GatewayMode.Service\r\n && connection.properties\r\n && connection.properties.displayName === 'localhost')\r\n }));\r\n }\r\n\r\n private installationTypeValidate(\r\n connection: Connection, installationType?: String[]): Observable<EnvironmentModuleToolConditionResult> {\r\n if (MsftSme.getValue<boolean>(MsftSme.self().Environment.configuration, 'gateway.disabled')) {\r\n return of({ show: true });\r\n }\r\n\r\n if (!installationType || !Array.isArray(installationType) || installationType.length === 0) {\r\n // Default to standard if property doesnt exist in the manifest.\r\n installationType = ['Standard'];\r\n }\r\n\r\n return this.caches.gatewayCache.createObservable({ params: {} })\r\n .pipe(\r\n catchError((error) => {\r\n const errorStrings = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error;\r\n const notification = this.appContext.notification.create(connection.name);\r\n notification.showError(\r\n errorStrings.ToolValidationGatewayInventoryError.title,\r\n errorStrings.ToolValidationGatewayInventoryError.message.format(Net.getErrorMessage(error)));\r\n return of(null);\r\n }),\r\n map(instance => <EnvironmentModuleToolConditionResult>{\r\n show: installationType.some(t => instance.installationType === t)\r\n }));\r\n }\r\n\r\n private inventoryValidate(\r\n connection: Connection, condition: EnvironmentModuleConditionMap): Observable<EnvironmentModuleToolConditionResult> {\r\n const nodeName = connection.activeAlias ? connection.activeAlias : connection.name;\r\n return this.caches.serverCache.createObservable({ params: { name: nodeName } })\r\n .pipe(\r\n catchError((error) => {\r\n const errorStrings = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error;\r\n const notification = this.appContext.notification.create(connection.name);\r\n notification.showError(\r\n errorStrings.ToolValidationInventoryError.title,\r\n errorStrings.ToolValidationInventoryError.message.format(Net.getErrorMessage(error)));\r\n return of(null);\r\n }),\r\n filter((instance: ServerInventory) => instance.serverName === nodeName),\r\n map(instance => <EnvironmentModuleToolConditionResult>{\r\n show: this.checkServerInventoryCondition(condition, instance)\r\n }));\r\n }\r\n\r\n private propertyValidate(\r\n connection: Connection, condition: EnvironmentModuleConditionMap): Observable<EnvironmentModuleToolConditionResult> {\r\n const propertyNames = Object.keys(condition);\r\n let result = true;\r\n for (const propertyName of propertyNames) {\r\n const propertyValue = connection.properties && connection.properties[propertyName];\r\n const conditionItem = condition[propertyName];\r\n if (conditionItem && !this.checkCondition(propertyValue, conditionItem)) {\r\n result = false;\r\n break;\r\n }\r\n }\r\n\r\n return of(<EnvironmentModuleToolConditionResult>{ show: result });\r\n }\r\n\r\n private toolInventoryValidate(\r\n connection: Connection,\r\n id: string,\r\n scriptOrCommand: string | PowerShellCommand): Observable<EnvironmentModuleToolConditionResult> {\r\n const command = PowerShell.getPowerShellCommand(scriptOrCommand);\r\n return this.toolInventoryCache.query(\r\n { ...{ name: connection.activeAlias ? connection.activeAlias : connection.name, id: id }, ...command })\r\n .pipe(\r\n map(inventory => <EnvironmentModuleToolConditionResult>{\r\n show: inventory.instance.state === EnvironmentModuleToolState.Available\r\n || inventory.instance.state === EnvironmentModuleToolState.NotConfigured,\r\n detail: inventory.instance.state,\r\n message: inventory.instance.message\r\n }),\r\n catchError((error) => {\r\n const message = Net.getErrorMessage(error);\r\n Logging.logError('ToolConditionValidator', `${id}: ${message}`);\r\n return of(<EnvironmentModuleToolConditionResult>{\r\n show: false,\r\n detail: EnvironmentModuleToolState.NotSupported,\r\n message\r\n });\r\n })\r\n );\r\n }\r\n\r\n private checkServerInventoryCondition(condition: EnvironmentModuleConditionMap, instance: ServerInventory): boolean {\r\n for (const property of ToolConditionValidator.serverInventoryProperties) {\r\n const conditionItem = condition[property.conditionName];\r\n if (conditionItem && !this.checkCondition(instance[property.dataName], conditionItem)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private checkCondition(data: any, condition: EnvironmentModuleConditionStatement): boolean {\r\n switch (condition.type) {\r\n case 'number':\r\n const numberValue: number = this.getNumberOrZero(data);\r\n const numberTest: number = this.getNumberOrZero(condition.value);\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.gt:\r\n return numberValue > numberTest;\r\n case ToolConditionValidator.operators.ge:\r\n return numberValue >= numberTest;\r\n case ToolConditionValidator.operators.lt:\r\n return numberValue < numberTest;\r\n case ToolConditionValidator.operators.le:\r\n return numberValue <= numberTest;\r\n case ToolConditionValidator.operators.eq:\r\n return numberValue === numberTest;\r\n case ToolConditionValidator.operators.ne:\r\n return numberValue !== numberTest;\r\n case ToolConditionValidator.operators.is:\r\n return !!numberValue;\r\n case ToolConditionValidator.operators.not:\r\n return !numberValue;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n case 'string':\r\n const stringValue: string = '' + data;\r\n const stringTest: string = '' + condition.value;\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.gt:\r\n return stringValue.toLowerCase() > stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.ge:\r\n return stringValue.toLowerCase() >= stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.lt:\r\n return stringValue.toLowerCase() < stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.le:\r\n return stringValue.toLowerCase() <= stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.eq:\r\n return stringValue.toLowerCase() === stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.ne:\r\n return stringValue.toLowerCase() !== stringTest.toLowerCase();\r\n case ToolConditionValidator.operators.is:\r\n return !!data;\r\n case ToolConditionValidator.operators.not:\r\n return !data;\r\n case ToolConditionValidator.operators.contains:\r\n return stringValue.toLowerCase().indexOf(stringTest.toLowerCase()) >= 0;\r\n case ToolConditionValidator.operators.notContains:\r\n return stringValue.toLowerCase().indexOf(stringTest.toLowerCase()) < 0;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n case 'boolean':\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.is:\r\n return !!data;\r\n case ToolConditionValidator.operators.not:\r\n return !data;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n case 'version':\r\n const versionValue: string = data;\r\n const versionTest: string = <string>condition.value;\r\n return this.compareVersion(versionValue, versionTest, condition.operator);\r\n\r\n case 'numberArray':\r\n const checkNumber: any = condition.value;\r\n if (!checkNumber\r\n || typeof checkNumber === 'string'\r\n || !checkNumber.length\r\n || typeof checkNumber[0] !== 'number') {\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedDataType.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n const numberArrayValue: number = this.getNumberOrZero(data);\r\n const numberArray: number[] = <number[]>condition.value;\r\n for (const numberItem of numberArray) {\r\n const numberArrayTest = this.getNumberOrZero(numberItem);\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.anyEq:\r\n if (numberArrayValue === numberArrayTest) {\r\n return true;\r\n }\r\n\r\n break;\r\n case ToolConditionValidator.operators.anyNe:\r\n if (numberArrayValue !== numberArrayTest) {\r\n return true;\r\n }\r\n\r\n break;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n }\r\n\r\n return false;\r\n\r\n case 'stringArray':\r\n const checkString: any = condition.value;\r\n if (!checkString\r\n || typeof checkString === 'string'\r\n || !checkString.length\r\n || typeof checkString[0] !== 'string') {\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedDataType.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n\r\n const stringArrayValue: string = '' + data;\r\n const stringArray: string[] = <string[]>condition.value;\r\n for (const stringArrayTest of stringArray) {\r\n switch (condition.operator) {\r\n case ToolConditionValidator.operators.anyEq:\r\n if (stringArrayValue.toLowerCase() === stringArrayTest.toLowerCase()) {\r\n return true;\r\n }\r\n\r\n break;\r\n case ToolConditionValidator.operators.anyNe:\r\n if (stringArrayValue.toLowerCase() !== stringArrayTest.toLowerCase()) {\r\n return true;\r\n }\r\n\r\n break;\r\n case ToolConditionValidator.operators.anyContains:\r\n if (stringArrayValue.toLowerCase().indexOf(stringArrayTest.toLowerCase()) >= 0) {\r\n return true;\r\n }\r\n\r\n break;\r\n case ToolConditionValidator.operators.anyNotContains:\r\n if (stringArrayValue.toLowerCase().indexOf(stringArrayTest.toLowerCase()) < 0) {\r\n return true;\r\n }\r\n\r\n break;\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedOperator.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n }\r\n\r\n return false;\r\n\r\n default:\r\n throw new Error(this.errorStrings.ToolValidationUnsupportedDataType.message.format(\r\n JSON.stringify(condition),\r\n JSON.stringify(data)));\r\n }\r\n }\r\n\r\n private compareVersion(left: string, right: string, operator: string): boolean {\r\n const leftSegments = left.split('.');\r\n const rightSegments = right.split('.');\r\n if (!leftSegments || leftSegments.length <= 0 || !rightSegments || rightSegments.length <= 0) {\r\n throw new Error(this.errorStrings.ToolValidationVersionFormat.message);\r\n }\r\n\r\n const count = Math.max(leftSegments.length, rightSegments.length);\r\n let status;\r\n for (let index = 0; index < count; index++) {\r\n if (rightSegments[index] === '*') {\r\n // quit comparison with wildcard.\r\n status = 0;\r\n break;\r\n }\r\n\r\n const leftSegment = this.getNumberOrZero(leftSegments[index]);\r\n const rightSegment = this.getNumberOrZero(rightSegments[index]);\r\n if (leftSegment === rightSegment) {\r\n // equal.\r\n status = 0;\r\n } else if (leftSegment > rightSegment) {\r\n // greater.\r\n status = 1;\r\n break;\r\n } else {\r\n // lesser.\r\n status = -1;\r\n break;\r\n }\r\n }\r\n\r\n switch (operator) {\r\n case ToolConditionValidator.operators.gt:\r\n return status > 0;\r\n case ToolConditionValidator.operators.ge:\r\n return status >= 0;\r\n case ToolConditionValidator.operators.lt:\r\n return status < 0;\r\n case ToolConditionValidator.operators.le:\r\n return status <= 0;\r\n case ToolConditionValidator.operators.eq:\r\n return status === 0;\r\n case ToolConditionValidator.operators.ne:\r\n return status !== 0;\r\n default:\r\n throw new Error(\r\n this.errorStrings.ToolValidationUnsupportedOperator.message.format(operator, left));\r\n }\r\n }\r\n\r\n private getNumberOrZero(data: any): number {\r\n const result = Number(data);\r\n return isNaN(result) ? 0 : result;\r\n }\r\n}\r\n"]}
@@ -48,6 +48,11 @@ export class ToolConditionValidator {
48
48
  conditionName: 'clusterFqdn',
49
49
  dataName: 'clusterFqdn'
50
50
  },
51
+ // string
52
+ {
53
+ conditionName: 'systemLockdownPolicy',
54
+ dataName: 'systemLockdownPolicy'
55
+ },
51
56
  // boolean
52
57
  {
53
58
  conditionName: 'isHyperVRoleInstalled',
@@ -89,11 +94,6 @@ export class ToolConditionValidator {
89
94
  dataName: 'isBritannicaEnabled'
90
95
  },
91
96
  // boolean
92
- {
93
- conditionName: 'isSystemLockdownPolicyEnforced',
94
- dataName: 'isSystemLockdownPolicyEnforced'
95
- },
96
- // boolean
97
97
  {
98
98
  conditionName: 'isHciServer',
99
99
  dataName: 'isHciServer'