Sessions¶
The plugin server has a small session manager API. It uses MongoDV for the backend. The MongoDB must have a database set up and should be configured for user authentication. These topics are beyond the scope of this document, but you may visit the MongoDB Documentation on how to set up and configure the database.
Sessman API¶
The sessman API uses the following endpoints:
Endpoint |
Usage and Parameters |
|---|---|
/sessman/new |
userid: user id associated with the session being created |
data: should be sent as POST data, in JSON format. |
|
/sessman/update |
data: should be sent as POST data, in JSON format. |
/sessman/get |
sessionid: The session ID given from /sessman/new |
userid: The userid used with /sessman/new |
The basic flow is to create a sessions with /sessman/new, or etrieve an existing session, /sessman/get. As data is updted, /sessman/update is called to update the session data.
Session data automatically expires after session_ttl.
All data from sessman are returned as JSON objects.
Configuration¶
Configuring the sessman plugin is a little different from other plugins, and, in fact introduced the JSON config interpolator. In the config file, under plugin_parms, a line is needed for the JSON config:
[plugin_parms]
sessman=json=sessman.json
And the sessman.json file:
{
"username": "ps_sessman",
"password": "<your secure password here>",
"server_url": "mongo.domain.tld:27017",
"database": "sessman",
"session_ttl": 86400,
}
The purpose of JSON is it allow for storing passwords that may cause parsing errors with configparser. The parameters needed are:
Parameter |
Usage |
|---|---|
username |
Username for the MongoDB database |
password |
Password for the MongoDB database |
server_url |
URL for the MongoDB server |
session_ttl |
Time to live for the session entries, in seconds. |
Example Javascript Session Class¶
class Session {
//
// Session is a class to implement expiring session data.
// a session is created, with a session id, which is stored in the class
// the data is available in Session.data.<key>. When the data is modified
// and the updateSession method is called, the session is updated and its expiry is
// reset
//
// Most of the methods are async and need to be called accordingly.
// To properly create a session use:
// Session.create(user, options)
//
// Options are:
// options = {
// base_url: the base portion of the url for url construction
// data: javascript object of initial session data
// auth: this is the apikey configured and sent in headers as a bearer token
// }
constructor(user, user_options) {
this.options = {
'base_url': "http://hp.ducksfeet.com:6123/sessman",
'auth': null,
'data': {},
}
if (user_options && typeof user_options == 'object')
Object.assign(this.options, user_options);
this.base_url = this.options.base_url;
this.user = user;
this.data = this.options.data;
console.log('base_url',this.base_url,'user',this.user,'data', this.data);
}
static async create(user, options) {
const instance = new Session(user, options);
await instance.createSession();
return instance;
}
get_command_url(command, parameters) {
// take object parameters and create a query string
// then create the url for the endppoint
let qry_str = '';
if (parameters && typeof parameters === 'object') {
Object.keys(parameters).forEach(k => {
if (qry_str)
qry_str = `${parms}&${k}=${parameters[k]}`;
else
qry_str = `${k}=${parameters[k]}`;
});
}
return `${this.base_url}/${command}?${qry_str}`;
}
async get_data(cmd, parameters, data) {
let rdata = undefined;
let method = 'POST';
let body = "";
let url = this.get_command_url(cmd, parameters);
let headers = {'Content-type': 'text/javascript'}
if (data !== undefined) {
body = JSON.stringify({
'data': data
});
}
if (this.options.auth)
headers['Authorization'] = `Bearer ${self.options.auth}`
console.log(`get_data: [url=${url}]`)
console.log(`get_data: [headers=${JSON.stringify(headers)}]`)
console.log(`get_data: [data=${JSON.stringify(data)}]`)
const response = await fetch(url, {
'headers': headers,
'method': method,
'body': body
});
if (response.ok) {
try {
const responseText = await response.text(); // Read the response body as text
const jsonData = JSON.parse(responseText); // Then parse it as JSON
return jsonData;
} catch (e) {
console.error("Error parsing JSON:", e);
const textData = await response.text();
return textData;
}
}
console.error(`Request failed with status: ${response.status}`);
return null;
}
async createSession() {
const rdata = await this.get_data('new', { 'user': this.user }, this.data); // Pass this.data as the request body
if (typeof rdata == 'object') {
console.log('Create session, data:', rdata);
if (rdata && rdata.session_id && rdata.data) {
this.session_id = rdata.session_id;
this.data = rdata.data;
} else {
console.error("Error: Invalid data received during session creation: ", rdata);
}
}
}
async updateSession() {
const rdata = await this.get_data('update', {
'session_id': this.session_id
}, this.data);
if (rdata && rdata.data) {
this.data = rdata.data;
} else {
console.error("Error: Invalid data received during session update.");
}
}
}