-
-
Notifications
You must be signed in to change notification settings - Fork 586
Integrate Silex with your infrastructure
⚠️ This page is obsolete: It concerns Silex v2. Please read Silex v3 "Getting started with self hosting" docs and Silex v3 "Connect Silex with your data storage and website hosting services"
The idea behind integrating Silex with your infrastructure is to customize how files are store in Silex:
- When the user opens/saves a website
- When the user loads/uploads assets
- When the user publishes a website
This page describes how to take control over
- The user experience to select a service, i.e. what appears by default when the user opens silex file browser
- The user experience to publish a website, i.e. customize the dialogs when you click "publish"
- Which cloud services are available to the user, e.g. Github, Dropbox, SFTP... or a custom service which saves to your servers or a data base
- Where the publication process ends up publishing, e.g. github page, your servers under the user name...
There is also a way to use Silex as an editor for one website only, which means:
- skip the Dashboard and open a website directly
- prevent the user from opening another site (hide the open menu and disable the shortcut)
- prevent the user from "saving as"
If you just want to select which services and publication options are available on your Silex instance, you can do that by hosting an instance of Silex and playing with the env vars
Related topics:
- Single site mode
- Publishing and Releasing Your Website
- How to Host An Instance of Silex
- How To Add Silex To Your Node.js Project
- Data Storage
- Silex for hosting providers
- Add custom templates
- Add custom components
Please read the following sections which explain what we mean here when talking of these terms
You might also be interested in reading more about Silex vocabulary.
Unifile services are low level code that allows read/write to cloud services. It uses the excellent unifile project (also by the Silex Labs team).
Here is why you may want to create a unifile service for your Silex instance
- Allow the user to save/load/publish websites and assets to/from another service, such as google drive or S3 or your servers
- Make it possible to add a custom hosting provider which publishes to your servers, see below
You can add services to your instance for your users. Start by creating a new nodejs project as explained in the page How To Add Silex To Your Node.js Project. In short, Silex is included in your project as an npm dependency.
Here is an example of a very simple unifile service which can be used in Silex:
const { FsConnector } = require('unifile');
/**
* Service connector extends the local filesystem connector (unifile-fs)
* The root URL will depend on the user name, i.e. in ${ rootUrl }/${ session.user }/
*/
class CustomService extends FsConnector {
// **
// extend Fs service
constructor(config) {
super(config);
// change fs infos
this.name = 'custom-service';
this.infos.name = 'custom-service';
this.infos.displayName = 'Custom Service disaplay name';
this.infos.description = 'Custom Service description';
}
// **
//Auth commands
getInfos(session) {
return Object.assign({
isLoggedIn: !!session.user,
isOAuth: false,
username: session.user
}, this.infos);
}
// In this example the form will set a user in the session
// The form is one specific form for this example
getAuthorizeURL(session) { return Promise.resolve('/login-form.html') }
// check authentication
// and create a root folder for the user
login(session, loginInfos) {
if(loginInfos.password === 'pass') {
// store the user
session.user = loginInfos.user;
// create the user's directory if it does not exist already
return this.mkdir(session, '')
.then(() => this.mkdir(session, 'Website'))
.catch((e) => session);
}
// logout if pass is not correct
session.user = null;
return Promise.resolve(session);
}
// **
//Filesystem commands: prepend the user to all paths
readdir(session, path) { return super.readdir(session, `/tmp/${ session.user }/${ path }`) }
stat(session, path) { return super.stat(session, `/tmp/${ session.user }/${ path }`) }
mkdir(session, path) { return super.mkdir(session, `/tmp/${ session.user }/${ path }`) }
writeFile(session, path, data) { return super.writeFile(session, `/tmp/${ session.user }/${ path }`, data) }
createWriteStream(session, path) { return super.createWriteStream(session, `/tmp/${ session.user }/${ path }`) }
readFile(session, path) { return super.readFile(session, `/tmp/${ session.user }/${ path }`) }
createReadStream(session, path) { return super.createReadStream(session, `/tmp/${ session.user }/${ path }`) }
rename(session, src, dest) { return super.rename(session, src, dest) }
unlink(session, path) { return super.unlink(session, `/tmp/${ session.user }/${ path }`) }
rmdir(session, path) { return super.rmdir(session, `/tmp/${ session.user }/${ path }`) }
batch(session, actions, message) { return super.batch(session, actions, message) }
}
// export for use in index.js
module.exports = CustomService;
Please read the comments in this code, it explains how
- This service expects the password to be pass, the user name can be any user name
- This service behaves like the Fs service (local file system) but all the paths are relative to
/tmp/
+ user name - When a user logs in, we create a new home folder for it in
/tmp/
+ user name
Read more about how to create a unifile service
This service uses a login form, which we need to create:
In your project, add a file named login-form.html
with this HTML code:
<form action="/ce/custom-service/login_callback" method="post" accept-charset="utf-8">
<h1>Unifile would like access to your files and folders.</h1>
<p>This is an example of a custom service. All the username work with the <strong>password "pass"</strong></p>
<div>
<label for="user">username</label>
<input type="text" name="user" placeholder="user" id="user">
</div>
<div>
<label for="password">password</label>
<input type="password" name="password" id="password">
</div>
<div>
<input type="submit" name="submit" value="Log in" id="submit">
</div>
</form>
Note that it will send the info to a route which Silex creates automatically, with the custom service name in it.
Modify the file index.js
of your project to look like this:
const { SilexServer, Config } = require('silex-website-builder');
const CustomService = require('./custom-service');
// create a default config
const config = new Config();
// disable other services
config.ceOptions.enableSftp = false;
// create the Silex server
const silex = new SilexServer(config);
// add our custom service
silex.unifile.use(new CustomService());
// define a form to get the user login and password
silex.app.use('/login-form.html', (req, res) => res.sendFile(__dirname + '/login-form.html'));
// start Silex
silex.start(function() {
console.log('server started');
});
Now you can type npm start
, open http://localhost:6805/
and click on "import". It should look like this:
Then double click on your service name:
Login with any user login and the password "pass", and you will see your folder /tmp/your-login-name
:
Also note that if your user is authenticated before it arrives in Silex, the file manager will detect that there is only 1 service and will open it automatically, so that your user will not even see the name of your custom service.
Now that we have a custom service we can add a custom hosting provider. A hosting provider is what controls this dialog in Silex:
Our hosting provider will publish in our user's special folder /tmp/
+ user name, and inside it, in a folder Website
. This is arbitrary and only an example.
Create a file at the root of your project named custom-hosting-provider.js
with this content:
module.exports = function(unifile) {
this.unifile = unifile;
};
module.exports.prototype.getOptions = function(session) {
const infos = this.unifile.getInfos(session, 'custom-service');
return {
name: 'custom-hosting-provider',
displayName: 'Custom hosting provider based on custom-service',
isLoggedIn: infos.isLoggedIn,
username: infos.username,
authorizeUrl: '/ce/custom-service/authorize',
dashboardUrl: 'https://www.custom-provider.com/projects',
pleaseCreateAVhost: 'create a new project in our service.',
vhostsUrl: '/hosting/custom-hosting-provider/vhost', // route created by silex automatically
buyDomainUrl: 'https://www.custom-provider.com/domains',
skipVhostSelection: true,
skipFolderSelection: true,
afterPublishMessage: 'Thx for using our service.<br><br>',
};
};
const WEBSITE_FOLDER_NAME = 'Website';
module.exports.prototype.getVhosts = async function(session) {
return [{
name: WEBSITE_FOLDER_NAME,
// domainUrl: `/hosting/custom-provider/vhost/get`,
skipDomainSelection: true,
publicationPath: {
//absPath: `/ce/github/get/${ WEBSITE_FOLDER_NAME }/gh-pages`,
name: WEBSITE_FOLDER_NAME,
folder: WEBSITE_FOLDER_NAME,
path: `${ WEBSITE_FOLDER_NAME }/`,
service: 'custom-service',
url: `/ce/custom-service/get/Website/`
}
}];
};
module.exports.prototype.finalizePublication = (from, to, session, onStatus) => Promise.resolve();
module.exports.prototype.getDefaultPageFileName = () => 'index.html';
help wanted: more details about the code here. Ask questions in the issues and create content here
Modify your index.js
file to look like this:
'use strict';
const { SilexServer, Config } = require('silex-website-builder');
const CustomProvider = require('./custom-hosting-provider');
// create a default config
const config = new Config();
// provide only our custom hosting to user when they want to publish
config.publisherOptions.skipHostingSelection = true;
config.publisherOptions.enableHostingUnifile = false;
// disable other services, show only our custom service
config.ceOptions.enableSftp = false;
// create the Silex server
const silex = new SilexServer(config);
// add our custom service
const CustomService = require('./custom-service');
silex.unifile.use(new CustomService());
// add our custom hosting provider
silex.publishRouter.addHostingProvider(new CustomProvider(silex.unifile))
// define a form to get the user login and password
silex.app.use('/login-form.html', (req, res) => res.sendFile(__dirname + '/login-form.html'));
// start Silex
silex.start(function() {
console.log('server started');
});
help wanted: more details about the code here. Ask questions in the issues and create content here
Type npm start
and open http://localhost:6805/
, then select a template, save it and click "publish" from the ☁ menu. You will see that Silex asks nothing to the user, it just publishes to the user's folder.
This is the documentation for Silex website builder. It is a collaborative effort, click edit and start contributing. Also have a look at these discussions.
WARNING: Support for Silex v2 has stopped. Try Silex v3 alpha, Read about it, Subscribe to the newsletter