feat: user migration + model
- link belongs to user - user api_key index
This commit is contained in:
+17
-5
@@ -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"] })
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user