This commit is contained in:
parent
f9072ead3c
commit
3e90e2fa9f
5
.env
5
.env
@ -2,4 +2,7 @@ DATABASE_URL=postgresql://mmap:yjhcfzXWrzslzl1331@8.217.64.157:5433/mmap
|
||||
JWT_SECRET="JvGpWgGWLHAhvhxN7BuOVtUWfMXm6xAqjClaTwOcAnI="
|
||||
RUST_LOG=debug
|
||||
PORT=3050
|
||||
TILE_SERVER="http://127.0.0.1:3060/api"
|
||||
TILE_SERVER="http://47.95.11.22:3060/api"
|
||||
KAFKA_BROKERS="8.217.64.157:9094"
|
||||
KAFKA_TOPIC=data-output
|
||||
KAFKA_GROUP_ID=mapp
|
||||
61
.github/workflows/docker.yml
vendored
Normal file
61
.github/workflows/docker.yml
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
name: Docker Build and Push
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
tags: [ 'v*' ]
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
|
||||
env:
|
||||
REGISTRY: crpi-8rsu3rjoi0n0hc4m.cn-hongkong.personal.cr.aliyuncs.com
|
||||
IMAGE_NAME: tmmapp/tiler
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Container Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.ALIYUN_USERNAME }}
|
||||
password: ${{ secrets.ALIYUN_PASSWORD }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha,prefix={{branch}}-
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Output image digest
|
||||
if: github.event_name != 'pull_request'
|
||||
run: echo ${{ steps.build.outputs.digest }}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT id, code, created_by, used_by, is_used, expires_at, created_at, used_at\n FROM invite_codes \n WHERE code = $1\n ",
|
||||
"query": "\n SELECT id, code, created_by, used_by, is_used, \n expires_at as \"expires_at: chrono::DateTime<chrono::Utc>\", \n created_at as \"created_at: chrono::DateTime<chrono::Utc>\", \n used_at as \"used_at: chrono::DateTime<chrono::Utc>\"\n FROM invite_codes \n WHERE code = $1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -30,17 +30,17 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "expires_at",
|
||||
"name": "expires_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_at",
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "used_at",
|
||||
"name": "used_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
@ -60,5 +60,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "353dee803eee3a4f1e68a8e5f391879128dfc59b963bd519e8dfb2fae24c6c3b"
|
||||
"hash": "19edd626ddc3d5053f2f0c39a7f98ef517de4d3d3445a96f901fd84ab3df2f9c"
|
||||
}
|
||||
58
.sqlx/query-2d227347f45a681968fcee4452e70d59604ee99538081add65cc92c2ec74720e.json
generated
Normal file
58
.sqlx/query-2d227347f45a681968fcee4452e70d59604ee99538081add65cc92c2ec74720e.json
generated
Normal file
@ -0,0 +1,58 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT \n id,\n ingestion_time as \"ingestion_time: chrono::DateTime<chrono::Utc>\",\n data_time as \"data_time: chrono::DateTime<chrono::Utc>\",\n source,\n storage_url,\n created_at as \"created_at: chrono::DateTime<chrono::Utc>\",\n updated_at as \"updated_at: chrono::DateTime<chrono::Utc>\"\n FROM data_ingestion \n WHERE source = $1\n ORDER BY data_time DESC \n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "ingestion_time: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamp"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "data_time: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamp"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "source",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "storage_url",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamp"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "updated_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamp"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "2d227347f45a681968fcee4452e70d59604ee99538081add65cc92c2ec74720e"
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT COUNT(*) FROM users WHERE is_activate = false",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "41e05b2ce23645a612d385f0faa02dad038c2facb9cb1d566fe7572d659c0a03"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT id, code, created_by, used_by, is_used, expires_at, created_at, used_at\n FROM invite_codes \n WHERE created_by = $1\n ORDER BY created_at DESC\n ",
|
||||
"query": "\n SELECT id, code, created_by, used_by, is_used, \n expires_at as \"expires_at: chrono::DateTime<chrono::Utc>\", \n created_at as \"created_at: chrono::DateTime<chrono::Utc>\", \n used_at as \"used_at: chrono::DateTime<chrono::Utc>\"\n FROM invite_codes \n WHERE created_by = $1\n ORDER BY created_at DESC\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -30,17 +30,17 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "expires_at",
|
||||
"name": "expires_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_at",
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "used_at",
|
||||
"name": "used_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
@ -60,5 +60,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "6e1bf3857d6eb4df7f14d0eca0823f39c50f1b18e61bc469d616598a20c5bb91"
|
||||
"hash": "567dd7f85208ee5cfc91eb5f86a752b1925aa726d3601f79715ed7e41788fbd9"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT id, username, email, password_hash, role as \"role: Role\", invite_code_id, created_at, updated_at\n FROM users WHERE username = $1\n ",
|
||||
"query": "\n SELECT id, username, email, password_hash, role as \"role: Role\", invite_code_id, is_activate, \n created_at as \"created_at: chrono::DateTime<chrono::Utc>\", \n updated_at as \"updated_at: chrono::DateTime<chrono::Utc>\"\n FROM users WHERE username = $1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -35,12 +35,17 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
"name": "is_activate",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "updated_at",
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "updated_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
@ -56,9 +61,10 @@
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "2ab074bca985746d32cb5d932c0012019486847c80eb12d5fccda6841a22613d"
|
||||
"hash": "56c51721fae7860a57aadbf46acd96277f498da55d10c5d640dd544f26ae301c"
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT COUNT(*) FROM users WHERE role = 'user'",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "56c6cd9cd434821ad87afdc1e0e9194d1965d2876676780275ecdb45ee9e16f5"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT id, code, created_by, used_by, is_used, expires_at, created_at, used_at\n FROM invite_codes \n WHERE id = $1\n ",
|
||||
"query": "\n SELECT id, code, created_by, used_by, is_used, \n expires_at as \"expires_at: chrono::DateTime<chrono::Utc>\", \n created_at as \"created_at: chrono::DateTime<chrono::Utc>\", \n used_at as \"used_at: chrono::DateTime<chrono::Utc>\"\n FROM invite_codes \n WHERE id = $1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -30,17 +30,17 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "expires_at",
|
||||
"name": "expires_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_at",
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "used_at",
|
||||
"name": "used_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
@ -60,5 +60,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "0325b8932e0a71f18e0018185b5559eb6ec748c67417efaf62520a690ca2b385"
|
||||
"hash": "669fc31e8b8eea3f51f5f0deb6fa3ad40844efb5778b342271fd2047492cef22"
|
||||
}
|
||||
44
.sqlx/query-9dff45451b7fe2804768c72642ba52aed5618d687519727c6a39fd7bb77c9237.json
generated
Normal file
44
.sqlx/query-9dff45451b7fe2804768c72642ba52aed5618d687519727c6a39fd7bb77c9237.json
generated
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT \n COUNT(*) as total_users,\n COUNT(CASE WHEN is_activate = true THEN 1 END) as total_active_users,\n COUNT(CASE WHEN is_activate = false THEN 1 END) as total_inactive_users,\n COUNT(CASE WHEN role = 'Admin' THEN 1 END) as total_admin_users,\n COUNT(CASE WHEN role = 'User' THEN 1 END) as total_user_users\n FROM users\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "total_users",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "total_active_users",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "total_inactive_users",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "total_admin_users",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "total_user_users",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "9dff45451b7fe2804768c72642ba52aed5618d687519727c6a39fd7bb77c9237"
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT id, username, email, password_hash, role as \"role: Role\", invite_code_id, created_at, updated_at FROM users LIMIT $1 OFFSET $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "username",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "email",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "password_hash",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "role: Role",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "invite_code_id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "updated_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "a27168afd0caa5f71fa1036e2508d0a7f83a74433a42d7a31c71a97c522aed79"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE users SET invite_code_id = $1 WHERE id = $2\n RETURNING id, username, email, password_hash, role as \"role: Role\", invite_code_id, created_at, updated_at\n ",
|
||||
"query": "\n UPDATE users SET invite_code_id = $1 WHERE id = $2\n RETURNING id, username, email, password_hash, role as \"role: Role\", invite_code_id, is_activate, \n created_at as \"created_at: chrono::DateTime<chrono::Utc>\", \n updated_at as \"updated_at: chrono::DateTime<chrono::Utc>\"\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -35,12 +35,17 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
"name": "is_activate",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "updated_at",
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "updated_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
@ -57,9 +62,10 @@
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "84af2d99fe5036ae0f0041aa539427312e89b9faba1c8b6900164fbd0f7a703e"
|
||||
"hash": "abca093e4f8ee335527fa29fcc79babe383e1d7ac92367fa24128db3b0d153f2"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT id, username, email, password_hash, role as \"role: Role\", invite_code_id, created_at, updated_at\n FROM users WHERE id = $1\n ",
|
||||
"query": "\n SELECT id, username, email, password_hash, role as \"role: Role\", invite_code_id, is_activate, \n created_at as \"created_at: chrono::DateTime<chrono::Utc>\", \n updated_at as \"updated_at: chrono::DateTime<chrono::Utc>\"\n FROM users WHERE id = $1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -35,12 +35,17 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
"name": "is_activate",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "updated_at",
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "updated_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
@ -56,9 +61,10 @@
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "3bdc7146e0751bcb04a3ed6831c0d094a5d4b38937542f5f1529748c8c6b3aa6"
|
||||
"hash": "ba6430e67988cda88df40d61f0a9b4ff715f5feb76fe20e7f9abafcc390e43c2"
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO users (username, email, password_hash, role)\n VALUES ($1, $2, $3, $4)\n RETURNING id, username, email, password_hash, role as \"role: Role\", invite_code_id, created_at, updated_at\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "username",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "email",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "password_hash",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "role: Role",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "invite_code_id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "updated_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "c2c999a6ab3b058deced5568868eff7e70cf981804cecd228b6477885e1386ae"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO users (username, email, password_hash, role)\n VALUES ($1, $2, $3, $4)\n RETURNING id, username, email, password_hash, role as \"role: Role\", invite_code_id, is_activate, created_at, updated_at\n ",
|
||||
"query": "\n INSERT INTO users (username, email, password_hash, role, is_activate)\n VALUES ($1, $2, $3, $4, $5)\n RETURNING id, username, email, password_hash, role as \"role: Role\", invite_code_id, is_activate, \n created_at as \"created_at: chrono::DateTime<chrono::Utc>\", \n updated_at as \"updated_at: chrono::DateTime<chrono::Utc>\"\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -40,12 +40,12 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "created_at",
|
||||
"name": "created_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "updated_at",
|
||||
"name": "updated_at: chrono::DateTime<chrono::Utc>",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
@ -54,7 +54,8 @@
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar"
|
||||
"Varchar",
|
||||
"Bool"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
@ -69,5 +70,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "8a1b2c956e1ff38b2a2a6179f5f7aaddd80dfef77ed05694ba17d7dedebac9dc"
|
||||
"hash": "d3f1440480f440bbc8577adfbebbf8165c800abf81f4ab74f4a65f6339637ae5"
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT COUNT(*) FROM users WHERE is_activate = true",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "d470eafcaff0b536c38e0d29a1a4f35867068c68ebed4b326517631a8e978da5"
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT COUNT(*) FROM users WHERE role = 'admin'",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "d718520b0f79dd1b0999cbb65bd334dca8d7209fa914355a38287af587ae8d4c"
|
||||
}
|
||||
119
Cargo.lock
generated
119
Cargo.lock
generated
@ -38,6 +38,19 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
@ -236,7 +249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8725874ecfbf399e071150b8619c4071d7b2b7a2f117e173dddef53c6bdb6bb1"
|
||||
dependencies = [
|
||||
"async-graphql",
|
||||
"axum",
|
||||
"axum 0.8.4",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"serde_json",
|
||||
@ -454,13 +467,42 @@ dependencies = [
|
||||
"fs_extra",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core 0.4.5",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"hyper-util",
|
||||
"itoa",
|
||||
"matchit 0.7.3",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tower 0.5.2",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5"
|
||||
dependencies = [
|
||||
"axum-core",
|
||||
"axum-core 0.5.2",
|
||||
"axum-macros",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@ -472,7 +514,7 @@ dependencies = [
|
||||
"hyper",
|
||||
"hyper-util",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"matchit 0.8.4",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
@ -492,6 +534,26 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"sync_wrapper",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.5.2"
|
||||
@ -518,8 +580,8 @@ version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45bf463831f5131b7d3c756525b305d40f1185b688565648a92e1392ca35713d"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-core",
|
||||
"axum 0.8.4",
|
||||
"axum-core 0.5.2",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"headers",
|
||||
@ -542,7 +604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418f97e310fb4e9bc5c38948ede899a2aa00911529aaf69ff38c454f4a653397"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
"axum 0.8.4",
|
||||
"axum-extra",
|
||||
"dashmap",
|
||||
"derive_builder",
|
||||
@ -572,7 +634,7 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84bb2eec9f1a2c150ce1204d843d690db0da305f6f2848cbfd4a840c830b4f0b"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum 0.8.4",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
@ -592,6 +654,23 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum_gcra"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b171b8669e7a83349c726cc857529da933b03c503ad64f6258e546e0ec924ca5"
|
||||
dependencies = [
|
||||
"ahash 0.8.12",
|
||||
"async-trait",
|
||||
"axum 0.7.9",
|
||||
"futures-util",
|
||||
"http",
|
||||
"pin-project-lite",
|
||||
"scc",
|
||||
"tokio",
|
||||
"tower 0.4.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.75"
|
||||
@ -1518,7 +1597,7 @@ version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"ahash 0.7.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2154,9 +2233,10 @@ dependencies = [
|
||||
"async-graphql",
|
||||
"async-graphql-axum",
|
||||
"async-stream",
|
||||
"axum",
|
||||
"axum 0.8.4",
|
||||
"axum-jwt-auth",
|
||||
"axum-reverse-proxy",
|
||||
"axum_gcra",
|
||||
"chrono",
|
||||
"clap",
|
||||
"dotenvy",
|
||||
@ -2177,6 +2257,12 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.8.4"
|
||||
@ -3173,6 +3259,15 @@ version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "scc"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22b2d775fb28f245817589471dd49c5edf64237f4a19d10ce9a92ff4651a27f4"
|
||||
dependencies = [
|
||||
"sdd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.27"
|
||||
@ -3188,6 +3283,12 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "sdd"
|
||||
version = "3.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
|
||||
|
||||
[[package]]
|
||||
name = "sea-query"
|
||||
version = "0.32.6"
|
||||
|
||||
@ -48,4 +48,5 @@ axum-reverse-proxy = "1.0.3"
|
||||
rustls = { version = "0.23", features = ["aws-lc-rs"] }
|
||||
clap = { version = "4.0", features = ["derive"] }
|
||||
rdkafka = "0.38.0"
|
||||
axum_gcra = "0.1.1"
|
||||
|
||||
|
||||
49
Dockerfile
Normal file
49
Dockerfile
Normal file
@ -0,0 +1,49 @@
|
||||
FROM rust:1.88.0-slim as builder
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
pkg-config \
|
||||
libssl-dev \
|
||||
libpq-dev \
|
||||
build-essential \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pkg-config --version && \
|
||||
pkg-config --libs openssl && \
|
||||
pkg-config --cflags openssl
|
||||
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
COPY src ./src
|
||||
|
||||
COPY .sqlx .sqlx
|
||||
|
||||
ENV SQLX_OFFLINE=true
|
||||
RUN cargo build --release
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
pkg-config \
|
||||
libssl-dev \
|
||||
libpq-dev \
|
||||
build-essential \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pkg-config --version && \
|
||||
pkg-config --libs openssl && \
|
||||
pkg-config --cflags openssl
|
||||
|
||||
RUN groupadd -r appuser && useradd -r -g appuser appuser
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /usr/src/app/target/release/mapp-tile /app/mapp-tile
|
||||
|
||||
RUN chown -R appuser:appuser /app
|
||||
USER appuser
|
||||
|
||||
EXPOSE 3060
|
||||
|
||||
# 运行应用程序
|
||||
CMD ["./mapp-tile"]
|
||||
24
src/app.rs
24
src/app.rs
@ -1,5 +1,6 @@
|
||||
use axum_gcra::{gcra::Quota, real_ip::RealIp, RateLimitLayer};
|
||||
use axum_reverse_proxy::ReverseProxy;
|
||||
use std::sync::Arc;
|
||||
use std::{num::NonZero, sync::Arc, time::Duration};
|
||||
use tokio::sync::broadcast;
|
||||
|
||||
use async_graphql::{
|
||||
@ -9,6 +10,7 @@ use async_graphql::{
|
||||
use async_graphql_axum::{GraphQLRequest, GraphQLResponse, GraphQLSubscription};
|
||||
use axum::{
|
||||
extract::{FromRef, State},
|
||||
http::Method,
|
||||
response::{Html, IntoResponse},
|
||||
routing::get,
|
||||
Router,
|
||||
@ -22,8 +24,8 @@ use crate::{
|
||||
config::Config,
|
||||
graphql::{subscription::StatusUpdate, MutationRoot, QueryRoot, SubscriptionRoot},
|
||||
services::{
|
||||
invite_code_service::InviteCodeService, system_config_service::SystemConfigService,
|
||||
user_service::UserService,
|
||||
invite_code_service::InviteCodeService, mosaic_service::MosaicService,
|
||||
system_config_service::SystemConfigService, user_service::UserService,
|
||||
},
|
||||
};
|
||||
|
||||
@ -47,12 +49,14 @@ pub fn create_router(
|
||||
let user_service = UserService::new(pool.clone(), config.jwt_secret.clone());
|
||||
let invite_code_service = InviteCodeService::new(pool.clone());
|
||||
let system_config_service = SystemConfigService::new(pool.clone());
|
||||
let mosaic_service = MosaicService::new(pool.clone());
|
||||
|
||||
let schema = Schema::build(QueryRoot, MutationRoot, SubscriptionRoot)
|
||||
.data(pool)
|
||||
.data(user_service)
|
||||
.data(invite_code_service)
|
||||
.data(system_config_service)
|
||||
.data(mosaic_service)
|
||||
.data(config.clone())
|
||||
.data(status_sender.clone())
|
||||
.finish();
|
||||
@ -77,6 +81,20 @@ pub fn create_router(
|
||||
Router::new()
|
||||
.route("/", get(graphql_playground))
|
||||
.route("/graphql", get(graphql_playground).post(graphql_handler))
|
||||
// .route_layer(
|
||||
// RateLimitLayer::<RealIp>::builder()
|
||||
// .with_route(
|
||||
// (Method::GET, "/graphql"),
|
||||
// Quota::new(Duration::from_millis(100), NonZero::new(10).unwrap()),
|
||||
// )
|
||||
// .with_route(
|
||||
// (Method::POST, "/graphql"),
|
||||
// Quota::new(Duration::from_millis(100), NonZero::new(10).unwrap()),
|
||||
// )
|
||||
// .with_global_fallback(false)
|
||||
// .with_gc_interval(1000)
|
||||
// .default_handle_error(),
|
||||
// )
|
||||
.route_service("/ws", GraphQLSubscription::new(schema))
|
||||
.layer(CorsLayer::permissive())
|
||||
.merge(router)
|
||||
|
||||
@ -7,6 +7,8 @@ use tokio::time::{interval, timeout};
|
||||
use tracing::{error, info, warn};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::services::mosaic_service::{self, MosaicService};
|
||||
|
||||
#[derive(SimpleObject, Clone, Debug)]
|
||||
pub struct StatusUpdate {
|
||||
pub id: Uuid,
|
||||
@ -44,6 +46,9 @@ impl SubscriptionRoot {
|
||||
|
||||
info!("新的WebSocket客户端连接到状态更新订阅");
|
||||
|
||||
let mosaic_service = ctx.data::<MosaicService>()?;
|
||||
let last_data = mosaic_service.last_data("cn").await?;
|
||||
|
||||
return Ok(async_stream::stream! {
|
||||
// 发送初始连接确认消息
|
||||
let welcome = StatusUpdate {
|
||||
@ -52,7 +57,7 @@ impl SubscriptionRoot {
|
||||
message: "WebSocket连接已建立".to_string(),
|
||||
timestamp: Utc::now(),
|
||||
data: Some("websocket_connected".to_string()),
|
||||
newest_dt: None,
|
||||
newest_dt: last_data.map(|data| data.data_time.format("%Y%m%d%H%M%S").to_string()),
|
||||
};
|
||||
yield welcome;
|
||||
|
||||
|
||||
@ -174,7 +174,7 @@ impl KafkaListener {
|
||||
),
|
||||
timestamp: Utc::now(),
|
||||
data: Some(message.get_file_path().to_string()),
|
||||
newest_dt: Some(message.get_data_time().to_string()),
|
||||
newest_dt: Some(format!("{}00", message.get_data_time())),
|
||||
};
|
||||
|
||||
if let Err(e) = self.status_sender.send(status_update) {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
pub mod invite_code_service;
|
||||
pub mod mosaic_service;
|
||||
pub mod system_config_service;
|
||||
pub mod user_service;
|
||||
|
||||
65
src/services/mosaic_service.rs
Normal file
65
src/services/mosaic_service.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use argon2::password_hash::{rand_core::OsRng, SaltString};
|
||||
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
|
||||
use async_graphql::{Error, Result};
|
||||
use chrono::{DateTime, Utc};
|
||||
use sea_query::{Expr, PostgresQueryBuilder};
|
||||
use sea_query_binder::SqlxBinder;
|
||||
use sqlx::PgPool;
|
||||
use tracing::info;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::auth::Claims;
|
||||
use crate::graphql::types::{
|
||||
CreateUserInput, LoginInput, LoginResponse, RegisterInput, UserInfoRespnose,
|
||||
};
|
||||
use crate::models::user::{Role, User};
|
||||
|
||||
use crate::services::invite_code_service::InviteCodeService;
|
||||
use crate::services::system_config_service::SystemConfigService;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DataIngestion {
|
||||
pub id: Uuid,
|
||||
pub ingestion_time: DateTime<Utc>,
|
||||
pub data_time: DateTime<Utc>,
|
||||
pub source: String,
|
||||
pub storage_url: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
pub struct MosaicService {
|
||||
pool: PgPool,
|
||||
}
|
||||
|
||||
impl MosaicService {
|
||||
pub fn new(pool: PgPool) -> Self {
|
||||
Self { pool }
|
||||
}
|
||||
|
||||
pub async fn last_data(&self, area: &str) -> Result<Option<DataIngestion>> {
|
||||
let result = sqlx::query_as!(
|
||||
DataIngestion,
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
ingestion_time as "ingestion_time: chrono::DateTime<chrono::Utc>",
|
||||
data_time as "data_time: chrono::DateTime<chrono::Utc>",
|
||||
source,
|
||||
storage_url,
|
||||
created_at as "created_at: chrono::DateTime<chrono::Utc>",
|
||||
updated_at as "updated_at: chrono::DateTime<chrono::Utc>"
|
||||
FROM data_ingestion
|
||||
WHERE source = $1
|
||||
ORDER BY data_time DESC
|
||||
LIMIT 1
|
||||
"#,
|
||||
area
|
||||
)
|
||||
.fetch_optional(&self.pool)
|
||||
.await
|
||||
.map_err(|e| Error::new(format!("Failed to get last data: {}", e)))?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user