From 68a7ec2e430f574a9f012f62aacb702830f44494 Mon Sep 17 00:00:00 2001 From: Ilya Mukhortov Date: Mon, 24 Aug 2026 10:41:07 +1000 Subject: [PATCH] feat: localize MedLogic UI and document Debian image Keep only Russian and English, trim diagnostics, and add a Taskfile that builds docker.med-logic.ru/olivetin:latest. Co-authored-by: Cursor --- AI.md | 36 -- CODE_OF_CONDUCT.md | 128 ---- Dockerfile.singlearch | 10 +- Makefile | 2 +- README.md | 101 +-- SECURITY.md | 71 --- Taskfile.yml | 28 + frontend/Makefile | 2 +- frontend/main.js | 46 +- frontend/resources/vue/App.vue | 47 +- frontend/resources/vue/views/ArgumentForm.vue | 27 +- .../resources/vue/views/DiagnosticsView.vue | 243 +------ .../resources/vue/views/ExecutionView.vue | 44 +- frontend/resources/vue/views/LoginView.vue | 21 +- lang/combined_output.json | 602 +++++------------- lang/de-DE.yaml | 91 --- lang/en.yaml | 30 + lang/es-ES.yaml | 91 --- lang/it-IT.yaml | 91 --- lang/ru.yaml | 121 ++++ lang/zh-Hans-CN.yaml | 91 --- lang/zh-Hant-TW.yaml | 91 --- 22 files changed, 460 insertions(+), 1554 deletions(-) delete mode 100644 AI.md delete mode 100644 CODE_OF_CONDUCT.md delete mode 100644 SECURITY.md create mode 100644 Taskfile.yml delete mode 100644 lang/de-DE.yaml delete mode 100644 lang/es-ES.yaml delete mode 100644 lang/it-IT.yaml create mode 100644 lang/ru.yaml delete mode 100644 lang/zh-Hans-CN.yaml delete mode 100644 lang/zh-Hant-TW.yaml diff --git a/AI.md b/AI.md deleted file mode 100644 index 6d6cd2c..0000000 --- a/AI.md +++ /dev/null @@ -1,36 +0,0 @@ -# OliveTin's AI Policy - -## Runtime: - -- [x] The project does not include any AI functionality at runtime. -- [x] No data, usage, or similar is sent to, or analyized by AI. - -## Development - Autonomy level - -OliveTin development uses up to **Level 2 of 5 (pair programmer)** on the [AI Levels of Autonomy in Software Engineering](https://blog.jread.com/posts/ai-levels-of-autonomy-in-software-engineering/) scale: AI may generate suggestions and non-trivial changes, but humans review and decide what lands in the project. - -## Development - Contributions - -- [x] The project **does accept** contributions that were written with AI help. **However**: - - The contribution must be attributed to a human username who takes responsibility for the code as if they wrote it themselves. - - AI often generates very unmaintainable code as it gets longer - loads of duplication, very little function re-use amd very poor at following style guides / idiomatic design. All code contributions (AI or not) are scrutinized hard for **maintainability** and **clean merging**. Please follow the CONTRIBUTORS guide. - - AI that helps with short tab completion is generally fine. - - AI that writes lots of new code across lots of files, or makes lots of superfluous changes is generally less likely to be accepted. - - Vibe coding is generally not a suitable way to contribute to this project. -- [x] Contributors should declare when AI has been used to help write contributions in the pull request body message. -- [x] The project uses AI as an **optional** part of the PR process (coderabbitai). Please raise any concerns about usage within the PR. - - [x] Suggestions from coderabbitai can be accepted verbaitem, but ideally it should be the PR author that uses coderabbitai as a guide, who then re-writes the contribution. -- [x] Maintainers are the only agents permitted to accept merges. - -## Development - Build process - -- [x] Linters, code review tools, and others which are enabled by AI are allowed, but cannot be added as part of the standard build process. - -## Community - -- [x] Only project admins are allowed to run bots in the community discord server (at the time of writing, the current bot, Japella, is not AI-enabled). -- [x] Support is currently not provided by AI. - -## Training - -- [x] You may use the OliveTin code base, documentation and repositories to train AI, but obviously usernames and personally identifiable information may not be stored. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 80913e9..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,128 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -contact@jread.com, or via Discord. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. diff --git a/Dockerfile.singlearch b/Dockerfile.singlearch index 4c8d4d9..84c0fe6 100644 --- a/Dockerfile.singlearch +++ b/Dockerfile.singlearch @@ -1,8 +1,5 @@ FROM --platform=linux/amd64 debian:13-slim -LABEL org.opencontainers.image.source https://github.com/OliveTin/OliveTin -LABEL org.opencontainers.image.title OliveTin - RUN mkdir -p /config /config/entities/ /var/www/olivetin \ && apt-get update \ && apt-get install -y --no-install-recommends \ @@ -14,6 +11,9 @@ RUN mkdir -p /config /config/entities/ /var/www/olivetin \ jq \ openssh-client \ passwd \ + unzip \ + tar \ + gzip \ && install -m 0755 -d /etc/apt/keyrings \ && curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \ && chmod a+r /etc/apt/keyrings/docker.asc \ @@ -26,10 +26,6 @@ RUN useradd --system --create-home olivetin -u 1000 EXPOSE 1337/tcp -COPY config.yaml /config -COPY var/entities/* /config/entities/ -COPY examples/backupScript.sh /opt/backupScript.sh -RUN chmod 755 /opt/backupScript.sh VOLUME /config COPY OliveTin /usr/bin/OliveTin diff --git a/Makefile b/Makefile index 1a3c195..e14b44b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ define delete-files - python -c "import shutil;shutil.rmtree('$(1)', ignore_errors=True)" + python3 -c "import shutil;shutil.rmtree('$(1)', ignore_errors=True)" endef service: diff --git a/README.md b/README.md index 1c7c510..e8ac762 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,31 @@ -
- project logo -

OliveTin

+# OliveTin (MedLogic) - OliveTin gives **safe** and **simple** access to predefined shell commands from a web interface. +Форк [OliveTin](https://github.com/OliveTin/OliveTin) для МИС «Медицина». -[![Maturity Badge](https://img.shields.io/badge/maturity-Production-brightgreen)](#none) -[![Discord](https://img.shields.io/discord/846737624960860180?label=Discord%20Server)](https://discord.gg/jhYWWpNJ3v) -[![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/awesome-selfhosted/awesome-selfhosted#automation) -[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5050/badge)](https://bestpractices.coreinfrastructure.org/projects/5050) +Исходный репозиторий: https://github.com/OliveTin/OliveTin -[![Go Report Card](https://goreportcard.com/badge/github.com/Olivetin/OliveTin)](https://goreportcard.com/report/github.com/OliveTin/OliveTin) -[![AI Autonomy Level](https://img.shields.io/badge/AI%20Autonomy-Level%202%20of%205%20(pair--programmer)-blue)](https://blog.jread.com/posts/ai-levels-of-autonomy-in-software-engineering/) +## Docker-образ -[OliveTin 2k to 3k upgrade guide](https://docs.olivetin.app/upgrade/2k3k.html) -
+Официальный образ OliveTin заменён. Этот форк собирает контейнер на **Debian 13 slim** (`debian:13-slim`), а не на базовом образе оригинала. -screenshot -More screenshots below +Тег локальной сборки: -All documentation can be found at [docs.olivetin.app](https://docs.olivetin.app). This includes installation and usage guide, etc. +```text +docker.med-logic.ru/olivetin:latest +``` -The AsciiDoc sources for that site live in this repository under [`docs/`](docs/) (Antora component). The [docs.olivetin.app](https://github.com/OliveTin/docs.olivetin.app) repository contains the Antora playbook, theme supplemental files, and the workflow that publishes GitHub Pages. +Сборка: -## Use cases +```bash +task build +``` -**Safely** give access to commands, for less technical people; +Dockerfile: `Dockerfile.singlearch`. -* eg: Give your family a button to `podman restart plex` -* eg: Give junior admins a simple web form with dropdowns, to start your custom script. `backupScript.sh --folder {{ customerName }}` -* eg: Enable SSH access to the server for the next 20 mins `firewall-cmd --add-service ssh --timeout 20m` +## Лицензия -**Simplify** complex commands, make them accessible and repeatable; +Проект распространяется на условиях **GNU Affero General Public License v3.0** (AGPL-3.0). -* eg: Expose complex commands on touchscreen tablets stuck on walls around your house. `wake-on-lan aa:bb:cc:11:22:33` -* eg: Run long-lived commands on your servers from your cell phone. `dnf update -y` -* eg: Define complex commands with lots of preset arguments, and turn a few arguments into dropdown select boxes. `docker rm {{ container }} && docker create {{ container }} && docker start {{ container }}` +Полный текст: [LICENSE](LICENSE). -[Join the community on Discord](https://discord.gg/jhYWWpNJ3v) to talk with other users about use cases, or to ask for support in getting started. - -## YouTube demo video - -[![YouTube demo video](https://raw.githubusercontent.com/OliveTin/OliveTin/main/var/marketing/YouTubeBanner.png)](https://www.youtube.com/watch?v=UBgOfNrzId4) - -## Features - -* **Responsive, touch-friendly UI** - great for tablets and mobile -* **Super simple config in YAML** - because if it's not YAML now-a-days, it's not "cloud native" :-) -* **Dark mode** - for those of you that roll that way. -* **Accessible** - passes all the accessibility checks in Firefox, and issues with accessibility are taken seriously. -* **Container** - available for quickly testing and getting it up and running, great for the selfhosted community. -* **Integrate with anything** - OliveTin just runs Linux shell commands, so theoretically you could integrate with a bunch of stuff just by using curl, ping, etc. However, writing your own shell scripts is a great way to extend OliveTin. -* **Lightweight on resources** - uses only a few MB of RAM and barely any CPU. Written in Go, with a web interface written as a modern, responsive, Single Page App that uses the REST/Connect RPC API. -* **Good amount of unit tests and style checks** - helps potential contributors be consistent, and helps with maintainability. - -## Screenshots - -Desktop web browser; - -

-screenshot -

- -Desktop web browser (dark mode); - -

-screenshot -

- -Mobile screen size (responsive layout); - -

-screenshot -

- -## No-Nonsense Software Principles - -OliveTin follows these principles: - -* **Open Source & Free Software**: following the [Open Source Definition](https://opensource.org/osd) and the [Free Software Definition](https://www.gnu.org/philosophy/free-sw.html). All code and assets are available under the [AGPL-3.0 License](LICENSE). -* **Independent**: No company owns the code or is responsible for the projects' governance. -* **Inclusive**: No "core", "pro", "premium" or "enterprise" version. The only version is the one you can download and run, and it has all the features. -* **Invisible**: No usage tracking, no user tracking, no ads, and no telemetry. -* **Internal**: No internet connection required for any functionality. - -## Documentation - -All documentation can be found at [docs.olivetin.app](https://docs.olivetin.app). This includes installation and usage guide, etc. - -You can find instructions in the docs on how to install as a **Linux package**, **Linux Container**, on **FreeBSD**, **Windows**, **macOS** and other platforms, too! - -## Donations & Sponsorship - -OliveTin does not accept monetary donations or sponsorship. See [Donations & Sponsorship](https://docs.olivetin.app/reference/donations_and_sponsorship.html) for the full explanation. - -* Free code signing provided by [SignPath.io](https://about.signpath.io/), certificate by [SignPath Foundation](https://signpath.org/). +Оригинальный OliveTin также лицензирован под AGPL-3.0. При использовании и дальнейшем распространении этого форка необходимо соблюдать условия AGPL-3.0, в том числе предоставление исходного кода при сетевом использовании модифицированной версии. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 798bc7d..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,71 +0,0 @@ -# Security Policy - -## Supported Versions - -The following branches are currently being supported with security updates: - -| Version | Supported | -| ------- | ------------------ | -| `main` (3k release branch) | :white_check_mark: - advisories will be published when patched in this branch | -| `release/2k` (2k release branch) | :white_check_mark: - receives security updates, but much slower | - -To understand more about 2k vs 3k, see the following docs; https://docs.olivetin.app/upgrade/2k3k.html - -## OliveTin *is* a remote code execution (RCE) "tool" - -The very purpose of OliveTin is to allow users to execute commands remotely on a machine. - -This means that, by design, OliveTin has much higher potential to be used for remote code execution (RCE), and any security vulnerabilities that do occur have the potential to be much more severe than in other types of software. - -We hope that you understand that while the project goes to great aims to be safe, and mitigate, that security vulnerabilities are inevitable, as they are with all software of all sizes - like Kubernetes, the Kernel, etc - and OliveTin has substantially less resources than those projects. - -With that being said, OliveTin tries to follow examples of best practice, so judge the project not on if/when it has security issues, but how security issues are responded to as the measure of quality. - -This is why we take security very seriously, and why we encourage responsible disclosure practices when reporting vulnerabilities. - -## Reporting a Vulnerability - -Please use responsible disclosure practices when reporting a vulnerability. **You will receive full credit for your discovery**, and we will work with you to ensure that the issue is resolved as quickly as **possible**. Please note that only James Read has access to security issues at the moment, so please be patient and understanding if you do not receive an immediate response. - -* **Option A (preferred)**: GitHub Security Advisories, which allows you to report a vulnerability privately and securely. Use this direct link to report privately: `https://github.com/OliveTin/OliveTin/security/advisories/new`. This allows you to provide details without making them public. - -* **Option B**: Please email `contact@jread.com` for responsible disclosure. - -The following notes might be helpful when reporting a vulnerability: - -* OliveTin does not offer a bug bounty program. -* GitHub usernames are how we you will be credited for discoveries reported via GitHub, if using emails we'll ask for your preferred name/handle to credit you with. -* CVEs will be requested via GitHub Security Advisories when appropriate, but we do not guarantee that all vulnerabilities will receive CVEs, as this is determined on a case-by-case basis. - -## Feature flags (alpha / experimental) - -OliveTin uses global `features.*` flags in `config.yaml` to ship unfinished or experimental functionality. - -* **All feature flags default to off.** Enabling a flag is an explicit operator choice. -* Functionality behind a feature flag is **alpha / experimental** until the flag is removed or the feature is graduated to a stable, default-on product surface. -* Private security reports **are accepted** for vulnerabilities that affect feature-flagged (alpha) functionality when that flag is enabled. Use Option A or B above; do not file a public issue that discloses exploit details. -* Reports that affect **stable, non-flagged** code paths remain in scope under this policy, even if a feature flag exists elsewhere in the project. - -Operators who enable experimental features should treat them as preview software and avoid relying on them in high-assurance production deployments. - -## Disclosure of how vulnerabilities were found - -It is incredibly useful to not just patch security vulnerabilities, but also to understand how they were found. If you are able to share this information, it can help us and the community to better understand potential attack vectors and improve the overall security of the project. - -## Duplicate reports - -If you are reporting via GitHub Security Advisories, search existing [repository advisories](https://github.com/OliveTin/OliveTin/security/advisories) for the same component and attack path before filing. Maintainers may close duplicate submissions and continue work on a single canonical advisory; duplicate reporters are still credited. - -Maintainers: see [.github/SECURITY_ADVISORY_DUPLICATES.md](.github/SECURITY_ADVISORY_DUPLICATES.md) for known duplicate pairs, triage steps, and OAuth2 issues that are easy to confuse with each other. - -## Process - -Once a vulnerability is reported, the process is; - -* Check [.github/SECURITY_ADVISORY_DUPLICATES.md](.github/SECURITY_ADVISORY_DUPLICATES.md) and open advisories for duplicates before accepting. -* Accept or reject the report, and communicate with the reporter about next steps. -* If accepted, patch using a temporary branch, and code review will be requested from the original reporter if they are interested. -* The severity of the vulnerability will be assessed using CVSS, and the patch will be prioritised accordingly. -* Once the patch is ready, it will be queued for a release onto the `next` branch (3k) or `release/2k` branch (2k) -* The reporter will be credited in the advisory and the release notes, but not the commit message. -* The commit message will contain a reference to the CVSS score (eg: MED) and the advisory ID. diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..1f8b776 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,28 @@ +version: "3" + +vars: + IMAGE: docker.med-logic.ru/olivetin:latest + +tasks: + default: + desc: Build docker.med-logic.ru/olivetin:latest + cmds: + - task: build + + webui-dist: + desc: Build frontend into ./webui + cmds: + - make webui-dist + + binary: + desc: Cross-compile OliveTin for linux/amd64 + dir: service + cmds: + - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o ../OliveTin . + + build: + desc: Build docker.med-logic.ru/olivetin:latest (linux/amd64) + cmds: + - task: webui-dist + - task: binary + - docker build --pull=false --platform linux/amd64 -f Dockerfile.singlearch -t {{.IMAGE}} . diff --git a/frontend/Makefile b/frontend/Makefile index 198081f..b050097 100644 --- a/frontend/Makefile +++ b/frontend/Makefile @@ -1,5 +1,5 @@ define delete-files - python -c "import shutil;shutil.rmtree('$(1)', ignore_errors=True)" + python3 -c "import shutil;shutil.rmtree('$(1)', ignore_errors=True)" endef codestyle: diff --git a/frontend/main.js b/frontend/main.js index 5574e46..1f78855 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -20,37 +20,45 @@ import App from './resources/vue/App.vue' import { initWebsocket } from './js/websocket.js' import combinedTranslations from '../lang/combined_output.json' +const DEFAULT_LOCALE = 'ru' + +function matchAvailableLocale (candidate, available) { + const lowerCandidate = candidate.toLowerCase() + const exact = available.find(locale => locale.toLowerCase() === lowerCandidate) + + if (exact) { + return exact + } + + const langPrefix = lowerCandidate.split('-')[0] + const languageOnly = available.find(locale => locale.toLowerCase() === langPrefix) + + if (languageOnly) { + return languageOnly + } + + return available.find(locale => locale.toLowerCase().startsWith(langPrefix + '-')) || null +} + function getSelectedLanguage () { const storedLanguage = localStorage.getItem('olivetin-language') + const available = Object.keys(combinedTranslations.messages || {}) - if (storedLanguage && storedLanguage !== 'auto') { + if (storedLanguage && storedLanguage !== 'auto' && available.includes(storedLanguage)) { return storedLanguage } - if (storedLanguage === 'auto') { - localStorage.removeItem('olivetin-language') - } - - if (navigator.languages && navigator.languages.length > 0) { - const available = Object.keys(combinedTranslations.messages || {}) - + if (storedLanguage === 'auto' && navigator.languages && navigator.languages.length > 0) { for (const candidate of navigator.languages) { - const lowerCandidate = candidate.toLowerCase() - const exact = available.find(locale => locale.toLowerCase() === lowerCandidate) + const matched = matchAvailableLocale(candidate, available) - if (exact) { - return exact - } - - const prefix = available.find(locale => locale.toLowerCase().startsWith(lowerCandidate.split('-')[0] + '-')) - - if (prefix) { - return prefix + if (matched) { + return matched } } } - return 'en' + return DEFAULT_LOCALE } async function initClient () { diff --git a/frontend/resources/vue/App.vue b/frontend/resources/vue/App.vue index f5ea422..070b824 100644 --- a/frontend/resources/vue/App.vue +++ b/frontend/resources/vue/App.vue @@ -196,7 +196,7 @@ diff --git a/frontend/resources/vue/views/ArgumentForm.vue b/frontend/resources/vue/views/ArgumentForm.vue index d086d1d..df74e02 100644 --- a/frontend/resources/vue/views/ArgumentForm.vue +++ b/frontend/resources/vue/views/ArgumentForm.vue @@ -1,17 +1,16 @@