Our Products:   CompleteFTP  edtFTPnet/Free  edtFTPnet/PRO  edtFTPj/Free  edtFTPj/PRO
+1 vote
761 views
in General by (240 points)

My customer uses CompleteFTP pro and very much likes it. They are asking if it is possible to include the CompleteFTP HTTPS site inside a new Web Application which I'm developing for them. This will likely be an Azure Web Application, and so authenticated with Azure AD and OAUTH / STS.

Ideally they would have the functions of their new app, but 1 navigation link that would show them CompleteFTP site inside the main application body, while retaining the chrome of the new app. At worst, some single-sign-on approach and jump to the other site would suffice.

I'm not sure what the most natural route to achieving this is: 

  • use your .NET component, but have to write a lot of basic pages that are already in your app
  • use some sort of (horrible) iframe style inclusion or wrapping
  • use authenticator extensions to make some sort of custom azure AD or STS style authentication
  • add some sort of SAML support into the new app to share the identity with CompleteFTP
  • am I going to need to move their (currently on-prem) CompleteFTP into Azure, and is that even possible?
  • ...etc.
It is early days and this was supposedly a 'quick' question! Rather than chase each rabbit hole, I was hoping I could get pointed roughly in the right direction?

by (240 points)
So, following on now using the V12 release, I am making progress!

I have 2 issues:


1) To access the index.jss page at the CompleteFTP HTTP server, a redirect is invoked back to /Login
This means my application is making the requests but as there is currently no logged in user the 'original' login page is being used.
I have noted that when using the CompleteFTP HTTP server directly, both the 'original' login and the one from the angular filemanager have to be completed.
I will be moving on to some sort of SSO arrangement soon, but for now it would be good if I can just accept a second login at the angular fileamanager?

2) By establishing a session directly and logging in, I can bypass the problem above for (1) and the index.jss calls begin to work:

for example the first response looks like:

{
    "id": 0,
    "result": {
        "serverName": "Server 1",
        "siteName": "Default Site",
        "welcomeMessage": "Complete FTP server",
        "userName": "Test",
        "homeFolder": "/Home/Test",
        "sharingEnabled": true
    }
}

...making a new folder results in an index.jss call that responds with:

{
    "id": 0,
    "result": {
        "canWrite": true,
        "canRemove": true,
        "canRename": true,
        "files": [
            {
                "name": "NewFolder",
                "rights": "drwxr-xr-x",
                "size": 0,
                "date": "Tue, 04 Dec 2018 09:58:32 UTC",
                "type": "dir"
            },
            {
                "name": "NewTest",
                "rights": "drwxr-xr-x",
                "size": 0,
                "date": "Tue, 04 Dec 2018 11:19:41 UTC",
                "type": "dir"
            }
        ]
    }
}

...all this looks great!
The 'rest' of the app that I am trying to host 'locally' (at the moment, just the clone of the completeftp-filemanager repo with url rewrite/reverse proxy to send index.jss to the CompleteFTP server) throws javascript errors and displays nothing:

 TypeError: Object doesn't support property or method 'map'
   at Anonymous function (http://localhost:8080/dist/angular-filemanager.min.js:3:12523)
   at Anonymous function (http://localhost:8080/bower_components/angular/angular.min.js:136:450)
   at m.prototype.$digest (http://localhost:8080/bower_components/angular/angular.min.js:147:403)
   at m.prototype.$apply (http://localhost:8080/bower_components/angular/angular.min.js:151:111)
   at l (http://localhost:8080/bower_components/angular/angular.min.js:103:84)
   at s (http://localhost:8080/bower_components/angular/angular.min.js:108:107)
   at y.onload (http://localhost:8080/bower_components/angular/angular.min.js:109:23) Possibly unhandled rejection: {}

I don't seem to be able to get a handle on these errors via the debugger. I guess my unfamiliarity with angular development does not help!

1 Answer

+1 vote
by (51.6k points)
selected by
 
Best answer

This sounds super interesting.  We'd be happy to work with you to get that going.

I think there are two main hurdles: one is the authentication issue, which you mentioned, and the other is cross-site protection built into browsers.  Perhaps the best way to overcome both of these is to have your app act as a proxy for the CompleteFTP file-manager's API.  

The next version of CompleteFTP, 12.0.0, which is due out next month, will include a new file-manager.  It's an open-source fork of angular-filemanager.  The repository in on GitHub at github.com/EnterpriseDT/completeftp-filemanager.  The server-side API is written entirely in Javascript (JSS).  It's invoked from the browser via JSON-RPC and all calls pass through a single point (index.jss).  For example, a file-list request looks like this:

{
  "method": "list",
  "id":0,
  "params": {
    "path": "/MyFiles"
  }
}

and the response looks like this:

{
  "id": 0,
  "result": {
    "canWrite": true,
    "canRemove": true,
    "canRename": true,
    "files": [{
        "name": "file001.dat",
        "rights": "drwxr-xr-x",
        "size": 79,
        "date": "Wed, 17 Oct 2018 03:22:37 UTC",
        "type": "file"
      }, {
        "name": "file002.dat",
        "rights": "drwxr-xr-x",
        "size": 37,
        "date": "Wed, 17 Oct 2018 03:22:37 UTC",
        "type": "file"
      }
    ]
  }
}

I imagine that you could host all of the AngularJS code on your server and replace index.jss with your own code that acts as a dumb proxy, forwarding the requests to CompleteFTP and sending the responses back to the client.  To get the client code to call your URL instead of index.jss is done by changing the values in the values array defined on line 49 of template.html.

You'll see that there's a login method in the API, so if the credentials for your app are the same as those for CompleteFTP, then you can perhaps just call that using the credentials that the user enters when logging into your app.  You could probably also use SAML if you like.

And yes, CompleteFTP runs fine on Azure.

How does that sound?

by (240 points)
This sounds perfect.
I'm giving this a try out. To get going, I've followed the instructions in the readme.md in the github repo, and applied this new folder in CompleteFTP manager.
The site comes up OK, and requests login using the new screen. With a wrong login, this successfully returns a message, but a correct login causes an error. These entries appeared in the logs:

Time    Level    Category    IP Address    Session    User    Message
14:39:19,460    ERROR    JSS    127.0.0.1    59    test    Function expected.
14:39:19,460    ERROR    JSS    127.0.0.1    59    test    /completeftp-filemanager/index.jss (51, 4): system.checkLogin();
14:39:19,460    ERROR    JSS    127.0.0.1    59    test    Function expected.
14:39:19,460    ERROR    JSS    127.0.0.1    59    test    /completeftp-filemanager/index.jss (51, 4): system.checkLogin();



I am currently in 'Development Mode' with CompleteFTP as my original trial expired. I'd like to get it going in DEV first before I ask them to change their live FTP site, but if I need a licensed version to do this I might be able to arrange that.
by (51.6k points)
This error happens because you're using a version of CompleteFTP that doesn't support system.checkLogin().  Version 12.0.0, for which the new file-manager is designed, is due for release later this week.  If you don't want to wait for that we can send you a release candidate if you open a ticket at enterprisedt.com/help.
by (240 points)
Awesome thanks!

Categories

...