Gitlab Community Edition Instance

Commit a52c70d0 authored by Gregor Thiem's avatar Gregor Thiem
Browse files

update to 1.9.3

- new public repo url
- fix gitlab urls
parent 75d84e9a
......@@ -17,9 +17,9 @@ jobs:
- shellcheck bin/heroku bin/setup
- sudo apt install -y jq && yarn run jsonlint
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js 16
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: 16
cache: yarn
......@@ -32,9 +32,9 @@ jobs:
matrix:
node-version: [12, 14, 16]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: yarn
......@@ -47,15 +47,15 @@ jobs:
matrix:
node-version: [12, 14, 16]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: yarn
- run: yarn --frozen-lockfile --prefer-offline
- run: yarn run build
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
if: github.ref == 'refs/heads/master' && matrix.node-version == '16'
with:
name: Prebuild with Node.js ${{ matrix.node-version }}
......
......@@ -21,10 +21,15 @@ mcnesium <git@mcnesium.com> mcnesium <mcnesium@users.noreply.gi
Sandro Jäckel <sandro.jaeckel@gmail.com> Sandro <sandro.jaeckel@gmail.com>
Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de> mrdrogdrog <tilman.vatteroth@tu-dortmund.de>
Tilman Vatteroth <git@tilmanvatteroth.de> mrdrogdrog <tilman.vatteroth@tu-dortmund.de>
Tilman Vatteroth <git@tilmanvatteroth.de> Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
Erik Michelson <github@erik.michelson.eu> Erik Michelson <erik@liltv.de>
Jonas Zohren <jonas.zohren@tu-dortmund.de> Jonas Zohren <15788906+jfowl@users.noreply.github.com>
Philip Molares <philip.molares@udo.edu> Philip Molares <git@molar.es>
Yannick Bungers <git@innay.de> Yannick Bungers <github@innay.de>
Renovate Bot <bot@renovateapp.com> renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
......@@ -9,6 +9,7 @@ Alexander Hesse <alexander.hesse@sandstorm-media.de>
Alexander Wellbrock <a.wellbrock@mailbox.org>
Amolith <amolith@nixnet.xyz>
Antoine Aflalo <antoine@warrantymaster.com>
aptalca <aptalca@users.noreply.github.com>
Augustin Trancart <augustin.trancart@oslandia.com>
bananaappletw <bananaappletw@gmail.com>
Bartlomiej Szala <fenix440@gmail.com>
......@@ -18,6 +19,7 @@ butlerx <butlerx@notthe.cloud>
Carles Bruguera <carlesba@gmail.com>
chandi <git@chandi.it>
chbmb <chbmb@linuxserver.io>
Chongyun Lee <uchkks@protonmail.com>
Christian Bläul <blaeul@quodata.de>
Christian Bläul <christian@blaeul.de>
Christian Schuhmann <madebyherzblut@users.noreply.github.com>
......@@ -30,9 +32,11 @@ CrazyPython <CrazyPython@users.noreply.github.com>
Cédric Couralet <cedric.couralet@gmail.com>
Daan Sprenkels <hello@dsprenkels.com>
Daniel Lublin <daniel@lublin.se>
Danilo Bargen <mail@dbrgn.ch>
Dario Ernst <daddel9@nebuk.de>
David Mehren <git@herrmehren.de>
David Sawatzke <d-git@sawatzke.dev>
Dennis Gaida <2392217+DennisGaida@users.noreply.github.com>
Devon Jue <djue129@gmail.com>
Dexter Chua <dalcde@yahoo.com.hk>
Dmytro Kytsmen <dmitrokytsmen@gmail.com>
......@@ -98,6 +102,7 @@ MartB <mart.b@outlook.de>
Martijnpold <martijntje7@gmail.com>
Martin Turoci <martinturoci@gmail.com>
Marvin Gaube <dev@marvingaube.de>
Matej Cotman <matej.cotman@eficode.com>
Mathias Merscher <Mathias.Merscher@dg-i.net>
Matteo Savatteri <matteosavatteri@lcm.mi.infn.it>
Matthias Lindinger <m.lindinger@live.de>
......@@ -107,9 +112,11 @@ Maxence Ahlouche <maxence.ahlouche@gmail.com>
mcnesium <git@mcnesium.com>
Mike <mike@sloppy.io>
Miranda Kastemaa <miranda@foldplop.com>
Moritz Schlarb <schlarbm@uni-mainz.de>
naimo <naimo@users.noreply.github.com>
neopostmodern <clemens@neopostmodern.com>
Nick Hahn <nick.hahn@posteo.de>
Nicolas Dietrich <nidi@mailbox.org>
Nils VAN ZUIJLEN <nils.van-zuijlen@mailo.com>
Norihito Nakae <norihito.n@gmail.com>
NV <nvsofts@gmail.com>
......@@ -128,6 +135,7 @@ PetrTodorov <info@petrtodorov.cz>
Philip Molares <philip.molares@udo.edu>
Philipp Zumstein <zuphilip@users.noreply.github.com>
pierreozoux <pierre@ozoux.net>
ProttoyChakraborty <pchakraborty2002@gmail.com>
Raccoon <raccoon@hackmd.io>
Ralph Krimmel <rkrimme1@gwdg.de>
Renan Rodrigues <renan.rodrigues@emnify.com>
......@@ -142,6 +150,7 @@ Sandro Jäckel <sandro.jaeckel@gmail.com>
schneems <richard.schneeman@gmail.com>
Sergio Valverde <svg153@users.noreply.github.com>
Simeon Keske <git@n0emis.eu>
Simon C <simonc@linux.com>
Simon Fish <si@mon.fish>
Simon Joda Stößer <SimJoSt@users.noreply.github.com>
snyk-bot <snyk-bot@snyk.io>
......@@ -155,7 +164,7 @@ Takeaki Matsumoto <takeaki.matsumoto@ntt.com>
The Gitter Badger <badger@gitter.im>
Thomas De Backer <thomasisdebacker5@gmail.com>
Thor77 <thor77@thor77.org>
Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
Tilman Vatteroth <git@tilmanvatteroth.de>
tkqubo <tk.qubo@gmail.com>
tkykm <tkykm@users.noreply.github.com>
Tobias Kremer <tobias.kremer@gmail.com>
......
......@@ -63,8 +63,14 @@ if (!config.useSSL && config.protocolUseSSL) {
app.set('trust proxy', 1)
}
// check if the request is from container healthcheck
function isContainerHealthCheck (req, _) {
return req.headers['user-agent'] === 'hedgedoc-container-healthcheck/1.0' && req.ip === '127.0.0.1'
}
// logger
app.use(morgan('combined', {
skip: isContainerHealthCheck,
stream: logger.stream
}))
......@@ -206,6 +212,7 @@ app.locals.authProviders = {
ldap: config.isLDAPEnable,
ldapProviderName: config.ldap.providerName,
saml: config.isSAMLEnable,
samlProviderName: config.saml.providerName,
oauth2: config.isOAuth2Enable,
oauth2ProviderName: config.oauth2.providerName,
openID: config.isOpenIDEnable,
......@@ -285,9 +292,9 @@ function syncAndListen () {
process.exit(1)
}
})
}).catch(() => {
}).catch((dbError) => {
if (currentDBTry < maxDBTries) {
logger.warn(`Database cannot be reached. Try ${currentDBTry} of ${maxDBTries}.`)
logger.warn(`Database cannot be reached. Try ${currentDBTry} of ${maxDBTries}. (${dbError})`)
currentDBTry++
setTimeout(function () {
syncAndListen()
......
#!/usr/bin/env node
// First configure the logger so it does not spam the console
const logger = require("../lib/logger");
logger.transports.forEach((transport) => transport.level = "warning")
// First configure the logger, so it does not spam the console
const logger = require('../lib/logger')
logger.transports.forEach((transport) => transport.level = 'warning')
const models = require("../lib/models/");
const readline = require("readline-sync");
const minimist = require("minimist");
const models = require('../lib/models/')
const readline = require('readline-sync')
const minimist = require('minimist')
function showUsage(tips) {
console.log(`${tips}
function showUsage (tips) {
console.log(`${tips}
Command-line utility to create users for email-signin.
......@@ -19,101 +19,102 @@ Usage: bin/manage_users [--pass password] (--add | --del) user-email
--del Delete user with specified user-email
--reset Reset user password with specified user-email
--pass Use password from cmdline rather than prompting
`);
process.exit(1);
`)
process.exit(1)
}
function getPass(argv, action) {
// Find whether we use cmdline or prompt password
if(typeof argv["pass"] !== 'string') {
return readline.question(`Password for ${argv[action]}:`, {hideEchoBack: true});
}
console.log("Using password from commandline...");
return argv["pass"];
function getPass (argv, action) {
// Find whether we use cmdline or prompt password
if (typeof argv['pass'] !== 'string') {
return readline.question(`Password for ${argv[action]}:`, { hideEchoBack: true })
}
console.log('Using password from commandline...')
return argv['pass']
}
// Using an async function to be able to use await inside
async function createUser(argv) {
const existing_user = await models.User.findOne({where: {email: argv["add"]}});
// Cannot create already-existing users
if(existing_user) {
console.log(`User with e-mail ${existing_user.email} already exists! Aborting ...`);
process.exit(2);
}
const pass = getPass(argv, "add");
// Lets try to create, and check success
const ref = await models.User.create({email: argv["add"], password: pass});
if(ref == undefined) {
console.log(`Could not create user with email ${argv["add"]}`);
process.exit(1);
} else
console.log(`Created user with email ${argv["add"]}`);
async function createUser (argv) {
const existing_user = await models.User.findOne({ where: { email: argv['add'] } })
// Cannot create already-existing users
if (existing_user) {
console.log(`User with e-mail ${existing_user.email} already exists! Aborting ...`)
process.exit(2)
}
const pass = getPass(argv, 'add')
if (pass.length === 0) {
console.log('Password cannot be empty!')
process.exit(1)
}
// Lets try to create, and check success
const ref = await models.User.create({ email: argv['add'], password: pass })
if (ref === undefined) {
console.log(`Could not create user with email ${argv['add']}`)
process.exit(1)
} else {
console.log(`Created user with email ${argv['add']}`)
}
}
// Using an async function to be able to use await inside
async function deleteUser(argv) {
// Cannot delete non-existing users
const existing_user = await models.User.findOne({where: {email: argv["del"]}});
if(!existing_user) {
console.log(`User with e-mail ${argv["del"]} does not exist, cannot delete`);
process.exit(1);
}
// Sadly .destroy() does not return any success value with all
// backends. See sequelize #4124
await existing_user.destroy();
console.log(`Deleted user ${argv["del"]} ...`);
async function deleteUser (argv) {
// Cannot delete non-existing users
const existing_user = await models.User.findOne({ where: { email: argv['del'] } })
if (!existing_user) {
console.log(`User with e-mail ${argv['del']} does not exist, cannot delete`)
process.exit(1)
}
// Sadly .destroy() does not return any success value with all
// backends. See sequelize #4124
await existing_user.destroy()
console.log(`Deleted user ${argv['del']} ...`)
}
// Using an async function to be able to use await inside
async function resetUser(argv) {
const existing_user = await models.User.findOne({where: {email: argv["reset"]}});
// Cannot reset non-existing users
if(!existing_user) {
console.log(`User with e-mail ${argv["reset"]} does not exist, cannot reset`);
process.exit(1);
}
const pass = getPass(argv, "reset");
// set password and save
existing_user.password = pass;
await existing_user.save();
console.log(`User with email ${argv["reset"]} password has been reset`);
async function resetUser (argv) {
const existing_user = await models.User.findOne({ where: { email: argv['reset'] } })
// Cannot reset non-existing users
if (!existing_user) {
console.log(`User with e-mail ${argv['reset']} does not exist, cannot reset`)
process.exit(1)
}
// set password and save
existing_user.password = getPass(argv, 'reset')
await existing_user.save()
console.log(`User with email ${argv['reset']} password has been reset`)
}
const options = {
add: createUser,
del: deleteUser,
reset: resetUser,
};
add: createUser,
del: deleteUser,
reset: resetUser,
}
// Perform commandline-parsing
const argv = minimist(process.argv.slice(2));
// Perform commandline-parsing and always treat 'pass' argument as string
const argv = minimist(process.argv.slice(2), { string: ['pass'] })
const keys = Object.keys(options);
const opts = keys.filter((key) => argv[key] !== undefined);
const action = opts[0];
const keys = Object.keys(options)
const opts = keys.filter((key) => argv[key] !== undefined)
const action = opts[0]
// Check for options missing
if (opts.length === 0) {
showUsage(`You did not specify either ${keys.map((key) => `--${key}`).join(' or ')}!`);
showUsage(`You did not specify either ${keys.map((key) => `--${key}`).join(' or ')}!`)
}
// Check if both are specified
if (opts.length > 1) {
showUsage(`You cannot ${action.join(' and ')} at the same time!`);
showUsage(`You cannot ${action.join(' and ')} at the same time!`)
}
// Check if not string
if (typeof argv[action] !== 'string') {
showUsage(`You must follow an email after --${action}`);
showUsage(`You must follow an email after --${action}`)
}
// Call respective processing functions
options[action](argv).then(function() {
options[action](argv).then(function () {
process.exit(0);
});
......@@ -103,16 +103,16 @@ these are rarely used for various reasons.
## Users and Privileges
| config file | environment | **default** and example value | description |
| --------------------- | --------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allowAnonymous` | `CMD_ALLOW_ANONYMOUS` | **`true`** or `false` | Set to allow anonymous usage (default is `true`). |
| `allowAnonymousEdits` | `CMD_ALLOW_ANONYMOUS_EDITS` | **`false`** or `true` | If `allowAnonymous` is `false`: allow users to select `freely` permission, allowing guests to edit existing notes (default is `false`). |
| `allowFreeURL` | `CMD_ALLOW_FREEURL` | **`false`** or `true` | Set to allow new note creation by accessing a nonexistent note URL. This is the behavior familiar from [Etherpad](https://github.com/ether/etherpad-lite). |
| `requireFreeURLAuthentication` | `CMD_REQUIRE_FREEURL_AUTHENTICATION` | **`false`** or `true` | Set to require authentication for FreeURL mode style note creation. |
| `defaultPermission` | `CMD_DEFAULT_PERMISSION` | **`editable`**, `freely`, `limited`, `locked`, `protected` or `private` | Set notes default permission (only applied on signed-in users). |
| `sessionName` | | **`connect.sid`** | Cookie session name. |
| `sessionLife` | `CMD_SESSION_LIFE` | **`14 * 24 * 60 * 60 * 1000`**, `1209600000` (14 days) | Cookie session life time in milliseconds. |
| `sessionSecret` | `CMD_SESSION_SECRET` | **`secret`** | Cookie session secret used to sign the session cookie. If none is set, one will randomly generated on each startup, meaning all your users will be logged out. |
| config file | environment | **default** and example value | description |
|--------------------------------|--------------------------------------|-------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `allowAnonymous` | `CMD_ALLOW_ANONYMOUS` | **`true`** or `false` | Set to allow anonymous usage (default is `true`). |
| `allowAnonymousEdits` | `CMD_ALLOW_ANONYMOUS_EDITS` | **`false`** or `true` | If `allowAnonymous` is `false`: allow users to select `freely` permission, allowing guests to edit existing notes (default is `false`). |
| `allowFreeURL` | `CMD_ALLOW_FREEURL` | **`false`** or `true` | Set to allow new note creation by accessing a nonexistent note URL. This is the behavior familiar from [Etherpad](https://github.com/ether/etherpad-lite). |
| `requireFreeURLAuthentication` | `CMD_REQUIRE_FREEURL_AUTHENTICATION` | **`false`** or `true` | Set to require authentication for FreeURL mode style note creation. |
| `defaultPermission` | `CMD_DEFAULT_PERMISSION` | **`editable`**, `freely`, `limited`, `locked`, `protected` or `private` | Set notes default permission (only applied on signed-in users). |
| `sessionName` | | **`connect.sid`** | Cookie session name. |
| `sessionLife` | `CMD_SESSION_LIFE` | **`14 * 24 * 60 * 60 * 1000`**, `1209600000` (14 days) | Cookie session life time in milliseconds. |
| `sessionSecret` | `CMD_SESSION_SECRET` | **`secret`** | Cookie session secret used to sign the session cookie. If none is set, one will randomly generated on each startup, meaning all your users will be logged out. Can be generated with e.g. `pwgen -s 64 1`. |
## Login methods
......@@ -228,6 +228,7 @@ these are rarely used for various reasons.
| | `CMD_SAML_ATTRIBUTE_ID` | **no default**, `sAMAccountName` | attribute map for `id` (optional, default: NameID of SAML response) |
| | `CMD_SAML_ATTRIBUTE_USERNAME` | **no default**, `mailNickname` | attribute map for `username` (optional, default: NameID of SAML response) |
| | `CMD_SAML_ATTRIBUTE_EMAIL` | **no default**, `mail` | attribute map for `email` (optional, default: NameID of SAML response if `CMD_SAML_IDENTIFIERFORMAT` is default) |
| | `CMD_SAML_PROVIDERNAME` | **no default**, `My institution` | Optional name to be displayed at login form indicating the SAML provider |
### Twitter Login
......
......@@ -3,7 +3,7 @@ openapi: 3.0.1
info:
title: HedgeDoc
description: HedgeDoc is an open source collaborative note editor. Several tasks of HedgeDoc can be automated through this API.
version: 1.9.2
version: 1.9.3
contact:
name: HedgeDoc on GitHub
url: https://github.com/hedgedoc/hedgedoc
......
# OAuth with Authelia SSO (self-hosted)
## Prerequisites
This guide assumes you have run and configured [Authelia](https://www.authelia.com/). If you want to get Authelia running quickly, there are example docker-compose files in the [Authelia Github repository](https://github.com/authelia/authelia/tree/master/examples/compose).
Also this guides assumes you run HedgeDoc via a [Docker container](../../setup/docker.md). Find out how the mentioned config environment variables are mapped to entries in the config file at our [configuration page](../../configuration.md).
## Steps
1. Set up the necessary OpenID Connect parameters in your Authelia `configuration.yml` as explained in the documentation at <https://www.authelia.com/docs/configuration/identity-providers/oidc.html>.
2. Make sure to generate safe secrets (such as `LENGTH=64; tr -cd '[:alnum:]' < /dev/urandom | fold -w "${LENGTH}" | head -n 1 | tr -d '\n' ; echo`)
3. A completed `identity_providers` section of the configuration may look like the following (the chosen Client ID `id` shouldn't actually be this guessable for safety reasons):
```yaml
identity_providers:
oidc:
hmac_secret: <hmac secret here> # use docker secrets for this
issuer_private_key: <issuer private key secret here> # use docker secrets for this
access_token_lifespan: 1h
authorize_code_lifespan: 1m
id_token_lifespan: 1h
refresh_token_lifespan: 90m
enable_client_debug_messages: false
clients:
- id: HedgeDoc # this should be changed to something more secure
description: HedgeDoc SSO
secret: <client secret here>
public: false
authorization_policy: two_factor
audience: []
scopes:
- openid
- email
- profile
redirect_uris:
- https://<your-hedgedoc-url>/auth/oauth2/callback
grant_types:
- refresh_token
- authorization_code
response_types:
- code
response_modes:
- form_post
- query
- fragment
userinfo_signing_algorithm: none
```
4. Restart Authelia to apply to new configuration and check for any errors in the log
5. In the `docker-compose.yml` of HedgeDoc add the following environment variables (you can choose different attributes for e.g. the display name - all available attributes you can find in the [scope definitions](https://www.authelia.com/docs/configuration/identity-providers/oidc.html#scope-definitions)):
```yaml
- CMD_URL_ADDPORT=false
- CMD_PROTOCOL_USESSL=true
- CMD_OAUTH2_PROVIDERNAME=Authelia
- CMD_OAUTH2_CLIENT_ID=HedgeDoc
- CMD_OAUTH2_CLIENT_SECRET=<client secret here>
- CMD_OAUTH2_SCOPE=openid email profile
- CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR=sub
- CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR=name
- CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR=email
- CMD_OAUTH2_USER_PROFILE_URL=https://<your-authelia-url>/api/oidc/userinfo
- CMD_OAUTH2_TOKEN_URL=https://<your-authelia-url>/api/oidc/token
- CMD_OAUTH2_AUTHORIZATION_URL=https://<your-authelia-url>/api/oidc/authorize
```
6. Run `docker-compose up -d` on HedgeDoc to apply your settings.
7. Sign in to your HedgeDoc using your Authelia login
......@@ -98,7 +98,7 @@ Here is an example config snippet:
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L]
ProxyPass / http://127.0.0.1:3000/
......
......@@ -28,7 +28,7 @@ services:
restart: always
app:
# Make sure to use the latest release from https://hedgedoc.org/latest-release
image: quay.io/hedgedoc/hedgedoc:1.9.2
image: quay.io/hedgedoc/hedgedoc:1.9.3
environment:
- CMD_DB_URL=postgres://hedgedoc:password@database:5432/hedgedoc
- CMD_DOMAIN=localhost
......@@ -44,7 +44,7 @@ volumes:
database:
uploads:
```
After executing `docker-compose up`, HedgeDoc should be available at [http://127.0.0.1:3000](http://127.0.0.1:3000).
After executing `docker-compose up`, HedgeDoc should be available at [http://localhost:3000](http://localhost:3000).
You can now continue to configure your container with environment variables.
Check out [the configuration docs](/configuration) for more details.
......
......@@ -16,7 +16,7 @@
1. Check if you meet the [requirements at the top of this document](#manual-installation).
2. Download the [latest release](https://hedgedoc.org/latest-release/) and extract it.
<small>Alternatively, you can use Git to clone the repository and checkout a release, e.g. with `git clone -b 1.9.2 https://github.com/hedgedoc/hedgedoc.git`.</small>
<small>Alternatively, you can use Git to clone the repository and checkout a release, e.g. with `git clone -b 1.9.3 https://github.com/hedgedoc/hedgedoc.git`.</small>
3. Enter the directory and execute `bin/setup`, which will install the dependencies and create example configs.
4. Configure HedgeDoc: To get started, you can use this minimal `config.json`:
```json
......@@ -58,7 +58,7 @@ If you want to upgrade HedgeDoc from an older version, follow these steps:
and the latest release.
2. Fully stop your old HedgeDoc server.
3. [Download](https://hedgedoc.org/latest-release/) the new release and extract it over the old directory.
<small>If you use Git, you can check out the new tag with e.g. `git fetch origin && git checkout 1.9.2`</small>
<small>If you use Git, you can check out the new tag with e.g. `git fetch origin && git checkout 1.9.3`</small>
5. Run `bin/setup`. This will take care of installing dependencies. It is safe to run on an existing installation.
6. *:octicons-light-bulb-16: If you used the release tarball for 1.7.0 or newer, this step can be skipped.*
Build the frontend bundle by running `yarn install` and `yarn build`. The extra `yarn install` is necessary as `bin/setup` does not install the build dependencies.
......
mkdocs==1.2.3
mkdocs-material==7.3.6
pymdown-extensions==9.1
mkdocs==1.3.0
mkdocs-material==8.2.9
pymdown-extensions==9.3
mdx_truly_sane_lists==1.2
......@@ -144,6 +144,7 @@ module.exports = {
tlsca: undefined
},
saml: {
providerName: undefined,
idpSsoUrl: undefined,
idpCert: undefined,
clientCert: undefined,
......
......@@ -134,6 +134,7 @@ module.exports = {
tlsca: process.env.CMD_LDAP_TLS_CA
},
saml: {
providerName: process.env.CMD_SAML_PROVIDERNAME,
idpSsoUrl: process.env.CMD_SAML_IDPSSOURL,
idpCert: process.env.CMD_SAML_IDPCERT,
clientCert: process.env.CMD_SAML_CLIENTCERT,
......
......@@ -27,7 +27,10 @@ exports.toIntegerConfig = function toIntegerConfig (configValue) {
exports.getGitCommit = function getGitCommit (repodir) {
try {
// prefer using git to get the current ref, as poking in .git is very fragile
return require('child_process').execSync('git rev-parse HEAD').replace('\n', '')
return require('child_process').execSync('git rev-parse HEAD', {
stdio: ['pipe', 'pipe', 'ignore'],
encoding: 'utf-8'
}).replace('\n', '')
} catch (e) {
// there was an error running git, try to parse refs ourselves
if (!fs.existsSync(repodir + '/.git/HEAD')) {
......
......@@ -50,6 +50,10 @@ const allowPDFEmbedDirectives = {
frameSrc: ['*'] // Chrome also checks PDFs against frame-src
}
const configuredGitLabInstanceDirectives = {
connectSrc: [config.gitlab.baseURL]
}
CspStrategy.computeDirectives = function () {
const directives = {}
mergeDirectives(directives, config.csp.directives)
......@@ -59,6 +63,7 @@ CspStrategy.computeDirectives = function () {
mergeDirectivesIf(config.dropbox.appKey, directives, dropboxDirectives)
mergeDirectivesIf(!config.csp.allowFraming, directives, disallowFramingDirectives)
mergeDirectivesIf(config.csp.allowPDFEmbed, directives, allowPDFEmbedDirectives)
mergeDirectivesIf(config.isGitlabSnippetsEnable, directives, configuredGitLabInstanceDirectives)
addInlineScriptExceptions(directives)
addUpgradeUnsafeRequestsOptionTo(directives)
addReportURI(directives)
......
......@@ -37,11 +37,11 @@ exports.generateAvatarURL = function (name, email = '', big = true) {
const hexDigest = hash.digest('hex')
if (email !== '' && config.allowGravatar) {
photo = 'https://cdn.libravatar.org/avatar/' + hexDigest
photo = `https://cdn.libravatar.org/avatar/${hexDigest}?default=identicon`
if (big) {
photo += '?s=400'
photo += '&s=400'
} else {
photo += '?s=96'
photo += '&s=96'
}
} else {
photo = config.serverURL + '/user/' + (name || email.substring(0, email.lastIndexOf('@')) || hexDigest) + '/avatar.svg'
......
......@@ -133,6 +133,10 @@ module.exports = function (sequelize, DataTypes) {
photo = generateAvatarURL(profile.username, profile.emails[0], bigger)
break
default:
if (profile.emails && profile.emails.length > 0) {
photo = generateAvatarURL(profile.username, profile.emails[0])
break
}
photo = generateAvatarURL(profile.username)
break
}
......
......@@ -156,9 +156,13 @@ function gitlabActionProjects (req, res, note) {
if (!user) {
return errors.errorNotFound(res)
}
const ret = { baseURL: config.gitlab.baseURL, version: config.gitlab.version }
ret.accesstoken = user.accessToken
ret.profileid = user.profileid