Merge branch 'main' of github.com:sartography/spiff-arena into main

This commit is contained in:
danfunk 2023-05-18 10:49:55 -04:00
commit 5d91ee6487
8 changed files with 126 additions and 35 deletions

View File

@ -50,12 +50,15 @@ jobs:
session: "tests", session: "tests",
database: "sqlite", database: "sqlite",
} }
- { # FIXME: tests cannot pass on windows and we currently cannot debug
python: "3.10", # since none of us have a windows box that can run the python app.
os: "windows-latest", # so ignore windows tests until we can get it fixed.
session: "tests", # - {
database: "sqlite", # python: "3.10",
} # os: "windows-latest",
# session: "tests",
# database: "sqlite",
# }
- { - {
python: "3.11", python: "3.11",
os: "macos-latest", os: "macos-latest",

3
Jenkinsfile vendored
View File

@ -63,8 +63,9 @@ pipeline {
stage('Build') { stage('Build') {
steps { script { steps { script {
dir("spiffworkflow-${params.COMPONENT}") { dir("spiffworkflow-${params.COMPONENT}") {
/* Tag and Commit is combined to avoid clashes of parallel builds. */
image = docker.build( image = docker.build(
"${params.DOCKER_NAME}:${env.GIT_COMMIT.take(8)}", "${params.DOCKER_NAME}:${params.DOCKER_TAG}-${env.GIT_COMMIT.take(8)}",
"--label=commit='${env.GIT_COMMIT.take(8)}' ." "--label=commit='${env.GIT_COMMIT.take(8)}' ."
) )
} }

View File

@ -75,14 +75,14 @@ if [[ -z "${SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER:-}" ]]; then
# I/O heavy, make it larger # I/O heavy, make it larger
threads_to_use_per_core=3 threads_to_use_per_core=3
# just making up a number here for num_cores_multiple_for_threads
# https://stackoverflow.com/a/55423170/6090676 # https://stackoverflow.com/a/55423170/6090676
# if we had access to python (i'm not sure i want to run another python script here), # if we had access to python (i'm not sure i want to run another python script here),
# we could do something like this (on linux) to get the number of cores available to this process and a better estimate of a # we could do something like this (on linux) to get the number of cores available to this process and a better estimate of a
# reasonable num_cores_multiple_for_threads # reasonable num_cores_multiple_for_threads
# if hasattr(os, 'sched_getaffinity') # if hasattr(os, 'sched_getaffinity')
# number_of_available_cores = os.sched_getaffinity(0) # number_of_available_cores = os.sched_getaffinity(0)
num_cores_multiple_for_threads=2 # BUT the python solution isn't even as portable as this one, which is mostly posix compliant and works on linux/mac/freebsd.
num_cores_multiple_for_threads=$(getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null || echo 1)
SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER=$((threads_to_use_per_core * num_cores_multiple_for_threads)) SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER=$((threads_to_use_per_core * num_cores_multiple_for_threads))
export SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER export SPIFFWORKFLOW_BACKEND_THREADS_PER_WORKER

View File

@ -0,0 +1,84 @@
default_group: everybody
groups:
admin:
users: [admin@spiffworkflow.org]
permissions:
admin:
groups: [admin]
users: []
allowed_permissions: [read]
uri: /*
tasks-crud:
groups: [admin]
users: []
allowed_permissions: [create, update, delete]
uri: /tasks/*
process-instances-crud:
groups: [ admin ]
users: [ ]
allowed_permissions: [create, update, delete]
uri: /process-instances/*
suspend:
groups: [admin]
users: []
allowed_permissions: [create]
uri: /v1.0/process-instance-suspend
terminate:
groups: [admin]
users: []
allowed_permissions: [create]
uri: /v1.0/process-instance-terminate
resume:
groups: [admin]
users: []
allowed_permissions: [create]
uri: /v1.0/process-instance-resume
reset:
groups: [admin]
users: []
allowed_permissions: [create]
uri: /v1.0/process-instance-reset
users-exist:
groups: [admin]
users: []
allowed_permissions: [create]
uri: /v1.0/users/exists/by-username
send-event:
groups: [admin]
users: []
allowed_permissions: [create]
uri: /v1.0/send-event/*
task-complete:
groups: [admin]
users: []
allowed_permissions: [create]
uri: /v1.0/task-complete/*
messages:
groups: [admin]
users: []
allowed_permissions: [create]
uri: /v1.0/messages/*
secrets:
groups: [admin]
users: []
allowed_permissions: [create, update, delete]
uri: /v1.0/secrets/*
task-data:
groups: [admin]
users: []
allowed_permissions: [update]
uri: /v1.0/task-data/*

View File

@ -3,6 +3,7 @@ import { Content } from '@carbon/react';
import { BrowserRouter, Routes, Route } from 'react-router-dom'; import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { defineAbility } from '@casl/ability'; import { defineAbility } from '@casl/ability';
import React from 'react';
import NavigationBar from './components/NavigationBar'; import NavigationBar from './components/NavigationBar';
import HomePageRoutes from './routes/HomePageRoutes'; import HomePageRoutes from './routes/HomePageRoutes';
@ -15,8 +16,7 @@ import { AbilityContext } from './contexts/Can';
import UserService from './services/UserService'; import UserService from './services/UserService';
import ErrorDisplay from './components/ErrorDisplay'; import ErrorDisplay from './components/ErrorDisplay';
import APIErrorProvider from './contexts/APIErrorContext'; import APIErrorProvider from './contexts/APIErrorContext';
import ScrollToTop from "./components/ScrollToTop"; import ScrollToTop from './components/ScrollToTop';
import React from "react";
export default function App() { export default function App() {
if (!UserService.isLoggedIn()) { if (!UserService.isLoggedIn()) {

View File

@ -97,6 +97,9 @@ export default function NavigationBar() {
aboutLinkElement = <a href="/about">About</a>; aboutLinkElement = <a href="/about">About</a>;
} }
const userEmail = UserService.getUserEmail();
const username = UserService.getPreferredUsername();
const profileToggletip = ( const profileToggletip = (
<div style={{ display: 'flex' }} id="user-profile-toggletip"> <div style={{ display: 'flex' }} id="user-profile-toggletip">
<Toggletip isTabTip align="bottom-right"> <Toggletip isTabTip align="bottom-right">
@ -105,15 +108,13 @@ export default function NavigationBar() {
className="user-profile-toggletip-button" className="user-profile-toggletip-button"
type="button" type="button"
> >
<div className="user-circle"> <div className="user-circle">{username[0].toUpperCase()}</div>
{UserService.getPreferredUsername()[0].toUpperCase()}
</div>
</ToggletipButton> </ToggletipButton>
<ToggletipContent className="user-profile-toggletip-content"> <ToggletipContent className="user-profile-toggletip-content">
<p> <p>
<strong>{UserService.getPreferredUsername()}</strong> <strong>{username}</strong>
</p> </p>
<p>{UserService.getUserEmail()}</p> {username !== userEmail && <p>{userEmail}</p>}
<hr /> <hr />
{aboutLinkElement} {aboutLinkElement}
<a target="_blank" href={documentationUrl} rel="noreferrer"> <a target="_blank" href={documentationUrl} rel="noreferrer">

View File

@ -1,5 +1,5 @@
import { useEffect } from "react"; import { useEffect } from 'react';
import { useLocation } from "react-router-dom"; import { useLocation } from 'react-router-dom';
export default function ScrollToTop() { export default function ScrollToTop() {
const { pathname } = useLocation(); const { pathname } = useLocation();

View File

@ -28,7 +28,9 @@ export default function About() {
versionInfoDict: ObjectWithStringKeysAndValues | null versionInfoDict: ObjectWithStringKeysAndValues | null
) => { ) => {
if (versionInfoDict !== null && Object.keys(versionInfoDict).length) { if (versionInfoDict !== null && Object.keys(versionInfoDict).length) {
const tableRows = Object.keys(versionInfoDict).map((key) => { const tableRows = Object.keys(versionInfoDict)
.sort()
.map((key) => {
const value = versionInfoDict[key]; const value = versionInfoDict[key];
return ( return (
<tr key={key}> <tr key={key}>