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:
Binary file not shown.
|
After Width: | Height: | Size: 665 B |
Binary file not shown.
|
After Width: | Height: | Size: 628 B |
@@ -0,0 +1,16 @@
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: #fafafa;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="swagger-ui.css" />
|
||||
<link rel="stylesheet" type="text/css" href="index.css" />
|
||||
<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
<script src="swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||
<script src="swagger-initializer.js" charset="UTF-8"> </script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Swagger UI: OAuth2 Redirect</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
'use strict';
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
var isValid, qp, arr;
|
||||
|
||||
if (/code|token|error/.test(window.location.hash)) {
|
||||
qp = window.location.hash.substring(1).replace('?', '&');
|
||||
} else {
|
||||
qp = location.search.substring(1);
|
||||
}
|
||||
|
||||
arr = qp.split("&");
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value);
|
||||
}
|
||||
) : {};
|
||||
|
||||
isValid = qp.state === sentState;
|
||||
|
||||
if ((
|
||||
oauth2.auth.schema.get("flow") === "accessCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorization_code"
|
||||
) && !oauth2.auth.code) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||
} else {
|
||||
let oauthErrorMsg;
|
||||
if (qp.error) {
|
||||
oauthErrorMsg = "["+qp.error+"]: " +
|
||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||
}
|
||||
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
run();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
run();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,19 @@
|
||||
window.onload = function() {
|
||||
//<editor-fold desc="Changeable Configuration Block">
|
||||
|
||||
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
|
||||
window.ui = SwaggerUIBundle({
|
||||
url: "/swagger/swagger.yaml",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: false,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "BaseLayout"
|
||||
});
|
||||
|
||||
//</editor-fold>
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -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
|
||||
Reference in New Issue
Block a user