mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-22 16:41:38 +03:00
authentication: adds user auth concept, sign out, and adds 3 images to a bucket upon user creation
This commit is contained in:
parent
8a63467e6f
commit
f66129f16d
@ -68,6 +68,21 @@ export const sendWalletAddressFilecoin = async (data) => {
|
||||
|
||||
// NOTE(jim):
|
||||
// New WWW Requests.
|
||||
|
||||
export const signIn = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: REQUEST_HEADERS,
|
||||
credentials: "include",
|
||||
body: JSON.stringify({ data }),
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/sign-in`, options);
|
||||
const json = await response.json();
|
||||
|
||||
return json;
|
||||
};
|
||||
|
||||
export const hydrateAuthenticatedUser = async (data) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
|
@ -1,3 +1,3 @@
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
require("dotenv").config();
|
||||
}
|
||||
export const session = {
|
||||
key: "WEB_SERVICE_SESSION_KEY",
|
||||
};
|
||||
|
@ -39,6 +39,10 @@ const transformPeers = (peersList) => {
|
||||
};
|
||||
|
||||
export const getSelectedState = (props) => {
|
||||
if (!props) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
status,
|
||||
messageList,
|
||||
@ -61,6 +65,10 @@ export const getSelectedState = (props) => {
|
||||
};
|
||||
|
||||
export const getInitialState = (props) => {
|
||||
if (!props) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
status,
|
||||
messageList,
|
||||
|
@ -51,7 +51,7 @@ const STYLES_ICON_ELEMENT = css`
|
||||
const STYLES_ICON_ELEMENT_CUSTOM = css`
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.07);
|
||||
background-image: url('/static/social.png');
|
||||
background-image: url("/static/social.png");
|
||||
background-size: cover;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
@ -169,10 +169,12 @@ export default class ApplicationHeader extends React.Component {
|
||||
style={{ right: 0, top: "48px", cursor: "pointer" }}
|
||||
onNavigateTo={this.props.onNavigateTo}
|
||||
onAction={this.props.onAction}
|
||||
onSignOut={this.props.onSignOut}
|
||||
navigation={[
|
||||
{ text: "Edit account", value: 13 },
|
||||
{ text: "Filecoin settings", value: 14 },
|
||||
{ text: "API Key & Tokens", value: 16 },
|
||||
{ text: "Sign out", value: 0, action: "SIGN_OUT" },
|
||||
]}
|
||||
/>
|
||||
}
|
||||
|
@ -44,6 +44,18 @@ export class PopoverNavigation extends React.Component {
|
||||
return (
|
||||
<div css={STYLES_POPOVER} style={this.props.style}>
|
||||
{this.props.navigation.map((each) => {
|
||||
if (each.action === "SIGN_OUT") {
|
||||
return (
|
||||
<div
|
||||
key={each.value}
|
||||
css={STYLES_POPOVER_ITEM}
|
||||
onClick={this.props.onSignOut}
|
||||
>
|
||||
{each.text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={each.value}
|
||||
|
10
knexfile.js
10
knexfile.js
@ -1,13 +1,15 @@
|
||||
import * as Environment from "~/node_common/environment";
|
||||
|
||||
module.exports = {
|
||||
development: {
|
||||
client: "pg",
|
||||
connection: {
|
||||
ssl: true,
|
||||
port: 5432,
|
||||
host: process.env.POSTGRES_HOSTNAME,
|
||||
database: process.env.POSTGRES_DATABASE,
|
||||
user: process.env.POSTGRES_ADMIN_USERNAME,
|
||||
password: process.env.POSTGRES_ADMIN_PASSWORD,
|
||||
host: Environment.POSTGRES_HOSTNAME,
|
||||
database: Environment.POSTGRES_DATABASE,
|
||||
user: Environment.POSTGRES_ADMIN_USERNAME,
|
||||
password: Environment.POSTGRES_ADMIN_PASSWORD,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -1,7 +1,3 @@
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
require("dotenv").config();
|
||||
}
|
||||
|
||||
import configs from "~/knexfile";
|
||||
import knex from "knex";
|
||||
|
||||
|
14
node_common/environment.js
Normal file
14
node_common/environment.js
Normal file
@ -0,0 +1,14 @@
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
require("dotenv").config();
|
||||
}
|
||||
|
||||
export const POSTGRES_ADMIN_PASSWORD = process.env.POSTGRES_ADMIN_PASSWORD;
|
||||
export const POSTGRES_ADMIN_USERNAME = process.env.POSTGRES_ADMIN_USERNAME;
|
||||
export const POSTGRES_HOSTNAME = process.env.POSTGRES_HOSTNAME;
|
||||
export const POSTGRES_DATABASE = process.env.POSTGRES_DATABASE;
|
||||
export const JWT_SECRET = process.env.JWT_SECRET;
|
||||
export const LOCAL_PASSWORD_SECRET = `$2b$13$${
|
||||
process.env.LOCAL_PASSWORD_SECRET
|
||||
}`;
|
||||
export const TEXTILE_HUB_KEY = process.env.TEXTILE_HUB_KEY;
|
||||
export const TEXTILE_HUB_SECRET = process.env.TEXTILE_HUB_SECRET;
|
@ -1,3 +1,10 @@
|
||||
import JWT from "jsonwebtoken";
|
||||
|
||||
import * as Environment from "~/node_common/environment";
|
||||
import * as Credentials from "~/common/credentials";
|
||||
import * as Strings from "~/common/strings";
|
||||
import * as Data from "~/node_common/data";
|
||||
|
||||
export const init = (middleware) => {
|
||||
return (req, res) =>
|
||||
new Promise((resolve, reject) => {
|
||||
@ -29,3 +36,36 @@ export const CORS = async (req, res, next) => {
|
||||
|
||||
next();
|
||||
};
|
||||
|
||||
export const RequireCookieAuthentication = async (req, res, next) => {
|
||||
if (Strings.isEmpty(req.headers.cookie)) {
|
||||
return res
|
||||
.status(403)
|
||||
.json({ decorator: "SERVER_AUTH_USER_NO_TOKEN", error: true });
|
||||
}
|
||||
|
||||
const token = req.headers.cookie.replace(
|
||||
/(?:(?:^|.*;\s*)WEB_SERVICE_SESSION_KEY\s*\=\s*([^;]*).*$)|^.*$/,
|
||||
"$1"
|
||||
);
|
||||
|
||||
try {
|
||||
const decoded = JWT.verify(token, Environment.JWT_SECRET);
|
||||
const user = await Data.getUserByUsername({
|
||||
username: decoded.username,
|
||||
});
|
||||
|
||||
if (!user || user.error) {
|
||||
return res
|
||||
.status(403)
|
||||
.json({ decorator: "SERVER_AUTH_USER_NOT_FOUND", error: true });
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return res
|
||||
.status(403)
|
||||
.json({ decorator: "SERVER_AUTH_USER_ERROR", error: true });
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
|
55
node_common/models.js
Normal file
55
node_common/models.js
Normal file
@ -0,0 +1,55 @@
|
||||
import * as Utilities from "~/node_common/utilities";
|
||||
import * as Data from "~/node_common/data";
|
||||
|
||||
import PG from "~/node_common/powergate";
|
||||
|
||||
export const getViewer = async ({ username }) => {
|
||||
const user = await Data.getUserByUsername({
|
||||
username,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (user.error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
buckets,
|
||||
bucketKey,
|
||||
bucketName,
|
||||
} = await Utilities.getBucketAPIFromUserToken(user.data.tokens.api);
|
||||
|
||||
let data = {
|
||||
id: user.id,
|
||||
data: user.data,
|
||||
peersList: null,
|
||||
messageList: null,
|
||||
status: null,
|
||||
addrsList: null,
|
||||
info: null,
|
||||
state: null,
|
||||
local: {
|
||||
photo: null,
|
||||
name: `node`,
|
||||
settings_deals_auto_approve: false,
|
||||
},
|
||||
library: user.data.library,
|
||||
};
|
||||
|
||||
PG.setToken(user.data.tokens.pg);
|
||||
|
||||
const updates = await Utilities.refresh({ PG });
|
||||
const updatesWithToken = await Utilities.refreshWithToken({
|
||||
PG,
|
||||
});
|
||||
|
||||
data = await Utilities.updateStateData(data, {
|
||||
...updates,
|
||||
...updatesWithToken,
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
import * as Environment from "~/node_common/environment";
|
||||
import * as Constants from "./constants";
|
||||
import * as Converter from "~/vendor/bytes-base64-converter.js";
|
||||
|
||||
@ -9,8 +10,17 @@ import { Libp2pCryptoIdentity } from "@textile/threads-core";
|
||||
const BUCKET_NAME = "data";
|
||||
|
||||
const TEXTILE_KEY_INFO = {
|
||||
key: process.env.TEXTILE_HUB_KEY,
|
||||
secret: process.env.TEXTILE_HUB_SECRET,
|
||||
key: Environment.TEXTILE_HUB_KEY,
|
||||
secret: Environment.TEXTILE_HUB_SECRET,
|
||||
};
|
||||
|
||||
export const parseAuthHeader = (value) => {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
|
||||
var matches = value.match(/(\S+)\s+(\S+)/);
|
||||
return matches && { scheme: matches[1], value: matches[2] };
|
||||
};
|
||||
|
||||
// NOTE(jim): Requires @textile/hub
|
||||
|
@ -68,6 +68,7 @@
|
||||
"react-tippy": "^1.3.4",
|
||||
"regenerator-runtime": "^0.13.5",
|
||||
"three": "^0.108.0",
|
||||
"universal-cookie": "^4.0.3",
|
||||
"uuid": "^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1,89 +1,14 @@
|
||||
import * as MW from "~/node_common/middleware";
|
||||
import * as Utilities from "~/node_common/utilities";
|
||||
import * as Constants from "~/node_common/constants";
|
||||
import * as Data from "~/node_common/data";
|
||||
|
||||
import PG from "~/node_common/powergate";
|
||||
import FS from "fs-extra";
|
||||
import path from "path";
|
||||
import * as Models from "~/node_common/models";
|
||||
|
||||
const initCORS = MW.init(MW.CORS);
|
||||
const initAuth = MW.init(MW.RequireCookieAuthentication);
|
||||
|
||||
export default async (req, res) => {
|
||||
initCORS(req, res);
|
||||
initAuth(req, res);
|
||||
|
||||
const user = await Data.getUserByUsername({
|
||||
username: req.body.data.username,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return res.status(200).json({ decorator: "SERVER_HYDRATE", error: true });
|
||||
}
|
||||
|
||||
if (user.error) {
|
||||
return res.status(200).json({ decorator: "SERVER_HYDRATE", error: true });
|
||||
}
|
||||
|
||||
const {
|
||||
buckets,
|
||||
bucketKey,
|
||||
bucketName,
|
||||
} = await Utilities.getBucketAPIFromUserToken(user.data.tokens.api);
|
||||
|
||||
// TODO(jim): This is obviously a test!
|
||||
// Slates will hold an index
|
||||
// Library will hold an index
|
||||
let data = {
|
||||
peersList: null,
|
||||
messageList: null,
|
||||
status: null,
|
||||
addrsList: null,
|
||||
info: null,
|
||||
state: null,
|
||||
local: {
|
||||
photo: null,
|
||||
name: `node`,
|
||||
settings_deals_auto_approve: false,
|
||||
},
|
||||
library: [
|
||||
{
|
||||
...Utilities.createFolder({ id: bucketName, name: "Data" }),
|
||||
children: [
|
||||
await Utilities.addFileFromFilePath({
|
||||
buckets,
|
||||
bucketKey,
|
||||
filePath: "./public/static/social.jpg",
|
||||
}),
|
||||
await Utilities.addFileFromFilePath({
|
||||
buckets,
|
||||
bucketKey,
|
||||
filePath: "./public/static/cube_000.jpg",
|
||||
}),
|
||||
await Utilities.addFileFromFilePath({
|
||||
buckets,
|
||||
bucketKey,
|
||||
filePath: "./public/static/cube_f7f7f7.jpg",
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// NOTE(jim): Should render a list of buckets.
|
||||
const roots = await buckets.list();
|
||||
console.log({ roots });
|
||||
|
||||
PG.setToken(user.data.tokens.pg);
|
||||
|
||||
const updates = await Utilities.refresh({ PG });
|
||||
const updatesWithToken = await Utilities.refreshWithToken({
|
||||
PG,
|
||||
});
|
||||
|
||||
data = await Utilities.updateStateData(data, {
|
||||
...updates,
|
||||
...updatesWithToken,
|
||||
});
|
||||
const data = await Models.getViewer({ username: req.body.data.username });
|
||||
|
||||
return res
|
||||
.status(200)
|
||||
|
80
pages/api/sign-in.js
Normal file
80
pages/api/sign-in.js
Normal file
@ -0,0 +1,80 @@
|
||||
import * as Environment from "~/node_common/environment";
|
||||
import * as MW from "~/node_common/middleware";
|
||||
import * as Utilities from "~/node_common/utilities";
|
||||
import * as Constants from "~/node_common/constants";
|
||||
import * as Credentials from "~/common/credentials";
|
||||
import * as Data from "~/node_common/data";
|
||||
import * as Strings from "~/common/strings";
|
||||
|
||||
import PG from "~/node_common/powergate";
|
||||
import FS from "fs-extra";
|
||||
import path from "path";
|
||||
import JWT from "jsonwebtoken";
|
||||
import BCrypt from "bcrypt";
|
||||
|
||||
const initCORS = MW.init(MW.CORS);
|
||||
|
||||
export default async (req, res) => {
|
||||
initCORS(req, res);
|
||||
|
||||
if (Strings.isEmpty(req.body.data.username)) {
|
||||
return res.status(500).send({ decorator: "SERVER_SIGN_IN", error: true });
|
||||
}
|
||||
|
||||
if (Strings.isEmpty(req.body.data.password)) {
|
||||
return res.status(500).send({ decorator: "SERVER_SIGN_IN", error: true });
|
||||
}
|
||||
|
||||
let user;
|
||||
try {
|
||||
user = await Data.getUserByUsername({ username: req.body.data.username });
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return res
|
||||
.status(403)
|
||||
.send({ decorator: "SERVER_SIGN_IN_FIND_USER", error: true });
|
||||
}
|
||||
|
||||
if (user.error) {
|
||||
return res
|
||||
.status(500)
|
||||
.send({ decorator: "SERVER_SIGN_IN_FIND_USER", error: true });
|
||||
}
|
||||
|
||||
const phaseOne = await BCrypt.hash(req.body.data.password, user.salt);
|
||||
const phaseTwo = await BCrypt.hash(phaseOne, user.salt);
|
||||
const phaseThree = await BCrypt.hash(
|
||||
phaseTwo,
|
||||
Environment.LOCAL_PASSWORD_SECRET
|
||||
);
|
||||
|
||||
if (phaseThree !== user.password) {
|
||||
return res
|
||||
.status(403)
|
||||
.send({ decorator: "SERVER_SIGN_IN_AUTH", error: true });
|
||||
}
|
||||
|
||||
const authorization = Utilities.parseAuthHeader(req.headers.authorization);
|
||||
if (authorization && !Strings.isEmpty(authorization.value)) {
|
||||
const verfied = JWT.verify(authorization.value, Environment.JWT_SECRET);
|
||||
|
||||
if (user.username === verfied.username) {
|
||||
return res.status(200).send({
|
||||
message: "You are already authenticated. Welcome back!",
|
||||
viewer: user,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const token = JWT.sign(
|
||||
{ user: user.id, username: user.username },
|
||||
Environment.JWT_SECRET
|
||||
);
|
||||
|
||||
return res
|
||||
.status(200)
|
||||
.send({ decorator: "SERVER_SIGN_IN", success: true, token });
|
||||
};
|
@ -1,6 +1,8 @@
|
||||
import * as MW from "~/node_common/middleware";
|
||||
import * as Data from "~/node_common/data";
|
||||
import * as Strings from "~/common/strings";
|
||||
import * as Environment from "~/node_common/environment";
|
||||
import * as Utilities from "~/node_common/utilities";
|
||||
|
||||
import PG from "~/node_common/powergate";
|
||||
import JWT from "jsonwebtoken";
|
||||
@ -9,7 +11,6 @@ import BCrypt from "bcrypt";
|
||||
import { Libp2pCryptoIdentity } from "@textile/threads-core";
|
||||
|
||||
const initCORS = MW.init(MW.CORS);
|
||||
const SECRET = `$2b$13$${process.env.LOCAL_PASSWORD_SECRET}`;
|
||||
|
||||
export default async (req, res) => {
|
||||
initCORS(req, res);
|
||||
@ -29,7 +30,7 @@ export default async (req, res) => {
|
||||
const salt = await BCrypt.genSalt(13);
|
||||
const hash = await BCrypt.hash(req.body.data.password, salt);
|
||||
const double = await BCrypt.hash(hash, salt);
|
||||
const triple = await BCrypt.hash(double, SECRET);
|
||||
const triple = await BCrypt.hash(double, Environment.LOCAL_PASSWORD_SECRET);
|
||||
|
||||
const FFS = await PG.ffs.create();
|
||||
const pg = FFS.token ? FFS.token : null;
|
||||
@ -38,12 +39,46 @@ export default async (req, res) => {
|
||||
const identity = await Libp2pCryptoIdentity.fromRandom();
|
||||
const api = identity.toString();
|
||||
|
||||
// TODO(jim):
|
||||
// Don't do this once you refactor.
|
||||
const {
|
||||
buckets,
|
||||
bucketKey,
|
||||
bucketName,
|
||||
} = await Utilities.getBucketAPIFromUserToken(api);
|
||||
|
||||
const user = await Data.createUser({
|
||||
email: req.body.data.email,
|
||||
password: triple,
|
||||
salt,
|
||||
username: req.body.data.username,
|
||||
data: { tokens: { pg, api } },
|
||||
data: {
|
||||
tokens: { pg, api },
|
||||
// TODO(jim):
|
||||
// Get rid of this after the refactor.
|
||||
library: [
|
||||
{
|
||||
...Utilities.createFolder({ id: bucketName, name: "Data" }),
|
||||
children: [
|
||||
await Utilities.addFileFromFilePath({
|
||||
buckets,
|
||||
bucketKey,
|
||||
filePath: "./public/static/social.jpg",
|
||||
}),
|
||||
await Utilities.addFileFromFilePath({
|
||||
buckets,
|
||||
bucketKey,
|
||||
filePath: "./public/static/cube_000.jpg",
|
||||
}),
|
||||
await Utilities.addFileFromFilePath({
|
||||
buckets,
|
||||
bucketKey,
|
||||
filePath: "./public/static/cube_f7f7f7.jpg",
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import * as Environment from "~/node_common/environment";
|
||||
import * as MW from "~/node_common/middleware";
|
||||
import * as Data from "~/node_common/data";
|
||||
|
||||
@ -7,8 +8,8 @@ import { Libp2pCryptoIdentity } from "@textile/threads-core";
|
||||
const initCORS = MW.init(MW.CORS);
|
||||
|
||||
const TEXTILE_KEY_INFO = {
|
||||
key: process.env.TEXTILE_HUB_KEY,
|
||||
secret: process.env.TEXTILE_HUB_SECRET,
|
||||
key: Environment.TEXTILE_HUB_KEY,
|
||||
secret: Environment.TEXTILE_HUB_SECRET,
|
||||
};
|
||||
|
||||
export default async (req, res) => {
|
||||
|
@ -2,6 +2,7 @@ import * as React from "react";
|
||||
import * as NavigationData from "~/common/navigation-data";
|
||||
import * as Actions from "~/common/actions";
|
||||
import * as State from "~/common/state";
|
||||
import * as Credentials from "~/common/credentials";
|
||||
|
||||
import SceneDataTransfer from "~/scenes/SceneDataTransfer";
|
||||
import SceneDeals from "~/scenes/SceneDeals";
|
||||
@ -38,6 +39,9 @@ import ApplicationNavigation from "~/components/core/ApplicationNavigation";
|
||||
import ApplicationHeader from "~/components/core/ApplicationHeader";
|
||||
import ApplicationLayout from "~/components/core/ApplicationLayout";
|
||||
import WebsitePrototypeWrapper from "~/components/core/WebsitePrototypeWrapper";
|
||||
import Cookies from "universal-cookie";
|
||||
|
||||
const cookies = new Cookies();
|
||||
|
||||
const getCurrentNavigationStateById = (navigation, targetId) => {
|
||||
let target = null;
|
||||
@ -79,8 +83,8 @@ export default class ApplicationPage extends React.Component {
|
||||
history: [{ id: 1, scrollTop: 0 }],
|
||||
currentIndex: 0,
|
||||
data: null,
|
||||
selected: null,
|
||||
viewer: null,
|
||||
selected: State.getSelectedState(this.props.viewer),
|
||||
viewer: State.getInitialState(this.props.viewer),
|
||||
sidebar: null,
|
||||
file: null,
|
||||
};
|
||||
@ -204,18 +208,48 @@ export default class ApplicationPage extends React.Component {
|
||||
|
||||
console.log(response);
|
||||
|
||||
response = await Actions.signIn({
|
||||
username: "test",
|
||||
password: "test",
|
||||
});
|
||||
|
||||
console.log(response);
|
||||
|
||||
if (response.error) {
|
||||
console.log("authentication error");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response.token) {
|
||||
cookies.set(Credentials.session.key, response.token);
|
||||
}
|
||||
|
||||
response = await Actions.hydrateAuthenticatedUser({
|
||||
username: "test",
|
||||
});
|
||||
|
||||
console.log(response);
|
||||
|
||||
if (!response || response.error) {
|
||||
console.log("You probably needed to be authenticated.");
|
||||
return null;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
viewer: State.getInitialState(response.data),
|
||||
selected: State.getSelectedState(response.data),
|
||||
});
|
||||
};
|
||||
|
||||
_handleSignOut = () => {
|
||||
const jwt = cookies.get(Credentials.session.key);
|
||||
|
||||
if (jwt) {
|
||||
cookies.remove(Credentials.session.key);
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
_handleViewerChange = (e) => {
|
||||
this.setState({
|
||||
viewer: { ...this.state.viewer, [e.target.name]: e.target.value },
|
||||
@ -348,7 +382,6 @@ export default class ApplicationPage extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
// TODO(jim): Render Sign In Screen.
|
||||
if (!this.state.viewer) {
|
||||
return (
|
||||
<WebsitePrototypeWrapper
|
||||
@ -390,6 +423,7 @@ export default class ApplicationPage extends React.Component {
|
||||
history={this.state.history}
|
||||
onNavigateTo={this._handleNavigateTo}
|
||||
onAction={this._handleAction}
|
||||
onSignOut={this._handleSignOut}
|
||||
/>
|
||||
);
|
||||
|
||||
|
29
server.js
29
server.js
@ -1,15 +1,12 @@
|
||||
if (process.env.NODE_ENV !== "www") {
|
||||
require("dotenv").config();
|
||||
}
|
||||
|
||||
import * as Environment from "~/node_common/environment";
|
||||
import * as Strings from "./common/strings";
|
||||
import * as Middleware from "./node_common/middleware";
|
||||
import * as Utilities from "./node_common/utilities";
|
||||
import * as Constants from "./node_common/constants";
|
||||
import * as Models from "./node_common/models";
|
||||
|
||||
import express from "express";
|
||||
import next from "next";
|
||||
import compression from "compression";
|
||||
import JWT from "jsonwebtoken";
|
||||
|
||||
const production =
|
||||
process.env.NODE_ENV === "production" || process.env.NODE_ENV === "www";
|
||||
@ -27,9 +24,29 @@ app.prepare().then(async () => {
|
||||
server.use("/public", express.static("public"));
|
||||
|
||||
server.get("/application", async (req, res) => {
|
||||
let viewer = null;
|
||||
|
||||
if (!Strings.isEmpty(req.headers.cookie)) {
|
||||
const token = req.headers.cookie.replace(
|
||||
/(?:(?:^|.*;\s*)WEB_SERVICE_SESSION_KEY\s*\=\s*([^;]*).*$)|^.*$/,
|
||||
"$1"
|
||||
);
|
||||
|
||||
if (!Strings.isEmpty(token)) {
|
||||
try {
|
||||
const decoded = JWT.verify(token, Environment.JWT_SECRET);
|
||||
|
||||
if (decoded.username) {
|
||||
viewer = await Models.getViewer({ username: decoded.username });
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
return app.render(req, res, "/application", {
|
||||
wsPort: null,
|
||||
production: productionWeb,
|
||||
viewer,
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user