fix: user id and link id int64 types

This commit is contained in:
sjdonado
2025-03-20 08:13:07 +01:00
parent 38f9cfd48e
commit 73ee4c4479
9 changed files with 33 additions and 45 deletions
+23 -28
View File
@@ -1,5 +1,3 @@
require "uuid"
module App::Controllers
class LinkController < App::Lib::BaseController
include App::Models
@@ -12,21 +10,19 @@ module App::Controllers
end
def create
user = current_user
body = parse_body(["url"])
url = body["url"].to_s
query = Database::Query.where(url: url, user_id: user.id.as(String)).limit(1)
query = Database::Query.where(url: url, user_id: current_user_id).limit(1)
existing_link = Database.all(Link, query, preload: [:clicks]).first?
if existing_link
return render_json({"data" => App::Serializers::Link.new(existing_link)})
end
link = Link.new
link.id = UUID.v4.to_s
link.url = url
link.user = user
link.slug = SlugService.shorten_url(url, user.id.to_s)
link.user_id = current_user_id
link.slug = SlugService.shorten_url(url, current_user_id)
changeset = Database.insert(link)
if !changeset.valid?
@@ -46,7 +42,7 @@ module App::Controllers
# slug autoindex has better perormance than the covering index
Database.raw_query("SELECT id, url FROM links WHERE slug = (?)", slug) do |result|
if result.move_next
link_data = {result.read(String), result.read(String)}
link_data = {result.read(Int64), result.read(String)}
end
end
raise App::NotFoundException.new(@env) unless link_data
@@ -66,10 +62,9 @@ module App::Controllers
end
def list_all
user = current_user
limit, cursor = pagination_params
query = Database::Query.where(user_id: user.id.as(String))
query = Database::Query.where(user_id: current_user_id)
query = query.where("id < ?", cursor) if cursor
query = query.order_by("id DESC").limit(limit + 1)
@@ -79,14 +74,13 @@ module App::Controllers
end
def get
user = current_user
link_id = @env.params.url["id"]
link_id = @env.params.url["id"].to_i64
query = Database::Query.where(id: link_id.as(String), user_id: user.id.as(String)).limit(1)
query = Database::Query.where(id: link_id, user_id: current_user_id).limit(1)
link = Database.all(Link, query).first?
raise App::NotFoundException.new(@env) if link.nil?
clicks_query = Database::Query.where(link_id: link_id.as(String))
clicks_query = Database::Query.where(link_id: link_id)
.order_by("id DESC")
.limit(100)
link.clicks = Database.all(Click, clicks_query)
@@ -95,17 +89,16 @@ module App::Controllers
end
def list_clicks
user = current_user
link_id = @env.params.url["id"]
link_id = @env.params.url["id"].to_i64
# Verify link exists and belongs to user
link_query = Database::Query.where(id: link_id.as(String), user_id: user.id.as(String)).limit(1)
link_query = Database::Query.where(id: link_id, user_id: current_user_id).limit(1)
link = Database.all(Link, link_query).first?
raise App::NotFoundException.new(@env) if link.nil?
limit, cursor = pagination_params
query = Database::Query.where(link_id: link_id.as(String))
query = Database::Query.where(link_id: link_id)
query = query.where("id < ?", cursor) if cursor
query = query.order_by("id DESC").limit(limit + 1)
@@ -115,8 +108,7 @@ module App::Controllers
end
def update
user = current_user
id = @env.params.url["id"]
id = @env.params.url["id"].to_i64
body = parse_body(["url"])
new_url = body["url"].to_s
@@ -124,16 +116,16 @@ module App::Controllers
link = Database.all(Link, query, preload: [:clicks]).first?
raise App::NotFoundException.new(@env) if link.nil?
raise App::ForbiddenException.new(@env) if link.user_id != user.id
raise App::ForbiddenException.new(@env) if link.user_id != current_user_id
# Check for existing URL
existing_query = Database::Query.where(url: new_url, user_id: user.id.to_s).limit(1)
existing_query = Database::Query.where(url: new_url, user_id: current_user_id).limit(1)
if Database.all(Link, existing_query).first?
raise App::UnprocessableEntityException.new(@env, { "url" => ["URL already exists"] })
end
link.url = new_url
link.slug = SlugService.shorten_url(new_url, user.id.to_s)
link.slug = SlugService.shorten_url(new_url, current_user_id)
changeset = Database.update(link)
if !changeset.valid?
@@ -144,12 +136,11 @@ module App::Controllers
end
def delete
user = current_user
id = @env.params.url["id"]
id = @env.params.url["id"].to_i64
link = Database.get(Link, id)
raise App::NotFoundException.new(@env) if !link
raise App::ForbiddenException.new(@env) if link.user_id != user.id
raise App::ForbiddenException.new(@env) if link.user_id != current_user_id
result = Database.raw_exec("DELETE FROM links WHERE id = (?)", link.id)
if result.rows_affected == 0
@@ -163,6 +154,10 @@ module App::Controllers
@env.get("user").as(User)
end
private def current_user_id : Int64
current_user.id.as(Int64)
end
private def track_click(link_id, client_ip, user_agent_str)
source = @env.params.query["utm_source"]? || "Direct"
referer = @env.request.headers["Referer"]?.try { |r| begin URI.parse(r).host rescue r end } || source
@@ -177,7 +172,7 @@ module App::Controllers
end
private def pagination_params
limit = (@env.params.query["limit"]? || "100").to_i
limit = (@env.params.query["limit"]? || "100").to_i32
cursor = @env.params.query["cursor"]?
{limit, cursor}
end
@@ -191,7 +186,7 @@ module App::Controllers
"data" => items.map { |item| yield item },
"pagination" => {
"has_more" => has_more,
"next" => next_cursor
"next_cursor" => next_cursor
}
})
end
+1 -1
View File
@@ -3,7 +3,7 @@ require "crecto"
module App::Models
class Click < Crecto::Model
schema :clicks do
field :id, String, primary_key: true
field :id, Int64, primary_key: true
field :user_agent, String
field :country, String
field :browser, String
+1 -1
View File
@@ -6,7 +6,7 @@ require "./user.cr"
module App::Models
class Link < Crecto::Model
schema :links do
field :id, String, primary_key: true
field :id, Int64, primary_key: true
field :slug, String
field :url, String
+1 -1
View File
@@ -4,7 +4,7 @@ require "crecto"
module App::Models
class User < Crecto::Model
schema :users do
field :id, String, primary_key: true
field :id, Int64, primary_key: true
field :name, String
field :api_key, String
end
-1
View File
@@ -8,7 +8,6 @@ require "../models/*"
module App::Services::Cli
def self.create_user(name, api_key = nil)
user = App::Models::User.new
user.id = UUID.v4.to_s
user.name = name
user.api_key = api_key || Random::Secure.urlsafe_base64()
+2 -3
View File
@@ -5,7 +5,7 @@ IpLookup.load_mmdb("data/GeoLite2-Country.mmdb")
module App::Services
class ClickTracker
@@queue = Channel(Tuple(String, String, String, String, String)).new(1000)
@@queue = Channel(Tuple(Int64, String, String, String, String)).new(1000)
@@initialized = false
def self.init
@@ -25,7 +25,6 @@ module App::Services
user_agent = user_agent_str != "Unknown" ? UserAgent.new(user_agent_str) : nil
click = App::Models::Click.new
click.id = UUID.v4.to_s
click.link_id = link_id
click.country = country
click.user_agent = user_agent_str
@@ -45,7 +44,7 @@ module App::Services
end
end
def self.track(link_id : String, client_ip : String, user_agent : String, source : String, referer : String)
def self.track(link_id : Int64, client_ip : String, user_agent : String, source : String, referer : String)
init if !@@initialized
@@queue.send({link_id, client_ip, user_agent, source, referer})
+1 -1
View File
@@ -2,7 +2,7 @@ require "digest"
require "base64"
module App::Services::SlugService
def self.shorten_url(url : String, user_id : String) : String
def self.shorten_url(url : String, user_id : Int64) : String
combined = "#{user_id}-#{url}"
crc32_hash = Digest::CRC32.digest(combined)
base62_encoded = Base64.urlsafe_encode(crc32_hash).strip.tr("-_=", "")