UnicoreCMS

Лаунчсервер Laminara

Аккаунты, скины, доступ к сборкам и новости через UnicoreProviderLaminara

Laminara — лаунчсервер, который умеет брать данные из сайта через модуль UnicoreProviderLaminara. Игрок входит в лаунчер логином и паролем от сайта, а сборки, скины и лента новостей подтягиваются оттуда же.

В отличие от GravitLauncher, сессии Laminara держит у себя: сама выпускает токены, крутит ротацию, обслуживает yggdrasil и узнаёт машину игрока. От сайта ей нужен только ответ «эта пара логин-пароль верна, и вот кто это» плюс справка об игроке. Поэтому контракт здесь короче — четыре ручки под /auth/laminara вместо одиннадцати у Gravit.

Что берётся с сайта

ПровайдерЧто делаетГде включается в config.json
АутентификацияВход по нику или почте с паролем и кодом 2FAauth.provider
СкиныСкин и плащ из кабинета — в лаунчере и в игре через yggdrasilyggdrasil.skinProvider
ДоступСборки по правам, ролям и донат-группам сайтаaccess.sources.<имя>.type
НовостиЛента новостей сайта в окне лаунчераnews.source.type

Все четыре включаются по имени unicore и работают независимо: можно взять с сайта только вход, а новости оставить свои.

Подключение

Выпустить ключ

Утилиты → API-ключи → Создать, право kernel.laminara.provider, в доверенные адреса — IP машины с лаунчсервером.

Право отдельное от kernel.provider: ключ лаунчсервера можно отозвать, не трогая интеграцию с GravitLauncher.

Поставить модуль

Бинарь из релизов модуля кладётся в каталог модулей лаунчсервера под именем unicore:

curl -L -o unicore https://github.com/MCXTeam/UnicoreProviderLaminara/releases/latest/download/unicore-linux-amd64
install -m 755 unicore /var/lib/laminara/modules/unicore

Имя файла — это ключ, по которому лаунчсервер найдёт настройки модуля, поэтому переименовать обязательно. Для arm-серверов рядом лежит unicore-linux-arm64 и checksums.txt.

Прописать адрес и ключ

Адрес сайта и ключ задаются один раз в modules.config.unicore, дальше провайдеры только выбираются по имени:

{
  "modules": {
    "dir": "/var/lib/laminara/modules",
    "config": {
      "unicore": {
        "url": "https://api.example.com",
        "apiKey": "ваш-ключ",
        "timeout": "5s",
        "cacheTTL": "1m"
      }
    }
  },

  "auth": { "provider": "unicore" },
  "yggdrasil": { "enabled": true, "skinProvider": "unicore" },
  "news": { "source": { "type": "unicore", "config": { "limit": 10 } } },
  "access": {
    "sources": { "site": { "type": "unicore" } },
    "rules": [{ "builds": ["*"], "source": "site", "message": "Сборка открыта по привилегии на сайте" }]
  }
}

После правки конфига перезапустите laminara-server.

Проверить

laminara-server exec "unicore"

Модуль покажет адрес сайта, наличие связи, название проекта и версию CMS. То же самое напрямую:

curl https://api.example.com/auth/laminara/ping \
  -H 'Authorization: Api-Key ваш-ключ'

Ключ без доверенных адресов не работает

Пустой список адресов означает отказ во всех запросах — так задумано для всех ключей, не только для этого. Подробности на странице API-ключи.

Настройки модуля

ПолеПо умолчаниюЧто значит
url—Адрес API сайта, без завершающего слэша
apiKey—Ключ с правом kernel.laminara.provider
timeout5sТаймаут запроса к сайту
cacheTTL1mСколько держать профиль игрока в памяти модуля

Профили кэшируются, потому что за ними модуль ходит часто: скины отдаются в том числе игровому серверу через yggdrasil, и на каждую проверку доступа к сборке тоже нужен профиль.

Доступ к сборкам

Отдельной ручки для сборок нет: список сборок живёт в лаунчсервере, а сайт только отвечает, что есть у игрока. Решение принимает модуль по профилю.

По правам

Основное → Настройки → «Сборки лаунчера Laminara» — перечислите идентификаторы сборок через запятую:

survival, skyblock, anarchy

На каждую сборку появится право laminara.build.<id> — его видно в конструкторе прав в группе «Лаунчер». Выдали право игроку, роли или донат-группе — сборка открылась в лаунчере.

Без этой настройки прав не будет

Права сборок заводятся динамически именно из этого списка. Пока сборка в нём не перечислена, права laminara.build.<id> в каталоге нет, и выдать его некому.

Шаблон права меняется в конфиге источника доступа, а пустая строка выключает проверку по правам совсем:

{
  "type": "unicore",
  "config": {
    "permission": "laminara.build.%build%",
    "groups": { "creative": ["vip", "premium"] },
    "failOpen": false
  }
}
ПолеПо умолчаниюЧто значит
permissionlaminara.build.%build%Шаблон права; пустая строка выключает проверку по правам
groups—Сборка и роли или донат-группы, которым она открыта
failOpenfalseПускать ли всех, пока сайт недоступен

По ролям и группам

Если заводить права не хочется, соответствие сборок и групп пишется прямо в конфиге — блок groups выше. Модуль сверит его с ролями и донат-группами из профиля. Со стороны сайта для этого ничего настраивать не нужно.

Игрок проходит, если у него есть право по шаблону либо одна из перечисленных групп. Забаненный на сайте не проходит никогда, даже при failOpen.

Ручки

Все под ключом с правом kernel.laminara.provider.

МетодПутьЧто делает
GET/auth/laminara/pingНазвание проекта и версия CMS
POST/auth/laminara/authenticateПроверка логина, пароля и кода 2FA
GET/auth/laminara/user?username= или ?uuid=Профиль без пароля
GET/auth/laminara/news?limit=20Новости для окна лаунчера

Профиль у authenticate и user одинаковый:

{
  "uuid": "d1b0f4a2-0000-4000-8000-000000000001",
  "username": "Steve",
  "roles": ["player", "moderator"],
  "groups": ["vip"],
  "permissions": ["laminara.build.survival"],
  "banned": false,
  "banReason": "",
  "textures": {
    "skin": { "url": "https://api.example.com/skin/Steve.png", "slim": false },
    "cape": { "url": "https://api.example.com/cape/Steve.png" }
  }
}

username — канонический ник, даже если вошли по почте: именно он попадёт в игру. В permissions приходят права игрока вместе с правами его ролей и активных донат-привилегий. У user поле banned заполняется по-настоящему — забаненный отдаётся профилем, а не ошибкой, потому что модуль отличает бан от «игрока нет».

Тексты новостей приходят без HTML: заголовок и тело прогоняются в простой текст, потому что лаунчер разметку не рендерит. limit по умолчанию — 20.

Ошибки входа

Тело ответа — { "error": "<код>" }, у блокировки добавляется reason.

Код HTTPerrorКогда
404auth.usernotfoundИгрока с таким ником или почтой нет
401auth.wrongpasswordПароль не подошёл
401auth.require2fa2FA включена, код не передан
401auth.wrong2faКод 2FA не подошёл
403auth.usernotactivatedПочта не подтверждена
403auth.userblockedАккаунт забанен
403auth.passwordchangerequiredАдминистратор потребовал сменить пароль

Получив auth.require2fa, лаунчер показывает поле для кода и повторяет запрос. Неверный логин, пароль и код игрок видит одинаково — «неверный логин или пароль», чтобы перебором нельзя было узнать список ников.

Смена пароля по требованию

Код auth.passwordchangerequired модуль пока показывает игроку как есть, без человеческого текста. Если вы включили принудительную смену пароля, предупредите игрока отдельно: сменить его можно только в кабинете на сайте.

Ограничения частоты

Ручки Laminara не троттлятся: лаунчсервер считает попытки входа сам, до обращения к сайту. Но неудачные входы сайт всё равно копит — после десяти промахов по одной учётке за 15 минут включается растущая пауза, до пяти минут. С подключённой каптчей порог поднимается до 25. Это та же защита, что и у входа на сайте, и она работает по учётной записи, а не по адресу лаунчсервера.

Команды в консоли

Модуль добавляет в консоль лаунчсервера команду unicore (алиас cms):

$ laminara-server exec "unicore user Steve"
Ник         Steve
UUID        d1b0f4a2-0000-4000-8000-000000000001
Роли        Player, Moderator
Группы      VIP
Права       laminara.build.survival
Бан         нет
Скин        https://api.example.com/skin/Steve.png
Плащ        —

$ laminara-server exec "unicore forget"
кэш профилей очищен

unicore forget сбрасывает кэш профилей — пригодится, когда право выдано только что, а лаунчер ещё показывает старое состояние.

Содержание