Skip to content

Young-Lord/online-clipboard

Repository files navigation

online-clipboard

netcut.cn style, minimal editable online clipboard.

Preview image

Developed using Flask, Vue 3, Vuetify 3, TypeScript. Full i18n support.

Runs on Node.js v18.16.0, Python 3.11.3.

Install

  1. Install poetry and yarn.
  2. Install Python and Node.js dependencies.
# Install python dependencies
pushd server
poetry install --no-root
popd
# Install nodejs dependencies
pushd frontend
yarn install
popd

Config

  1. Edit server/app/note_const.py, server/app/config.py.
  2. Copy .env.development to .env.production and edit it. Also edit .env if needed.
  3. Generate APP_SECRET as described in server/app/config.py and save it to .env.production.
  4. Init database using flask db upgrade in server directory.
  5. Modify server/app/__init__.py and configure ProxyFix if you are deploying behind a reverse proxy.

Run

First, you need to build frontend files.

cd frontend
yarn build

Then, you can run the server.

cd server
FLASK_ENV=production poetry run python wsgi.py
# PowerShell: $env:FLASK_ENV='production'; poetry run python wsgi.py

Note

Use with curl

# Get clip named my_clip
curl http://example.com/raw/my_clip?my_password

Debug

# frontend
cd frontend
yarn dev
# backend
cd server
poetry run python wsgi.py

Backend database initailization

poetry shell
flask db init
flask db migrate
flask db upgrade

Security

Password protect: sha512(note.password) through Internet, pbkdf2_sha256(sha512(note.password)) in database.

File access: JWT generated with note.name and pbkdf2_sha256(sha512(note.password)) (the hash stored in database as above)

Content encryption: AES-256-CBC/PKCS7 with sha256(note.password), see CryptoJS behaviour

IIS

Example rule:

<?xml version="1.0" encoding="UTF-8"?> 
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="clip-server" stopProcessing="true">
                    <match url="^clip-basepath(/(api|raw|socket\.io).+)$" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{CACHE_URL}" pattern="^(.+)?://.+$" />
                    </conditions>
                    <serverVariables>
                        <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
                        <set name="HTTP_X_FORWARDED_PREFIX" value="/clip-basepath/" />
                        <set name="HTTP_X_FORWARDED_HOST" value="example.com" />
                    </serverVariables>
                    <action type="Rewrite" url="{C:1}://127.0.0.1:5000{R:1}" />
                </rule>
                <rule name="clip-frontend" stopProcessing="true">
                    <match url="^clip-basepath(/.*)?$" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/clip-basepath/index.html" />
                </rule>
            </rules>
        </rewrite>
        <security>
            <requestFiltering>
                <requestLimits maxAllowedContentLength="209715200" />
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>

URL Rewrite

  • Download and install URL Rewrite
  • View Server Variables: add HTTP_SEC_WEBSOCKET_EXTENSIONS, HTTP_X_FORWARDED_PREFIX, HTTP_X_FORWARDED_HOST to allowlist
  • URL Rewrite Rules: see web.config below
  • Virtual directory: point from clip-basepath to server/app/templates

Upload size limit

How to set URL length and HTTP POST content length limits in IIS - WKB240363

WebSocket Server

Clip uses Socket.IO to support Instant Sync feature, which allows multi users to edit together. A WebSocket server will run on the same port of backend Flask server.