# Family Safety Tracker API

REST API для обмена геолокацией между членами семьи.

## Аутентификация

Сервис использует JWT токены для авторизации.

### JWT Токен

При успешном `POST /login` возвращается JWT токен:

```json
{
  "user": {...},
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

**Структура токена:**
- `issuer: "family_safety_tracker"`
- `payload: {"user_id": N, "login": "user"}`

### Авторизация

Защищённые эндпоинты (`/watch`, `/geo`, `/share`) требуют JWT в заголовке:

```http
Authorization: Bearer <jwt_token>
```

---

## Таблица эндпоинтов

| Метод | URL | Описание | Защита |
|-------|-----|----------|--------|
| `POST` | `/login` | Вход в систему | — |
| `POST` | `/reg` | Регистрация нового пользователя | — |
| `GET` | `/watch?unique_id=...` | Получить последнюю позицию по share-ссылке | ✅ |
| `PUT` | `/geo?id=N` | Обновить геопозицию | ✅ |
| `POST` | `/share` | Создать share-ссылку | ✅ |

---

## Эндпоинты

### `POST /login` — Вход

#### Запрос

```bash
curl -X POST http://localhost:9090/reg \
  -H "Content-Type: application/json" \
  -d '{"login": "ivan", "password": "secret123"}'
```

#### PowerShell

```powershell
$body = @{ login = "ivan"; password = "secret123" } | ConvertTo-Json
Invoke-RestMethod -Uri http://localhost:9090/reg -Method Post -Body $body -ContentType "application/json"
```

#### Успешный ответ (200)

```json
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

#### Ошибки

| Код | Сообщение |
|-----|-----------|
| `401` | `Invalid credentials` — неверный логин или пароль |

---

### `POST /reg` — Регистрация

#### Запрос

```http
Content-Type: application/json

{"login": "maria", "password": "newpass"}
```

#### Успешный ответ (201)

Ничего не возвращается.

---

### `GET /watch?unique_id=...` — Получить позицию

#### Запрос

```http
Authorization: Bearer <jwt_token>

GET /watch?unique_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890
```

#### Успешный ответ (200)

```json
{
  "id": 42,
  "x": 55.7558,
  "y": 37.6173,
  "created_at": "2024-01-01T12:00:00Z",
  "expires_at": "2024-01-01T12:05:00Z"
}
```

#### Ошибки

| Код | Сообщение |
|-----|-----------|
| `404` | `Share link not found` — неверный `unique_id` |
| `404` | `No position available` — share-ссылка создана, но позиция не была добавлена |

---

### `PUT /geo?id=N` — Обновить позицию

#### Запрос

```http
Authorization: Bearer <jwt_token>
Content-Type: application/json

PUT /geo?id=1

{
  "x": 55.7558,
  "y": 37.6173
}
```

#### Успешный ответ (200)

Ничего не возвращается.

---

### `POST /share` — Создать share-ссылку

#### Запрос

```http
Authorization: Bearer <jwt_token>
Content-Type: application/json

{
  "x": 55.7558,
  "y": 37.6173
}
```

#### Успешный ответ (201)

```json
{
  "geo_id": 5,
  "share_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```

---

## Примеры запросов

### Регистрация

```bash
curl -X POST http://localhost:8080/reg \
  -H "Content-Type: application/json" \
  -d '{"login": "ivan", "password": "secret123"}'
```

### Вход

```bash
curl -X POST http://localhost:9090/login \
  -H "Content-Type: application/json" \
  -d '{"login": "ivan", "password": "secret123"}'
```

#### PowerShell

```powershell
$body = @{ login = "ivan"; password = "secret123" } | ConvertTo-Json
Invoke-RestMethod -Uri http://localhost:9090/login -Method Post -Body $body -ContentType "application/json"
```

### Создание share-ссылки

```bash
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

curl -X POST http://localhost:9090/share \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"x": 55.7558, "y": 37.6173}'
```

#### PowerShell

```powershell
$token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
$body = @{ x = 55.7558; y = 37.6173 } | ConvertTo-Json
Invoke-RestMethod -Uri http://localhost:9090/share -Method Post -Headers @{ Authorization = "Bearer $token"; "Content-Type" = "application/json" } -Body $body
```

### Получение позиции

```bash
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
SHARE_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"

curl "http://localhost:9090/watch?unique_id=$SHARE_ID" \
  -H "Authorization: Bearer $TOKEN"
```

#### PowerShell

```powershell
$token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
$shareId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Invoke-RestMethod -Uri "http://localhost:9090/watch?unique_id=$shareId" -Method Get -Headers @{ Authorization = "Bearer $token" }
```

### Обновление позиции

```bash
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

curl -X PUT "http://localhost:9090/geo?id=1" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"x": 55.7558, "y": 37.6173}'
```

#### PowerShell

```powershell
$token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
$body = @{ x = 55.7558; y = 37.6173 } | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:9090/geo?id=1" -Method Put -Headers @{ Authorization = "Bearer $token"; "Content-Type" = "application/json" } -Body $body
```

---

## Технические детали

### Сервер
- Порт: `9090` (изменяется через `PORT`)

### Технологии
- **Dart** (SDK `^3.10.1`)
- **Shelf** + **Shelf Router** — HTTP фреймворк
- **PostgreSQL** — база данных
- **bcrypt** — хэширование паролей
- **dart_jsonwebtoken** — JWT-токены
- **dotenv** — переменные окружения

### Переменные окружения

| Переменная | Описание |
|------------|----------|
| `PORT` | Порт сервера (по умолчанию 8080) |
| `POSTGRES_HOST` | Хост PostgreSQL |
| `POSTGRES_DB` | База данных |
| `POSTGRES_USER` | Пользователь |
| `POSTGRES_PASSWORD` | Пароль |
| `JWT_SECRET` | Секрет для JWT-токенов |

### Автоматическая миграция

При запуске сервера таблицы создаются автоматически:
- `users` — пользователи
- `geopositions` — геопозиции  
- `logs` — логи

---

## Структура проекта

```
bin/
├── server.dart          # Точка входа
├── routes/
│   ├── auth_routes.dart # Маршруты авторизации
│   └── geo_routes.dart  # Маршруты геолокации
├── repositories/
│   ├── user_repo.dart
│   └── geoposition_repo.dart
├── models/
│   ├── user.dart
│   ├── geoposition.dart
│   └── log.dart
└── database/
    └── database_provider.dart
```

---

## Запуск

```bash
dart pub get
dart run bin/server.dart
```

## Лицензия

MIT
