Uploaded image for project: 'Hippo CMS'
  1. Hippo CMS
  2. CMS-13416

Back-end: Fix [Page] and [Channel] menu for CMS Users that are not in role webmaster for a channel

    XMLWordPrintable

Details

    • Improvement
    • Status: Closed
    • Normal
    • Resolution: Fixed
    • None
    • 14.3.0
    • None

    Description

      Currently all cms users get to see the [Page] and [Channel] menu button in CM. I think that is ok. However, a user who is not a webmaster of the channel should not get the options 'New', Copy', 'Delete' etc. This can be checked by whether the user is in role webmaster (for the current channel / page). Same goes for [Channel -> Settings] : only webmasters should get to see these I'd think.

      abogaart, can you sort out on what basis the CM UI currently checks whether to show or not show the [Page] menu and how the CM UI decides which options (New, Copy, Delete) are enabled. Then we can solve this.

      Note: when clicking on the [Page] button, a 'resty' call to

      org.hippoecm.hst.pagecomposer.jaxrs.services.SiteMapResource#getSiteMapItem
      

      is done. The HST backend could indicate which options the current user is allowed. Only need to first find out how the CM UI decides which menu options to enable. Same goes for the Channel Menu

      Technical Approach

      The HST will get a RESTY (rpc) call which menu items there are for Channel and for Page (and later for XPage) and then PER menu item indicate whether the menu item is visible and whether it is enabled or not. The response for example will be something like

      { 
          "channel" : { 
                 "visible" :  true
                 "enabled" :  true
                " settings" : { 
                       "visible" :  true
                       "enabled" :  true
                  } 
                 " publish" : { 
                       "visible" :  true
                       "enabled" :  true
                  } 
                 " discard" : { 
                       "visible" :  true
                       "enabled" :  true
                  } 
                 " manage" : { 
                       "visible" :  true
                       "enabled" :  true
                  } 
          }
        "page" : { 
                 "visible" :  true
                 "enabled" :  true
                " new" : { 
                       "visible" :  true
                       "enabled" :  true
                  } 
                 " copy" : { 
                       "visible" :  true
                       "enabled" :  true
                  } 
                 " delete" : { 
                       "visible" :  true
                       "enabled" :  true
                  }
          } 
        "xpage" : { 
                 "visible" :  false
                 "enabled" :  false
                " new" : { 
                       "visible" :  false
                       "enabled" :  false
                  } 
                 " copy" : { 
                       "visible" :  false
                       "enabled" :  false
                  } 
                 " delete" : { 
                       "visible" :  false
                       "enabled" :  false
                  }
          } 
      }
      

      Debatable

      Note that we'll have to figure out whether we have separate REST endpoints for Channel, Page and XPage menu or that there is 1 REST endpoint. abogaart, WDYT?

      Arthur: I think one endpoint would be ideal. Below I've listed the current available actions and I'll try to summarize the backend state they require to be executed.

      Breakdown of current logic for displaying the "channel" and the "page" menu

      channel menu

      • visible: no check
      • enabled: no check
      • optional icon to indicate changes is triggered by checking local state

        settings

      • visible: SessionService.hasWriteAccess()
      • enabled: SessionService.hasWriteAccess() && hasChannel() && channel.previewHstConfigExists && channel.hasCustomProperties;

        publish

      • visible: SessionService.hasWriteAccess() && !ProjectService.isBranch()
      • enabled: local state check

        confirm

      • visible: SessionService.hasWriteAccess() && ProjectService.isBranch()
      • enabled: local state check

        discard-changes

      • visible: SessionService.hasWriteAccess()
      • enabled: local state check

        manage-changes

      • visible: SessionService.hasWriteAccess()
      • enabled: SessionService.canManageChanges() && local state check

        accept

      • visible: SessionService.hasWriteAccess() && ProjectService.isBranch()
      • enabled: ProjectService.isAcceptEnabled()

        reject

      • visible: SessionService.hasWriteAccess() && ProjectService.isBranch()
      • enabled: ProjectService.isRejectEnabled()

        delete

      • visible: SessionService.hasWriteAccess()
      • enabled: SessionService.canDeleteChannel()

        close

      • visible: always
      • enabled: always

       


      page menu

        tools

      • visible: PageToolsService.hasExtensions();
      • enabled: always
      • onclick: it constructs a pageUrl that is sent as a parameter to the page extension
        • pageUrl: channel.url + page.pathInfo

        properties

      • visible: SessionService.hasWriteAccess()
      • enabled: SitemapItemService.hasItem() && !item.isHomePage && !item.isLocked() && item.workspaceConfiguration && !item.inherited
      • onclick: open the page-properties editor. The page properties are read from the SitemapItemService which has been updated when the page-menu is opened.
        • We could decide to return these properties as part of the payload for the menu, or find a way to lazy-load them when the page-properties editor is actually openend (let the page-properties editor load them instead of the menu doing it)

        copy

      • visible: SessionService.hasWriteAccess()
      • enabled: SiteMapItemService.hasItem() && !SiteMapItemService.isLocked() && (ChannelService.hasWorkspace() || (SessionService.isCrossChannelPageCopySupported() && ChannelService.hasPageModifiableChannels()))
      • onclick: it opens the page-copy subpage that uses the sitemap-item in SitemapItemService and pageModifiableChannels in ChannelService (both are loaded when opening the pageMenu)

        move

      • visible: SessionService.hasWriteAccess()
      • enabled: SitemapItemService.hasItem() && !item.isHomePage && !item.isLocked() && item.workspaceConfiguration && !item.inherited
      • onclick: it opens the page-move subpage that uses the sitemap-item in SitemapItemService (loaded by opening pageMenu)

        delete

      • visible: SessionService.hasWriteAccess()
      • enabled: SitemapItemService.hasItem() && !item.isHomePage && !item.isLocked() && item.workspaceConfiguration && !item.inherited
      • onclick: shows a dialog based on data from the sitemap-item in SitemapItemService (loaded by opening pageMenu)

        new

      • visible: SessionService.hasWriteAccess()
      • enabled: ChannelService.hasWorkspace() && ChannelService.hasPrototypes()
      • onclick: opens the page-new subpage

       

      Note:

      • SessionService.hasWriteAccess() is deprecated
      • ProjectService state is loaded when channel is initialised
      • PageToolsService is updated when a page changes

       

      #1

      {
         "name":"_any_",
         "id":"ffc78451-6546-4ed2-8c2c-f78473f2a9f2",
         "parentId":"2ca0e6e1-2b1a-4dac-a1eb-a7b88e057938",
         "pathInfo":"/land",
         "parentPathInfo":"land",
         "isHomePage":false,
         "pageTitle":null,
         "localParameters":{
      
         },
         "roles":[
      
         ],
         "componentConfigurationId":null,
         "cacheable":false,
         "workspaceConfiguration":false,
         "inherited":true,
         "lockedBy":null,
         "lockedOn":null,
         "versionStamp":0,
         "relativeContentPath":"landingpages/${1}",
         "primaryDocumentRepresentation":{
            "path":"/content/documents/myproject/landingpages/${1}",
            "displayName":"${1}",
            "exists":false,
            "selected":true,
            "document":false
         },
         "availableDocumentRepresentations":[
            {
               "path":"/content/documents/myproject/landingpages/${1}",
               "displayName":"${1}",
               "exists":false,
               "selected":true,
               "document":false
            }
         ],
         "scheme":"http",
         "wildCard":false,
         "any":true,
         "containsWildCard":false,
         "containsAny":false,
         "parentLocation":{
            "location":"localhost/land/",
            "id":"2ca0e6e1-2b1a-4dac-a1eb-a7b88e057938"
         },
         "hasContainerItemInPageDefinition":false,
         "numberOfChildren":0,
         "explicitElement":false
      }
      

      #2

      {
         "id":"myproject-preview",
         "name":"My Project",
         "channelSettingsEditable":true,
         "type":"website",
         "hostname":"localhost",
         "hostGroup":"dev-localhost",
         "contextPath":"/site",
         "cmsPreviewPrefix":"_cmsinternal",
         "mountPath":"",
         "channelPath":"/hst:myproject/hst:configurations/myproject-preview/hst:workspace/hst:channel",
         "url":"http://localhost:8080/site",
         "hstMountPoint":"/hst:myproject/hst:sites/myproject",
         "hstConfigPath":"/hst:myproject/hst:configurations/myproject-preview",
         "contentRoot":"/content/documents/myproject",
         "composerModeEnabled":false,
         "properties":{
      
         },
         "channelInfoClassName":null,
         "channelInfoMixinNames":null,
         "mountId":"05bbf493-8220-49b0-9c83-43b06aa49e77",
         "siteMapId":"c6920f00-d73c-4892-a890-46d2f2d0f9e9",
         "locale":"en_US",
         "previewHstConfigExists":true,
         "workspaceExists":true,
         "hasCustomProperties":false,
         "deletable":false,
         "changedBySet":[
      
         ],
         "defaultDevice":"default",
         "devices":[
      
         ],
         "viewportMap":{
      
         },
         "channelNodeLockedBy":null,
         "lastModifiedBy":null,
         "lockedOn":null,
         "lastModified":null,
         "branchId":null,
         "branchOf":null,
         "configurationLocked":false,
         "preview":true
      }
      

      Attachments

        Issue Links

          Activity

            People

              ntrajkovski Nikola Trajkovski
              aschrijvers Ard Schrijvers
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: