1

I've implemented an Alfresco repository webscript (in Java) to programmatically create a new site.

I notice that there's a SiteService interface which I thought could be used to do this -

SiteInfo site = siteService.createSite("site-dashboard", "mySite", 
"mySite", "", SiteVisibility.PUBLIC);

However, this results in the creation of a non-functional site, and although it's visible within the Alfresco Share dashboard, I'm not able to use it.

I then came across this code sample, which is doing exactly what I want. BUT the code includes a section to do authentication, involving sending the user's login and password details to a dologin web service. Don't really want to do this.

But as the user has already logged in via Alfresco Share, they should already be authenticated.

If I call the create-site webscript from my code, as shown in the example (without the initial call to dologin), I'm getting a 401 (unauthorised) return code.

So my question is, how do I tell the create-site webscript about my authentication? I read about using an authentication ticket here. Is this ticket stored in the session, and if so, how do I access it within my Java code? If I could get the ticket, then this would be sufficient to invoke the create-site webscript.

Update: I've added the alf_ticket parameter as suggested by the comment, but I'm still getting a 401 response.

My current code is:

    public NodeRef createServiceChange(String serviceChangeName) {

        HttpClient client = new HttpClient();

        String ticket = authService.getCurrentTicket();

        PostMethod createSitePost = new PostMethod("http://localhost:8081/share/service/modules/create-site");

        JSONObject siteObject = new JSONObject();
        try {
            siteObject.put("shortName", serviceChangeName);
            siteObject.put("visiblity", "Public");
            siteObject.put("sitePreset", "site-dashboard");
            siteObject.put("title", serviceChangeName);
            siteObject.put("description", serviceChangeName);
            siteObject.put("alf_ticket", ticket);

            createSitePost.setRequestHeader("Content-Type", "application/json");
            createSitePost.setRequestHeader("Accept", "application/json");
            createSitePost.setRequestEntity(new StringRequestEntity(siteObject.toString(), "application/json", "UTF-8"));

            int status = client.executeMethod(createSitePost);
            System.out.println("create a site script status :: " + status);

            if (status == HttpStatus.SC_OK) {
                System.out.println("Site created OK");
            }
            else{
                System.out.println("There is error in site creation");
            }
        } catch (JSONException err) {
            err.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (HttpException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }
Andrew Fielden
  • 3,751
  • 3
  • 31
  • 47
  • If you're in Java, what about [AuthenticationService.getCurrentTicket()](http://dev.alfresco.com/resource/AlfrescoOne/5.1/PublicAPI/org/alfresco/service/cmr/security/AuthenticationService.html#getCurrentTicket()) ? – Gagravarr Nov 08 '18 at 11:32
  • Thanks again. It looked very promising, but the Post request still returns 401 – Andrew Fielden Nov 08 '18 at 13:55
  • I don't think Share will be looking for the ticket in the json body, try passing it as a header or on the url query string – Gagravarr Nov 08 '18 at 14:14
  • Good idea, but annoyingly, neither adding the ticket as a request parameter, or header item makes any difference to the result. :( – Andrew Fielden Nov 08 '18 at 14:45
  • I have to say I'm really surprised that Alfresco doesn't make the process of programmatic site creation much easier than this. I mean come on Alfresco, this is fundamental, site creation is the bread and butter of your functionality! – Andrew Fielden Nov 09 '18 at 10:33
  • And why do all the site creation examples I've seen, involve calling doLogin, with a hardcoded user name and password? That's not acceptable. I should be able to call a site creation webscript, having already been authorised to do so. – Andrew Fielden Nov 09 '18 at 10:42
  • Alfresco is, broadly, designed so it's easy for Share to talk to the Alfresco Repo, but not the other way around... In your Share config, what (if any) `` connector blocks do you have defined? – Gagravarr Nov 09 '18 at 11:39
  • You're right. In fact I'm changing my approach here. Instead of creating a repo webscript, I'm switching to the share side. I've not messed around with the share config. If you could point me at a resource which cleanly invokes the create-site service, from a share webscript, that would be useful. – Andrew Fielden Nov 09 '18 at 14:33
  • See https://docs.alfresco.com/5.1/concepts/dev-extensions-share-surf-web-scripts.html for details of getting the remote `connector` object on the share side that'll let you call Repo webscripts as the current user – Gagravarr Nov 13 '18 at 17:22

1 Answers1

1

So I've managed to successfully create a site, programmatically, and here's what I did:

First, forget about writing a repository (platform) webscript. Creation of sites in Alfresco is done by invoking a Share module, so you'll need to implement either a page, or custom menu item to create a site. I was also getting a lot of problems with authentication, but if you log in to the system via Alfresco Share, and in your Javascript, use the provided Alfresco Ajax request, then authentication shouldn't be a problem.

Here are the components I used:-

  1. Create a Share page to create your site. In the Freemarker template (.ftl) add a form to collect the site details.
  2. Attach a button on the form to the following Javascript function. Note that I cobbled this together from various code fragments on the web, so it could use some cleaning up. But it basically works for me -

    function create_site()
    {
    var sc_form = document.forms.namedItem('sc_form');
    var name = sc_form.elements.namedItem('name').value;
    
    var url = Alfresco.constants.URL_CONTEXT + "service/modules/create-site";
    
    Alfresco.util.Ajax.request({
    
        method : Alfresco.util.Ajax.POST,
    
        url : url,
    
        dataObj: {
            sitePreset: "site-dashboard",
            visibility: "PUBLIC",
            title: name,
            shortName: name,
            description: name
        },
    
        requestContentType: Alfresco.util.Ajax.JSON,
    
        successCallback: 
        {
            fn: function(res){
               alert("success");
               alert(res.responseText);                                                                                            
            },
    
            scope: this
    
        },
    
        failureCallback: 
        {
           fn: function(response)
           {
              Alfresco.util.PopupManager.displayPrompt(
              {
                 title: Alfresco.util.message("message.failure", this.name),
                 text: "search failed"
              });                                          
           },
           scope: this
        }
    });
    }
    
Andrew Fielden
  • 3,751
  • 3
  • 31
  • 47