Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
2 changes: 1 addition & 1 deletion .github/workflows/reuse-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout git repository
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand Down
12 changes: 5 additions & 7 deletions .github/workflows/reuse-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout git repository
uses: actions/checkout@v4
- uses: actions/setup-node@v3
uses: actions/checkout@v5

- uses: actions/setup-node@v5
with:
node-version: 24
cache: 'npm'

- name: Install dependencies
run: |
npm ci --no-audit --no-fund --omit=optional
npm i --no-save @rollup/rollup-linux-x64-gnu
run: npm ci

- name: Run quality checks
run: npm run quality
Expand Down
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
data/
node_modules/
worker/config/local-*
api/config/local-*
**/config/local-*
.config/
.type/
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ FROM node:24.11.1-alpine3.22 AS base

WORKDIR /app
ENV NODE_ENV=production
ENV DEBUG=upgrade*

# =============================
# Package preparation (stripping version for caching)
Expand Down
18 changes: 9 additions & 9 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,24 @@
"@types/ws": "^8.5.12"
},
"dependencies": {
"@data-fair/lib-express": "^1.20.4",
"@data-fair/lib-node": "^2.8.1",
"@data-fair/lib-utils": "^1.6.1",
"@data-fair/lib-express": "^1.22.5",
"@data-fair/lib-node": "^2.12.1",
"@data-fair/lib-utils": "^1.10.1",
"@data-fair/processings-shared": "*",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"config": "^4.0.0",
"config": "^4.4.1",
"crypto-random-string": "^5.0.0",
"express": "^5.0.1",
"fs-extra": "^11.2.0",
"express": "^5.2.0",
"fs-extra": "^11.3.0",
"http-terminator": "^3.2.0",
"memoizee": "^0.4.17",
"mongodb": "^6.10.0",
"multer": "^2.0.1",
"mongodb": "^6.17.0",
"multer": "^2.0.2",
"nanoid": "^5.0.8",
"resolve-path": "^1.4.0",
"semver": "^7.7.4",
"tmp-promise": "^3.0.3",
"ws": "^8.18.0"
"ws": "^8.18.2"
}
}
5 changes: 2 additions & 3 deletions api/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { assertValid, type ApiConfig } from '../config/type/index.ts'
import type { ApiConfig } from '../config/type/index.ts'
import { assertValid } from '../config/type/index.ts'
import config from 'config'

// we reload the config instead of using the singleton from the config module for testing purposes
// @ts-ignore
const apiConfig = process.env.NODE_ENV === 'test' ? config.util.loadFileConfigs(process.env.NODE_CONFIG_DIR, { skipConfigSources: true }) : config
assertValid(apiConfig, { lang: 'en', name: 'config', internal: true })

config.util.makeImmutable(apiConfig)

export default apiConfig as ApiConfig

export const uiConfig = {
Expand Down
14 changes: 8 additions & 6 deletions api/src/limits/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ const isAccountMember = async (req: Request, res: Response, next: NextFunction)
const sessionState = await session.req(req)
if (!sessionState.user) return res.status(401).send()
if (sessionState.user.adminMode) return next()
if (!['organization', 'user'].includes(req.params.type)) return res.status(400).send('Wrong consumer type')
if (req.params.type === 'user') {
if (sessionState.user.id !== req.params.id) return res.status(403).send()
const type = req.params.type as string
const id = req.params.id as string
if (!['organization', 'user'].includes(type)) return res.status(400).send('Wrong consumer type')
if (type === 'user') {
if (sessionState.user.id !== id) return res.status(403).send()
}
if (req.params.type === 'organization') {
const org = sessionState.user.organizations.find(o => o.id === req.params.id)
if (type === 'organization') {
const org = sessionState.user.organizations.find(o => o.id === id)
if (!org) return res.status(403).send()
}
next()
Expand All @@ -49,7 +51,7 @@ router.post('/:type/:id', async (req, res) => {

// A user can get limits information for himself only
router.get('/:type/:id', isAccountMember, async (req, res) => {
const consumer = { type: req.params.type as 'organization' | 'user', id: req.params.id, name: req.params.id, department: '' }
const consumer = { type: req.params.type as 'organization' | 'user', id: req.params.id as string, name: req.params.id as string, department: '' }
const limits = await getLimits(mongo.db, consumer)
if (!limits) return res.status(404).send()
if ('_id' in limits) delete limits._id
Expand Down
30 changes: 17 additions & 13 deletions api/src/plugins/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,18 +258,20 @@ router.get('/:id', async (req, res) => {
})

router.delete('/:id', permissions.isSuperAdmin, async (req, res) => {
if (!req.params.id) throw httpError(400, 'Plugin ID is required')
if (!fs.existsSync(path.join(pluginsDir, req.params.id))) throw httpError(404, 'Plugin not found')

await fs.remove(path.join(pluginsDir, req.params.id))
await fs.remove(path.join(pluginsDir, req.params.id + '-config.json'))
await fs.remove(path.join(pluginsDir, req.params.id + '-access.json'))
await fs.remove(path.join(pluginsDir, req.params.id + '-metadata.json'))
const id = req.params.id as string
if (!id) throw httpError(400, 'Plugin ID is required')
if (!fs.existsSync(path.join(pluginsDir, id))) throw httpError(404, 'Plugin not found')

await fs.remove(path.join(pluginsDir, id))
await fs.remove(path.join(pluginsDir, id + '-config.json'))
await fs.remove(path.join(pluginsDir, id + '-access.json'))
await fs.remove(path.join(pluginsDir, id + '-metadata.json'))
res.status(204).send()
})

router.put('/:id/config', permissions.isSuperAdmin, async (req, res) => {
const pluginPath = path.join(pluginsDir, req.params.id, 'plugin.json')
const id = req.params.id as string
const pluginPath = path.join(pluginsDir, id, 'plugin.json')
if (!await fs.pathExists(pluginPath)) {
throw httpError(404, 'Plugin not found')
}
Expand All @@ -278,27 +280,29 @@ router.put('/:id/config', permissions.isSuperAdmin, async (req, res) => {
const validate = ajv.compile(pluginConfigSchema)
const valid = validate(req.body)
if (!valid) return res.status(400).send(validate.errors)
await fs.writeJson(path.join(pluginsDir, req.params.id + '-config.json'), req.body)
await fs.writeJson(path.join(pluginsDir, id + '-config.json'), req.body)
res.send(req.body)
})

router.put('/:id/metadata', permissions.isSuperAdmin, async (req, res) => {
if (!await fs.pathExists(path.join(pluginsDir, req.params.id, 'plugin.json'))) {
const id = req.params.id as string
if (!await fs.pathExists(path.join(pluginsDir, id, 'plugin.json'))) {
throw httpError(404, 'Plugin not found')
}

const validate = ajv.compile(pluginMetadataSchema)
const valid = validate(req.body)
if (!valid) return res.status(400).send(validate.errors)
await fs.writeJson(path.join(pluginsDir, req.params.id + '-metadata.json'), req.body)
await fs.writeJson(path.join(pluginsDir, id + '-metadata.json'), req.body)
res.send(req.body)
})

router.put('/:id/access', permissions.isSuperAdmin, async (req, res) => {
if (!await fs.pathExists(path.join(pluginsDir, req.params.id, 'plugin.json'))) {
const id = req.params.id as string
if (!await fs.pathExists(path.join(pluginsDir, id, 'plugin.json'))) {
throw httpError(404, 'Plugin not found')
}

await fs.writeJson(path.join(pluginsDir, req.params.id + '-access.json'), req.body)
await fs.writeJson(path.join(pluginsDir, id + '-access.json'), req.body)
res.send(req.body)
})
19 changes: 11 additions & 8 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ services:
# reverse proxy for the whole environment
#####
nginx:
image: nginx:1.23.1-alpine
image: nginx:1.29.4-alpine
network_mode: host
volumes:
- ./dev/resources/nginx.conf:/etc/nginx/nginx.conf:ro
Expand All @@ -29,20 +29,21 @@ services:
- MAILDEV_ACTIVE=true
- MONGO_URL=mongodb://localhost:27017/simple-directory
- STORAGE_TYPE=file
- AUTHRATELIMIT_ATTEMPTS=200
- AUTHRATELIMIT_ATTEMPTS=500
- AUTHRATELIMIT_DURATION=30
- OBSERVER_ACTIVE=false
- MANAGE_PARTNERS=true
- MANAGE_DEPARTMENTS=true
- CIPHER_PASSWORD=cipherpassword
- CIPHER_PASSWORD=dev
volumes:
- ./dev/resources/users.json:/webapp/data/users.json
- ./dev/resources/organizations.json:/webapp/data/organizations.json
- ./dev/resources/users.json:/app/data/users.json
- ./dev/resources/organizations.json:/app/data/organizations.json

data-fair:
profiles:
- dev
- test
image: ghcr.io/data-fair/data-fair:master
image: ghcr.io/data-fair/data-fair:5
restart: on-failure:10
network_mode: host
depends_on:
Expand Down Expand Up @@ -107,12 +108,14 @@ services:
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms128m -Xmx128m"
- ES_HEAP_SIZE=128m
- "ES_JAVA_OPTS=-Xms128m -Xmx128m -server"
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9200"]
timeout: 10s
start_period: 10s
timeout: 5s
interval: 2s
retries: 50

Expand Down
Loading
Loading