mirror of
https://github.com/flameshikari/outline-ru.git
synced 2026-06-13 04:05:10 +03:00
@@ -0,0 +1,11 @@
|
|||||||
|
APP_PATH=/opt/outline
|
||||||
|
SRC_PATH=./outline
|
||||||
|
|
||||||
|
ADDRESS=localhost
|
||||||
|
PORT_OUTLINE=10240
|
||||||
|
PORT_OIDC=10241
|
||||||
|
PORT_REDIS=10242
|
||||||
|
PORT_POSTGRES=10243
|
||||||
|
|
||||||
|
COMMON=outline
|
||||||
|
SECRET=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
||||||
@@ -9,8 +9,8 @@ on:
|
|||||||
- .github/workflows/**
|
- .github/workflows/**
|
||||||
- outline/**
|
- outline/**
|
||||||
- tools/translation.json
|
- tools/translation.json
|
||||||
- tools/language.patch
|
- tools/patches/**
|
||||||
- Dockerfile
|
- Dockerfile.prod
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
@@ -79,6 +79,10 @@ jobs:
|
|||||||
cache-from: type=gha,scope=build-${{ matrix.arch }}
|
cache-from: type=gha,scope=build-${{ matrix.arch }}
|
||||||
cache-to: type=gha,mode=max,scope=build-${{ matrix.arch }}
|
cache-to: type=gha,mode=max,scope=build-${{ matrix.arch }}
|
||||||
platforms: linux/${{ matrix.arch }}
|
platforms: linux/${{ matrix.arch }}
|
||||||
|
file: Dockerfile.prod
|
||||||
|
build-args: |
|
||||||
|
APP_PATH=/opt/outline
|
||||||
|
SRC_PATH=./outline
|
||||||
labels: ${{ steps.metadata.outputs.labels }}
|
labels: ${{ steps.metadata.outputs.labels }}
|
||||||
outputs: type=image,"name=${{ github.repository }},ghcr.io/${{ github.repository }}",push-by-digest=true,name-canonical=true,push=true
|
outputs: type=image,"name=${{ github.repository }},ghcr.io/${{ github.repository }}",push-by-digest=true,name-canonical=true,push=true
|
||||||
|
|
||||||
|
|||||||
+16
-37
@@ -1,18 +1,14 @@
|
|||||||
ARG APP_PATH=/opt/outline
|
FROM node:20 AS base
|
||||||
ARG SRC_PATH=./outline
|
|
||||||
|
|
||||||
FROM node:20 AS deps
|
|
||||||
ARG APP_PATH
|
ARG APP_PATH
|
||||||
ARG SRC_PATH
|
ARG SRC_PATH
|
||||||
WORKDIR $APP_PATH
|
WORKDIR $APP_PATH
|
||||||
|
|
||||||
|
FROM base AS deps
|
||||||
COPY ${SRC_PATH}/package.json ${SRC_PATH}/yarn.lock ./
|
COPY ${SRC_PATH}/package.json ${SRC_PATH}/yarn.lock ./
|
||||||
RUN yarn install --production=true --frozen-lockfile --network-timeout 1000000 && \
|
RUN yarn install --production=true --frozen-lockfile --network-timeout 1000000 && \
|
||||||
yarn cache clean
|
yarn cache clean
|
||||||
|
|
||||||
FROM node:20 AS build
|
FROM base AS build
|
||||||
ARG APP_PATH
|
|
||||||
ARG SRC_PATH
|
|
||||||
WORKDIR $APP_PATH
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y patch cmake && \
|
apt-get install -y patch cmake && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
@@ -22,35 +18,18 @@ ENV NODE_OPTIONS="--max-old-space-size=24000"
|
|||||||
RUN yarn install --no-optional --frozen-lockfile --network-timeout 1000000 && \
|
RUN yarn install --no-optional --frozen-lockfile --network-timeout 1000000 && \
|
||||||
yarn cache clean
|
yarn cache clean
|
||||||
COPY ${SRC_PATH} .
|
COPY ${SRC_PATH} .
|
||||||
COPY ./tools/language.patch .
|
COPY --from=deps $APP_PATH/node_modules ./node_modules
|
||||||
RUN patch -p1 < language.patch
|
COPY ./tools/patches/* .
|
||||||
COPY ./tools/translation.json ./shared/i18n/locales/ru_RU/translation.json
|
RUN for patch in $(ls *.patch); do patch -p1 < $patch; done
|
||||||
|
RUN cat <<EOF > /entrypoint.sh
|
||||||
|
npx yarn concurrently -n "dev,i18n" \
|
||||||
|
"yarn dev:watch" \
|
||||||
|
"yarn nodemon \
|
||||||
|
--watch './shared/i18n/locales/ru_RU' \
|
||||||
|
--exec 'yarn build:i18n'"
|
||||||
|
EOF
|
||||||
ARG CDN_URL
|
ARG CDN_URL
|
||||||
RUN yarn build && rm -rf node_modules
|
|
||||||
|
|
||||||
FROM node:22-slim AS release
|
|
||||||
ARG APP_PATH
|
|
||||||
ARG SRC_PATH
|
|
||||||
WORKDIR $APP_PATH
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y curl && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
ARG DATA_PATH=/var/lib/outline/data
|
ARG DATA_PATH=/var/lib/outline/data
|
||||||
ARG USER=nodejs
|
|
||||||
RUN useradd -m -U ${USER} && \
|
|
||||||
mkdir -p ${DATA_PATH} && \
|
|
||||||
chown -R ${USER}:${USER} ${APP_PATH} ${DATA_PATH}/.. && \
|
|
||||||
chmod 1777 ${DATA_PATH}
|
|
||||||
COPY --chown=${USER} --from=deps $APP_PATH/node_modules ./node_modules
|
|
||||||
COPY --chown=${USER} --from=build $APP_PATH/build ./build
|
|
||||||
COPY --chown=${USER} --from=build $APP_PATH/server ./server
|
|
||||||
COPY --chown=${USER} --from=build $APP_PATH/public ./public
|
|
||||||
COPY --chown=${USER} --from=build $APP_PATH/.sequelizerc .
|
|
||||||
COPY --chown=${USER} --from=build $APP_PATH/package.json .
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
ENV PORT=3000
|
|
||||||
USER ${USER}
|
|
||||||
EXPOSE ${PORT}
|
|
||||||
VOLUME ${DATA_PATH}
|
VOLUME ${DATA_PATH}
|
||||||
HEALTHCHECK --interval=1m CMD curl -fs localhost:${PORT}/_health | grep -q OK || exit 1
|
STOPSIGNAL SIGKILL
|
||||||
CMD ["yarn", "start"]
|
ENTRYPOINT ["bash", "/entrypoint.sh"]
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
FROM node:20 AS base
|
||||||
|
ARG APP_PATH
|
||||||
|
ARG SRC_PATH
|
||||||
|
WORKDIR $APP_PATH
|
||||||
|
|
||||||
|
FROM base AS deps
|
||||||
|
COPY ${SRC_PATH}/package.json ${SRC_PATH}/yarn.lock ./
|
||||||
|
RUN yarn install --production=true --frozen-lockfile --network-timeout 1000000 && \
|
||||||
|
yarn cache clean
|
||||||
|
|
||||||
|
FROM base AS build
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y patch cmake && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
COPY ${SRC_PATH}/patches ./patches
|
||||||
|
COPY ${SRC_PATH}/package.json ${SRC_PATH}/yarn.lock ./
|
||||||
|
ENV NODE_OPTIONS="--max-old-space-size=24000"
|
||||||
|
RUN yarn install --no-optional --frozen-lockfile --network-timeout 1000000 && \
|
||||||
|
yarn cache clean
|
||||||
|
COPY ${SRC_PATH} .
|
||||||
|
COPY ./tools/patches/lang.patch .
|
||||||
|
RUN for patch in $(ls *.patch); do patch -p1 < $patch; done
|
||||||
|
COPY ./tools/translation.json ./shared/i18n/locales/ru_RU/translation.json
|
||||||
|
ARG CDN_URL
|
||||||
|
RUN yarn build && rm -rf node_modules
|
||||||
|
|
||||||
|
FROM node:22-slim AS release
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y curl && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
ARG DATA_PATH=/var/lib/outline/data
|
||||||
|
ARG USER=nodejs
|
||||||
|
ARG APP_PATH
|
||||||
|
WORKDIR $APP_PATH
|
||||||
|
RUN useradd -m -U ${USER} && \
|
||||||
|
mkdir -p ${DATA_PATH} && \
|
||||||
|
chown -R ${USER}:${USER} ${APP_PATH} ${DATA_PATH}/.. && \
|
||||||
|
chmod 1777 ${DATA_PATH}
|
||||||
|
COPY --chown=${USER} --from=deps $APP_PATH/node_modules ./node_modules
|
||||||
|
COPY --chown=${USER} --from=build $APP_PATH/build ./build
|
||||||
|
COPY --chown=${USER} --from=build $APP_PATH/server ./server
|
||||||
|
COPY --chown=${USER} --from=build $APP_PATH/public ./public
|
||||||
|
COPY --chown=${USER} --from=build $APP_PATH/.sequelizerc .
|
||||||
|
COPY --chown=${USER} --from=build $APP_PATH/package.json .
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV PORT=3000
|
||||||
|
USER ${USER}
|
||||||
|
EXPOSE ${PORT}
|
||||||
|
VOLUME ${DATA_PATH}
|
||||||
|
HEALTHCHECK --interval=1m CMD curl -fs localhost:${PORT}/_health | grep -q OK || exit 1
|
||||||
|
CMD ["yarn", "start"]
|
||||||
@@ -35,23 +35,48 @@ services:
|
|||||||
|
|
||||||
## 🛠️ Разработка
|
## 🛠️ Разработка
|
||||||
|
|
||||||
|
### Ключевые файлы
|
||||||
|
|
||||||
|
- русский перевод — [tools/translation.json](./tools/translation.json)
|
||||||
|
- английский перевод — [outline/shared/i18n/locales/en_US/translation.json](https://github.com/outline/outline/blob/main/shared/i18n/locales/en_US/translation.json)
|
||||||
|
- временный файл — [tools/translation.tmp.json]() (существует только локально)
|
||||||
|
|
||||||
|
### Быстрый старт
|
||||||
|
|
||||||
|
0. Клонирование репозитория с подмодулем:
|
||||||
|
```sh
|
||||||
|
git clone --recurse-submodules git@github.com:flameshikari/outline-ru.git
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Пулл изменений в подмодуле и переключение на коммит с целевой версией:
|
||||||
|
```sh
|
||||||
|
cd outline
|
||||||
|
git pull --rebase --tags
|
||||||
|
git checkout v0.85.0
|
||||||
|
cd -
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Запуск контейнеров:
|
||||||
|
```sh
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
Веб-интерфейс Outline будет доступен по [этой ссылке](http://localhost:10240).
|
||||||
|
|
||||||
|
3. Формирование временного файла с помощью [tools/diff.py](./tools/diff.py):
|
||||||
|
```sh
|
||||||
|
python tools/diff.py
|
||||||
|
```
|
||||||
|
После можно приступить к переводу сфомированного временного файла. Любые изменения в русском переводе обновят [открытую веб-страницу](http://localhost:10240) через пару секунд.
|
||||||
|
|
||||||
### Описание
|
### Описание
|
||||||
|
|
||||||
Контейнер Outline описан в одном [Dockerfile](./Dockerfile) на основе двух оригинальных с применением [патча](./tools/language.patch) поверх исходного кода Outline (он подключен к этому репозиторию в качестве подмодуля) и копированием [файла перевода](./tools/translation.json). Патч, помимо добавления отсутствующих строк в код, меняет некоторые upstream-ссылки, чтобы Outline мониторил этот контейнер на наличие новых версий, а не оригинальный.
|
Скрипт [tools/diff.py](./tools/diff.py) используется для объединения английского и русского переводов во временный файл. Скрипт не имеет интерактивного режима и каких-либо аргументов/опций, он просто запускается (с выводом некоторой полезной информации) и делает следующее:
|
||||||
|
|
||||||
В [docker-compose.yml](./docker-compose.yml) описаны четыре контейнера (кликабельные названия далее — это localhost-ссылки): [Outline](http://localhost:10240), Redis, Postgres и [тестовый OIDC-сервер](http://localhost:10241) (логин/пароль: `outline`). Также там описана вся конфигурация контейнеров; настраивайте под себя по желанию. После первой сборки контейнера большинство слоёв берётся из кэша, сам Outline после изменений пересобирается около полминуты-минуты (тут зависит от железа). Пайплайн примерно такой: перевёл → собрал → проверил.
|
|
||||||
|
|
||||||
Скрипт [diff.py](./tools/diff.py) используется для объединения переводов [английского](https://github.com/outline/outline/blob/main/shared/i18n/locales/en_US/translation.json) с [русским](./tools/translation.json) во временный файл `./tools/translation.tmp.json`. Скрипт не имеет интерактивного режима и каких-либо аргументов/опций, он просто запускается (с выводом некоторой полезной информации) и делает следующее:
|
|
||||||
|
|
||||||
- сохраняет актуальные переведённые строки
|
- сохраняет актуальные переведённые строки
|
||||||
- удаляет неактуальные переведённые строки
|
- удаляет неактуальные переведённые строки
|
||||||
- если в файле перевода есть одинаковые key/value пары, то они считаются исключениями (например, `HTML` или `API`) и переносятся как есть
|
- если в русском переводе есть одинаковые key/value пары, то они считаются исключениями (например, `HTML` или `API`) и переносятся как есть
|
||||||
- новые непереведённые строки добавляются в конец
|
- новые непереведённые строки добавляются в конец
|
||||||
|
|
||||||
> Возможно, для коллективного перевода стоило использовать [Crowdin](https://crowdin.com), но что-то руки не дошли ¯\\_(ツ)_/¯
|
|
||||||
|
|
||||||
Во временном файле вручную делается перевод новых строк, а затем [файл перевода](./tools/translation.json) вручную заменяется временным файлом.
|
|
||||||
|
|
||||||
> Если во временном файле присутствуют две одинаковые непереведённые строки, но одна из них с суффиксом `_plural` (множественное число), например:
|
> Если во временном файле присутствуют две одинаковые непереведённые строки, но одна из них с суффиксом `_plural` (множественное число), например:
|
||||||
>
|
>
|
||||||
> ```json
|
> ```json
|
||||||
@@ -69,33 +94,3 @@ services:
|
|||||||
> "{{ count }} comment_2": "{{ count }} комментариев"
|
> "{{ count }} comment_2": "{{ count }} комментариев"
|
||||||
> }
|
> }
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
### Команды
|
|
||||||
|
|
||||||
0. Клонирование репозитория с подмодулем
|
|
||||||
```sh
|
|
||||||
git clone --recurse-submodules git@github.com:flameshikari/outline-ru.git
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Пулл изменений в подмодуле и переключение на коммит с целевой версией
|
|
||||||
```sh
|
|
||||||
cd outline
|
|
||||||
git pull --rebase --tags
|
|
||||||
git checkout v0.85.0
|
|
||||||
cd -
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Формирование временного файла с помощью [diff.py](./tools/diff.py)
|
|
||||||
```sh
|
|
||||||
python ./tools/diff.py
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Замена [файла перевода](./tools/translation.json) после перевода строк во временном файле
|
|
||||||
```
|
|
||||||
cp ./tools/translation.tmp.json ./tools/translation.json
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Сборка контейнера
|
|
||||||
```sh
|
|
||||||
docker compose up -d --build
|
|
||||||
```
|
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
volumes:
|
||||||
|
outline:
|
||||||
|
name: outline
|
||||||
|
outline-postgres:
|
||||||
|
name: outline-postgres
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
name: outline
|
||||||
|
|
||||||
|
services:
|
||||||
|
outline:
|
||||||
|
container_name: outline
|
||||||
|
image: flameshikari/outline-ru:nightly
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.prod
|
||||||
|
args:
|
||||||
|
- APP_PATH=${APP_PATH}
|
||||||
|
- SRC_PATH=${SRC_PATH}
|
||||||
|
network_mode: host
|
||||||
|
pull_policy: always
|
||||||
|
volumes:
|
||||||
|
- outline:/var/lib/outline/data
|
||||||
|
depends_on:
|
||||||
|
- outline-postgres
|
||||||
|
- outline-redis
|
||||||
|
- outline-oidc
|
||||||
|
environment:
|
||||||
|
FILE_STORAGE: local
|
||||||
|
FORCE_HTTPS: false
|
||||||
|
PORT: ${PORT_OUTLINE}
|
||||||
|
URL: http://${ADDRESS}:${PORT_OUTLINE}
|
||||||
|
SECRET_KEY: ${SECRET}
|
||||||
|
UTILS_SECRET: ${SECRET}
|
||||||
|
REDIS_URL: redis://${ADDRESS}:${PORT_REDIS}
|
||||||
|
DATABASE_URL: postgres://${COMMON}:${COMMON}@${ADDRESS}:${PORT_POSTGRES}/${COMMON}
|
||||||
|
PGSSLMODE: disable
|
||||||
|
OIDC_ISSUER_URL: http://${ADDRESS}:${PORT_OIDC}
|
||||||
|
OIDC_CLIENT_ID: ${COMMON}
|
||||||
|
OIDC_CLIENT_SECRET: ${COMMON}
|
||||||
|
|
||||||
|
outline-oidc:
|
||||||
|
container_name: outline-oidc
|
||||||
|
image: ghcr.io/soluto/oidc-server-mock:0.11.0
|
||||||
|
ports:
|
||||||
|
- ${PORT_OIDC}:80
|
||||||
|
healthcheck:
|
||||||
|
test: curl -fs ${ADDRESS}/health || exit 1
|
||||||
|
start_period: 2s
|
||||||
|
interval: 1s
|
||||||
|
timeout: 100ms
|
||||||
|
retries: 10
|
||||||
|
environment:
|
||||||
|
ASPNETCORE_URLS: http://+:80
|
||||||
|
ASPNETCORE_ENVIRONMENT: Development
|
||||||
|
CLIENTS_CONFIGURATION_INLINE: |
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"ClientId": "${COMMON}",
|
||||||
|
"ClientSecrets": ["${COMMON}"],
|
||||||
|
"RedirectUris": ["http://${ADDRESS}:${PORT_OUTLINE}/auth/oidc.callback"],
|
||||||
|
"AllowedGrantTypes": ["authorization_code"],
|
||||||
|
"AllowedScopes": ["openid", "profile", "email"],
|
||||||
|
"RequirePkce": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
USERS_CONFIGURATION_INLINE: |
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"SubjectId": "1",
|
||||||
|
"Username": "${COMMON}",
|
||||||
|
"Password": "${COMMON}",
|
||||||
|
"Claims": [
|
||||||
|
{
|
||||||
|
"Type": "email",
|
||||||
|
"Value": "mail@example.com",
|
||||||
|
"ValueType": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Type": "name",
|
||||||
|
"Value": "Outline",
|
||||||
|
"ValueType": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
SERVER_OPTIONS_INLINE: |
|
||||||
|
{
|
||||||
|
"AccessTokenJwtType": "JWT",
|
||||||
|
"Discovery": {
|
||||||
|
"ShowKeySet": true
|
||||||
|
},
|
||||||
|
"Authentication": {
|
||||||
|
"CookieSameSiteMode": "Lax",
|
||||||
|
"CheckSessionCookieSameSiteMode": "Lax"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOGIN_OPTIONS_INLINE: |
|
||||||
|
{
|
||||||
|
"AllowRememberLogin": false
|
||||||
|
}
|
||||||
|
LOGOUT_OPTIONS_INLINE: |
|
||||||
|
{
|
||||||
|
"AutomaticRedirectAfterSignOut": true
|
||||||
|
}
|
||||||
|
ASPNET_SERVICES_OPTIONS_INLINE: |
|
||||||
|
{
|
||||||
|
"ForwardedHeadersOptions": {
|
||||||
|
"ForwardedHeaders" : "All"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outline-redis:
|
||||||
|
container_name: outline-redis
|
||||||
|
image: redis:7
|
||||||
|
ports:
|
||||||
|
- ${PORT_REDIS}:6379
|
||||||
|
healthcheck:
|
||||||
|
test: redis-cli ping
|
||||||
|
interval: 10s
|
||||||
|
timeout: 30s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
outline-postgres:
|
||||||
|
container_name: outline-postgres
|
||||||
|
image: postgres:17
|
||||||
|
ports:
|
||||||
|
- ${PORT_POSTGRES}:5432
|
||||||
|
volumes:
|
||||||
|
- outline-postgres:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: pg_isready
|
||||||
|
interval: 30s
|
||||||
|
timeout: 20s
|
||||||
|
retries: 3
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${COMMON}
|
||||||
|
POSTGRES_PASSWORD: ${COMMON}
|
||||||
|
POSTGRES_DB: ${COMMON}
|
||||||
+18
-118
@@ -10,131 +10,31 @@ networks:
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
outline:
|
outline:
|
||||||
container_name: outline
|
extends:
|
||||||
image: flameshikari/outline-ru:nightly
|
file: docker-compose.prod.yml
|
||||||
build: .
|
service: outline
|
||||||
network_mode: host
|
image: !reset
|
||||||
pull_policy: always
|
pull_policy: !reset
|
||||||
volumes:
|
build:
|
||||||
- outline:/var/lib/outline/data
|
dockerfile: !reset
|
||||||
depends_on:
|
depends_on:
|
||||||
- outline-postgres
|
- outline-postgres
|
||||||
- outline-redis
|
- outline-redis
|
||||||
- outline-oidc
|
- outline-oidc
|
||||||
environment:
|
volumes:
|
||||||
FILE_STORAGE: local
|
- ./tools/translation.json:/opt/outline/shared/i18n/locales/ru_RU/translation.json
|
||||||
FORCE_HTTPS: false
|
|
||||||
PORT: 10240
|
|
||||||
URL: http://localhost:10240
|
|
||||||
SECRET_KEY: deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
|
||||||
UTILS_SECRET: deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
|
||||||
REDIS_URL: redis://localhost:10242
|
|
||||||
DATABASE_URL: postgres://outline:outline@localhost:10243/outline
|
|
||||||
PGSSLMODE: disable
|
|
||||||
OIDC_ISSUER_URL: http://localhost:10241
|
|
||||||
OIDC_CLIENT_ID: outline
|
|
||||||
OIDC_CLIENT_SECRET: outline
|
|
||||||
# OIDC_AUTH_URI: http://localhost:10241/connect/authorize
|
|
||||||
# OIDC_TOKEN_URI: http://localhost:10241/connect/token
|
|
||||||
# OIDC_USERINFO_URI: http://localhost:10241/connect/userinfo
|
|
||||||
# OIDC_SCOPES: openid profile email
|
|
||||||
# OIDC_USERNAME_CLAIM: username
|
|
||||||
|
|
||||||
outline-oidc:
|
outline-oidc:
|
||||||
container_name: outline-oidc
|
extends:
|
||||||
image: ghcr.io/soluto/oidc-server-mock:0.11.0
|
file: docker-compose.prod.yml
|
||||||
ports:
|
service: outline-oidc
|
||||||
- 10241:80
|
|
||||||
healthcheck:
|
|
||||||
test: curl -fs localhost/health || exit 1
|
|
||||||
start_period: 2s
|
|
||||||
interval: 1s
|
|
||||||
timeout: 100ms
|
|
||||||
retries: 10
|
|
||||||
environment:
|
|
||||||
ASPNETCORE_URLS: http://+:80
|
|
||||||
ASPNETCORE_ENVIRONMENT: Development
|
|
||||||
CLIENTS_CONFIGURATION_INLINE: |
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"ClientId": "outline",
|
|
||||||
"ClientSecrets": ["outline"],
|
|
||||||
"RedirectUris": ["http://localhost:10240/auth/oidc.callback"],
|
|
||||||
"AllowedGrantTypes": ["authorization_code"],
|
|
||||||
"AllowedScopes": ["openid", "profile", "email"],
|
|
||||||
"RequirePkce": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
USERS_CONFIGURATION_INLINE: |
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"SubjectId": "1",
|
|
||||||
"Username": "outline",
|
|
||||||
"Password": "outline",
|
|
||||||
"Claims": [
|
|
||||||
{
|
|
||||||
"Type": "email",
|
|
||||||
"Value": "mail@example.com",
|
|
||||||
"ValueType": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "name",
|
|
||||||
"Value": "Outline",
|
|
||||||
"ValueType": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
SERVER_OPTIONS_INLINE: |
|
|
||||||
{
|
|
||||||
"AccessTokenJwtType": "JWT",
|
|
||||||
"Discovery": {
|
|
||||||
"ShowKeySet": true
|
|
||||||
},
|
|
||||||
"Authentication": {
|
|
||||||
"CookieSameSiteMode": "Lax",
|
|
||||||
"CheckSessionCookieSameSiteMode": "Lax"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOGIN_OPTIONS_INLINE: |
|
|
||||||
{
|
|
||||||
"AllowRememberLogin": false
|
|
||||||
}
|
|
||||||
LOGOUT_OPTIONS_INLINE: |
|
|
||||||
{
|
|
||||||
"AutomaticRedirectAfterSignOut": true
|
|
||||||
}
|
|
||||||
ASPNET_SERVICES_OPTIONS_INLINE: |
|
|
||||||
{
|
|
||||||
"ForwardedHeadersOptions": {
|
|
||||||
"ForwardedHeaders" : "All"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
outline-redis:
|
outline-redis:
|
||||||
container_name: outline-redis
|
extends:
|
||||||
image: redis:7
|
file: docker-compose.prod.yml
|
||||||
ports:
|
service: outline-redis
|
||||||
- 10242:6379
|
|
||||||
healthcheck:
|
|
||||||
test: redis-cli ping
|
|
||||||
interval: 10s
|
|
||||||
timeout: 30s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
outline-postgres:
|
outline-postgres:
|
||||||
container_name: outline-postgres
|
extends:
|
||||||
image: postgres:17
|
file: docker-compose.prod.yml
|
||||||
ports:
|
service: outline-postgres
|
||||||
- 10243:5432
|
|
||||||
volumes:
|
|
||||||
- outline-postgres:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: pg_isready
|
|
||||||
interval: 30s
|
|
||||||
timeout: 20s
|
|
||||||
retries: 3
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: outline
|
|
||||||
POSTGRES_PASSWORD: outline
|
|
||||||
POSTGRES_DB: outline
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
diff --git a/server/routes/index.ts b/server/routes/index.ts
|
||||||
|
index 26fbded27..478de1922 100644
|
||||||
|
--- a/server/routes/index.ts
|
||||||
|
+++ b/server/routes/index.ts
|
||||||
|
@@ -103,7 +103,7 @@ router.get("/locales/:lng.json", async (ctx) => {
|
||||||
|
await send(ctx, path.join(lng, "translation.json"), {
|
||||||
|
setHeaders: (res, _, stats) => {
|
||||||
|
res.setHeader("Last-Modified", formatRFC7231(stats.mtime));
|
||||||
|
- res.setHeader("Cache-Control", `public, max-age=${7 * Day.seconds}`);
|
||||||
|
+ res.setHeader("Cache-Control", "no-store");
|
||||||
|
res.setHeader(
|
||||||
|
"ETag",
|
||||||
|
crypto.createHash("md5").update(stats.mtime.toISOString()).digest("hex")
|
||||||
|
diff --git a/vite.config.ts b/vite.config.ts
|
||||||
|
index 32b52d44e..26d611fee 100644
|
||||||
|
--- a/vite.config.ts
|
||||||
|
+++ b/vite.config.ts
|
||||||
|
@@ -45,6 +45,17 @@ export default () =>
|
||||||
|
: { strict: true },
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
+ {
|
||||||
|
+ name: 'reload',
|
||||||
|
+ configureServer(server) {
|
||||||
|
+ const { ws, watcher } = server;
|
||||||
|
+ watcher.on('change', file => {
|
||||||
|
+ if (file.endsWith('build/shared/i18n/locales/ru_RU/translation.json')) {
|
||||||
|
+ ws.send({ type: 'full-reload' });
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ },
|
||||||
|
+ },
|
||||||
|
// https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme
|
||||||
|
react({
|
||||||
|
babel: {
|
||||||
Reference in New Issue
Block a user