"`
diff --git a/docs/user_guide/user-management.md b/docs/user_guide/user-management.md
new file mode 100644
index 0000000000..d8a05b5451
--- /dev/null
+++ b/docs/user_guide/user-management.md
@@ -0,0 +1,16 @@
+---
+id: user-management
+title: User Management
+---
+
+> This feature was introduced in Unleash v4 for Unleash Open-Source.
+
+From the `Admin > Users` you can manage users with access to Unleash. To add a new user to your Unleash instance simply click the "Add user" button:
+
+![Add user button](../assets/user_admin-add-user.png)
+
+Fill out the required fields about the user in the modal. You need to choose which role the new user should have on the "root level". E.g. giving the user an Editor role will allow the user to create a new project.
+
+![Add user button](../assets/user_admin_add_user_modal.png).
+
+If you have configured an email server the user will receive the invite link in her inbox, otherwise you should share the magic invite link to Unleash presented in the confirmation dialogue.
diff --git a/docs/user_guide/whats-new-v4.md b/docs/user_guide/whats-new-v4.md
new file mode 100644
index 0000000000..0b16f44567
--- /dev/null
+++ b/docs/user_guide/whats-new-v4.md
@@ -0,0 +1,54 @@
+---
+id: v4-whats-new
+title: What's new in v4?
+---
+
+Version 4 of Unleash brings a lot of improvements to Unleash. In this document we will highlight some of the things that has been added.
+
+### Upgrade with ease
+
+Unleash can either be hosted by us or self-hosted. If you have a managed Unleash Enterprise instance you are automatically upgraded to version 4. If you manage Unleash yourself (either Open-Source or Enterprise Self-hosted) we recommend reading the [migration guide](../deploy/migration_guide).
+
+**PS! The first time you access Unleash v4 from a self-hosted instance you will need to login with the default admin user:**
+
+- username: `admin`
+- password: `unleash4all`
+
+_(We recommend changing the password of the default user from the admin section.)_
+
+### Role-Based Access Control
+
+With Role-Based Access Control you can now assign groups to users in order to control access. You can control access to root resources in addition to controlling access to [projects](./projects). _Please be aware that all existing users will become "Owner" of all existing projects as part of the migration from v3 to v4._
+
+[Read more](./rbac)
+
+### New Addons
+
+Addons make it easy to integrate Unleash with other systems. In version 4 we bring two new integrations to Unleash:
+
+- [Microsoft Teams](../addons/teams)
+- [Datadog](../datadog)
+
+### Improved UX
+
+Unleash v4 includes a new implementation of the frontend based on [Material-ui](https://material-ui.com). This will make it much easier for us to improve the Unleash Admin UI and our ambition is to make it intuitive to use even for non-developers. The improved UX is made available in Unleash Open-Source and Unleash Enterprise.
+
+### New SSO Option
+
+In version 4 we added support for [OpenID Connect](https://openid.net/connect/) as part of the Unleash Enterprise offering. OpenID Connect is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
+
+### User Management
+
+In version 4 we improved the User Management and made it available for Unleash Open-Source and Unleash Enterprise. Starting in v4 all users accessing Unleash needs to exist in the Unleash in order to gain access (because they need to have the proper permission from RBAC.)
+
+[Read more](./user-management)
+
+### API access
+
+In version 4 we improved the API Access and made it available for Unleash Open-Source and Unleash Enterprise. Starting from Unleash v4 we require all SDKs to use an access token in order to connect to Unleash.
+
+[Read more](../advanced/api_access)
+
+### Custom stickiness
+
+In Unleash Enterprise v4 you can configure stickiness when your are doing a gradual rollout with the "flexible rollout" strategy or together with feature toggle variants. This means that you can now have a consistent behavior bases on any field available on the [Unleash context](./unleash_context).
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000000..861daea3fe
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1 @@
+This section has been moved to a separate repository: https://github.com/Unleash/unleash-examples
diff --git a/examples/basic-auth-hook.js b/examples/basic-auth-hook.js
deleted file mode 100644
index 269b4164fe..0000000000
--- a/examples/basic-auth-hook.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* eslint-disable import/no-unresolved */
-
-'use strict';
-
-const auth = require('basic-auth');
-const { User } = require('../dist/lib/server-impl.js');
-
-function basicAuthentication(app) {
- app.use('/api/admin/', (req, res, next) => {
- const credentials = auth(req);
-
- if (credentials) {
- // you will need to do some verification of credentials here.
- const user = new User({ email: `${credentials.name}@domain.com` });
- req.user = user;
- return next();
- }
-
- return res
- .status('401')
- .set({ 'WWW-Authenticate': 'Basic realm="example"' })
- .end('access denied');
- });
-}
-
-module.exports = basicAuthentication;
diff --git a/examples/basic-auth-unleash.js b/examples/basic-auth-unleash.js
deleted file mode 100644
index 49536a503f..0000000000
--- a/examples/basic-auth-unleash.js
+++ /dev/null
@@ -1,19 +0,0 @@
-'use strict';
-
-// const unleash = require('unleash-server');
-const unleash = require('../dist/lib/server-impl.js');
-
-const basicAuth = require('./basic-auth-hook');
-
-unleash
- .start({
- databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
- adminAuthentication: 'custom',
- preRouterHook: basicAuth,
- })
- .then(server => {
- // eslint-disable-next-line no-console
- console.log(
- `Unleash started on http://localhost:${server.app.get('port')}`,
- );
- });
diff --git a/examples/client-auth-unleash.js b/examples/client-auth-unleash.js
deleted file mode 100644
index d7f57959af..0000000000
--- a/examples/client-auth-unleash.js
+++ /dev/null
@@ -1,27 +0,0 @@
-'use strict';
-
-// const unleash = require('unleash-server');
-const unleash = require('../dist/lib/server-impl.js');
-
-// You typically will not hard-code this value in your code!
-const sharedSecret = '12312Random';
-
-unleash
- .start({
- databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
- preRouterHook: app => {
- app.use('/api/client', (req, res, next) => {
- if (req.header('authorization') === sharedSecret) {
- next();
- } else {
- res.sendStatus(401);
- }
- });
- },
- })
- .then(server => {
- // eslint-disable-next-line no-console
- console.log(
- `Unleash started on http://localhost:${server.app.get('port')}`,
- );
- });
diff --git a/examples/express-parent-app.js b/examples/express-parent-app.js
deleted file mode 100644
index d41ab056ca..0000000000
--- a/examples/express-parent-app.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* eslint-disable import/no-unresolved */
-
-'use strict';
-
-const express = require('express');
-const unleash = require('../dist/lib/server-impl.js');
-
-const app = express();
-unleash
- .create({
- databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
- baseUriPath: '/unleash',
- })
- .then(unl => {
- app.use(unl.app); // automatically mounts to baseUriPath
- app.listen(process.env.PORT);
- });
diff --git a/examples/google-auth-hook.js b/examples/google-auth-hook.js
deleted file mode 100644
index 120772a9b2..0000000000
--- a/examples/google-auth-hook.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/* eslint-disable import/no-extraneous-dependencies */
-
-'use strict';
-
-/**
- * Google OAuth 2.0
- *
- * You should read Using OAuth 2.0 to Access Google APIs:
- * https://developers.google.com/identity/protocols/OAuth2
- *
- * This example assumes that all users authenticating via
- * google should have access. You would probably limit access
- * to users you trust.
- *
- * The implementation assumes the following environment variables:
- *
- * - GOOGLE_CLIENT_ID
- * - GOOGLE_CLIENT_SECRET
- * - GOOGLE_CALLBACK_URL
- */
-
-const passport = require('@passport-next/passport');
-const GoogleOAuth2Strategy = require('@passport-next/passport-google-oauth2')
- .Strategy;
-
-// const { User, AuthenticationRequired } = require('unleash-server');
-const { User, AuthenticationRequired } = require('../dist/lib/server-impl.js');
-
-passport.use(
- new GoogleOAuth2Strategy(
- {
- clientID: process.env.GOOGLE_CLIENT_ID,
- clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- callbackURL: process.env.GOOGLE_CALLBACK_URL,
- },
-
- (accessToken, refreshToken, profile, done) => {
- done(
- null,
- new User({
- name: profile.displayName,
- email: profile.emails[0].value,
- }),
- );
- },
- ),
-);
-
-function enableGoogleOauth(app) {
- app.use(passport.initialize());
- app.use(passport.session());
-
- passport.serializeUser((user, done) => done(null, user));
- passport.deserializeUser((user, done) => done(null, user));
- app.get(
- '/api/admin/login',
- passport.authenticate('google', { scope: ['email'] }),
- );
-
- app.get(
- '/api/auth/callback',
- passport.authenticate('google', {
- failureRedirect: '/api/admin/error-login',
- }),
- (req, res) => {
- // Successful authentication, redirect to your app.
- res.redirect('/');
- },
- );
-
- app.use('/api/admin/', (req, res, next) => {
- if (req.user) {
- return next();
- }
- // Instruct unleash-frontend to pop-up auth dialog
- return res
- .status('401')
- .json(
- new AuthenticationRequired({
- path: '/api/admin/login',
- type: 'custom',
- message: `You have to identify yourself in order to use Unleash.
- Click the button and follow the instructions.`,
- }),
- )
- .end();
- });
-}
-
-module.exports = enableGoogleOauth;
diff --git a/examples/google-auth-unleash.js b/examples/google-auth-unleash.js
deleted file mode 100644
index 0e1ba899f7..0000000000
--- a/examples/google-auth-unleash.js
+++ /dev/null
@@ -1,19 +0,0 @@
-'use strict';
-
-// const unleash = require('unleash-server');
-const unleash = require('../dist/lib/server-impl.js');
-
-const enableGoogleOauth = require('./google-auth-hook');
-
-unleash
- .start({
- databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
- adminAuthentication: 'custom',
- preRouterHook: enableGoogleOauth,
- })
- .then(server => {
- // eslint-disable-next-line no-console
- console.log(
- `Unleash started on http://localhost:${server.app.get('port')}`,
- );
- });
diff --git a/examples/keycloak-auth-hook.js b/examples/keycloak-auth-hook.js
deleted file mode 100644
index 7a379a9c45..0000000000
--- a/examples/keycloak-auth-hook.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/* eslint-disable import/no-extraneous-dependencies */
-/* eslint-disable import/no-unresolved */
-
-'use strict';
-
-/**
- * Keycloak hook for securing an Unleash server
- *
- * This example assumes that all users authenticating via
- * keycloak should have access. You would probably limit access
- * to users you trust.
- *
- * The implementation assumes the following environment variables:
- *
- * - AUTH_HOST
- * - AUTH_REALM
- * - AUTH_CLIENT_ID
- */
-
-const KeycloakStrategy = require('@exlinc/keycloak-passport');
-const passport = require('passport');
-
-// const { User, AuthenticationRequired } = require('unleash-server');
-const { User, AuthenticationRequired } = require('../dist/lib/server-impl.js');
-
-const host = process.env.AUTH_HOST;
-const realm = process.env.AUTH_REALM;
-const clientID = process.env.AUTH_CLIENT_ID;
-const contextPath = process.env.CONTEXT_PATH;
-
-passport.use(
- 'keycloak',
- new KeycloakStrategy(
- {
- host,
- realm,
- clientID,
- clientSecret: "We don't need that, but is required",
- callbackURL: `${contextPath}/api/auth/callback`,
- authorizationURL: `${host}/auth/realms/${realm}/protocol/openid-connect/auth`,
- tokenURL: `${host}/auth/realms/${realm}/protocol/openid-connect/token`,
- userInfoURL: `${host}/auth/realms/${realm}/protocol/openid-connect/userinfo`,
- },
-
- (accessToken, refreshToken, profile, done) => {
- done(
- null,
- new User({
- name: profile.fullName,
- email: profile.email,
- }),
- );
- },
- ),
-);
-
-function enableKeycloakOauth(app) {
- app.use(passport.initialize());
- app.use(passport.session());
-
- passport.serializeUser((user, done) => done(null, user));
- passport.deserializeUser((user, done) => done(null, user));
-
- app.get('/api/admin/login', passport.authenticate('keycloak'));
-
- app.get(
- '/api/auth/callback',
- passport.authenticate('keycloak'),
- (req, res) => {
- res.redirect(`${contextPath}/`);
- },
- );
-
- app.use('/api/admin/', (req, res, next) => {
- if (req.user) {
- return next();
- }
- // Instruct unleash-frontend to pop-up auth dialog
- return res
- .status('401')
- .json(
- new AuthenticationRequired({
- path: `${contextPath}/api/admin/login`,
- type: 'custom',
- message: `You have to identify yourself in order to use Unleash.
- Click the button and follow the instructions.`,
- }),
- )
- .end();
- });
-}
-
-module.exports = enableKeycloakOauth;
diff --git a/examples/keycloak-auth-unleash.js b/examples/keycloak-auth-unleash.js
deleted file mode 100644
index 9efc7ffab3..0000000000
--- a/examples/keycloak-auth-unleash.js
+++ /dev/null
@@ -1,19 +0,0 @@
-'use strict';
-
-// const unleash = require('unleash-server');
-const unleash = require('../dist/lib/server-impl.js');
-
-const enableKeycloak = require('./keycloak-auth-hook');
-
-unleash
- .start({
- databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
- adminAuthentication: 'custom',
- preRouterHook: enableKeycloak,
- })
- .then(server => {
- // eslint-disable-next-line no-console
- console.log(
- `Unleash started on http://localhost:${server.app.get('port')}`,
- );
- });
diff --git a/package.json b/package.json
index d7a74648d0..80bb84dd4c 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,6 @@
},
"dependencies": {
"async": "^3.1.0",
- "basic-auth": "^2.0.1",
"bcrypt": "^5.0.1",
"compression": "^1.7.3",
"connect-session-knex": "^2.0.0",
@@ -104,8 +103,6 @@
},
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.1",
- "@passport-next/passport": "^3.1.0",
- "@passport-next/passport-google-oauth2": "^1.0.0",
"@types/bcrypt": "^3.0.0",
"@types/express": "^4.17.11",
"@types/node": "^14.14.37",
@@ -129,8 +126,6 @@
"lint-staged": "^10.0.7",
"lolex": "^6.0.0",
"nyc": "^15.1.0",
- "passport": "^0.4.1",
- "passport-google-auth": "^1.0.2",
"prettier": "^1.19.1",
"proxyquire": "^2.1.3",
"rimraf": "^3.0.2",
diff --git a/website/core/Footer.js b/website/core/Footer.js
index 3c5a5ff98a..ffdce7d025 100644
--- a/website/core/Footer.js
+++ b/website/core/Footer.js
@@ -34,12 +34,9 @@ class Footer extends React.Component {
Docs
-
+
Getting Started
-
- Securing Unleash
-
API Reference
@@ -56,8 +53,8 @@ class Footer extends React.Component {
Slack community
- Unleash-hosted.com
+ href="https://www.getunleash.io">
+ getunleash.io
(
const ProjectTitle = () => (
-
+
{siteConfig.tagline}
);
diff --git a/website/sidebars.json b/website/sidebars.json
index e940c93d11..6ea4398c86 100644
--- a/website/sidebars.json
+++ b/website/sidebars.json
@@ -2,29 +2,35 @@
"documentation": {
"Getting started": [
"user_guide/index",
+ "user_guide/v4-whats-new",
"user_guide/create_feature_toggle",
"user_guide/activation_strategy",
"user_guide/control_rollout",
"user_guide/projects",
"user_guide/unleash_context",
- "user_guide/technical_debt",
- "user_guide/native_apps",
- "user_guide/single_page_apps"
+ "user_guide/user-management",
+ "user_guide/rbac",
+ "user_guide/api-token",
+ "user_guide/technical_debt"
],
- "Working with the SDK": [
+ "Unleash SDKs": [
"sdks/index",
"sdks/java_sdk",
"sdks/node_sdk",
"sdks/dot_net_sdk",
"sdks/go_sdk",
"sdks/python_sdk",
- "sdks/ruby_sdk"
+ "sdks/ruby_sdk",
+ "sdks/unleash-proxy",
+ "sdks/proxy-javascript",
+ "sdks/community"
],
"Addons framework": [
"addons/index",
"addons/webhook",
"addons/slack",
- "addons/jira-commenter"
+ "addons/teams",
+ "addons/datadog"
],
"Advanced": [
"advanced/strategy_constraints",
@@ -54,7 +60,7 @@
"api/admin/context",
"api/admin/projects"
],
- "Internal": ["api/internal/internal", "api/internal/health"],
+ "Status": ["api/internal/internal", "api/internal/health"],
"Specification": ["api/open_api"]
},
"Deploy and manage": {
@@ -62,6 +68,7 @@
"deploy/getting_started",
"deploy/configuring_unleash",
"deploy/securing_unleash",
+ "deploy/email",
"deploy/google_auth",
"deploy/database_backup",
"deploy/migration_guide",
@@ -70,12 +77,5 @@
},
"Integrations": {
"Integrations": ["integrations/integrations"]
- },
- "Contribute": {
- "Contribute to Unleash": [
- "developer_guide",
- "client_specification",
- "database_schema"
- ]
}
}
diff --git a/website/siteConfig.js b/website/siteConfig.js
index bfddedc98a..08411a4f87 100644
--- a/website/siteConfig.js
+++ b/website/siteConfig.js
@@ -55,7 +55,7 @@ const users = [
];
const siteConfig = {
- title: 'Unleash', // Title for your website.
+ title: '', // Title for your website.
tagline: 'The enterprise ready feature toggle service',
url: 'https://docs.getunleash.io', // Your website URL
baseUrl: '/', // Base URL for your project */
@@ -75,7 +75,6 @@ const siteConfig = {
{ doc: 'user_guide/index', label: 'Documentation' },
{ doc: 'deploy/getting_started', label: 'Deploy and manage' },
{ doc: 'integrations/integrations', label: 'Integrations' },
- { doc: 'developer_guide', label: 'Contribute' },
{ doc: 'api/client/features', label: 'API' },
{ href: 'https://www.unleash-hosted.com/pricing', label: 'Enterprise' },
{ page: 'help', label: 'Help' },
@@ -86,13 +85,13 @@ const siteConfig = {
users,
/* path to images for header/footer */
- headerIcon: 'img/logo-inverted.png',
- footerIcon: 'img/logo-inverted.png',
+ headerIcon: 'img/Logo_White_Transparent_Horizontal.png',
+ footerIcon: 'img/Logo_White_Transparent_Horizontal.png',
favicon: 'img/favicon/favicon.ico',
/* Colors for website */
colors: {
- primaryColor: '#3f51b5',
+ primaryColor: '#39535b',
secondaryColor: '#697ce5',
},
diff --git a/website/static/img/Logo_DarkBlue_Transparent_Horizontal.png b/website/static/img/Logo_DarkBlue_Transparent_Horizontal.png
new file mode 100644
index 0000000000..b3f8ab9d6a
Binary files /dev/null and b/website/static/img/Logo_DarkBlue_Transparent_Horizontal.png differ
diff --git a/website/static/img/Logo_White_Transparent_Horizontal.png b/website/static/img/Logo_White_Transparent_Horizontal.png
new file mode 100644
index 0000000000..d19d74bae1
Binary files /dev/null and b/website/static/img/Logo_White_Transparent_Horizontal.png differ
diff --git a/website/static/img/favicon/favicon.ico b/website/static/img/favicon/favicon.ico
index fed2443a05..2bfe97c212 100644
Binary files a/website/static/img/favicon/favicon.ico and b/website/static/img/favicon/favicon.ico differ
diff --git a/website/static/img/unleash-logo-scaled.png b/website/static/img/unleash-logo-scaled.png
new file mode 100644
index 0000000000..20c89016fe
Binary files /dev/null and b/website/static/img/unleash-logo-scaled.png differ