Skip to content

Commit

Permalink
experimental-local-file-access
Browse files Browse the repository at this point in the history
  • Loading branch information
magland committed Jul 21, 2023
1 parent c669cd3 commit fb60cfd
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 0 deletions.
2 changes: 2 additions & 0 deletions experimental-local-file-access/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
package-lock.json
14 changes: 14 additions & 0 deletions experimental-local-file-access/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "experimental-local-file-access",
"version": "0.0.1",
"description": "experimental service for allowing neurosift to access local files",
"main": "src/index.js",
"author": "Jeremy Magland",
"license": "Apache-2.0",
"dependencies": {
"express": "^4.18.2"
},
"scripts": {
"start": "node src/index.js"
}
}
47 changes: 47 additions & 0 deletions experimental-local-file-access/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# experimental-local-file-access

This is a simple server that allows you to access local NWB files using Neurosift.

## Instructions

**Prerequisites:**

* A recent version of NodeJS (tested with v18.16.1)

**Step 1: Prepare a directory where you will store your .nwb files**

```bash
export NWB_DIR=/path/to/your/nwb/files
```

**Step 2: Install the dependencies and run the server**

```bash
# cd to this directory
cd experimental-local-file-access

npm install
npm run start $NWB_DIR
```

**Step 3: Open the neurosift web app in your browser and point to an nwb file**

```bash
https://flatironinstitute.github.io/neurosift/?p=/nwb&url=http://localhost:61762/files/testing.nwb
```

This will load the nwb file from `$NWB_DIR/testing.nwb`

## Using a different port

By default, the port is 61762. You can change this by setting the `PORT` environment variable in the run command:

```bash
PORT=12345 npm run start $NWB_DIR
```

## Security considerations

This server will expose the contents of files in the directory you specify to anyone who can access the server. This does not include hidden files (those starting with "."). This is not a problem if you are running the server on your local machine and only accessing it from your local machine. However, if you are running the server on a machine that is accessible from the internet, you should take precautions to ensure that only authorized users can access the server, if you have sensitive files.

There is also a possibility that websites you visit could get read access to your files. However, the configuration will prevent this from happening unless the website is being served from the allowed domains (flatironinsitute.github.io and localhost:3000).
59 changes: 59 additions & 0 deletions experimental-local-file-access/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const express = require('express')
const app = express()
const port = process.env.PORT || 61762
const dir = process.argv[2]
if (!dir) {
console.error('Please specify a directory.')
process.exit(-1)
}

// Allow CORS from flatironinstitute.github.io and localhost:3000
const allowedOrigins = ['https://flatironinstitute.github.io', 'http://localhost:3000']
app.use((req, resp, next) => {
const origin = req.get('origin')
const allowedOrigin = allowedOrigins.includes(origin) ? origin : undefined
if (allowedOrigin) {
resp.header('Access-Control-Allow-Origin', allowedOrigin)
resp.header('Access-Control-Allow-Headers', "Origin, X-Requested-With, Content-Type, Accept")
}
next()
})

// Serve files
app.get('/files/:fileName(*)', async (req, resp) => {
const fileName = req.params.fileName

// Check if the file is shareable
if (!isShareable(fileName)) {
resp.send(500).send('Access to this file is forbidden.')
return
}

// Send the file
const options = {
root: dir
}
resp.sendFile(fileName, options, function (err) {
// I think it's important to have an error handler even if it's just this. (not sure though)
})
})

function isShareable(f) {
const bb = f.split('/')
if (bb.includes('..')) {
// don't allow access to parent directories
return false
}
const fileName = bb[bb.length - 1]
if (fileName.startsWith('.')) {
if (!['.zattrs'].includes(fileName)) {
// don't show hidden files (with some exceptions)
return false
}
}
return true
}

app.listen(port, () => {
console.info(`Serving files in ${dir} on port ${port}.`)
});

0 comments on commit fb60cfd

Please sign in to comment.