feat: user migration + model

- link belongs to user
- user api_key index
This commit is contained in:
Juan Rodriguez
2024-05-13 22:33:38 +02:00
parent 80feadfbd2
commit 0ad534065c
8 changed files with 72 additions and 10 deletions
+17 -5
View File
@@ -8,12 +8,14 @@ module App::Controllers::Link
include App::Lib
def call(env)
user = env.get("user").as(User)
body = parse_body(env, ["url"])
link = Link.new
link.id = UUID.v4.to_s
link.url = body["url"].to_s
link.slug = Random::Secure.urlsafe_base64(4)
link.user = user
changeset = Database.insert(link)
if !changeset.valid?
@@ -48,17 +50,17 @@ module App::Controllers::Link
end
end
class Read < App::Lib::BaseController
class All < App::Lib::BaseController
include App::Models
include App::Lib
def call(env)
id = env.params.url["id"]
user = env.get("user").as(User)
link = Database.get(Link, id)
raise App::NotFoundException.new(env) if !link
query = Database::Query.where(user_id: user.id.as(String))
links = Database.all(Link, query)
response = {"data" => App::Serializers::Link.new(link)}
response = {"data" => links.map { |link| App::Serializers::Link.new(link) }}
response.to_json
end
end
@@ -68,12 +70,17 @@ module App::Controllers::Link
include App::Lib
def call(env)
user = env.get("user").as(User)
id = env.params.url["id"]
body = parse_body(env, ["url"])
link = Database.get(Link, id)
raise App::NotFoundException.new(env) if !link
if link.user_id != user.id
raise App::ForbiddenException.new(env)
end
link.url = body["url"].to_s
link.click_counter = 0
@@ -92,11 +99,16 @@ module App::Controllers::Link
include App::Lib
def call(env)
user = env.get("user").as(User)
id = env.params.url["id"]
link = Database.get(Link, id)
raise App::NotFoundException.new(env) if !link
if link.user_id != user.id
raise App::ForbiddenException.new(env)
end
result = Database.raw_exec("DELETE FROM links WHERE id = (?)", link.id) # tempfix: Database.delete does not work
if result.rows_affected == 0
raise App::UnprocessableEntityException.new(env, { "id" => ["Row delete failed"] })
+6
View File
@@ -1,6 +1,8 @@
require "sqlite3"
require "crecto"
require "./user.cr"
module App::Models
class Link < Crecto::Model
schema :links do
@@ -8,9 +10,13 @@ module App::Models
field :slug, String
field :url, String
field :click_counter, Int64, default: 0
belongs_to :user, User
end
unique_constraint :slug
validate_required [:slug, :url]
validate_format :url, /\A(?:https?:\/\/)?(?:[\w-]+\.)+[\w-]+(?:\/\S*)?/
end
end
+16
View File
@@ -0,0 +1,16 @@
require "sqlite3"
require "crecto"
module App::Models
class User < Crecto::Model
schema :users do
field :id, String, primary_key: true
field :name, String
field :api_key, String
end
validate_required [:name, :api_key]
has_many :links, Link, dependent: :destroy
end
end
+1
View File
@@ -1,3 +1,4 @@
vars {
baseUrl: http://localhost:4000
apiKey: xYBDV_vGC3_pcGss3Z2lGA
}
@@ -2,11 +2,14 @@
-- SQL in section 'Up' is executed when this migration is applied
CREATE TABLE links (
id TEXT PRIMARY KEY NOT NULL,
slug VARCHAR(100) UNIQUE NOT NULL,
user_id TEXT NOT NULL,
slug VARCHAR(4) UNIQUE NOT NULL,
url TEXT NOT NULL,
click_counter INTEGER NOT NULL DEFAULT 0,
created_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL
updated_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- +micrate Down
@@ -0,0 +1,13 @@
-- +micrate Up
-- SQL in section 'Up' is executed when this migration is applied
CREATE TABLE users (
id TEXT PRIMARY KEY NOT NULL,
name VARCHAR(100) NOT NULL,
api_key VARCHAR(64) UNIQUE NOT NULL,
created_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at INTEGER DEFAULT CURRENT_TIMESTAMP NOT NULL
);
-- +micrate Down
-- SQL section 'Down' is executed when this migration is rolled back
DROP TABLE users;
@@ -0,0 +1,7 @@
-- +micrate Up
-- SQL in section 'Up' is executed when this migration is applied
CREATE INDEX IF NOT EXISTS index_users_api_key ON users (api_key);
-- +micrate Down
-- SQL section 'Down' is executed when this migration is rolled back
DROP INDEX IF EXISTS index_users_api_key;
+7 -3
View File
@@ -4,11 +4,15 @@ require "./app/config/*"
require "./app/lib/*"
require "./app/models/*"
require "./app/serializers/*"
require "./app/middlewares/*"
require "./app/routes"
error 500 { |env| { "error" => "Internal Server Error" }.to_json }
error 401 { |env| { "error" => "Unauthorized" }.to_json }
error 404 { |env| { "error" => "Not Found" }.to_json }
add_context_storage_type(App::Models::User)
add_handler(App::Middlewares::Auth.new)
error 500 { |env| {"error" => "Internal Server Error" }.to_json}
error 401 { |env| {"error" => "Unauthorized" }.to_json}
error 404 { |env| {"error" => "Not Found" }.to_json}
Kemal.run