Merge remote-tracking branch 'origin/master'
All checks were successful
Build and Publish / build_and_publish (push) Successful in 1m30s

# Conflicts:
#	src/static/index.html
This commit is contained in:
Nexus 2024-07-11 17:09:30 +01:00
commit 7af49cbb84
Signed by: nex
GPG key ID: 0FA334385D0B689F
4 changed files with 72 additions and 20 deletions

View file

@ -5,21 +5,33 @@ on: [push]
jobs:
build_and_publish:
runs-on: [ubuntu-latest]
permissions:
contents: read
packages: write
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: git.i-am.nexus/nex/link-elongater
- name: Log into forgejo CR
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@v3
with:
registry: git.i-am.nexus
username: nex
password: ${{ secrets.CR_TOKEN }}
- name: Build Docker image
run: |
docker build -t git.i-am.nexus/nex/link-elongater:latest .
- name: Push to forgejo CR
run: |
docker push -a git.i-am.nexus/nex/link-elongater
password: ${{ secrets.CR_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=git.i-am.nexus/nex/link-elongater:master
cache-to: type=inline

View file

@ -7,7 +7,9 @@ from tortoise.contrib.pydantic import pydantic_model_creator
class Redirect(Model):
uuid = fields.UUIDField(primary_key=True, default=uuid.uuid4)
slug = fields.CharField(max_length=32779, index=False, default=lambda: secrets.token_urlsafe(1024))
slug = fields.CharField(
max_length=32779, index=False, default=lambda: secrets.token_urlsafe(1024)
)
destination = fields.CharField(max_length=8192)
created_at = fields.DatetimeField(auto_now_add=True)
expires = fields.DatetimeField(null=True)

View file

@ -8,7 +8,7 @@ import db
import requests
from fastapi import FastAPI, Request, HTTPException, status, Form
from fastapi.staticfiles import StaticFiles
from fastapi.responses import RedirectResponse
from fastapi.responses import RedirectResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from contextlib import asynccontextmanager
from tortoise.contrib.fastapi import RegisterTortoise
@ -94,6 +94,7 @@ async def list_redirects():
@app.post("/api/create", response_model=db.RedirectPydantic)
async def create_redirect(
response: JSONResponse,
destination: str = Form(...),
expires: typing.Optional[datetime.datetime] = Form(None),
max_visits: typing.Optional[int] = Form(None),
@ -106,6 +107,11 @@ async def create_redirect(
elif parsed.scheme not in ["http", "https"]:
raise HTTPException(status_code=400, detail="Invalid URL - must be HTTP/HTTPS")
existing = await db.Redirect.get_or_none(destination=destination)
if existing is not None:
response.status_code = 200
return await db.RedirectPydantic.from_tortoise_orm(existing)
match slug_type:
case "urlsafe":
slug = secrets.token_urlsafe(slug_length // 2)
@ -130,7 +136,10 @@ async def create_redirect(
while await db.Redirect.get_or_none(slug=slug) is not None:
slug = secrets.token_urlsafe(slug_length // 2)
redirect = await db.Redirect.create(destination=destination, expires=expires, max_visits=max_visits, slug=slug)
redirect = await db.Redirect.create(
destination=destination, expires=expires, max_visits=max_visits, slug=slug
)
response.status_code = 201
return await db.RedirectPydantic.from_tortoise_orm(redirect)

View file

@ -5,6 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Link Elongater - Create Redirect</title>
<script>
function onChange(e) {
let slugLength = parseInt(document.getElementById("slug_length").value);
let netloc = window.location.origin;
const totalLength = netloc.length + 3 + slugLength;
document.getElementById("urllen").textContent = totalLength;
}
function onSubmit(e) {
e.preventDefault();
let formData = new FormData(e.target);
@ -44,9 +50,31 @@
"DOMContentLoaded",
() => {
document.querySelector("form").addEventListener("submit", onSubmit);
document.getElementById("slug_length").addEventListener("input", onChange);
}
)
</script>
<style>
body {
font-family: sans-serif;
}
form {
display: grid;
gap: 0.5em;
}
label {
font-weight: bold;
}
input, select {
width: 100%;
}
button {
width: 100%;
}
#result {
margin-top: 1em;
}
</style>
</head>
<body>
<h1>Create redirect</h1>
@ -60,10 +88,11 @@
<input type="url" id="destination" name="destination" required/><br/>
<label for="expires">Expires:</label>
<input type="date" id="expires" name="expires"/><br/>
<label for="max_visits">Max visits:</label>
<label for="max_visits">Max visits (default: unlimited):</label>
<input type="number" id="max_visits" name="max_visits"/><br/>
<label for="slug_length">Slug length:</label>
<input type="number" id="slug_length" name="slug_length" value="1000" min="2" max="16389"/><br/>
<input type="number" id="slug_length" name="slug_length" value="1000" min="2" max="16389"/>
<p>URL length will total to <span id="urllen">a lot of</span> characters.</p><br/>
<label for="slug_type">Slug type:</label>
<select id="slug_type" name="slug_type" value="urlsafe">
<option value="urlsafe">Base64 (urlsafe)</option>