Backend and frontend are reloaded on code change.

This commit is contained in:
Clement Michaud 2019-01-11 22:11:54 +01:00
parent be357f8e69
commit fe14bde29b
17 changed files with 2003 additions and 96 deletions

View File

@ -1,20 +1,18 @@
FROM node:8.7.0-alpine FROM node:8.7.0-alpine
WORKDIR /usr/src WORKDIR /usr/app
COPY package.json /usr/src/package.json ADD package.json package.json
RUN apk --update add --no-cache --virtual \ RUN apk --update add --no-cache --virtual \
.build-deps make g++ python && \ .build-deps make g++ python && \
npm install && \ npm install && \
apk del .build-deps apk del .build-deps
COPY dist/server /usr/src/server
COPY dist/shared /usr/src/shared
EXPOSE 8080 EXPOSE 8080
VOLUME /usr/app/src
VOLUME /etc/authelia VOLUME /etc/authelia
VOLUME /var/lib/authelia VOLUME /var/lib/authelia
CMD ["node", "server/src/index.js", "/etc/authelia/config.yml"] CMD ["npm", "run-script", "start"]

9
client-react/Dockerfile Normal file
View File

@ -0,0 +1,9 @@
FROM node:10.15.0-jessie
WORKDIR /usr/app
ADD package.json package.json
RUN npm i
CMD ["npm", "start"]

View File

@ -0,0 +1,14 @@
version: '2'
services:
authelia-frontend-dev:
build:
context: client-react
restart: always
volumes:
- ./client-react/tsconfig.json:/usr/app/tsconfig.json
- ./client-react/public:/usr/app/public
- ./client-react/src:/usr/app/src
networks:
example-network:
aliases:
- authelia-frontend

View File

@ -2,6 +2,7 @@ import { createStyles, Theme } from "@material-ui/core";
const styles = createStyles((theme: Theme) => ({ const styles = createStyles((theme: Theme) => ({
fields: { fields: {
marginTop: theme.spacing.unit * 3,
marginBottom: theme.spacing.unit, marginBottom: theme.spacing.unit,
}, },
field: { field: {

View File

@ -22,7 +22,6 @@
font-size: 1.4em; font-size: 1.4em;
font-weight: bold; font-weight: bold;
border-bottom: 1px solid #c7c7c7; border-bottom: 1px solid #c7c7c7;
margin-bottom: 20px;
display: inline-block; display: inline-block;
padding-right: 10px; padding-right: 10px;
padding-bottom: 5px; padding-bottom: 5px;

View File

@ -1,4 +1,4 @@
import React, { Component, KeyboardEvent } from "react"; import React, { Component, KeyboardEvent, ChangeEvent } from "react";
import TextField from '@material-ui/core/TextField'; import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
@ -16,13 +16,19 @@ interface Props extends RouterProps, WithStyles {}
interface State { interface State {
rememberMe: boolean; rememberMe: boolean;
username: string;
password: string;
loginButtonDisabled: boolean;
} }
class FirstFactorView extends Component<Props, State> { class FirstFactorView extends Component<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props) super(props)
this.state = { this.state = {
rememberMe: false rememberMe: false,
username: '',
password: '',
loginButtonDisabled: false,
} }
} }
@ -32,6 +38,14 @@ class FirstFactorView extends Component<Props, State> {
}) })
} }
onUsernameChanged = (e: ChangeEvent<HTMLInputElement>) => {
this.setState({username: e.target.value});
}
onPasswordChanged = (e: ChangeEvent<HTMLInputElement>) => {
this.setState({password: e.target.value});
}
onLoginClicked = () => { onLoginClicked = () => {
this.authenticate(); this.authenticate();
} }
@ -52,7 +66,8 @@ class FirstFactorView extends Component<Props, State> {
className={classes.input} className={classes.input}
variant="outlined" variant="outlined"
id="username" id="username"
label="Username"> label="Username"
onChange={this.onUsernameChanged}>
</TextField> </TextField>
</div> </div>
<div className={classes.field}> <div className={classes.field}>
@ -62,6 +77,7 @@ class FirstFactorView extends Component<Props, State> {
variant="outlined" variant="outlined"
label="Password" label="Password"
type="password" type="password"
onChange={this.onPasswordChanged}
onKeyPress={this.onPasswordKeyPressed}> onKeyPress={this.onPasswordKeyPressed}>
</TextField> </TextField>
</div> </div>
@ -71,7 +87,8 @@ class FirstFactorView extends Component<Props, State> {
<Button <Button
onClick={this.onLoginClicked} onClick={this.onLoginClicked}
variant="contained" variant="contained"
color="primary"> color="primary"
disabled={this.state.loginButtonDisabled}>
Login Login
</Button> </Button>
</div> </div>
@ -98,7 +115,26 @@ class FirstFactorView extends Component<Props, State> {
} }
private authenticate() { private authenticate() {
this.props.history.push('/2fa'); this.setState({loginButtonDisabled: true})
fetch('/api/firstfactor', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
})
}).then(async (res) => {
const json = await res.json();
if ('error' in json) {
console.log('ERROR!');
this.setState({loginButtonDisabled: false});
return;
}
this.props.history.push('/2fa');
});
} }
} }

View File

@ -13,7 +13,7 @@ session:
# Configuration of the storage backend used to store data and secrets. i.e. totp data # Configuration of the storage backend used to store data and secrets. i.e. totp data
storage: storage:
local: local:
path: /etc/authelia/storage path: /var/lib/authelia
# TOTP Issuer Name # TOTP Issuer Name
# #

View File

@ -10,7 +10,7 @@ port: 8080
# Level of verbosity for logs # Level of verbosity for logs
logs_level: debug logs_level: debug
# Default redirection URL # Default redirection URL
# #
# If user tries to authenticate without any referer, Authelia # If user tries to authenticate without any referer, Authelia
# does not know where to redirect the user to at the end of the # does not know where to redirect the user to at the end of the
@ -75,15 +75,15 @@ authentication_backend:
user: cn=admin,dc=example,dc=com user: cn=admin,dc=example,dc=com
password: password password: password
# File backend configuration. # File backend configuration.
# #
# With this backend, the users database is stored in a file # With this backend, the users database is stored in a file
# which is updated when users reset their passwords. # which is updated when users reset their passwords.
# Therefore, this backend is meant to be used in a dev environment # Therefore, this backend is meant to be used in a dev environment
# and not in production since it prevents Authelia to be scaled to # and not in production since it prevents Authelia to be scaled to
# more than one instance. # more than one instance.
# #
## file: ## file:
## path: ./users_database.yml ## path: ./users_database.yml
@ -93,13 +93,13 @@ authentication_backend:
# resource to users or group of users. # resource to users or group of users.
# #
# If 'access_control' is not defined, ACL rules are disabled and the `bypass` # If 'access_control' is not defined, ACL rules are disabled and the `bypass`
# rule is applied, i.e., access is allowed to anyone. Otherwise restrictions follow # rule is applied, i.e., access is allowed to anyone. Otherwise restrictions follow
# the rules defined. # the rules defined.
# #
# Note: One can use the wildcard * to match any subdomain. # Note: One can use the wildcard * to match any subdomain.
# It must stand at the beginning of the pattern. (example: *.mydomain.com) # It must stand at the beginning of the pattern. (example: *.mydomain.com)
# #
# Note: You must put patterns containing wildcards between simple quotes for the YAML # Note: You must put patterns containing wildcards between simple quotes for the YAML
# to be syntaxically correct. # to be syntaxically correct.
# #
# Definition: A `rule` is an object with the following keys: `domain`, `subject`, # Definition: A `rule` is an object with the following keys: `domain`, `subject`,
@ -116,7 +116,7 @@ authentication_backend:
# `one_factor`, `two_factor` or `deny`. # `one_factor`, `two_factor` or `deny`.
# #
# - `resources` is a list of regular expressions that matches a set of resources to # - `resources` is a list of regular expressions that matches a set of resources to
#  apply the policy to. This parameter is optional and matches any resource if not # apply the policy to. This parameter is optional and matches any resource if not
# provided. # provided.
# #
# Note: the order of the rules is important. The first policy matching # Note: the order of the rules is important. The first policy matching
@ -196,7 +196,7 @@ session:
# is restricted to the subdomain of the issuer. # is restricted to the subdomain of the issuer.
domain: example.com domain: example.com
# The redis connection details # The redis connection details
redis: redis:
host: redis host: redis
port: 6379 port: 6379
@ -212,7 +212,7 @@ regulation:
# Set it to 0 to disable regulation. # Set it to 0 to disable regulation.
max_retries: 3 max_retries: 3
# The time range during which the user can attempt login before being banned. # The time range during which the user can attempt login before being banned.
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window. # The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
find_time: 120 find_time: 120
@ -224,7 +224,7 @@ regulation:
# You must use only an available configuration: local, mongo # You must use only an available configuration: local, mongo
storage: storage:
# The directory where the DB files will be saved # The directory where the DB files will be saved
## local: ## local:
## path: /var/lib/authelia/store ## path: /var/lib/authelia/store
# Settings to connect to mongo server # Settings to connect to mongo server

View File

@ -6,11 +6,10 @@ services:
dockerfile: Dockerfile.dev dockerfile: Dockerfile.dev
restart: always restart: always
volumes: volumes:
- ./server:/usr/src/server - ./scripts:/usr/app/scripts
- ./dist/server/src/public_html:/usr/src/server/src/public_html - ./server:/usr/app/server
- ./client:/usr/src/client - ./shared:/usr/app/shared
- ./shared:/usr/src/shared - ./config.template.yml:/usr/app/config.yml:ro
- ./config.template.yml:/etc/authelia/config.yml:ro
environment: environment:
- NODE_TLS_REJECT_UNAUTHORIZED=0 - NODE_TLS_REJECT_UNAUTHORIZED=0
depends_on: depends_on:
@ -19,9 +18,3 @@ services:
example-network: example-network:
aliases: aliases:
- authelia - authelia
command:
- "./node_modules/.bin/ts-node"
- "-P"
- "server/tsconfig.json"
- "server/src/index.ts"
- "/etc/authelia/config.yml"

View File

@ -6,11 +6,10 @@ services:
dockerfile: Dockerfile.dev dockerfile: Dockerfile.dev
restart: always restart: always
volumes: volumes:
- ./server:/usr/src/server - ./package.json:/usr/app/package.json
- ./dist/server/src/public_html:/usr/src/server/src/public_html - ./server:/usr/app/server
- ./client:/usr/src/client - ./shared:/usr/app/shared
- ./shared:/usr/src/shared - ./config.template.yml:/usr/app/config.yml:ro
- ./config.minimal.yml:/etc/authelia/config.yml:ro
- /tmp/authelia:/tmp/authelia - /tmp/authelia:/tmp/authelia
- ./users_database.yml:/etc/authelia/users_database.yml - ./users_database.yml:/etc/authelia/users_database.yml
environment: environment:
@ -19,9 +18,3 @@ services:
- redis - redis
networks: networks:
- example-network - example-network
command:
- "./node_modules/.bin/ts-node"
- "-P"
- "server/tsconfig.json"
- "server/src/index.ts"
- "/etc/authelia/config.yml"

View File

@ -12,7 +12,6 @@ http {
resolver 127.0.0.11 ipv6=off; resolver 127.0.0.11 ipv6=off;
set $upstream_endpoint http://authelia:8080; set $upstream_endpoint http://authelia:8080;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
@ -45,7 +44,6 @@ http {
root /usr/share/nginx/html/home; root /usr/share/nginx/html/home;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
@ -62,7 +60,6 @@ http {
resolver 127.0.0.11 ipv6=off; resolver 127.0.0.11 ipv6=off;
set $upstream_verify http://authelia:8080/api/verify; set $upstream_verify http://authelia:8080/api/verify;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;

View File

@ -10,23 +10,49 @@ http {
server_name login.example.com; server_name login.example.com;
resolver 127.0.0.11 ipv6=off; resolver 127.0.0.11 ipv6=off;
set $upstream_endpoint http://authelia:8080; set $frontend_endpoint http://authelia-frontend:3000;
set $backend_endpoint http://authelia:8080;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN"; add_header X-Frame-Options "SAMEORIGIN";
# Serves the portal application.
location / { location / {
# Allow websockets for webpack to auto-reload.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass $frontend_endpoint;
}
# Serves the portal application.
location /sockjs-node {
# Allow websockets for webpack to auto-reload.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass $frontend_endpoint;
}
# Serves the portal application.
location /static {
proxy_pass $frontend_endpoint;
}
# Serve the backend API for the portal.
location /api {
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_intercept_errors on; proxy_intercept_errors on;
proxy_pass $upstream_endpoint; proxy_pass $backend_endpoint;
if ($request_method !~ ^(POST)$){ if ($request_method !~ ^(POST)$){
error_page 401 = /error/401; error_page 401 = /error/401;
@ -43,7 +69,6 @@ http {
resolver 127.0.0.11 ipv6=off; resolver 127.0.0.11 ipv6=off;
set $upstream_endpoint http://nginx-backend; set $upstream_endpoint http://nginx-backend;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
@ -65,7 +90,6 @@ http {
set $upstream_endpoint http://nginx-backend; set $upstream_endpoint http://nginx-backend;
set $upstream_headers http://httpbin:8000/headers; set $upstream_headers http://httpbin:8000/headers;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
@ -133,7 +157,6 @@ http {
set $upstream_verify http://authelia:8080/api/verify; set $upstream_verify http://authelia:8080/api/verify;
set $upstream_endpoint http://nginx-backend; set $upstream_endpoint http://nginx-backend;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
@ -184,7 +207,6 @@ http {
set $upstream_verify http://authelia:8080/api/verify; set $upstream_verify http://authelia:8080/api/verify;
set $upstream_endpoint http://nginx-backend; set $upstream_endpoint http://nginx-backend;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
@ -235,7 +257,6 @@ http {
set $upstream_verify http://authelia:8080/api/verify; set $upstream_verify http://authelia:8080/api/verify;
set $upstream_endpoint http://nginx-backend; set $upstream_endpoint http://nginx-backend;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
@ -287,7 +308,6 @@ http {
set $upstream_endpoint http://nginx-backend; set $upstream_endpoint http://nginx-backend;
set $upstream_headers http://httpbin:8000/headers; set $upstream_headers http://httpbin:8000/headers;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;
@ -357,7 +377,6 @@ http {
resolver 127.0.0.11 ipv6=off; resolver 127.0.0.11 ipv6=off;
set $upstream_endpoint http://authelia:8080; set $upstream_endpoint http://authelia:8080;
ssl on;
ssl_certificate /etc/ssl/server.crt; ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key; ssl_certificate_key /etc/ssl/server.key;

1906
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@
"authelia": "./dist/server/src/index.js" "authelia": "./dist/server/src/index.js"
}, },
"scripts": { "scripts": {
"start": "./node_modules/.bin/nodemon -e js,ts,json --exec ./scripts/run-dev-server.sh",
"test": "./node_modules/.bin/grunt test-unit", "test": "./node_modules/.bin/grunt test-unit",
"cover": "NODE_ENV=test nyc npm t", "cover": "NODE_ENV=test nyc npm t",
"serve": "node dist/server/index.js" "serve": "node dist/server/index.js"
@ -23,6 +24,7 @@
"title": "Authelia API documentation" "title": "Authelia API documentation"
}, },
"dependencies": { "dependencies": {
"@types/react-redux": "^6.0.12",
"ajv": "^6.3.0", "ajv": "^6.3.0",
"bluebird": "^3.5.0", "bluebird": "^3.5.0",
"body-parser": "^1.15.2", "body-parser": "^1.15.2",
@ -43,6 +45,7 @@
"pug": "^2.0.0-rc.2", "pug": "^2.0.0-rc.2",
"randomatic": "^3.1.0", "randomatic": "^3.1.0",
"randomstring": "^1.1.5", "randomstring": "^1.1.5",
"react-redux": "^6.0.0",
"redis": "^2.8.0", "redis": "^2.8.0",
"speakeasy": "^2.0.0", "speakeasy": "^2.0.0",
"u2f": "^0.1.2", "u2f": "^0.1.2",
@ -104,6 +107,7 @@
"jsdom": "^11.0.0", "jsdom": "^11.0.0",
"mocha": "^5.0.5", "mocha": "^5.0.5",
"mockdate": "^2.0.1", "mockdate": "^2.0.1",
"nodemon": "^1.18.9",
"nyc": "^13.1.0", "nyc": "^13.1.0",
"power-assert": "^1.4.4", "power-assert": "^1.4.4",
"proxyquire": "^2.0.1", "proxyquire": "^2.0.1",

View File

@ -4,6 +4,7 @@ set -e
docker-compose \ docker-compose \
-f docker-compose.dev.yml \ -f docker-compose.dev.yml \
-f client-react/docker-compose.yml \
-f example/compose/docker-compose.base.yml \ -f example/compose/docker-compose.base.yml \
-f example/compose/mongo/docker-compose.yml \ -f example/compose/mongo/docker-compose.yml \
-f example/compose/redis/docker-compose.yml \ -f example/compose/redis/docker-compose.yml \

3
scripts/run-dev-server.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
./node_modules/.bin/ts-node -P ./server/tsconfig.json ./server/src/index.ts ./config.yml

View File

@ -2,8 +2,6 @@
import BluebirdPromise = require("bluebird"); import BluebirdPromise = require("bluebird");
import request = require("request"); import request = require("request");
import assert = require("assert"); import assert = require("assert");
import express = require("express");
import nodemailer = require("nodemailer");
import Endpoints = require("../../shared/api"); import Endpoints = require("../../shared/api");
declare module "request" { declare module "request" {