@@ 79,7 79,7 @@ dependencies = [
"serde_urlencoded",
"sha-1",
"slab",
- "time",
+ "time 0.2.24",
]
[[package]]
@@ 245,7 245,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"socket2",
- "time",
+ "time 0.2.24",
"tinyvec",
"url",
]
@@ 474,6 474,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+name = "chrono"
+version = "0.4.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+dependencies = [
+ "libc",
+ "num-integer",
+ "num-traits",
+ "time 0.1.44",
+ "winapi 0.3.9",
+]
+
+[[package]]
name = "const_fn"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 486,7 499,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f"
dependencies = [
"percent-encoding",
- "time",
+ "time 0.2.24",
"version_check",
]
@@ 794,7 807,7 @@ checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6"
dependencies = [
"cfg-if 1.0.0",
"libc",
- "wasi 0.10.1+wasi-snapshot-preview1",
+ "wasi 0.10.0+wasi-snapshot-preview1",
]
[[package]]
@@ 982,6 995,7 @@ name = "k0r"
version = "0.1.0"
dependencies = [
"actix-web",
+ "chrono",
"exitcode",
"failure",
"failure_derive",
@@ 1192,6 1206,25 @@ dependencies = [
]
[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1793,6 1826,17 @@ dependencies = [
[[package]]
name = "time"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
+dependencies = [
+ "libc",
+ "wasi 0.10.0+wasi-snapshot-preview1",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "time"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "273d3ed44dca264b0d6b3665e8d48fb515042d42466fad93d2a45b90ec4058f7"
@@ 2035,9 2079,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasi"
-version = "0.10.1+wasi-snapshot-preview1"
+version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasm-bindgen"
@@ 1,4 1,5 @@
use actix_web::{web, Error as AWError};
+use chrono::Utc;
use failure::Error;
use failure_derive::Fail;
use futures::{Future, TryFutureExt};
@@ 27,7 28,7 @@ pub enum DBError {
pub enum DBValue {
String(String),
Number(i64),
- // Bool(bool),
+ Bool(bool),
None,
}
@@ 40,11 41,13 @@ pub struct UrlPostData {
pub url: String,
pub title: Option<String>,
pub description: Option<String>,
+ pub expiry: Option<i64>,
pub key: String,
}
/// Possible database queries, used with db::query
pub enum Queries {
+ ForceSync,
NeedsInit,
CountUsers,
InitDB,
@@ 95,6 98,7 @@ URLs|title
URLs|url
URLs|user_id
URLs|visits
+URLs|expiry
Users|api_key
Users|is_admin
Users|rate_limit
@@ 111,6 115,11 @@ Users|rowid",
}
}
+fn sync_database(conn: Connection) -> Result {
+ conn.execute("PRAGMA wal_checkpoint(TRUNCATE);", NO_PARAMS)?;
+ Ok(DBValue::Bool(true))
+}
+
/// Initializes a new SQlite database with the default schema.
fn init_database(conn: Connection) -> Result {
conn.execute_batch(
@@ 129,8 138,9 @@ fn init_database(conn: Connection) -> Result {
visits INTEGER DEFAULT 0,
title TEXT,
description TEXT,
- created_at DATETIME,
- user_id INTEGER NOT NULL,
+ expiry DATETIME,
+ created_at DATETIME,
+ user_id INTEGER NOT NULL,
FOREIGN KEY(user_id) REFERENCES Users(rowid)
);
COMMIT;",
@@ 147,7 157,7 @@ fn count_users(conn: Connection) -> Result {
conn.query_row("SELECT COUNT(rowid) FROM USERS", NO_PARAMS, |row| {
row.get(0)
})
- .map(|v| DBValue::Number(v))
+ .map(DBValue::Number)
.map_err(|src| {
let msg = "Could not check users.".to_owned();
Error::from(DBError::SqliteError { msg, src })
@@ 174,10 184,11 @@ fn create_user(conn: Connection, rate_limit: i64, is_admin: bool) -> Result {
/// short_code is simply the base36 version of the table id
fn get_url(conn: Connection, short_code: &str) -> Result {
let row_id = ShortCode::from_code(short_code)?.n;
+ let now = Utc::now().timestamp();
conn.query_row(
- "SELECT url FROM URLs WHERE rowid = ?",
- &[row_id as i64],
+ "SELECT url FROM URLs WHERE rowid = ? and expiry > ?",
+ &[row_id as i64, now],
|row| row.get(0),
)
.map(DBValue::String)
@@ 195,7 206,7 @@ fn store_url(conn: Connection, data: &UrlPostData) -> Result {
|row| row.get(0),
)?;
let _ = conn.execute_named(
- "INSERT INTO URLs VALUES(:url, 0, :title, :description, DATETIME('now'), :user_id)",
+ "INSERT INTO URLs VALUES(:url, 0, :title, :description, DATETIME('now'), DATETIME(?), :user_id)",
&[
(":url", &data.url),
(":title", data.title.as_ref().unwrap_or(&String::from(""))),
@@ 203,6 214,7 @@ fn store_url(conn: Connection, data: &UrlPostData) -> Result {
":description",
data.description.as_ref().unwrap_or(&String::from("")),
),
+ (":expiry", data.expiry.as_ref().unwrap_or(&i64::MAX)),
(":user_id", &(user_id.to_string())),
],
)?;
@@ 219,6 231,7 @@ pub fn query(
) -> impl Future<Output = std::result::Result<DBValue, AWError>> {
let pool = pool.clone();
web::block(move || match query {
+ Queries::ForceSync => sync_database(pool.get()?),
Queries::NeedsInit => check_database_schema(pool.get()?),
Queries::CountUsers => count_users(pool.get()?),
Queries::InitDB => init_database(pool.get()?),