todod/src/main.cr

270 lines
6.1 KiB
Crystal
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

require "kemal"
require "uuid"
require "file_utils"
require "authd"
require "./project.cr"
require "./requests.cr"
authd_key = nil : String?
storage_directory = "./projects"
# Itll get replaced later. But FIXME, this is only a temporary workaround.
authd = nil.unsafe_as AuthD::Client
Kemal.config.extra_options do |parser|
parser.on "-k file", "--jwt-key file", "Provides the JWT key for authd." do |file|
authd_key = File.read(file).chomp
end
parser.on "-S dir", "--storage dir", "Provides a directory in which to store kanbands data and projects." do |dir|
storage_directory = dir
end
end
sockets = [] of HTTP::WebSocket
users = {} of HTTP::WebSocket => AuthD::User
get "/" do
File.read "index.html"
end
get "/style.css" do |env|
env.response.content_type = "text/css"
File.read "style.css"
end
get "/main.js" do |env|
env.response.content_type = "text/javascript"
File.read "main.js"
end
ws "/socket" do |socket|
socket.on_close do
users.delete socket
sockets.delete socket
end
socket.on_message do |message_as_s|
message = JSON.parse(message_as_s).as_h
case message["type"]
when "login"
request = Requests::Login.from_json message_as_s
login = request.login
password = request.password
user = authd.get_user? login, password
unless user
socket.send({
type: "login-error",
error: "Invalid credentials."
}.to_json)
next
end
users[socket] = user
sockets << socket
socket.send({
type: "login"
}.to_json)
socket.send({
type: "list-projects",
projects: Project.all storage_directory
}.to_json)
when "new-project"
user = users[socket] # FIXME: make it an authentication error
request = Requests::NewProject.from_json message_as_s
project = Project.new request.name
project.write! storage_directory
# FIXME: Only notify concerned users.
sockets.each &.send({
type: "project",
project: project
}.to_json)
when "project"
user = users[socket] # FIXME: make it an authentication error
request = Requests::Tasks.from_json message_as_s
project = Project.get_from_id request.project, storage_directory
socket.send({
type: "project",
project: project
}.to_json)
when "edit-project"
user = users[socket] # FIXME: make it an authentication error
request = Requests::EditProject.from_json message_as_s
project = Project.get_from_id request.project, storage_directory
if name = request.name
project.name = name
end
if color = request.color
project.color = color
end
project.write! storage_directory
# FIXME: Only notify concerned users.
sockets.each &.send({
type: "project",
project: project
}.to_json)
when "new-column"
user = users[socket] # FIXME: make it an authentication error
request = Requests::NewColumn.from_json message_as_s
project = Project.get_from_id request.project, storage_directory
project.columns << Column.new request.name
project.write! storage_directory
# FIXME: Only notify concerned users.
sockets.each &.send({
type: "project",
project: project
}.to_json)
when "new-task"
user = users[socket] # FIXME: make it an authentication error
request = Requests::NewTask.from_json message_as_s
project = Project.get_from_id request.project, storage_directory
column = project.columns.find(&.id.==(request.column)).not_nil!
project.tasks << Task.new request.title, user.uid, request.description, column.id
project.write! storage_directory
# FIXME: Only notify concerned users.
sockets.each &.send({
type: "project",
project: project
}.to_json)
when "edit-task"
user = users[socket] # FIXME: make it an authentication error
request = Requests::EditTask.from_json message_as_s
project = Project.get_from_id request.project, storage_directory
task = project.tasks.find(&.id.==(request.task)).not_nil!
if column = request.column
column = project.columns.find(&.id.==(column)).not_nil!
task.column = column.id
end
if title = request.title
task.title = title
end
if description = request.description
task.description = description
end
# FIXME: Check its a valid UID.
if assigned_to = request.assigned_to
# FIXME: Probably not the best way to handle this corner-case.
assigned_to = nil if assigned_to == -1
task.assigned_to = assigned_to
end
project.write! storage_directory
# FIXME: Only notify concerned users.
sockets.each &.send({
type: "project",
project: project
}.to_json)
when "delete-task"
user = users[socket]
request = Requests::DeleteTask.from_json message_as_s
project = Project.get_from_id request.project, storage_directory
project.tasks.select! &.id.!=(request.task)
project.write! storage_directory
# FIXME: Only notify concerned users.
sockets.each &.send({
type: "project",
project: project
}.to_json)
when "edit-column"
user = users[socket] # FIXME: make it an authentication error
request = Requests::EditColumn.from_json message_as_s
project = Project.get_from_id request.project, storage_directory
column = project.columns.find(&.id.==(request.column)).not_nil!
if name = request.name
column.name = name
end
puts project.columns.to_json
project.write! storage_directory
# FIXME: Only notify concerned users.
sockets.each &.send({
type: "project",
project: project
}.to_json)
when "delete-column"
user = users[socket]
request = Requests::DeleteColumn.from_json message_as_s
project = Project.get_from_id request.project, storage_directory
project.columns.select! &.id.!=(request.column)
project.tasks.select! &.column.!=(request.column)
project.write! storage_directory
# FIXME: Only notify concerned users.
sockets.each &.send({
type: "project",
project: project
}.to_json)
when "get-user"
request = Requests::GetUser.from_json message_as_s
user = authd.get_user? request.uid
socket.send({
type: "user",
user: user
}.to_json)
end
end
end
Kemal.run do
authd = AuthD::Client.new
key = authd_key
authd.key = key if key.is_a? String
end