Skip to content

Commit

Permalink
Merge pull request #102 from UW-Macrostrat/edit-ssr
Browse files Browse the repository at this point in the history
Edit ssr
  • Loading branch information
CannonLock authored Dec 19, 2023
2 parents 1a1b4b3 + cde4aa9 commit b65207c
Show file tree
Hide file tree
Showing 43 changed files with 2,289 additions and 25 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ VITE_MACROSTRAT_TILESERVER_V2='https://dev.macrostrat.org/tiles'
VITE_MACROSTRAT_TILESERVER_V1='https://tiles.macrostrat.org'
VITE_MACROSTRAT_TILESERVER_DOMAIN='https://dev.macrostrat.org/tiles'
VITE_MACROSTRAT_API_DOMAIN='https://macrostrat.org'
VITE_MACROSTRAT_INGEST_API=https://dev.macrostrat.org/api/ingest
VITE_CORELLE_API_DOMAIN='https://rotate.macrostrat.org'
PUBLIC_URL='/'
PUBLIC_URL='/'
SECRET_KEY='Replace with api signing key'
8 changes: 6 additions & 2 deletions .github/workflows/build-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: Build Development

on:
push:
branches: [ '**' ]
tags:
- v[0-9]+.[0-9]+.[0-9]+-** # Semver Pre-Release
pull_request:
Expand All @@ -25,7 +26,10 @@ jobs:
tags: |
type=semver,pattern={{version}}
type=raw,value=latest-itb
type=ref,enable=true,prefix=pr-,suffix=-{{date 'YYYYMMDDHHmmss'}},event=pr
type=ref,event=pr,suffix=-{{date 'YYYYMMDDHHmmss'}}
type=ref,event=branch,suffix=-{{date 'YYYYMMDDHHmmss'}}
type=ref,event=tag,suffix=-{{date 'YYYYMMDDHHmmss'}}
type=raw,value=latest-itb-{{date 'YYYYMMDDHHmmss'}}
type=raw,value=sha-{{sha}}
-
name: Set up Docker Buildx
Expand All @@ -39,7 +43,7 @@ jobs:
password: ${{ secrets.HARBOR_CLI_SECRET }}
-
name: Build and push
uses: docker/build-push-action@v3
uses: docker/build-push-action@v5
with:
context: .
push: true
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/build-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ jobs:
with:
images: hub.opensciencegrid.org/macrostrat/web
tags: |
type=ref,event=pr,suffix=-{{date 'YYYYMMDDHHmmss'}}
type=ref,event=branch,suffix=-{{date 'YYYYMMDDHHmmss'}}
type=semver,pattern={{version}}
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=sha-{{sha}}
Expand All @@ -36,7 +38,7 @@ jobs:
password: ${{ secrets.HARBOR_CLI_SECRET }}
-
name: Build and push
uses: docker/build-push-action@v3
uses: docker/build-push-action@v5
with:
context: .
push: true
Expand Down
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM node:20 AS build

ENV NODE_ENV=production

WORKDIR /usr/src/app
COPY . ./

RUN yarn cache clean
RUN yarn add

CMD ["sh", "server/server.sh"]
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"bootstrap": "yarn",
"dev": "yarn run server:dev",
"build": "vite build",
"server": "node ./server/index.js",
"server": "node --env-file=.env ./server/index.js",
"server:dev": "yarn run server",
"server:prod": "cross-env NODE_ENV=production npm run server"
},
Expand Down Expand Up @@ -47,10 +47,12 @@
"dependencies": {
"@blueprintjs/core": "^4.14.1",
"@blueprintjs/select": "4",
"@blueprintjs/table": "^4",
"@lagunovsky/redux-react-router": "^3.2.0",
"@loadable/component": "^5.14.1",
"@macrostrat-web/data-sheet-test": "workspace:*",
"@macrostrat-web/globe": "workspace:*",
"@macrostrat-web/security": "workspace:*",
"@macrostrat/api-utils": "workspace:*",
"@macrostrat/api-views": "workspace:*",
"@macrostrat/column-components": "workspace:*",
Expand Down Expand Up @@ -85,6 +87,7 @@
"chroma-js": "^2.4.2",
"classnames": "^2.2.6",
"compression": "^1.7.4",
"cookie-parser": "^1.4.6",
"cross-env": "^7.0.3",
"d3-array": "^3.1.1",
"d3-axis": "^3.0.0",
Expand All @@ -97,6 +100,7 @@
"express": "^4.18.2",
"history": "^5.3.0",
"immutability-helper": "^3.1.1",
"jose": "^5.1.2",
"mapbox-gl": "^2.15.0",
"new-github-issue-url": "^1.0.0",
"pbf": "^3.2.1",
Expand All @@ -119,9 +123,10 @@
"topojson-client": "^3.0.0",
"transition-hook": "^1.5.2",
"ts-node": "^10.9.1",
"use-debounce": "^9.0.4",
"use-react-router-breadcrumbs": "^3.2.1",
"use-resize-observer": "^9.1.0",
"vike": "^0.4.150",
"vike": "0.4.150-commit-63b1c32",
"vite": "^4.4.9",
"vite-plugin-cesium": "^1.2.22"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/globe-dev/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import Map from "./map-comparison";
import {
getMapPositionForHash,
applyMapPositionToHash,
} from "/Users/Daven/Projects/Macrostrat/Software/web/src/pages/map/map-interface/app-state/reducers/hash-string";
} from "../../../src/pages/map/map-interface/app-state/reducers/hash-string";

function VisControl({ show, setShown, name }) {
const className = show ? "active" : "";
Expand Down
6 changes: 6 additions & 0 deletions packages/security/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "@macrostrat-web/security",
"private": true,
"main": "src/index.ts",
"license": "ISC"
}
22 changes: 22 additions & 0 deletions packages/security/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

// Handles fetch requests that require authentication
export const secureFetch = async (url, options) => {

options = {
credentials: "include",
...options,
}

const response = await fetch(url, options);

if (response.status === 401 || response.status === 403) {

const url = new URL(`${import.meta.env.VITE_MACROSTRAT_INGEST_API}/security/login`);
url.searchParams.append("return_url", `${window.location.origin}/dev/security/endpoint`);

window.open(url, '_blank').focus();
throw {name: "UnauthorizedError", message: "User is not logged in"}
}

return response
}
34 changes: 29 additions & 5 deletions server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@
// - To use your environment variables defined in your .env files, you need to install dotenv, see https://vike.dev/env
// - To use your path aliases defined in your vite.config.js, you need to tell Node.js about them, see https://vike.dev/path-aliases

import express from "express";
import compression from "compression";
import express from "express"
import compression from "compression"
import { renderPage } from "vike/server";
import { root } from "./root.js";
const isProduction = process.env.NODE_ENV === "production";
import { root } from "./root.js"

// Auth imports
import cookieParser from "cookie-parser"
import * as jose from "jose"

const isProduction = process.env.NODE_ENV === "production"

startServer();

async function startServer() {
const app = express();

app.use(compression());
app.use(cookieParser());

// Vite integration
if (isProduction) {
Expand Down Expand Up @@ -43,9 +49,27 @@ async function startServer() {

// vike middleware. It should always be our last middleware (because it's a
// catch-all middleware superseding any middleware placed after it).
app.get("*", async (req, res, next) => {
app.get('*', async (req, res, next) => {

// Pull out the authorization cookie and decrypt it
let user = undefined

try {
const authHeader = req.cookies?.Authorization
const secret = new TextEncoder().encode(
process.env.SECRET_KEY
);
const jwt = authHeader.substring(7, authHeader.length)
user = (await jose.jwtVerify(jwt, secret)).payload


} catch (e) {
// I don't care if it fails, it just means the user isn't logged in
}

const pageContextInit = {
urlOriginal: req.originalUrl,
user: user
};

const pageContext = await renderPage(pageContextInit);
Expand Down
25 changes: 24 additions & 1 deletion src/components/map-navbar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@ export function ParentRouteButton({
return h(LinkButton, { to: "..", icon, minimal: true, ...rest });
}

export function MapNavbar({ title, isOpen, setOpen, parentRoute }) {
export function MapNavbar({
title,
isOpen,
setOpen,
parentRoute,
minimal = false,
}) {
if (minimal) {
return MapMinimalNavbar({ isOpen, setOpen });
}
const { isLoading } = useMapStatus();
return h(FloatingNavbar, { className: "searchbar map-navbar" }, [
h([h(ParentRouteButton, { parentRoute }), h("h2.map-title", title)]),
Expand All @@ -32,3 +41,17 @@ export function MapNavbar({ title, isOpen, setOpen, parentRoute }) {
}),
]);
}

function MapMinimalNavbar({ isOpen, setOpen }) {
const { isLoading } = useMapStatus();
return h("div.map-minimal-navbar map-navbar", [
h(FloatingNavbar, { className: "searchbar" }, [
h(MapLoadingButton, {
active: isOpen,
onClick: () => setOpen(!isOpen),
isLoading,
}),
]),
h("div.spacer"),
]);
}
8 changes: 8 additions & 0 deletions src/components/map-navbar/main.module.sass
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@
.map-title
// Allow the title to wrap on hover
overflow-x: visible

.map-minimal-navbar
display: flex
flex-direction: row
&>.spacer
flex-grow: 1
.map-navbar
min-width: 0
9 changes: 9 additions & 0 deletions src/pages/dev/security/endpoint/index.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {default as h} from "@macrostrat/hyper";

export function Page() {

return h("div", [
h("span", "You are logged in, you can now close this tab.")
]);
}

20 changes: 20 additions & 0 deletions src/pages/dev/security/index.page.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { render, redirect } from 'vike/abort'

export const guard = (pageContext) => {
const { user } = pageContext

console.log("User: ", user)

if (user === undefined) {
// Render the login page while preserving the URL. (This is novel technique
// which we explain down below.)
throw redirect(`${import.meta.env.VITE_MACROSTRAT_INGEST_API}/security/login?return_url=${pageContext.url}`)
/* The more traditional way, redirect the user:
throw redirect('/login')
*/
}
if (!user.groups.includes(1)) {
// Render the error page and show message to the user
return render(403, 'Only admins are allowed to access this page.')
}
}
9 changes: 9 additions & 0 deletions src/pages/dev/security/index.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {default as h} from "@macrostrat/hyper";

export function Page() {

return h("div", [
h("h1", "Secure Page")
]);
}

1 change: 1 addition & 0 deletions src/pages/map/map-interface/app-state/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export default appReducer;
export * from "./core";
export * from "./map";
export * from "./types";
export * from "./hash-string";

/*
function overallReducer(state: AppState, action: Action): AppState {
Expand Down
20 changes: 20 additions & 0 deletions src/pages/maps/@id/edit/components/cell/editable-cell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

import {EditableCell2, EditableCell2Props} from "@blueprintjs/table";

import hyper from "@macrostrat/hyper";
import styles from "./main.module.sass";
import { getTableUpdate } from "~/pages/maps/@id/edit/table-util";

export const h = hyper.styled(styles);


interface EditableCell extends EditableCell2Props {
columnName: string,
rowIndex: number
}

export const EditableCell = ({...props}: EditableCell2Props) => {

return h(EditableCell2, {...props});
}
19 changes: 19 additions & 0 deletions src/pages/maps/@id/edit/components/cell/editor-popover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {Button, MenuItem} from "@blueprintjs/core";
import {Select2, ItemRenderer} from "@blueprintjs/select";
import {EditableCell2Props} from "@blueprintjs/table";
import React, {useEffect, useMemo} from "react";

// @ts-ignore
import hyper from "@macrostrat/hyper";

import "@blueprintjs/core/lib/css/blueprint.css"
import "@blueprintjs/select/lib/css/blueprint-select.css";
import styles from "../../edit-table.module.sass";


const h = hyper.styled(styles);


export const EditorPopover = () => {

}
4 changes: 4 additions & 0 deletions src/pages/maps/@id/edit/components/cell/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface CellProps extends React.HTMLProps<HTMLTableCellElement> {
value: string;
onChange: (value: string) => void;
}
Loading

0 comments on commit b65207c

Please sign in to comment.