Commit d0af481d authored by Pedro Eduardo Trujillo's avatar Pedro Eduardo Trujillo
Browse files

Merge branch 'dev' into 'master'

Permite uso de símbolos en email y password

See merge request redmic-project/client/web!99
parents be66c780 151fbc52
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ yarn install
OAUTH_URL=https://redmic.grafcan.es/api/oauth \
OAUTH_CLIENT_ID=app \
OAUTH_CLIENT_SECRET=secretKey \
API_URL=https://api.redmic.grafcan.es/api \
API_URL=https://redmic.grafcan.es/api \
PRODUCTION=0 \
npm start -- --port=80
```
@@ -41,6 +41,14 @@ Para optimizar la ejecución es necesario realizar un proceso de "compilación"

Más información en <https://gitlab.com/redmic-project/client/web/-/wikis/dojo-compile>.

## Páginas estáticas

Para permitir el consumo de la aplicación desde clientes que no soportan ejecución Javascript, existe una funcionalidad de pre-renderizado de las páginas, que sólo actúa cuando se identifica a este tipo de clientes.

Esto es útil para clientes como los bots de redes sociales, que necesitan tener la página ya procesada para extraer los diferentes meta-tags asociados. De esta manera, podrán crear enlaces enriquecidos hacia la plataforma cuando los usuarios compartan contenido.

Para activarlo, basta con lanzar previamente el servicio [Prerender](https://gitlab.com/redmic-project/client/prerender) e indicar dónde está accesible mediante la variable `PRERENDER_URL`. En caso de que el cliente no lo requiera o que no se encuentre el servicio activo, simplemente se responderá con contenido dinámico.

## Testeo

Se ha preparado una batería de pruebas, tanto unitarias como funcionales, que permiten evaluar el estado del proyecto a medida que se aplican cambios en la base de código.
+26 −25
Original line number Diff line number Diff line
let express = require('express'),
const express = require('express'),
	bodyParser = require('body-parser'),
	fs = require('fs'),
	path = require('path'),
	http = require('http'),
	https = require('https');
	https = require('https'),

let logger, params, version, robotsContent, sitemapContent, sitemapLastUpdated,
	oauthUrl = process.env.OAUTH_URL,
	oauthClientId = process.env.OAUTH_CLIENT_ID,
	oauthClientSecret = process.env.OAUTH_CLIENT_SECRET,
@@ -13,6 +12,8 @@ let logger, params, version, robotsContent, sitemapContent, sitemapLastUpdated,
	apiUrl = process.env.API_URL,
	sitemapUrl = process.env.SITEMAP_URL;

let logger, params, version, robotsContent, sitemapContent, sitemapLastUpdated;

function getLang(req) {

	return req && req.headers && req.headers['content-language'] || params.lang;
@@ -77,7 +78,7 @@ function onOwnRequestResponse(bindParams, internalRes) {
			content += nestedChunks[i].toString();
		}

		let originalRes = nestedBindParams.originalRes,
		const originalRes = nestedBindParams.originalRes,
			onSuccess = nestedBindParams.onSuccess || onOwnRequestSuccess,
			onError = nestedBindParams.onError || onOwnRequestError,
			afterResponse = nestedBindParams.afterResponse;
@@ -98,7 +99,7 @@ function onOwnRequestSuccess(originalRes, content) {

	originalRes.status(this.statusCode).send(content);

	let internalUrl = this.req.protocol + '//' + this.req.host + this.req.path,
	const internalUrl = this.req.protocol + '//' + this.req.host + this.req.path,
		internalRequestMessage = `INTERNAL ${this.req.method} ${internalUrl} ${this.statusCode}`;

	logger.info(internalRequestMessage);
@@ -113,7 +114,7 @@ function onOwnRequestError(originalRes, err) {
		description: 'Something went wrong at server. Please, try again.'
	});

	let errorMessage = err instanceof Object ? err.toString() : err;
	const errorMessage = err instanceof Object ? err.toString() : err;
	logger.error(errorMessage);
}

@@ -121,12 +122,12 @@ function onSitemapRequest(_req, res) {

	res.set('Content-Type', 'text/xml');

	let currTimestamp = Date.now();
	const currTimestamp = Date.now();

	if (!sitemapContent || !sitemapContent.length || sitemapLastUpdated < currTimestamp - 300000) {
		let afterResponseCallback = (status, content) => sitemapContent = status ? content : '';
		const afterResponseCallback = (status, content) => sitemapContent = status ? content : '';

		let internalReq = https.request(sitemapUrl, onOwnRequestResponse.bind(this, {
		const internalReq = https.request(sitemapUrl, onOwnRequestResponse.bind(this, {
			originalRes: res,
			afterResponse: afterResponseCallback
		}));
@@ -149,7 +150,7 @@ function onRobotsRequest(req, res) {
		robotsContent = 'User-agent: *\n';

		if (production) {
			let sitemapPath = 'https://' + req.hostname + '/sitemap.xml',
			const sitemapPath = 'https://' + req.hostname + '/sitemap.xml',
				sitemapLine = 'Sitemap: ' + sitemapPath;

			robotsContent += 'Allow: /\n\n' + sitemapLine;
@@ -176,17 +177,13 @@ function onOauthTokenRequest(req, res) {

	res.set('Content-Type', 'application/json');

	let body = req.body,
		password = body.password,
		username = body.username,

		getTokenUrl = oauthUrl + '/token',
		clientCredentials = oauthClientId + ':' + oauthClientSecret,
		base64ClientCredentials = Buffer.from(clientCredentials).toString('base64'),

	const getTokenUrl = oauthUrl + '/token',
		reqLibrary = getTokenUrl.indexOf('https') === -1 ? http : https;

	let options = {
	const clientCredentials = oauthClientId + ':' + oauthClientSecret,
		base64ClientCredentials = Buffer.from(clientCredentials).toString('base64');

	const options = {
		method: 'POST',
		headers: {
			'Content-Type': 'application/x-www-form-urlencoded',
@@ -194,23 +191,27 @@ function onOauthTokenRequest(req, res) {
		}
	};

	let bindParams = {
	const bindParams = {
		originalRes: res,
		onError: onOauthRequestError
	};

	let internalReq = reqLibrary.request(getTokenUrl, options, onOwnRequestResponse.bind(this, bindParams));
	const internalReq = reqLibrary.request(getTokenUrl, options, onOwnRequestResponse.bind(this, bindParams));

	internalReq.on('error', onOauthRequestError.bind(this, res));

	let bodyData = 'grant_type=password&username=' + username + '&password=' + password + '&scope=write';
	const body = req.body,
		password = encodeURIComponent(body.password),
		username = encodeURIComponent(body.username),
		bodyData = 'grant_type=password&username=' + username + '&password=' + password + '&scope=write';

	internalReq.write(bodyData);
	internalReq.end();
}

function onOauthRequestError(originalRes, err) {

	let error = JSON.parse(err),
	const error = JSON.parse(err),
		errorType = error.error,
		errorDescription = error.error_description;

@@ -245,12 +246,12 @@ function exposeRoutes(app) {

function exposeContents(app, directoryName) {

	let pathOptions = {
	const pathOptions = {
		maxAge: 600000,
		index: false
	};

	let exposedPath = path.join(__dirname, '..', directoryName),
	const exposedPath = path.join(__dirname, '..', directoryName),
		staticPropName = 'static',
		servedPath = express[staticPropName](exposedPath, pathOptions);

+11 −8
Original line number Diff line number Diff line
var packageJson = require('../package.json'),
const packageJson = require('../package.json'),
	version = packageJson.version,

	params = require('./params')(version),

	logging = require('./logging'),
	logger = logging.logger,
	cluster;
	logger = logging.logger;

let cluster;

if (params.cluster) {
	cluster = require('cluster');
}

if (cluster && cluster.isMaster) {
	var numCpus = require('os').cpus().length;
	const numCpus = require('os').cpus().length;

	for (var i = 0; i < numCpus; i++) {
	for (let i = 0; i < numCpus; i++) {
		cluster.fork();
	}

@@ -23,20 +24,22 @@ if (cluster && cluster.isMaster) {
		logger.error('worker %i died (%s)', worker.process.pid, signal);
	});
} else {
	var express = require('express'),
	const express = require('express'),
		http = require('http'),

		metrics = require('./metrics')(logger, '/metrics'),
		prerender = require('./prerender')(logger),
		exposure = require('./exposure')(logger, params, version),

		port = params.port,
		debug = params.debug,
		pid = process.pid;
		pid = process.pid,

	var app = express();
		app = express();

	logging.registerAppLogger(params, app);
	metrics.registerAppMetrics(app);
	prerender.registerAppPrerender(app);
	exposure.exposeApp(app);

	http.createServer(app).listen(port, function() {
+3 −3
Original line number Diff line number Diff line
var morgan = require('morgan'),
const morgan = require('morgan'),
	winston = require('winston');

var logConsoleTransport = new (winston.transports.Console)({
const logConsoleTransport = new (winston.transports.Console)({
	level: 'silly',
	format: winston.format.combine(
		winston.format.splat(),
@@ -16,7 +16,7 @@ var logConsoleTransport = new (winston.transports.Console)({
	)
});

var logger = winston.createLogger({
const logger = winston.createLogger({
	transports: [
		logConsoleTransport
	],
+9 −9
Original line number Diff line number Diff line
var promClient = require('prom-client'),
const promClient = require('prom-client'),
	responseTime = require('response-time');

var register = promClient.register,
const register = promClient.register,
	counter = promClient.Counter,
	histogram = promClient.Histogram,
	summary = promClient.Summary,
	logger,
	promPath;
	summary = promClient.Summary;

var numOfRequests = new counter({
let logger, promPath;

const numOfRequests = new counter({
	name: 'numOfRequests',
	help: 'Number of requests made',
	labelNames: ['method']
});

var pathsTaken = new counter({
const pathsTaken = new counter({
	name: 'pathsTaken',
	help: 'Paths taken in the app',
	labelNames: ['path']
});

var responses = new summary({
const responses = new summary({
	name: 'responses',
	help: 'Response time in millis',
	labelNames: ['method', 'path', 'status']
@@ -50,7 +50,7 @@ function injectMetricsRoute(app) {

		res.set('Content-Type', register.contentType);

		var metricsPromise = register.metrics();
		const metricsPromise = register.metrics();

		metricsPromise.then(
			(function(response, value) {
Loading