mirror of
https://github.com/SinTan1729/chhoto-url
synced 2024-12-26 23:58:35 -06:00
Compare commits
4 commits
168cff94a2
...
5fb8587628
Author | SHA1 | Date | |
---|---|---|---|
|
5fb8587628 | ||
6cdacda510 | |||
ed2be0e883 | |||
0fce881654 |
7 changed files with 70 additions and 23 deletions
4
Makefile
4
Makefile
|
@ -21,7 +21,9 @@ docker-stop:
|
||||||
docker ps -aq --filter "name=chhoto-url" | xargs -r docker rm
|
docker ps -aq --filter "name=chhoto-url" | xargs -r docker rm
|
||||||
|
|
||||||
docker-test: docker-local docker-stop
|
docker-test: docker-local docker-stop
|
||||||
docker run -p 4567:4567 --name chhoto-url -e password="${PASSWORD}" -d chhoto-url
|
docker run -p 4567:4567 --name chhoto-url -e password="${PASSWORD}" -e public_mode="${PUBLIC_MODE}" \
|
||||||
|
-e site_url="${SITE_URL}" -e db_url="${DB_URL}" -e redirect_method="${REDIRECT_METHOD}" \
|
||||||
|
-e slug_style="${SLUG_STYLE}" -e slug_length="${SLUG_LENGTH}" -d chhoto-url
|
||||||
docker logs chhoto-url -f
|
docker logs chhoto-url -f
|
||||||
|
|
||||||
docker-dev: build-dev
|
docker-dev: build-dev
|
||||||
|
|
|
@ -45,6 +45,8 @@ for small. URL means, well... URL. So the name simply means Small URL.
|
||||||
- Counts number of hits for each short link in a privacy respecting way
|
- Counts number of hits for each short link in a privacy respecting way
|
||||||
i.e. only the hit is recorded, and nothing else.
|
i.e. only the hit is recorded, and nothing else.
|
||||||
- Has a mobile friendly UI.
|
- Has a mobile friendly UI.
|
||||||
|
- Has a public mode, where anyone can add links without authentication. Deleting
|
||||||
|
or listing available links will need admin access using the password.
|
||||||
- Allows setting the URL of your website, in case you want to conveniently
|
- Allows setting the URL of your website, in case you want to conveniently
|
||||||
generate short links locally.
|
generate short links locally.
|
||||||
- Links are stored in an SQLite database.
|
- Links are stored in an SQLite database.
|
||||||
|
@ -128,6 +130,9 @@ default, the auto-generated links are adjective-name pairs. You can use UIDs by
|
||||||
the `slug_style` variable to `UID`. You can also set the length of those slug by setting
|
the `slug_style` variable to `UID`. You can also set the length of those slug by setting
|
||||||
the `slug_length` variable. It defaults to 8, and a minimum of 4 is supported.
|
the `slug_length` variable. It defaults to 8, and a minimum of 4 is supported.
|
||||||
|
|
||||||
|
To enable public mode, set `public_mode` to `Enable`. With this, anyone will be able to add
|
||||||
|
links. Listing existing links or deleting links will need admin access using the password.
|
||||||
|
|
||||||
## Instructions for CLI usage
|
## Instructions for CLI usage
|
||||||
The application can be used from the terminal using something like `curl`. In all the examples
|
The application can be used from the terminal using something like `curl`. In all the examples
|
||||||
below, replace `http://localhost:4567` with where your instance of `chhoto-url` is accessible.
|
below, replace `http://localhost:4567` with where your instance of `chhoto-url` is accessible.
|
||||||
|
|
|
@ -30,7 +30,7 @@ const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
// Add new links
|
// Add new links
|
||||||
#[post("/api/new")]
|
#[post("/api/new")]
|
||||||
async fn add_link(req: String, data: web::Data<AppState>, session: Session) -> HttpResponse {
|
async fn add_link(req: String, data: web::Data<AppState>, session: Session) -> HttpResponse {
|
||||||
if auth::validate(session) {
|
if env::var("public_mode") == Ok(String::from("Enable")) || auth::validate(session) {
|
||||||
let out = utils::add_link(req, &data.db);
|
let out = utils::add_link(req, &data.db);
|
||||||
if out.0 {
|
if out.0 {
|
||||||
HttpResponse::Created().body(out.1)
|
HttpResponse::Created().body(out.1)
|
||||||
|
@ -48,19 +48,20 @@ async fn getall(data: web::Data<AppState>, session: Session) -> HttpResponse {
|
||||||
if auth::validate(session) {
|
if auth::validate(session) {
|
||||||
HttpResponse::Ok().body(utils::getall(&data.db))
|
HttpResponse::Ok().body(utils::getall(&data.db))
|
||||||
} else {
|
} else {
|
||||||
HttpResponse::Unauthorized().body("Not logged in!")
|
let body = if env::var("public_mode") == Ok(String::from("Enable")) {
|
||||||
|
"Using public mode."
|
||||||
|
} else {
|
||||||
|
"Not logged in!"
|
||||||
|
};
|
||||||
|
HttpResponse::Unauthorized().body(body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the site URL
|
// Get the site URL
|
||||||
#[get("/api/siteurl")]
|
#[get("/api/siteurl")]
|
||||||
async fn siteurl(session: Session) -> HttpResponse {
|
async fn siteurl() -> HttpResponse {
|
||||||
if auth::validate(session) {
|
let site_url = env::var("site_url").unwrap_or(String::from("unset"));
|
||||||
let site_url = env::var("site_url").unwrap_or(String::from("unset"));
|
HttpResponse::Ok().body(site_url)
|
||||||
HttpResponse::Ok().body(site_url)
|
|
||||||
} else {
|
|
||||||
HttpResponse::Unauthorized().body("Not logged in!")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the version number
|
// Get the version number
|
||||||
|
@ -116,6 +117,16 @@ async fn login(req: String, session: Session) -> HttpResponse {
|
||||||
HttpResponse::Ok().body("Correct password!")
|
HttpResponse::Ok().body("Correct password!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle logout
|
||||||
|
#[delete("/api/logout")]
|
||||||
|
async fn logout(session: Session) -> HttpResponse {
|
||||||
|
if session.remove("chhoto-url-auth").is_some() {
|
||||||
|
HttpResponse::Ok().body("Logged out!")
|
||||||
|
} else {
|
||||||
|
HttpResponse::Unauthorized().body("You don't seem to be logged in.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete a given shortlink
|
// Delete a given shortlink
|
||||||
#[delete("/api/del/{shortlink}")]
|
#[delete("/api/del/{shortlink}")]
|
||||||
async fn delete_link(
|
async fn delete_link(
|
||||||
|
@ -168,6 +179,7 @@ async fn main() -> Result<()> {
|
||||||
.service(add_link)
|
.service(add_link)
|
||||||
.service(delete_link)
|
.service(delete_link)
|
||||||
.service(login)
|
.service(login)
|
||||||
|
.service(logout)
|
||||||
.service(Files::new("/", "./resources/").index_file("index.html"))
|
.service(Files::new("/", "./resources/").index_file("index.html"))
|
||||||
.default_service(web::get().to(error404))
|
.default_service(web::get().to(error404))
|
||||||
})
|
})
|
||||||
|
|
|
@ -31,6 +31,10 @@ services:
|
||||||
# The length is 8 by default, and a minimum of 4 is allowed
|
# The length is 8 by default, and a minimum of 4 is allowed
|
||||||
# - slug_style=Pair
|
# - slug_style=Pair
|
||||||
# - slug_length=8
|
# - slug_length=8
|
||||||
|
|
||||||
|
# In case you want to provide public access to adding links (and not
|
||||||
|
# delete, or listing), change the following option to Enable
|
||||||
|
# - public_mode=Disable
|
||||||
volumes:
|
volumes:
|
||||||
- db:/urls.sqlite
|
- db:/urls.sqlite
|
||||||
networks:
|
networks:
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p name="loading-text">Loading links table...</p>
|
<p id="loading-text">Loading links table...</p>
|
||||||
<table class="pure-table">
|
<table class="pure-table">
|
||||||
<caption>Active links</caption>
|
<caption>Active links</caption>
|
||||||
<br />
|
<br />
|
||||||
|
@ -65,7 +65,9 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div name="github-link">
|
<div name="links-div">
|
||||||
|
<a id="admin-button" href="javascript:getLogin()">login</a>
|
||||||
|
|
||||||
<a id="version-number" href="https://github.com/SinTan1729/chhoto-url" target="_blank" rel="noopener noreferrer"
|
<a id="version-number" href="https://github.com/SinTan1729/chhoto-url" target="_blank" rel="noopener noreferrer"
|
||||||
hidden>Source Code</a>
|
hidden>Source Code</a>
|
||||||
<!-- The version number would be inserted here -->
|
<!-- The version number would be inserted here -->
|
||||||
|
|
|
@ -26,14 +26,32 @@ const getVersion = async () => {
|
||||||
return ver;
|
return ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showVersion = async () => {
|
||||||
|
let version = await getVersion();
|
||||||
|
link = document.getElementById("version-number");
|
||||||
|
link.innerText = "v" + version;
|
||||||
|
link.href = "https://github.com/SinTan1729/chhoto-url/releases/tag/" + version;
|
||||||
|
link.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getLogin = async () => {
|
||||||
|
document.getElementById("container").style.filter = "blur(2px)";
|
||||||
|
document.getElementById("login-dialog").showModal();
|
||||||
|
document.getElementById("password").focus();
|
||||||
|
}
|
||||||
|
|
||||||
const refreshData = async () => {
|
const refreshData = async () => {
|
||||||
let res = await fetch(prepSubdir("/api/all"));
|
let res = await fetch(prepSubdir("/api/all"));
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
let errorMsg = await res.text();
|
let errorMsg = await res.text();
|
||||||
console.log(errorMsg);
|
console.log(errorMsg);
|
||||||
document.getElementById("container").style.filter = "blur(2px)";
|
if (errorMsg == "Using public mode.") {
|
||||||
document.getElementById("login-dialog").showModal();
|
loading_text = document.getElementById("loading-text");
|
||||||
document.getElementById("password").focus();
|
loading_text.style.display = "none";
|
||||||
|
showVersion();
|
||||||
|
} else {
|
||||||
|
getLogin();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let data = await res.json();
|
let data = await res.json();
|
||||||
displayData(data);
|
displayData(data);
|
||||||
|
@ -41,16 +59,14 @@ const refreshData = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayData = async (data) => {
|
const displayData = async (data) => {
|
||||||
let version = await getVersion();
|
showVersion();
|
||||||
link = document.getElementById("version-number")
|
|
||||||
link.innerText = "v" + version;
|
|
||||||
link.href = "https://github.com/SinTan1729/chhoto-url/releases/tag/" + version;
|
|
||||||
link.hidden = false;
|
|
||||||
|
|
||||||
let site = await getSiteUrl();
|
let site = await getSiteUrl();
|
||||||
|
admin_button = document.getElementById("admin-button");
|
||||||
|
admin_button.innerText = "logout";
|
||||||
|
admin_button.href = "javascript:logOut()";
|
||||||
|
|
||||||
table_box = document.querySelector(".pure-table");
|
table_box = document.querySelector(".pure-table");
|
||||||
loading_text = document.getElementsByName("loading-text")[0];
|
loading_text = document.getElementById("loading-text");
|
||||||
|
|
||||||
if (data.length == 0) {
|
if (data.length == 0) {
|
||||||
table_box.style.visibility = "hidden";
|
table_box.style.visibility = "hidden";
|
||||||
|
@ -221,6 +237,12 @@ const submitLogin = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const logOut = async () => {
|
||||||
|
let reply = await fetch(prepSubdir("/api/logout"), {method: "DELETE"}).then(res => res.text());
|
||||||
|
console.log(reply);
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
await refreshData();
|
await refreshData();
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ form input[name="shortUrl"]::placeholder {
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[name="github-link"] {
|
div[name="links-div"] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0.5%;
|
right: 0.5%;
|
||||||
top: 0.5%;
|
top: 0.5%;
|
||||||
|
|
Loading…
Reference in a new issue