js/base/context.js
// NPM IMPORTS
import assert from 'assert'
import fs from 'fs'
import path from 'path'
import mustache from 'mustache'
// COMMON IMPORTS
import T from '../utils/types'
import {is_browser} from '../utils/is_browser'
/**
* Cryptography library.
* @private
*/
let forge = undefined
if ( is_browser() )
{
forge = require('forge-browser').forge
} else {
forge = require('node-forge')
}
/**
* Contextual constant for this file logs.
* @private
*/
const context = 'common/base/context'
/**
* Runtime context methods (browser/server, locales, i18n).
*
* @author Luc BORIES
* @license Apache-2.0
*
* @example
* API:
* ->constructor(arg_runtime):nothing - constructor.
*
* PATHS API:
* ->get_base_dir():string - Get project base directory, the root directory of the project.
* ->get_world_dir():string - Get topology world resources directory, by default: the root directory of the project.
*
* ->get_absolute_path(arg_relative_path1, arg_relative_path2, arg_relative_path3):string - Get absolute path of given relative path.
* Search strategy:
* 1-Joining given ordered paths
* 2-Joining base directory and given ordered paths
* 3-Joining world resources directory and given ordered paths
*
* ->get_absolute_plugin_path(arg_relative_plugin, arg_relative_path1, arg_relative_path2):string - Get absolute path of given relative plugin name.
* Call get_absolute_path(arg_relative_plugin, arg_relative_path1, arg_relative_path2)
*
* ->get_absolute_package_path(arg_relative_pkg, arg_relative_path1, arg_relative_path2):string - Get absolute path of given relative package name.
* Call get_absolute_path(arg_relative_pkg, arg_relative_path1, arg_relative_path2)
* Call get_absolute_path( path.join('../../../node_modules', arg_relative_pkg), arg_relative_path1, arg_relative_path2)
* Call get_absolute_path( path.join('../../node_modules', arg_relative_pkg), arg_relative_path1, arg_relative_path2)
* Call get_absolute_path( path.join('../node_modules', arg_relative_pkg), arg_relative_path1, arg_relative_path2)
* Call get_absolute_path( path.join('node_modules', arg_relative_pkg), arg_relative_path1, arg_relative_path2)
*
* ->get_absolute_public_path(arg_relative_public, arg_relative_path1, arg_relative_path2):string - Get absolute path of given relative public path.
* Call get_absolute_path(arg_relative_public, arg_relative_path1, arg_relative_path2)
* If not found, search with prefixes [base_public, world_public, 'public', '..', '../public', '../..', '../../public', '../../..', '../../../public']
* Call get_absolute_path( join(prefix, arg_relative_public), arg_relative_path1, arg_relative_path2)
*
* ->get_absolute_resources_path(arg_relative_resource, arg_relative_path1, arg_relative_path2):string - Get absolute path of given relative resource file.
* Call get_absolute_path( path.join('resources', arg_relative_resource), arg_relative_path1, arg_relative_path2)
*
* CREDENTIALS API:
* ->get_credentials(arg_request):object - Get credentials.
* ->get_credentials_string(arg_credentials):string - Get credentials string as 'username=...&password=...&token=...'.
* ->get_url_with_credentials(arg_url, arg_request):string - Get given url augmented with credentials string.
*
* ->render_credentials_template(arg_html, arg_request_or_credentials):string - Render credentials template.
* Call mustache.render(arg_html, credentials_datas)
* with const credentials_datas = credentials_obj.get_credentials_for_template()
* credentials_datas.credentials_str = credentials_str
* credentials_datas.credentials_url = credentials_url
* credentials_datas.credentials_basic_base64 = base64_encoded
* credentials_datas.url = '{{url}}'
*/
export default class Context
{
/**
* Create a context instance.
*
* @param {object} arg_runtime - current runtime.
*
* @returns {nothing}
*/
constructor(arg_runtime)
{
assert( T.isObject(arg_runtime) && arg_runtime.is_server_runtime, context + ':bad runtime object')
/**
* Class type flag.
* @type {boolean}
*/
this.is_context = true
/**
* Runtime instance.
* @type {Runtime}
*/
this.$runtime = arg_runtime
}
// *************************************************** FILE PATH ********************************************************
/**
* Get project base directory, the root directory of the project.
*
* @returns {string} - absolute root directory path.
*/
get_base_dir()
{
return this.$runtime ? this.$runtime.get_setting('base_dir') : null
}
/**
* Get topology world resources directory, by default: the root directory of the project.
*
* @returns {string} - absolute root directory path.
*/
get_world_dir()
{
return this.$runtime ? this.$runtime.get_setting('world_dir') : this.get_base_dir()
}
/**
* Get absolute path of given relative path.
*
* @param {string} arg_relative_path1 - relative path 1.
* @param {string} arg_relative_path2 - relative path 2.
* @param {string} arg_relative_path3 - relative path 3.
*
* @returns {string} - absolute path.
*/
get_absolute_path(arg_relative_path1, arg_relative_path2, arg_relative_path3)
{
assert( T.isString(arg_relative_path1), context + ':get_absolute_path: bad paths strings')
let base_dir = path.isAbsolute(arg_relative_path1) ? '' : this.get_base_dir()
assert( T.isString(base_dir), context + ':get_absolute_path: bad base dir string')
// console.log(this.get_world_dir(), 'world_dir')
// console.log('get_absolute_path:with ', arg_relative_path1, arg_relative_path2, arg_relative_path3)
const default_extension = '.js'
let ext = undefined
let p0 = undefined
let p1 = undefined
let p2 = undefined
if ( T.isString(arg_relative_path2) )
{
if ( T.isString(arg_relative_path3) )
{
ext = path.extname(arg_relative_path3)
p0 = path.join(arg_relative_path1, arg_relative_path2, arg_relative_path3)
p1 = path.join(this.get_world_dir(), arg_relative_path1, arg_relative_path2, arg_relative_path3)
p2 = path.join(base_dir, arg_relative_path1, arg_relative_path2, arg_relative_path3)
}
else
{
ext = path.extname(arg_relative_path2)
p0 = path.join(arg_relative_path1, arg_relative_path2)
p1 = path.join(this.get_world_dir(), arg_relative_path1, arg_relative_path2)
p2 = path.join(base_dir, arg_relative_path1, arg_relative_path2)
}
}
else
{
ext = path.extname(arg_relative_path1)
p0 = arg_relative_path1
p1 = path.join(this.get_world_dir(), arg_relative_path1)
p2 = path.join(base_dir, arg_relative_path1)
}
// console.log('get_absolute_path:', p0, p1, p2)
if ( path.isAbsolute(p0) )
{
// WITHOUT DEFAULT EXTENSION
try
{
const fs_stat = fs.statSync(p0)
if ( fs_stat.isFile() || fs_stat.isDirectory() )
{
// console.log(context + ':get_absolute_path:path found [%s] for [%s, %s, %s]', p0, arg_relative_path1, arg_relative_path2, arg_relative_path3)
return p0
}
}
catch(e) {}
// WITH DEFAULT EXTENSION
try
{
const fs_stat = fs.statSync(p0 + default_extension)
if ( fs_stat.isFile() || fs_stat.isDirectory() )
{
// console.log(context + ':get_absolute_path:path found [%s] for [%s, %s, %s]', p0, arg_relative_path1, arg_relative_path2, arg_relative_path3)
return p0 + default_extension
}
}
catch(e) {}
}
if ( path.isAbsolute(p1) )
{
// WITHOUT DEFAULT EXTENSION
try
{
const fs_stat = fs.statSync(p1)
if ( fs_stat.isFile() || fs_stat.isDirectory() )
{
// console.log(context + ':get_absolute_path:path found [%s] for [%s, %s, %s]', p1, arg_relative_path1, arg_relative_path2, arg_relative_path3)
return p1
}
}
catch(e) {}
// WITH DEFAULT EXTENSION
try
{
const fs_stat = fs.statSync(p1 + default_extension)
if ( fs_stat.isFile() || fs_stat.isDirectory() )
{
// console.log(context + ':get_absolute_path:path found [%s] for [%s, %s, %s] with .js', p1, arg_relative_path1, arg_relative_path2, arg_relative_path3)
return p1 + default_extension
}
}
catch(e) {}
}
if ( path.isAbsolute(p2) )
{
// WITHOUT DEFAULT EXTENSION
try
{
const fs_stat = fs.statSync(p2)
if ( fs_stat.isFile() || fs_stat.isDirectory() )
{
// console.log(context + ':get_absolute_path:path found [%s] for [%s, %s, %s]', p2, arg_relative_path1, arg_relative_path2, arg_relative_path3)
return p2
}
}
catch(e) {}
// WITH DEFAULT EXTENSION
try
{
const fs_stat = fs.statSync(p2 + default_extension)
if ( fs_stat.isFile() || fs_stat.isDirectory() )
{
// console.log(context + ':get_absolute_path:path found [%s] for [%s, %s, %s] with .js', p2, arg_relative_path1, arg_relative_path2, arg_relative_path3)
return p2 + default_extension
}
}
catch(e) {}
}
// if (ext == '')
// {
// const path_1_is_directory = path.dirname(arg_relative_path1) == arg_relative_path1
// const path_2_is_directory = path.dirname(arg_relative_path2) == arg_relative_path2
// const path_3_is_directory = path.dirname(arg_relative_path3) == arg_relative_path3
// const part_1 = (! path_1_is_directory && arg_relative_path1 && ! arg_relative_path2) ? arg_relative_path1 + '.js' : arg_relative_path1
// const part_2 = (! path_2_is_directory && arg_relative_path2 && ! arg_relative_path3) ? arg_relative_path2 + '.js' : arg_relative_path2
// const part_3 = arg_relative_path3 ? arg_relative_path3 + (! path_3_is_directory ? '.js' : '') : undefined
// const absolute_path = this.get_absolute_path(part_1, part_2, part_3)
// return absolute_path
// }
console.error(context + ':get_absolute_path:path not found [\n%s, \n%s, \n%s\n] for [\n%s, \n%s, \n%s\n]', p0, p1, p2, arg_relative_path1, arg_relative_path2, arg_relative_path3)
return undefined
}
/**
* Get absolute path of given relative plugin name.
*
* @param {string} arg_relative_plugin - plugin name.
* @param {string} arg_relative_path1 - relative path 1.
* @param {string} arg_relative_path2 - relative path 2.
*
* @returns {string} - absolute path.
*/
get_absolute_plugin_path(arg_relative_plugin, arg_relative_path1, arg_relative_path2)
{
assert( T.isString(arg_relative_plugin), context + 'get_absolute_plugin_path: bad plugin name string')
if ( path.isAbsolute(arg_relative_plugin) )
{
return this.get_absolute_path(arg_relative_plugin, arg_relative_path1, arg_relative_path2)
}
return this.get_absolute_path('plugins', arg_relative_plugin, arg_relative_path1, arg_relative_path2)
}
/**
* Get absolute path of given relative package name.
*
* @param {string} arg_relative_pkg - package name.
* @param {string} arg_relative_path1 - relative path 1.
* @param {string} arg_relative_path2 - relative path 2.
*
* @returns {string} - absolute path.
*/
get_absolute_package_path(arg_relative_pkg, arg_relative_path1, arg_relative_path2)
{
assert( T.isString(arg_relative_pkg), context + 'get_absolute_package_path: bad package name string')
if ( path.isAbsolute(arg_relative_pkg) )
{
return this.get_absolute_path(arg_relative_pkg, arg_relative_path1, arg_relative_path2)
}
// debugger
let p = this.get_absolute_path( path.join('../../../node_modules', arg_relative_pkg), arg_relative_path1, arg_relative_path2)
// console.log('get_absolute_package_path:../../../node_modules:', p)
if (p)
{
return p
}
p = this.get_absolute_path( path.join('../../node_modules', arg_relative_pkg), arg_relative_path1, arg_relative_path2)
// console.log('get_absolute_package_path:../../../node_modules:', p)
if (p)
{
return p
}
p = this.get_absolute_path( path.join('../node_modules', arg_relative_pkg), arg_relative_path1, arg_relative_path2)
// console.log('get_absolute_package_path:../../../node_modules:', p)
if (p)
{
return p
}
return this.get_absolute_path( path.join('node_modules', arg_relative_pkg), arg_relative_path1, arg_relative_path2)
}
/**
* Get absolute path of given relative public path.
*
* @param {string} arg_relative_public - public path.
* @param {string} arg_relative_path1 - relative path 1.
* @param {string} arg_relative_path2 - relative path 2.
*
* @returns {string} - absolute path.
*/
get_absolute_public_path(arg_relative_public, arg_relative_path1, arg_relative_path2)
{
assert( T.isString(arg_relative_public), context + 'get_absolute_public_path: bad path string')
if ( path.isAbsolute(arg_relative_public) )
{
// console.log('get_absolute_public_path:absolute:', arg_relative_public)
return this.get_absolute_path(arg_relative_public, arg_relative_path1, arg_relative_path2)
}
const base_public = path.join(this.get_base_dir(), 'public')
const world_public = path.join(this.get_world_dir(), 'public')
const searchs = [base_public, world_public, 'public', '..', '../public', '../..', '../../public', '../../..', '../../../public']
// console.log('get_absolute_public_path:base_public:', base_public)
// console.log('get_absolute_public_path:world_public:', world_public)
let p = undefined
let index = 0
let prefix = undefined
while( ! p && index < searchs.length )
{
prefix = searchs[index]
p = this.get_absolute_path( path.join(prefix, arg_relative_public), arg_relative_path1, arg_relative_path2)
// console.log('get_absolute_public_path:prefix=%s:', prefix, p)
++index
}
return p
}
/**
* Get absolute path of given relative resource file.
*
* @param {string} arg_relative_resource - resource file name.
* @param {string} arg_relative_path1 - relative path 1.
* @param {string} arg_relative_path2 - relative path 2.
*
* @returns {string} - absolute path.
*/
get_absolute_resources_path(arg_relative_resource, arg_relative_path1, arg_relative_path2)
{
assert( T.isString(arg_relative_resource), context + 'get_absolute_resources_path: bad resource file string')
return this.get_absolute_path( path.join('resources', arg_relative_resource), arg_relative_path1, arg_relative_path2)
}
// *************************************************** URL ********************************************************
/**
* Get credentials.
*
* @param {object} arg_request - request object.
*
* @returns {object} credentials plain object.
*/
get_credentials(arg_request)
{
// logs.debug('get_credentials')
const auth_mgr = this.$runtime ? this.$runtime.security().authentication() : null
if (! auth_mgr)
{
return undefined
}
if ( ! arg_request )
{
return undefined
}
const credentials = auth_mgr.get_credentials(arg_request)
return credentials
}
/**
* Get credentials string.
*
* @param {object} arg_credentials - Credetials object.
*
* @returns {string} credentials string.
*/
get_credentials_string(arg_credentials)
{
if (! arg_credentials)
{
return ''
}
// TODO: use security token
return 'username=' + arg_credentials.get_user() + '&password=' + arg_credentials.get_pass_digest() + '&token=' + arg_credentials.get_token()
}
/**
* Get given url augmented with credentials string.
*
* @param {string} arg_url - image asset relative url.
* @param {object|Credentials} arg_request_or_credentials - request object or Credentials instance.
*
* @returns {string} absolute url.
*/
get_url_with_credentials(arg_url, arg_request_or_credentials)
{
// logs.debug('get_url_with_credentials')
// TODO ARGS = REQUEST OR CRENDETIALS ??
// NO CREDENTIALS, NO REQUEST
if ( ! arg_request_or_credentials )
{
return arg_url + '?{{credentials_url}}'
}
// GET CREDENTIALS
const credentials = arg_request_or_credentials.is_credentials ? arg_request_or_credentials : (arg_request_or_credentials.credentials ? arg_request_or_credentials.credentials : undefined)
// GET CREDENTIALS STRING
const credentials_str = this.get_credentials_string(credentials)
if (credentials_str)
{
return arg_url + '?' + credentials_str
}
return arg_url
}
/**
* Render credentials template.
*
* @param {string} arg_html - template html string.
* @param {Request|Credentials} arg_request_or_credentials - request object.
*
* @returns {string} rendered template.
*/
render_credentials_template(arg_html, arg_request_or_credentials)
{
assert( T.isObject(arg_request_or_credentials), context + ':render_credentials_template:bad arg_request_or_credentials object')
let credentials_obj = arg_request_or_credentials.is_credentials ? arg_request_or_credentials : this.get_credentials(arg_request_or_credentials)
let credentials_str = this.get_credentials_string(credentials_obj)
let credentials_url = this.get_credentials_string(credentials_obj)
// console.log(credentials_str, 'credentials_str')
// TODO 2 cases:
/*
url:string
var:JSON.stringiy(object)
*/
if (credentials_str)
{
const base64_encoded = forge.util.encode64(credentials_obj.username + ':' + credentials_obj.password)
const credentials_datas = credentials_obj.get_credentials_for_template()
credentials_datas.credentials_str = credentials_str
credentials_datas.credentials_url = credentials_url
credentials_datas.credentials_basic_base64 = base64_encoded
credentials_datas.url = '{{url}}'
// credentials_token:credentials_obj.token,
// credentials_user_name:credentials_obj.username,
// credentials_pass_digest:credentials_obj.password,
// credentials_login:credentials_obj.ts_login,
// credentials_expire:credentials_obj.expire,
// credentials_basic_base64:base64_encoded
// // credentials_obj: `{ \"username\":\"${credentials_obj.username}\", "password":"${credentials_obj.password}" }`
// }
return mustache.render(arg_html, credentials_datas)
}
return arg_html
}
// TODO:TO CLEAN OR IMPLEMENT
// get_relative_url(arg_url)
// {
// return arg_url
// }
// get_absolute_url(arg_url)
// {
// return arg_url
// }
// get_absolute_plugin_url(arg_plugin)
// {
// return arg_plugin
// }
}