Add Android support with configurable server URL and location permissions

- Add shared_preferences for persisting server URL
- Add SettingsService and PlatformService
- Add server URL input field on non-web platforms
- Make ApiConfig baseUrl configurable at runtime
- Add Android location permissions (ACCESS_FINE/COURSE_LOCATION, INTERNET)
- Request location permission on login and map init
- Fix geo_id type: use String instead of int (UUID format)
- Align share_service with API spec: remove unique_id, use share_id only
- Fix watch endpoint response: last_update instead of created_at
- Add error handling with SnackBars for geo operations
- Wrap login screen in SingleChildScrollView for keyboard handling
- Update map tile layer with userAgentPackageName for OSM
This commit is contained in:
dmit.b
2026-05-15 17:38:56 +03:00
parent ca90c6c3fc
commit f1e88b1ac3
26 changed files with 1255 additions and 297 deletions
+619
View File
@@ -0,0 +1,619 @@
openapi: 3.0.0
info:
title: Mesh backend REST API
version: 1.0.0
description: Описание API
servers:
- url: http://localhost:8888/api
paths:
/info:
get:
tags:
- Common
summary: Запрос статуса сервера
responses:
'200':
description: On success
content:
application/json:
schema:
$ref: '#/components/schemas/BackendInfo'
/blockRule:
get:
tags:
- BlockRule
summary: Запрос правил блокировок
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/BlockPriorityRule'
delete:
tags:
- BlockRule
summary: Удалить правило
requestBody:
description: Удалить правило
content:
application/json:
schema:
$ref: '#/components/schemas/BlockPriorityRule'
required: true
responses:
'200':
description: On success
'400':
description: On error
'404':
description: Не найдено
post:
tags:
- BlockRule
summary: Добавить правило блокировки
requestBody:
description: Правило блокировки (объект json)
content:
application/json:
schema:
$ref: '#/components/schemas/BlockPriorityRule'
required: true
responses:
'200':
description: On success
'400':
description: On error
/priorityRule:
get:
tags:
- PriorityRule
summary: Запрос правил приоритета (Qos)
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/BlockPriorityRule'
delete:
tags:
- PriorityRule
summary: Удалить правила приоритета
requestBody:
description: Удалить правило приоритета (Qos)
content:
application/json:
schema:
$ref: '#/components/schemas/BlockPriorityRule'
required: true
responses:
'200':
description: On success
'400':
description: On error
'404':
description: Не найдено
post:
tags:
- PriorityRule
summary: Добавить правило приоритета (Qos)
requestBody:
description: Правило приоритета (Qos) (объект json)
content:
application/json:
schema:
$ref: '#/components/schemas/BlockPriorityRule'
required: true
responses:
'200':
description: On success
'400':
description: On error
/interface:
get:
tags:
- Interface
summary: Запрос сетевых интерфейсов
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Interface'
put:
tags:
- Interface
summary: Обновить интерфейс
parameters:
- name: interface
in: query
description: Interface object
required: true
schema:
$ref: '#/components/schemas/Interface'
requestBody:
description: Обновить интерфейс
content:
application/json:
schema:
$ref: '#/components/schemas/Interface'
required: true
responses:
'200':
description: On success
'400':
description: On error
/config:
get:
tags:
- Config
summary: Запрос настроек
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Config'
put:
tags:
- Config
summary: Обновить настройки
parameters:
- name: Config
in: query
description: Config object
required: true
schema:
$ref: '#/components/schemas/Config'
requestBody:
description: Обновить Config
content:
application/json:
schema:
$ref: '#/components/schemas/Config'
required: true
responses:
'200':
description: On success
'400':
description: On error
/stats:
get:
tags:
- Common
summary: Запрос статистики сервера
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Stat'
/commandList:
get:
tags:
- CommandList
summary: Запрос списка команд
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Command'
put:
tags:
- CommandList
summary: Перезапись списка команд
requestBody:
description: Перезапись списка команд
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Command'
responses:
'200':
description: On success
/commandRun/{id}:
post:
tags:
- CommandRun
summary: Запустить команду
parameters:
- name: id
in: path
description: ID of command
required: true
schema:
type: string
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/CommandResult'
'400':
description: On error
'404':
description: Не найдено
'405':
description: Конфиг нельзя запустить
delete:
tags:
- CommandRun
summary: Остановить команду
parameters:
- name: id
in: path
description: ID of command
required: true
schema:
type: string
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/CommandResult'
'400':
description: On error
/command:
post:
tags:
- Command
summary: Добавить команду
parameters:
- name: command
in: query
description: Command object
required: true
schema:
$ref: '#'#/components/schemas/Command'
requestBody:
description: Добавить команду
content:
application/json:
schema:
$ref: '#/components/schemas/Command'
required: true
responses:
'200':
description: Успех
'400':
description: ID занят
'409':
description: Конфиг или скрипт уже существуют
get:
tags:
- Command
summary: Запросить команду с телом
parameters:
- name: id
in: query
description: Command ID
required: true
schema:
type: string
responses:
'200':
description: On success
'400':
description: On error
delete:
tags:
- Command
summary: Удалить команду
parameters:
- name: id
in: query
description: Command ID
required: true
schema:
type: string
responses:
'200':
description: On success
'400':
description: On error
'404':
description: Не найдено
put:
tags:
- Command
summary: Обновить команду
parameters:
- name: command
in: query
description: Command object
required: true
schema:
$ref: '#'#/components/schemas/Command'
requestBody:
description: Обновить команду
content:
application/json:
schema:
$ref: '#/components/schemas/Command'
required: true
responses:
'200':
description: On success
'400':
description: On error
/commandStatuses:
get:
tags:
- CommandStatus
summary: Запрос статусов выполнения команд
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/CommandResult'
'400':
description: On error
/graphInfo:
get:
tags:
- NodeInfo
summary: Запрос связей между точками
responses:
'200':
description: On success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/NodeInfo'
'400':
description: On error
/hotspot:
get:
tags:
- Hotspot
summary: Запросить информацию о точке
parameters:
- name: id
in: query
description: Hotspot ID
required: true
schema:
type: string
responses:
'200':
description: On success
'400':
description: On error
components:
schemas:
Interface:
type: object
properties:
name:
type: string
default: eth0
ip:
type: string
default: 192.168.1.1
netmask:
type: string
default: 255.255.255.0
mac:
type: string
default: 4A:30:10:21:10:1A
mtu:
type: integer
default: 0
active:
type: boolean
default: true
loopback:
type: boolean
default: false
readonly:
type: boolean
default: false
Config:
type: object
properties:
secret:
type: string
default: error
channel:
type: integer
default: 0
width:
type: integer
default: 0
power:
type: integer
default: 0
distance:
type: integer
default: 0
Command:
type: object
properties:
id:
type: string
default: error
contentType:
type: string
default: error
path:
type: string
default: error
content:
type: string
default: error
needConfirmation:
type: boolean
default: false
CommandResult:
type: object
properties:
id:
type: string
default: "name unknown"
exitCode:
type: integer
default: 0
output:
type: string
default: "command stdout"
error:
type: string
default: "command stderr"
running:
type: boolean
default: false
Stat:
type: object
properties:
name:
type: string
default: "unknown"
spots:
type: array
items:
type: number
default: 0.0
interval:
type: integer
default: 5
units:
type: string
default: "db"
min:
type: number
default: 0.0
max:
type: number
default: 100.0
HotspotInfo:
type: object
properties:
name:
type: string
default: "unknown"
signal:
type: number
default: 0.0
hops:
type: integer
default: 5
rx:
type: integer
default: 5
tx:
type: integer
default: 5
bytesReceived:
type: integer
default: 5
bytesSent:
type: integer
default: 5
connectionTime:
type: integer
default: 5,
inactiveTime:
type: integer
default: 5,
stats:
type: array
items:
$ref: '#/components/schemas/Stat'
BackendInfo:
type: object
properties:
version:
type: string
default: "unknown"
arch:
type: string
default: "unknown"
uptime:
type: integer
default: 0
hostname:
type: string
default: "unknown"
buildNum:
type: integer
default: 9999
buildType:
type: string
default: "unknown"
buildDate:
type: string
default: "unknown"
pipVersion:
type: string
default: "unknown"
frontVersion:
type: string
default: "unknown"
frontBuild:
type: string
default: "unknown"
NodeInfo:
type: object
properties:
mac:
type: string
default: "unknown"
connections:
type: array
items:
type: string
default: node
BlockPriorityRule:
type: object
properties:
name:
type: string
default: "unknown"
protocol:
type: string
default: "tcp"
port:
type: integer
default: 389
allow:
type: boolean
default: false
direction:
type: boolean
default: true
priority:
type: integer
default: 0