Split client and server

Client and server now have their own tsconfig so that the transpilation is only
done on the part that is being modified.

It also allows faster transpilation since tests are now excluded from tsconfig.
They are compiled by ts-node during unit tests execution.
This commit is contained in:
Clement Michaud 2017-10-07 00:09:42 +02:00
parent 444d278a1e
commit d8ff186303
214 changed files with 370 additions and 256 deletions

2
.gitignore vendored
View File

@ -31,3 +31,5 @@ dist/
/config.yml
example/ldap/private.ldif
package-lock.json

View File

@ -5,7 +5,8 @@ WORKDIR /usr/src
COPY package.json /usr/src/package.json
RUN npm install --production
COPY dist/src/server /usr/src
COPY dist/server /usr/src/server
COPY dist/shared /usr/src/shared
ENV PORT=80
EXPOSE 80
@ -13,4 +14,4 @@ EXPOSE 80
VOLUME /etc/authelia
VOLUME /var/lib/authelia
CMD ["node", "index.js", "/etc/authelia/config.yml"]
CMD ["node", "server/src/index.js", "/etc/authelia/config.yml"]

View File

@ -2,75 +2,90 @@ module.exports = function (grunt) {
const buildDir = "dist";
grunt.initConfig({
env: {
"env-test-server-unit": {
TS_NODE_PROJECT: "server"
},
"env-test-client-unit": {
TS_NODE_PROJECT: "client"
}
},
run: {
options: {},
"build": {
"compile-server": {
cmd: "./node_modules/.bin/tsc",
args: ['-p', 'tsconfig.json']
args: ['-p', 'server/tsconfig.json']
},
"tslint": {
"compile-client": {
cmd: "./node_modules/.bin/tsc",
args: ['-p', 'client/tsconfig.json']
},
"lint-server": {
cmd: "./node_modules/.bin/tslint",
args: ['-c', 'tslint.json', '-p', 'tsconfig.json']
args: ['-c', 'server/tslint.json', '-p', 'server/tsconfig.json']
},
"unit-tests": {
"lint-client": {
cmd: "./node_modules/.bin/tslint",
args: ['-c', 'client/tslint.json', '-p', 'client/tsconfig.json']
},
"test-server-unit": {
cmd: "./node_modules/.bin/mocha",
args: ['--compilers', 'ts:ts-node/register', '--recursive', 'test/unit']
args: ['--colors', '--compilers', 'ts:ts-node/register', '--recursive', 'server/test']
},
"integration-tests": {
"test-client-unit": {
cmd: "./node_modules/.bin/mocha",
args: ['--colors', '--compilers', 'ts:ts-node/register', '--recursive', 'client/test']
},
"test-int": {
cmd: "./node_modules/.bin/cucumber-js",
args: ["--compiler", "ts:ts-node/register", "./test/features"]
args: ["--colors", "--compiler", "ts:ts-node/register", "./test/features"]
},
"docker-build": {
cmd: "docker",
args: ['build', '-t', 'clems4ever/authelia', '.']
},
"docker-restart": {
cmd: "./scripts/dc-dev.sh",
args: ['restart', 'authelia']
},
"minify": {
cmd: "./node_modules/.bin/uglifyjs",
args: [`${buildDir}/src/server/public_html/js/authelia.js`, '-o', `${buildDir}/src/server/public_html/js/authelia.min.js`]
args: [`${buildDir}/server/src/public_html/js/authelia.js`, '-o', `${buildDir}/server/src/public_html/js/authelia.min.js`]
},
"apidoc": {
cmd: "./node_modules/.bin/apidoc",
args: ["-i", "src/server", "-o", "doc"]
},
"make-dev-views": {
"include-minified-script": {
cmd: "sed",
args: ["-i", "s/authelia\.min/authelia/", `${buildDir}/src/server/views/layout/layout.pug`]
args: ["-i", "s/authelia\.min/authelia/", `${buildDir}/server/src/views/layout/layout.pug`]
}
},
copy: {
resources: {
expand: true,
cwd: 'src/server/resources/',
cwd: 'server/src/resources/',
src: '**',
dest: `${buildDir}/src/server/resources/`
dest: `${buildDir}/server/src/resources/`
},
views: {
expand: true,
cwd: 'src/server/views/',
cwd: 'server/src/views/',
src: '**',
dest: `${buildDir}/src/server/views/`
dest: `${buildDir}/server/src/views/`
},
images: {
expand: true,
cwd: 'src/client/img',
cwd: 'client/src/img',
src: '**',
dest: `${buildDir}/src/server/public_html/img/`
dest: `${buildDir}/server/src/public_html/img/`
},
thirdparties: {
expand: true,
cwd: 'src/client/thirdparties',
cwd: 'client/src/thirdparties',
src: '**',
dest: `${buildDir}/src/server/public_html/js/`
dest: `${buildDir}/server/src/public_html/js/`
},
},
browserify: {
dist: {
src: ['dist/src/client/index.js'],
dest: `${buildDir}/src/server/public_html/js/authelia.js`,
src: ['dist/client/src/index.js'],
dest: `${buildDir}/server/src/public_html/js/authelia.js`,
options: {
browserifyOptions: {
standalone: 'authelia'
@ -80,7 +95,7 @@ module.exports = function (grunt) {
},
watch: {
views: {
files: ['src/server/views/**/*.pug'],
files: ['server/src/views/**/*.pug'],
tasks: ['copy:views'],
options: {
interrupt: false,
@ -88,7 +103,7 @@ module.exports = function (grunt) {
}
},
resources: {
files: ['src/server/resources/*.ejs'],
files: ['server/src/resources/*.ejs'],
tasks: ['copy:resources'],
options: {
interrupt: false,
@ -96,7 +111,7 @@ module.exports = function (grunt) {
}
},
images: {
files: ['src/client/img/**'],
files: ['client/src/img/**'],
tasks: ['copy:images'],
options: {
interrupt: false,
@ -104,7 +119,7 @@ module.exports = function (grunt) {
}
},
css: {
files: ['src/client/**/*.css'],
files: ['client/src/**/*.css'],
tasks: ['concat:css', 'cssmin'],
options: {
interrupt: true,
@ -112,7 +127,7 @@ module.exports = function (grunt) {
}
},
client: {
files: ['src/client/**/*.ts'],
files: ['client/src/**/*.ts'],
tasks: ['build-dev'],
options: {
interrupt: true,
@ -120,7 +135,7 @@ module.exports = function (grunt) {
}
},
server: {
files: ['src/server/**/*.ts'],
files: ['server/src/**/*.ts'],
tasks: ['build-dev', 'run:docker-restart', 'run:make-dev-views' ],
options: {
interrupt: true,
@ -130,14 +145,14 @@ module.exports = function (grunt) {
},
concat: {
css: {
src: ['src/client/css/*.css'],
dest: `${buildDir}/src/server/public_html/css/authelia.css`
src: ['client/src/css/*.css'],
dest: `${buildDir}/server/src/public_html/css/authelia.css`
},
},
cssmin: {
target: {
files: {
[`${buildDir}/src/server/public_html/css/authelia.min.css`]: [`${buildDir}/src/server/public_html/css/authelia.css`]
[`${buildDir}/server/src/public_html/css/authelia.min.css`]: [`${buildDir}/server/src/public_html/css/authelia.css`]
}
}
}
@ -149,20 +164,26 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-run');
grunt.loadNpmTasks('grunt-env');
grunt.registerTask('default', ['build-dist']);
grunt.registerTask('build-resources', ['copy:resources', 'copy:views', 'copy:images', 'copy:thirdparties', 'concat:css']);
grunt.registerTask('compile-server', ['run:lint-server', 'run:compile-server'])
grunt.registerTask('compile-client', ['run:lint-client', 'run:compile-client'])
grunt.registerTask('build-common', ['run:tslint', 'run:build', 'browserify:dist', 'build-resources']);
grunt.registerTask('build-dev', ['build-common', 'run:make-dev-views']);
grunt.registerTask('build-dist', ['build-common', 'run:minify', 'cssmin']);
grunt.registerTask('test-server', ['env:env-test-server-unit', 'run:test-server-unit'])
grunt.registerTask('test-client', ['env:env-test-client-unit', 'run:test-client-unit'])
grunt.registerTask('test-unit', ['test-server', 'test-client']);
grunt.registerTask('test-int', ['run:test-int']);
grunt.registerTask('copy-resources', ['copy:resources', 'copy:views', 'copy:images', 'copy:thirdparties', 'concat:css']);
grunt.registerTask('build-client', ['compile-client', 'browserify']);
grunt.registerTask('build-server', ['compile-server', 'copy-resources']);
grunt.registerTask('build', ['build-client', 'build-server']);
grunt.registerTask('build-dist', ['build', 'run:minify', 'cssmin', 'run:include-minified-script']);
grunt.registerTask('docker-build', ['run:docker-build']);
grunt.registerTask('docker-restart', ['run:docker-restart']);
grunt.registerTask('unit-tests', ['run:unit-tests']);
grunt.registerTask('integration-tests', ['run:integration-tests']);
grunt.registerTask('test', ['unit-tests']);
grunt.registerTask('default', ['build-dist']);
};

View File

Before

Width:  |  Height:  |  Size: 814 B

After

Width:  |  Height:  |  Size: 814 B

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -9,7 +9,7 @@ import ResetPasswordRequest from "./lib/reset-password/reset-password-request";
import ResetPasswordForm from "./lib/reset-password/reset-password-form";
import jslogger = require("js-logger");
import jQuery = require("jquery");
import u2fApi = require("u2f-api");
import U2fApi = require("u2f-api");
jslogger.useDefaults();
jslogger.setLevel(jslogger.INFO);
@ -19,7 +19,7 @@ export = {
FirstFactor(window, jQuery, FirstFactorValidator, jslogger);
},
secondfactor: function () {
SecondFactor(window, jQuery, u2fApi);
SecondFactor(window, jQuery, U2fApi);
},
register_totp: function() {
TOTPRegister(window, jQuery);

View File

@ -1,7 +1,7 @@
import BluebirdPromise = require("bluebird");
import Endpoints = require("../../../server/endpoints");
import Constants = require("../../../server/constants");
import Endpoints = require("../../../../shared/api");
import Constants = require("../../../../shared/constants");
export function validate(username: string, password: string,
redirectUrl: string, onlyBasicAuth: boolean, $: JQueryStatic): BluebirdPromise<string> {

View File

@ -3,8 +3,8 @@ import JSLogger = require("js-logger");
import UISelectors = require("./UISelectors");
import { Notifier } from "../Notifier";
import { QueryParametersRetriever } from "../QueryParametersRetriever";
import Constants = require("../../../server/constants");
import Endpoints = require("../../../server/endpoints");
import Constants = require("../../../../shared/constants");
import Endpoints = require("../../../../shared/api");
export default function (window: Window, $: JQueryStatic,
firstFactorValidator: typeof FirstFactorValidator, jslogger: typeof JSLogger) {

View File

@ -1,6 +1,6 @@
import BluebirdPromise = require("bluebird");
import Endpoints = require("../../../server/endpoints");
import Endpoints = require("../../../../shared/api");
import Constants = require("./constants");
import { Notifier } from "../Notifier";

View File

@ -1,7 +1,7 @@
import BluebirdPromise = require("bluebird");
import Endpoints = require("../../../server/endpoints");
import Endpoints = require("../../../../shared/api");
import Constants = require("./constants");
import jslogger = require("js-logger");
import { Notifier } from "../Notifier";

View File

@ -1,6 +1,6 @@
import BluebirdPromise = require("bluebird");
import Endpoints = require("../../../server/endpoints");
import Endpoints = require("../../../../shared/api");
export function validate(token: string, $: JQueryStatic): BluebirdPromise<string> {
return new BluebirdPromise<string>(function (resolve, reject) {

View File

@ -2,8 +2,8 @@
import U2fApi = require("u2f-api");
import U2f = require("u2f");
import BluebirdPromise = require("bluebird");
import { SignMessage } from "../../../server/lib/routes/secondfactor/u2f/sign_request/SignMessage";
import Endpoints = require("../../../server/endpoints");
import { SignMessage } from "../../../../shared/SignMessage";
import Endpoints = require("../../../../shared/api");
import { INotifier } from "../INotifier";
function finishU2fAuthentication(responseData: U2fApi.SignResponse, $: JQueryStatic): BluebirdPromise<void> {

View File

@ -4,11 +4,11 @@ import jslogger = require("js-logger");
import TOTPValidator = require("./TOTPValidator");
import U2FValidator = require("./U2FValidator");
import Endpoints = require("../../../server/endpoints");
import Constants = require("./constants");
import { Notifier } from "../Notifier";
import { QueryParametersRetriever } from "../QueryParametersRetriever";
import ServerConstants = require("../../../server/constants");
import Endpoints = require("../../../../shared/api");
import ServerConstants = require("../../../../shared/constants");
export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi) {

View File

@ -2,9 +2,9 @@
import BluebirdPromise = require("bluebird");
import U2f = require("u2f");
import u2fApi = require("u2f-api");
import Endpoints = require("../../../server/endpoints");
import jslogger = require("js-logger");
import { Notifier } from "../Notifier";
import Endpoints = require("../../../../shared/api");
export default function (window: Window, $: JQueryStatic) {
const notifier = new Notifier(".notification", $);

View File

@ -3,7 +3,7 @@ import Assert = require("assert");
import Sinon = require("sinon");
import JQueryMock = require("./mocks/jquery");
import { Notifier } from "../../../src/client/lib/Notifier";
import { Notifier } from "../src/lib/Notifier";
describe("test notifier", function() {
const SELECTOR = "dummy-selector";

View File

@ -1,5 +1,5 @@
import FirstFactorValidator = require("../../../../src/client/lib/firstfactor/FirstFactorValidator");
import FirstFactorValidator = require("../../src/lib/firstfactor/FirstFactorValidator");
import JQueryMock = require("../mocks/jquery");
import BluebirdPromise = require("bluebird");
import Assert = require("assert");

View File

@ -1,6 +1,6 @@
import Sinon = require("sinon");
import { INotifier } from "../../../../src/client/lib/INotifier";
import { INotifier } from "../../src/lib/INotifier";
export class NotifierStub implements INotifier {
successStub: Sinon.SinonStub;

View File

@ -1,5 +1,5 @@
import TOTPValidator = require("../../../../src/client/lib/secondfactor/TOTPValidator");
import TOTPValidator = require("../../src/lib/secondfactor/TOTPValidator");
import JQueryMock = require("../mocks/jquery");
import BluebirdPromise = require("bluebird");
import Assert = require("assert");

View File

@ -1,9 +1,9 @@
import U2FValidator = require("../../../../src/client/lib/secondfactor/U2FValidator");
import { INotifier } from "../../../../src/client/lib/INotifier";
import U2FValidator = require("../../src/lib/secondfactor/U2FValidator");
import { INotifier } from "../../src/lib/INotifier";
import JQueryMock = require("../mocks/jquery");
import U2FApiMock = require("../mocks/u2f-api");
import { SignMessage } from "../../../../src/server/lib/routes/secondfactor/u2f/sign_request/SignMessage";
import { SignMessage } from "../../../shared/SignMessage";
import BluebirdPromise = require("bluebird");
import Assert = require("assert");
import { NotifierStub } from "../mocks/NotifierStub";

View File

@ -2,8 +2,8 @@
import sinon = require("sinon");
import assert = require("assert");
import UISelector = require("../../../../src/client/lib/totp-register/ui-selector");
import TOTPRegister = require("../../../../src/client/lib/totp-register/totp-register");
import UISelector = require("../../src/lib/totp-register/ui-selector");
import TOTPRegister = require("../../src/lib/totp-register/totp-register");
describe("test totp-register", function() {
let jqueryMock: any;

View File

@ -6,17 +6,19 @@
"noImplicitAny": true,
"sourceMap": true,
"removeComments": true,
"outDir": "dist",
"outDir": "../dist",
"baseUrl": ".",
"paths": {
"*": [
"./src/types/*",
"./node_modules/@types/*"
"./types/*",
"../shared/types/*"
]
}
},
"includes": [
"src/**/*",
"include": [
"src/**/*"
],
"exclude": [
"test/**/*"
]
}

View File

@ -3,7 +3,8 @@ services:
authelia:
volumes:
- ./test:/usr/src/test
- ./dist/src/server:/usr/src
- ./dist/server:/usr/src/server
- ./dist/shared:/usr/src/shared
- ./node_modules:/usr/src/node_modules
- ./config.template.yml:/etc/authelia/config.yml:ro
networks:

View File

@ -3,7 +3,7 @@
"version": "3.4.0",
"description": "2FA Single Sign-On server for nginx using LDAP, TOTP and U2F",
"bin": {
"authelia": "./dist/src/server/index.js"
"authelia": "./dist/server/src/index.js"
},
"scripts": {
"test": "./node_modules/.bin/grunt unit-tests",
@ -83,6 +83,7 @@
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-cssmin": "^2.2.0",
"grunt-contrib-watch": "^1.0.0",
"grunt-env": "^0.4.4",
"grunt-run": "^0.6.0",
"istanbul": "^0.4.5",
"jquery": "^3.2.1",

View File

@ -3,6 +3,10 @@
DC_SCRIPT=./scripts/example-commit/dc-example.sh
EXPECTED_SERVICES_COUNT=6
build_services() {
$DC_SCRIPT build authelia
}
start_services() {
$DC_SCRIPT up -d mongo redis openldap authelia nginx smtp
sleep 3
@ -32,7 +36,7 @@ run_integration_tests() {
expect_services_count $EXPECTED_SERVICES_COUNT
sleep 5
./node_modules/.bin/grunt run:integration-tests
./node_modules/.bin/grunt run:test-int
shut_services
}
@ -59,6 +63,9 @@ set -e
echo "Make sure services are not already running"
shut_services
# Build the container
build_services
# Prepare & test example from end user perspective
run_integration_tests

View File

@ -6,7 +6,7 @@ docker --version
docker-compose --version
# Run unit tests
grunt test
grunt test-unit
# Build the app from Typescript and package
grunt build-dist

View File

@ -31,7 +31,7 @@ import Error403Get = require("./routes/error/403/get");
import Error404Get = require("./routes/error/404/get");
import { ServerVariablesHandler } from "./ServerVariablesHandler";
import Endpoints = require("../endpoints");
import Endpoints = require("../../../shared/api");
function withLog(fn: (req: Express.Request, res: Express.Response) => void) {
return function(req: Express.Request, res: Express.Response) {

View File

@ -14,6 +14,16 @@ interface SearchEntry {
object: any;
}
declare module "ldapjs" {
export interface ClientAsync {
on(event: string, callback: (data?: any) => void): void;
bindAsync(username: string, password: string): BluebirdPromise<void>;
unbindAsync(): BluebirdPromise<void>;
searchAsync(base: string, query: Ldapjs.SearchOptions): BluebirdPromise<EventEmitter>;
modifyAsync(userdn: string, change: Ldapjs.Change): BluebirdPromise<void>;
}
}
export class Client implements IClient {
private userDN: string;
private password: string;

View File

@ -2,7 +2,7 @@
import express = require("express");
import objectPath = require("object-path");
import winston = require("winston");
import Endpoints = require("../../../endpoints");
import Endpoints = require("../../../../../shared/api");
import AuthenticationValidator = require("../../AuthenticationValidator");
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
import BluebirdPromise = require("bluebird");

View File

@ -6,11 +6,11 @@ import express = require("express");
import { AccessController } from "../../access_control/AccessController";
import { AuthenticationRegulator } from "../../AuthenticationRegulator";
import { GroupsAndEmails } from "../../ldap/IClient";
import Endpoint = require("../../../endpoints");
import Endpoint = require("../../../../../shared/api");
import ErrorReplies = require("../../ErrorReplies");
import { ServerVariablesHandler } from "../../ServerVariablesHandler";
import AuthenticationSession = require("../../AuthenticationSession");
import Constants = require("../../../constants");
import Constants = require("../../../../../shared/constants");
export default function (req: express.Request, res: express.Response): BluebirdPromise<void> {
const username: string = req.body.username;

Some files were not shown because too many files have changed in this diff Show More