Compare commits
No commits in common. "master" and "postgres" have entirely different histories.
6 changed files with 16 additions and 74 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -740,7 +740,7 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kosyncrs"
|
name = "kosyncrs"
|
||||||
version = "2.0.0"
|
version = "1.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "kosyncrs"
|
name = "kosyncrs"
|
||||||
version = "2.0.0"
|
version = "1.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
|
@ -28,14 +28,14 @@ Connect to the database as user *kosync* (with psql) and create the database tab
|
||||||
```sql
|
```sql
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
username TEXT UNIQUE NOT NULL,
|
username TEXT NOT NULL,
|
||||||
password TEXT
|
password TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE progresses (
|
CREATE TABLE progresses (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
user_id BIGINT,
|
user_id BIGINT,
|
||||||
document TEXT NOT NULL,
|
document TEXT UNIQUE NOT NULL,
|
||||||
progress TEXT NOT NULL,
|
progress TEXT NOT NULL,
|
||||||
percentage REAL NOT NULL,
|
percentage REAL NOT NULL,
|
||||||
device TEXT NOT NULL,
|
device TEXT NOT NULL,
|
||||||
|
@ -45,4 +45,4 @@ CREATE TABLE progresses (
|
||||||
REFERENCES users(id) ON DELETE CASCADE,
|
REFERENCES users(id) ON DELETE CASCADE,
|
||||||
UNIQUE (user_id, document)
|
UNIQUE (user_id, document)
|
||||||
);
|
);
|
||||||
```
|
```
|
|
@ -1,52 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import psycopg2
|
|
||||||
import re
|
|
||||||
import redis
|
|
||||||
|
|
||||||
con = redis.Redis()
|
|
||||||
|
|
||||||
pgcon = psycopg2.connect("postgresql://kosync:mypassword@localhost/kosync")
|
|
||||||
pgcur = pgcon.cursor()
|
|
||||||
|
|
||||||
userkeys = con.keys('user:*:key')
|
|
||||||
|
|
||||||
for key in userkeys:
|
|
||||||
key = key.decode('utf-8')
|
|
||||||
match = re.search('user:(.*):key', key)
|
|
||||||
username = match.group(1)
|
|
||||||
password = con.get(key).decode('utf-8')
|
|
||||||
|
|
||||||
documentkeys = con.keys('user:' + username + ':document:*')
|
|
||||||
if len(documentkeys) == 0:
|
|
||||||
print("Skipped:", username)
|
|
||||||
continue
|
|
||||||
|
|
||||||
pgcur.execute("INSERT INTO users (username, password) VALUES (%s, %s) ON CONFLICT (username) DO UPDATE SET username = %s, password = %s",
|
|
||||||
(username, password, username, password))
|
|
||||||
|
|
||||||
pgcur.execute("SELECT id FROM users WHERE username = %s", (username,))
|
|
||||||
res = pgcur.fetchone()
|
|
||||||
user_id = res[0]
|
|
||||||
|
|
||||||
for dockey in documentkeys:
|
|
||||||
dockey = dockey.decode('utf-8')
|
|
||||||
|
|
||||||
match = re.search("user:.*:(.*)", dockey)
|
|
||||||
document = match.group(1)
|
|
||||||
|
|
||||||
docvals = con.hgetall(dockey)
|
|
||||||
|
|
||||||
progress = docvals[b"progress"].decode()
|
|
||||||
percentage = docvals[b"percentage"].decode()
|
|
||||||
device = docvals[b"device"].decode()
|
|
||||||
device_id = docvals[b"device_id"].decode()
|
|
||||||
timestamp = docvals[b"timestamp"].decode()
|
|
||||||
|
|
||||||
pgcur.execute("INSERT INTO progresses (user_id, document, progress, percentage, device, device_id, timestamp) VALUES (%s, %s, %s, %s, %s, %s, %s) ON CONFLICT (user_id, document) DO UPDATE SET user_id = %s, document = %s, progress = %s, percentage = %s, device = %s, device_id = %s, timestamp = %s",
|
|
||||||
(user_id, document, progress, percentage, device, device_id, timestamp, user_id, document, progress, percentage, device, device_id, timestamp))
|
|
||||||
|
|
||||||
pgcon.commit()
|
|
||||||
|
|
||||||
pgcur.close()
|
|
||||||
pgcon.close()
|
|
24
src/main.rs
24
src/main.rs
|
@ -39,15 +39,12 @@ pub struct GetProgress {
|
||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let pg_url: String = env::var("PG_URL")
|
let pg_url: String = env::var("PG_URL")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|v| v.parse().ok())
|
.and_then(|v| v.parse().ok())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let listen_port: String = env::var("PORT").ok().and_then(|v| v.parse().ok()).unwrap();
|
|
||||||
|
|
||||||
let db_pool = PgPoolOptions::new()
|
let db_pool = PgPoolOptions::new()
|
||||||
.max_connections(64)
|
.max_connections(64)
|
||||||
|
@ -64,12 +61,10 @@ async fn main() {
|
||||||
.route("/syncs/progress", put(update_progress))
|
.route("/syncs/progress", put(update_progress))
|
||||||
.route("/syncs/progress/{document}", get(get_progress))
|
.route("/syncs/progress/{document}", get(get_progress))
|
||||||
.route("/healthcheck", get(healthcheck))
|
.route("/healthcheck", get(healthcheck))
|
||||||
.route("/version", get(version))
|
|
||||||
.with_state(db_pool);
|
.with_state(db_pool);
|
||||||
|
|
||||||
let mut bind_with = "127.0.0.1:".to_owned();
|
// run it with hyper on localhost:3003
|
||||||
bind_with += &listen_port;
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3003")
|
||||||
let listener = tokio::net::TcpListener::bind(bind_with)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, app).await.unwrap();
|
||||||
|
@ -79,15 +74,14 @@ async fn root() -> &'static str {
|
||||||
"KOreader sync server"
|
"KOreader sync server"
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn version() -> &'static str {
|
|
||||||
VERSION
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create_user(
|
async fn create_user(
|
||||||
State(db_pool): State<PgPool>,
|
State(db_pool): State<PgPool>,
|
||||||
Json(payload): Json<User>,
|
Json(payload): Json<User>,
|
||||||
) -> (StatusCode, Json<Value>) {
|
) -> (StatusCode, Json<Value>) {
|
||||||
let username = payload.username.trim().to_owned();
|
//let client = redis::Client::open("redis://127.0.0.1/").unwrap();
|
||||||
|
//let mut con = client.get_connection().unwrap();
|
||||||
|
|
||||||
|
let username = payload.username;
|
||||||
let password = payload.password;
|
let password = payload.password;
|
||||||
|
|
||||||
let row: (i64,) = sqlx::query_as("SELECT COUNT(id) FROM users WHERE username = $1")
|
let row: (i64,) = sqlx::query_as("SELECT COUNT(id) FROM users WHERE username = $1")
|
||||||
|
@ -134,7 +128,7 @@ async fn authorize(db: impl PgExecutor<'_>, username: &str, password: &str) -> b
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn auth_user(State(db_pool): State<PgPool>, headers: HeaderMap) -> (StatusCode, Json<Value>) {
|
async fn auth_user(State(db_pool): State<PgPool>, headers: HeaderMap) -> (StatusCode, Json<Value>) {
|
||||||
let username = headers["x-auth-user"].to_str().unwrap_or("").trim();
|
let username = headers["x-auth-user"].to_str().unwrap_or("");
|
||||||
let password = headers["x-auth-key"].to_str().unwrap_or("");
|
let password = headers["x-auth-key"].to_str().unwrap_or("");
|
||||||
|
|
||||||
let mut tx = db_pool.begin().await.unwrap();
|
let mut tx = db_pool.begin().await.unwrap();
|
||||||
|
@ -156,7 +150,7 @@ async fn update_progress(
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
Json(payload): Json<UpdateProgress>,
|
Json(payload): Json<UpdateProgress>,
|
||||||
) -> StatusCode {
|
) -> StatusCode {
|
||||||
let username = headers["x-auth-user"].to_str().unwrap_or("").trim();
|
let username = headers["x-auth-user"].to_str().unwrap_or("");
|
||||||
let password = headers["x-auth-key"].to_str().unwrap_or("");
|
let password = headers["x-auth-key"].to_str().unwrap_or("");
|
||||||
|
|
||||||
let mut tx = db_pool.begin().await.unwrap();
|
let mut tx = db_pool.begin().await.unwrap();
|
||||||
|
@ -202,7 +196,7 @@ async fn get_progress(
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
Path(document): Path<String>,
|
Path(document): Path<String>,
|
||||||
) -> (StatusCode, Json<Value>) {
|
) -> (StatusCode, Json<Value>) {
|
||||||
let username = headers["x-auth-user"].to_str().unwrap_or("").trim();
|
let username = headers["x-auth-user"].to_str().unwrap_or("");
|
||||||
let password = headers["x-auth-key"].to_str().unwrap_or("");
|
let password = headers["x-auth-key"].to_str().unwrap_or("");
|
||||||
|
|
||||||
let mut tx = db_pool.begin().await.unwrap();
|
let mut tx = db_pool.begin().await.unwrap();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
Description=KOReader Sync Server
|
Description=KOReader Sync Server
|
||||||
After=syslog.target
|
After=syslog.target
|
||||||
After=network.target
|
After=network.target
|
||||||
After=postgresql.service
|
After=redis.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
RestartSec=2s
|
RestartSec=2s
|
||||||
|
@ -11,7 +11,7 @@ User=myuser
|
||||||
Group=users
|
Group=users
|
||||||
WorkingDirectory=/home/myuser
|
WorkingDirectory=/home/myuser
|
||||||
ExecStart=/usr/local/bin/kosyncrs
|
ExecStart=/usr/local/bin/kosyncrs
|
||||||
Environment=PG_URL=postgresql://kosync:password@localhost/kosync PORT=3003
|
Environment="PG_URL=postgresql://kosync:password@localhost/kosync"
|
||||||
Restart=always
|
Restart=always
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
|
Loading…
Reference in a new issue