Merge pull request #580 from netlify/identity-widget
Authentication with Netlify Identity and Git Gateway
This commit is contained in:
commit
caa5c69522
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "netlify-cms",
|
||||
"version": "0.5.0-beta.1",
|
||||
"version": "0.5.0-beta.7",
|
||||
"description": "Netlify CMS lets content editors work on structured content stored in git",
|
||||
"main": "dist/cms.js",
|
||||
"scripts": {
|
||||
@ -68,6 +68,7 @@
|
||||
"exports-loader": "^0.6.4",
|
||||
"extract-text-webpack-plugin": "^2.1.2",
|
||||
"file-loader": "^0.11.2",
|
||||
"gotrue-js": "^0.9.3",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"imports-loader": "^0.7.1",
|
||||
"jest": "^20.0.4",
|
||||
@ -101,7 +102,6 @@
|
||||
"dateformat": "^1.0.12",
|
||||
"deep-equal": "^1.0.1",
|
||||
"fuzzy": "^0.1.1",
|
||||
"gotrue-js": "^0.9.3",
|
||||
"history": "^2.1.2",
|
||||
"immutability-helper": "^2.0.0",
|
||||
"immutable": "^3.7.6",
|
||||
@ -115,6 +115,7 @@
|
||||
"mdast-util-definitions": "^1.2.2",
|
||||
"mdast-util-to-string": "^1.0.4",
|
||||
"moment": "^2.11.2",
|
||||
"node-sass": "^3.10.0",
|
||||
"normalize.css": "^4.2.0",
|
||||
"preliminaries": "1.1.0",
|
||||
"preliminaries-parser-toml": "1.1.0",
|
||||
|
@ -77,7 +77,8 @@ export function logoutUser() {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const backend = currentBackend(state.config);
|
||||
backend.logout();
|
||||
dispatch(logout());
|
||||
Promise.resolve(backend.logout()).then(() => {
|
||||
dispatch(logout());
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { attempt, isError } from 'lodash';
|
||||
import TestRepoBackend from "./test-repo/implementation";
|
||||
import GitHubBackend from "./github/implementation";
|
||||
import NetlifyAuthBackend from "./netlify-auth/implementation";
|
||||
import GitGatewayBackend from "./git-gateway/implementation";
|
||||
import { resolveFormat } from "../formats/formats";
|
||||
import { selectListMethod, selectEntrySlug, selectEntryPath, selectAllowNewEntries, selectFolderEntryExtension } from "../reducers/collections";
|
||||
import { createEntry } from "../valueObjects/Entry";
|
||||
@ -36,12 +36,12 @@ const slugFormatter = (template = "{{slug}}", entryData) => {
|
||||
const identifier = identifiers.find(ident => ident !== undefined);
|
||||
|
||||
if (identifier === undefined) {
|
||||
throw new Error("Collection must have a field name that is a valid entry identifier");
|
||||
throw new Error("Collection must have a field name that is a valid entry identifier");
|
||||
}
|
||||
|
||||
return identifier;
|
||||
};
|
||||
|
||||
|
||||
return template.replace(/\{\{([^\}]+)\}\}/g, (_, field) => {
|
||||
switch (field) {
|
||||
case "year":
|
||||
@ -88,11 +88,11 @@ class Backend {
|
||||
}
|
||||
|
||||
logout() {
|
||||
if (this.authStore) {
|
||||
this.authStore.logout();
|
||||
} else {
|
||||
throw new Error("User isn't authenticated.");
|
||||
}
|
||||
return Promise.resolve(this.implementation.logout()).then(() => {
|
||||
if (this.authStore) {
|
||||
this.authStore.logout();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getToken = () => this.implementation.getToken();
|
||||
@ -292,8 +292,8 @@ export function resolveBackend(config) {
|
||||
return new Backend(new TestRepoBackend(config), authStore);
|
||||
case "github":
|
||||
return new Backend(new GitHubBackend(config), authStore);
|
||||
case "netlify-auth":
|
||||
return new Backend(new NetlifyAuthBackend(config), authStore);
|
||||
case "git-gateway":
|
||||
return new Backend(new GitGatewayBackend(config), authStore);
|
||||
default:
|
||||
throw new Error(`Backend not found: ${ name }`);
|
||||
}
|
||||
|
@ -1,28 +1,54 @@
|
||||
import React from "react";
|
||||
import Input from "react-toolbox/lib/input";
|
||||
import Button from "react-toolbox/lib/button";
|
||||
import { Notifs } from 'redux-notifications';
|
||||
import { Toast } from '../../components/UI/index';
|
||||
import { Card, Icon } from "../../components/UI";
|
||||
import logo from "./netlify_logo.svg";
|
||||
import styles from "./AuthenticationPage.css";
|
||||
|
||||
let component = null;
|
||||
|
||||
if (window.netlifyIdentity) {
|
||||
window.netlifyIdentity.on('login', (user) => {
|
||||
component && component.handleIdentityLogin(user);
|
||||
});
|
||||
window.netlifyIdentity.on('logout', () => {
|
||||
component && component.handleIdentityLogout();
|
||||
});
|
||||
}
|
||||
|
||||
export default class AuthenticationPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.identity = window.netlifyIdentity;
|
||||
this.state = {user: this.identity && this.identity.gotrue && this.identity.gotrue.currentUser()};
|
||||
component = this;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.identity && !this.state.user) {
|
||||
this.identity.on('login', (user) => {
|
||||
this.props.onLogin(user);
|
||||
this.identity.close();
|
||||
});
|
||||
this.identity.on('signup', (user) => {
|
||||
this.props.onLogin(user);
|
||||
this.identity.close();
|
||||
});
|
||||
this.identity.open();
|
||||
if (!this.loggedIn && window.netlifyIdentity && window.netlifyIdentity.currentUser()) {
|
||||
this.props.onLogin(window.netlifyIdentity.currentUser());
|
||||
window.netlifyIdentity.close();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
component = null;
|
||||
}
|
||||
|
||||
handleIdentityLogin = (user) => {
|
||||
this.props.onLogin(user);
|
||||
window.netlifyIdentity.close();
|
||||
}
|
||||
|
||||
handleIdentityLogout = () => {
|
||||
window.netlifyIdentity.open();
|
||||
}
|
||||
|
||||
handleIdentity = () => {
|
||||
if (window.netlifyIdentity.currentUser()) {
|
||||
this.props.onLogin(user);
|
||||
} else {
|
||||
window.netlifyIdentity.open();
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,6 +92,15 @@ export default class AuthenticationPage extends React.Component {
|
||||
const { errors } = this.state;
|
||||
const { error } = this.props;
|
||||
|
||||
if (window.netlifyIdentity) {
|
||||
return <section className={styles.root}>
|
||||
<Notifs CustomComponent={Toast} />
|
||||
<Button className={styles.button} raised onClick={this.handleIdentity}>
|
||||
Login with Netlify Identity
|
||||
</Button>
|
||||
</section>
|
||||
}
|
||||
|
||||
return (
|
||||
<section className={styles.root}>
|
||||
<Card className={styles.card}>
|
@ -11,38 +11,40 @@ const localHosts = {
|
||||
'127.0.0.1': true,
|
||||
'0.0.0.0': true
|
||||
}
|
||||
const defaults = {
|
||||
identity: '/.netlify/identity',
|
||||
gateway: '/.netlify/git/github'
|
||||
}
|
||||
|
||||
function getEndpoint(endpoint, netlifySiteURL) {
|
||||
if (localHosts[document.location.host] && netlifySiteURL && endpoint.match(/^\/\.netlify\//)) {
|
||||
const parts = [netlifySiteURL];
|
||||
if (!netlifySiteURL.match(/\/$/)) { parts.push("/"); }
|
||||
parts.push(endpoint);
|
||||
if (localHosts[document.location.host.split(":").shift()] && netlifySiteURL && endpoint.match(/^\/\.netlify\//)) {
|
||||
const parts = [];
|
||||
if (netlifySiteURL) {
|
||||
parts.push(netlifySiteURL);
|
||||
if (!netlifySiteURL.match(/\/$/)) { parts.push("/"); }
|
||||
}
|
||||
parts.push(endpoint.replace(/^\//, ''));
|
||||
return parts.join("");
|
||||
}
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
export default class NetlifyAuth extends GitHubBackend {
|
||||
export default class GitGateway extends GitHubBackend {
|
||||
constructor(config) {
|
||||
super(config, true);
|
||||
if (config.getIn(["backend", "auth_url"]) == null) { throw new Error("The NetlifyAuth backend needs an \"auth_url\" in the backend configuration."); }
|
||||
|
||||
if (config.getIn(["backend", "github_proxy_url"]) == null) {
|
||||
throw new Error("The NetlifyAuth backend needs an \"github_proxy_url\" in the backend configuration.");
|
||||
}
|
||||
|
||||
this.accept_roles = (config.getIn(["backend", "accept_roles"]) || List()).toArray();
|
||||
|
||||
const netlifySiteURL = localStorage.getItem("netlifySiteURL");
|
||||
const APIUrl = getEndpoint(config.getIn(["backend", "auth_url"]), netlifySiteURL);
|
||||
this.github_proxy_url = getEndpoint(config.getIn(["backend", "github_proxy_url"]), netlifySiteURL);
|
||||
this.authClient = new GoTrue({APIUrl});
|
||||
const APIUrl = getEndpoint(config.getIn(["backend", "identity_url"], defaults.identity), netlifySiteURL);
|
||||
this.github_proxy_url = getEndpoint(config.getIn(["backend", "gateway_url"], defaults.gateway), netlifySiteURL);
|
||||
this.authClient = window.netlifyIdentity ? window.netlifyIdentity.gotrue : new GoTrue({APIUrl});
|
||||
|
||||
AuthenticationPage.authClient = this.authClient;
|
||||
}
|
||||
|
||||
setUser() {
|
||||
const user = this.authClient.currentUser();
|
||||
const user = this.authClient && this.authClient.currentUser();
|
||||
if (!user) return Promise.reject();
|
||||
return this.authenticate(user);
|
||||
}
|
||||
@ -58,7 +60,7 @@ export default class NetlifyAuth extends GitHubBackend {
|
||||
const userRoles = get(jwtDecode(token), 'app_metadata.roles', []);
|
||||
if (validRole) {
|
||||
const userData = {
|
||||
name: user.user_metadata.name,
|
||||
name: user.user_metadata.name || user.email.split('@').shift(),
|
||||
email: user.email,
|
||||
metadata: user.user_metadata,
|
||||
};
|
||||
@ -74,6 +76,14 @@ export default class NetlifyAuth extends GitHubBackend {
|
||||
});
|
||||
}
|
||||
|
||||
logout() {
|
||||
if (window.netlifyIdentity) {
|
||||
return window.netlifyIdentity.logout();
|
||||
}
|
||||
const user = this.authClient.currentUser();
|
||||
return user && user.logout();
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this.tokenPromise();
|
||||
}
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -42,6 +42,11 @@ export default class GitHub {
|
||||
);
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.token = null;
|
||||
return;
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return Promise.resolve(this.token);
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ import React from 'react';
|
||||
import Input from "react-toolbox/lib/input";
|
||||
import Button from "react-toolbox/lib/button";
|
||||
import { Card, Icon } from "../../components/UI";
|
||||
import logo from "../netlify-auth/netlify_logo.svg";
|
||||
import styles from "../netlify-auth/AuthenticationPage.css";
|
||||
import logo from "../git-gateway/netlify_logo.svg";
|
||||
import styles from "../git-gateway/AuthenticationPage.css";
|
||||
|
||||
export default class AuthenticationPage extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -36,6 +36,10 @@ export default class TestRepo {
|
||||
return Promise.resolve({ email: state.email, name: nameFromEmail(state.email) });
|
||||
}
|
||||
|
||||
logout() {
|
||||
return null;
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user