This commit is contained in:
2025-09-12 19:19:08 +03:00
803 changed files with 3147 additions and 357487 deletions

View File

@@ -0,0 +1,77 @@
local session = require("internal.session")
local log = require("internal.log")
local jwt = require("internal.crypt.jwt")
local bc = require("internal.crypt.bcrypt")
local db = require("internal.database.sqlite").connect("db/root.db", {log = true})
local sha256 = require("internal.crypt.sha256")
log.info("Someone at "..session.request.address.." trying to get master access")
local function close_db()
if db then
db:close()
db = nil
end
end
local params = session.request.params.get()
local function check_missing(arr, p)
local is_missing = {}
local ok = true
for _, key in ipairs(arr) do
if p[key] == nil then
table.insert(is_missing, key)
ok = false
end
end
return ok, is_missing
end
local ok, mp = check_missing({"master_secret", "master_name", "my_key"}, params)
if not ok then
close_db()
session.response.send_error(-32602, "Missing params", mp)
end
if type(params.master_secret) ~= "string" then
close_db()
session.response.send_error(-32050, "Access denied")
end
if type(params.master_name) ~= "string" then
close_db()
session.response.send_error(-32050, "Access denied")
end
local master, err = db:query_row("SELECT * FROM master_units WHERE master_name = ?", {params.master_name})
if not master then
log.event("DB query failed:", err)
close_db()
session.response.send_error(-32050, "Access denied")
end
local ok = bc.compare(master.master_secret, params.master_secret)
if not ok then
log.warn("Login failed: wrong password")
close_db()
session.response.send_error(-32050, "Access denied")
end
local token = jwt.encode({
secret = require("_config").token(),
payload = {
session_uuid = session.id,
master_id = master.id,
key = sha256.sum(params.my_key)
},
expires_in = 3600
})
close_db()
session.response.send({
token = token
})
-- G7HgOgl72o7t7u7r

11
com/Echo.lua Normal file
View File

@@ -0,0 +1,11 @@
local s = require("internal.session")
if not s.request.params.__fetched.data then
s.response.error = {
code = 123,
message = "params.data is missing"
}
return
end
s.response.send(s.request.params.__fetched)

57
com/List.lua Normal file
View File

@@ -0,0 +1,57 @@
-- com/List.lua
local session = require("internal.session")
local params = session.request.params.get()
if params.about then
session.response.result = {
description = "Returns a list of available methods",
params = {
layer = "select which layer list to display"
}
}
return
end
local function isValidName(name)
return name:match("^[%w]+$") ~= nil
end
local function scanDirectory(basePath, targetPath)
local res = {}
local fullPath = basePath.."/"..targetPath
local handle = io.popen('find "'..fullPath..'" -type f -name "*.lua" 2>/dev/null')
if handle then
for filePath in handle:lines() do
local parts = {}
for part in filePath:gsub(".lua$", ""):gmatch("[^/]+") do
table.insert(parts, part)
end
local allValid = true
for _, part in ipairs(parts) do
if not isValidName(part) then
allValid = false
break
end
end
if allValid then
local relPath = filePath:gsub("^"..basePath.."/", ""):gsub(".lua$", ""):gsub("/", ">")
table.insert(res, relPath)
end
end
handle:close()
end
return #res > 0 and res or nil
end
local basePath = "com"
local layer = params.layer and params.layer:gsub(">", "/") or nil
session.response.send({
answer = layer and scanDirectory(basePath, layer) or scanDirectory(basePath, "")
})

View File

@@ -1,8 +0,0 @@
if not In.Params.msg or In.Params.msg == "" then
Out.Error = {
message = "there must be a msg parameter"
}
return
end
Out.Result.answer = In.Params.msg

View File

@@ -1 +0,0 @@
Out.Result.answer = "pong"

69
com/Zones/GetZoneInfo.lua Normal file
View File

@@ -0,0 +1,69 @@
local session = require("internal.session")
local log = require("internal.log")
local jwt = require("internal.crypt.jwt")
local bc = require("internal.crypt.bcrypt")
local sha256 = require("internal.crypt.sha256")
local dbdriver = require("internal.database.sqlite")
local db_root = dbdriver.connect("db/root.db", {log = true})
local db_zone = nil
local function close_db()
if db_root then
db_root:close()
db_root = nil
end
if db_zone then
db_zone:close()
db_zone = nil
end
end
local token = session.request.headers.get("authorization")
if not token or type(token) ~= "string" then
close_db()
session.response.send_error(-32050, "Access denied")
end
local prefix = "Bearer "
if token:sub(1, #prefix) ~= prefix then
close_db()
session.response.send_error(-32052, "Invalid Authorization scheme")
end
local access_token = token:sub(#prefix + 1)
local err, data = jwt.decode(access_token, { secret = require("_config").token() })
if err or not data then
close_db()
session.response.send_error(-32053, "Cannod parse JWT", {err})
end
if data.master_id then
end
local params = session.request.params.get()
local function check_missing(arr, p)
local is_missing = {}
local ok = true
for _, key in ipairs(arr) do
if p[key] == nil then
table.insert(is_missing, key)
ok = false
end
end
return ok, is_missing
end
local ok, mp = check_missing({"zone_name"}, params)
if not ok then
close_db()
session.response.send_error(-32602, "Missing params", mp)
end
close_db()

119
com/_Auth/DeleteUnit.lua Normal file
View File

@@ -0,0 +1,119 @@
-- com/DeleteUnit.lua
---@diagnostic disable: redefined-local
local db = require("internal.database.sqlite").connect("db/user-database.db", {log = true})
local log = require("internal.log")
local session = require("internal.session")
local crypt = require("internal.crypt.bcrypt")
local jwt = require("internal.crypt.jwt")
local sha256 = require("internal.crypt.sha256")
local params = session.request.params.get()
local token = session.request.headers.get("authorization")
local function close_db()
if db then
db:close()
db = nil
end
end
local function error_response(message, code, data)
session.response.error = {
code = code or nil,
message = message,
data = data or nil
}
close_db()
end
if not token or type(token) ~= "string" then
return error_response("Access denied")
end
local prefix = "Bearer "
if token:sub(1, #prefix) ~= prefix then
return error_response("Invalid Authorization scheme")
end
local access_token = token:sub(#prefix + 1)
local err, data = jwt.decode(access_token, { secret = require("_config").token() })
if err or not data then
session.response.error = {
message = err
}
return
end
-- if data.session_uuid ~= session.id then
-- return error_response("Access denied")
-- end
-- if data.key ~= sha256.sum(session.request.address .. session.id .. session.request.headers.get("user-agent", "noagent")) then
-- return error_response("Access denied")
-- end
if not params then
return error_response("no params provided")
end
if not (params.username and params.email and params.password) then
return error_response("no username/email/password provided")
end
local existing, err = db:query(
"SELECT password FROM users WHERE email = ? AND username = ? AND deleted = 0 LIMIT 1",
{
params.email,
params.username
}
)
if err ~= nil then
log.error("Password fetch failed: " .. tostring(err))
return error_response("Database query failed: " .. tostring(err))
end
if not existing or #existing == 0 then
return error_response("Unit not found")
end
local hashed_password = existing[1].password
local ok = crypt.compare(hashed_password, params.password)
if not ok then
log.warn("Wrong password attempt for: " .. params.username)
return error_response("Invalid password")
end
local ctx, err = db:exec(
[[
UPDATE users
SET deleted = 1,
deleted_at = CURRENT_TIMESTAMP
WHERE email = ? AND username = ? AND deleted = 0
]],
{ params.email, params.username }
)
if err ~= nil then
log.error("Soft delete failed: " .. tostring(err))
return error_response("Soft delete failed: " .. tostring(err))
end
local res, err = ctx:wait()
if err ~= nil then
log.error("Soft delete confirmation failed: " .. tostring(err))
return error_response("Soft delete confirmation failed: " .. tostring(err))
end
session.response.result = {
rows_affected = res,
message = "Unit soft-deleted successfully"
}
log.info("user " .. params.username .. " soft-deleted successfully")
close_db()

76
com/_Auth/GetAccess.lua Normal file
View File

@@ -0,0 +1,76 @@
-- com/GetAccess
---@diagnostic disable: redefined-local
local db = require("internal.database.sqlite").connect("db/user-database.db", {log = true})
local log = require("internal.log")
local session = require("internal.session")
local crypt = require("internal.crypt.bcrypt")
local jwt = require("internal.crypt.jwt")
local sha256 = require("internal.crypt.sha256")
local params = session.request.params.get()
local secret = require("_config").token()
local function close_db()
if db then
db:close()
db = nil
end
end
local function error_response(message, code, data)
session.response.error = {
code = code or nil,
message = message,
data = data or nil
}
close_db()
end
if not params then
return error_response("No params provided")
end
if not (params.username and params.email and params.password) then
return error_response("Missing username, email or password")
end
local unit, err = db:query(
"SELECT id, username, email, password, created_at FROM users WHERE email = ? AND username = ? AND deleted = 0 LIMIT 1",
{
params.email,
params.username
}
)
if err then
log.error("DB query error: " .. tostring(err))
return error_response("Database query failed")
end
if not unit or #unit == 0 then
return error_response("Unit not found")
end
unit = unit[1]
local ok = crypt.compare(unit.password, params.password)
if not ok then
log.warn("Login failed: wrong password for " .. params.username)
return error_response("Invalid password")
end
local token = jwt.encode({
secret = secret,
payload = { session_uuid = session.id,
admin_user = params.username,
key = sha256.sum(session.request.address .. session.id .. session.request.headers.get("user-agent", "noagent"))
},
expires_in = 3600
})
session.response.result = {
access_token = token
}
close_db()

109
com/_Auth/PutNewUnit.lua Normal file
View File

@@ -0,0 +1,109 @@
-- com/PutNewUnit.lua
---@diagnostic disable: redefined-local
local db = require("internal.database.sqlite").connect("db/user-database.db", {log = true})
local log = require("internal.log")
local session = require("internal.session")
local crypt = require("internal.crypt.bcrypt")
local jwt = require("internal.crypt.jwt")
local sha256 = require("internal.crypt.sha256")
local params = session.request.params.get()
local token = session.request.headers.get("authorization")
local function close_db()
if db then
db:close()
db = nil
end
end
local function error_response(message, code, data)
session.response.error = {
code = code or nil,
message = message,
data = data or nil
}
close_db()
end
if not token or type(token) ~= "string" then
return error_response("Access denied")
end
local prefix = "Bearer "
if token:sub(1, #prefix) ~= prefix then
return error_response("Invalid Authorization scheme")
end
local access_token = token:sub(#prefix + 1)
local err, data = jwt.decode(access_token, { secret = require("_config").token() })
if err or not data then
session.response.error = {
message = err
}
return
end
if data.session_uuid ~= session.id then
return error_response("Access denied")
end
if data.key ~= sha256.sum(session.request.address .. session.id .. session.request.headers.get("user-agent", "noagent")) then
return error_response("Access denied")
end
if not params then
return error_response("no params provided")
end
if not (params.username and params.email and params.password) then
return error_response("no username/email/password provided")
end
local hashPass = crypt.generate(params.password, crypt.DefaultCost)
local existing, err = db:query("SELECT 1 FROM users WHERE deleted = 0 AND (email = ? OR username = ?) LIMIT 1", {
params.email,
params.username
})
if err ~= nil then
log.error("Email check failed: "..tostring(err))
return error_response("Database check failed: "..tostring(err))
end
if existing and #existing > 0 then
return error_response("Unit already exists")
end
local ctx, err = db:exec(
"INSERT INTO users (username, email, password, first_name, last_name, phone_number) VALUES (?, ?, ?, ?, ?, ?)",
{
params.username,
params.email,
hashPass,
params.first_name or "",
params.last_name or "",
params.phone_number or ""
}
)
if err ~= nil then
log.error("Insert failed: "..tostring(err))
return error_response("Insert failed: "..tostring(err))
end
local res, err = ctx:wait()
if err ~= nil then
log.error("Insert confirmation failed: "..tostring(err))
return error_response("Insert confirmation failed: "..tostring(err))
end
session.response.result = {
rows_affected = res,
message = "Unit created successfully"
}
close_db()

66
com/_DB/Put.lua Normal file
View File

@@ -0,0 +1,66 @@
---@diagnostic disable: redefined-local
local db = require("internal.database-sqlite").connect("db/test.db", {log = true})
local log = require("internal.log")
local session = require("internal.session")
if not (session.request.params.name and session.request.params.email) then
session.response.error = {
code = -32602,
message = "Name and email are required"
}
return
end
local existing, err = db:query("SELECT 1 FROM users WHERE email = ? LIMIT 1", {
session.request.params.email
})
if err ~= nil then
session.response.error = {
code = -32603,
message = "Database check failed: "..tostring(err)
}
log.error("Email check failed: "..tostring(err))
return
end
if existing and #existing > 0 then
session.response.error = {
code = -32604,
message = "Email already exists"
}
return
end
local ctx, err = db:exec(
"INSERT INTO users (name, email) VALUES (?, ?)",
{
session.request.params.name,
session.request.params.email
}
)
if err ~= nil then
session.response.error = {
code = -32605,
message = "Insert failed: "..tostring(err)
}
log.error("Insert failed: "..tostring(err))
return
end
local res, err = ctx:wait()
if err ~= nil then
session.response.error = {
code = -32606,
message = "Insert confirmation failed: "..tostring(err)
}
log.error("Insert confirmation failed: "..tostring(err))
return
end
session.response.result = {
success = true,
rows_affected = res,
message = "User created successfully"
}
db:close()

29
com/_Net/GetExpl.lua Normal file
View File

@@ -0,0 +1,29 @@
local session = require("internal.session")
local net = require("internal.net")
local reqAddr
local logReq = true
if session.request.params and session.request.params.url then
reqAddr = session.request.params.url
else
session.response.error = {
code = -32602,
message = "no url provided"
}
return
end
local resp = net.http.get_request(logReq, reqAddr)
if resp then
session.response.result.answer = {
status = resp.status,
body = resp.body
}
return
end
session.response.error = {
data = "error while requesting"
}

35
com/_Net/PostExpl.lua Normal file
View File

@@ -0,0 +1,35 @@
local session = require("internal.session")
local net = require("internal.net")
local log = require("internal.log")
local reqAddr
local logReq = true
local payload
log.debug(session.request.params)
if not (session.request.params and session.request.params.url) then
session.response.error = {
code = -32602,
message = "no url or payload provided"
}
return
end
reqAddr = session.request.params.url
payload = session.request.params.payload
local resp = net.http.post_request(logReq, reqAddr, "application/json", payload)
if resp then
session.response.result.answer = {
status = resp.status,
body = resp.body
}
return
end
session.response.error = {
data = "error while requesting"
}

View File

@@ -1,11 +1,54 @@
---@alias AnyTable table<string, any>
--@diagnostic disable: missing-fields, missing-return
---@type AnyTable
In = {
Params = {},
}
---@alias Any any
---@alias AnyTable table<string, Any>
---@type AnyTable
Out = {
Result = {},
}
--- Global session module interface
---@class SessionIn
---@field params AnyTable Request parameters
---@class SessionOut
---@field result Any|string? Result payload (table or primitive)
---@field error { code: integer, message: string, data: Any }? Optional error info
---@class SessionModule
---@field request SessionIn Input context (read-only)
---@field response SessionOut Output context (write results/errors)
--- Global log module interface
---@class LogModule
---@field info fun(msg: string) Log informational message
---@field debug fun(msg: string) Log debug message
---@field error fun(msg: string) Log error message
---@field warn fun(msg: string) Log warning message
---@field event fun(msg: string) Log event (generic)
---@field event_error fun(msg: string) Log event error
---@field event_warn fun(msg: string) Log event warning
--- Global net module interface
---@class HttpResponse
---@field status integer HTTP status code
---@field status_text string HTTP status text
---@field body string Response body
---@field content_length integer Content length
---@field headers AnyTable Map of headers
---@class HttpModule
---@field get fun(log: boolean, url: string): HttpResponse, string? Perform GET
---@field post fun(log: boolean, url: string, content_type: string, payload: string): HttpResponse, string? Perform POST
---@class NetModule
---@field http HttpModule HTTP client functions
--- Global variables declaration
---@global
---@type SessionModule
_G.session = session or {}
---@global
---@type LogModule
_G.log = log or {}
---@global
---@type NetModule
_G.net = net or {}

View File

@@ -2,15 +2,3 @@
package.path = package.path .. ";/usr/lib64/lua/5.1/?.lua;/usr/local/share/lua/5.1/?.lua" .. ";./com/?.lua;"
package.cpath = package.cpath .. ";/usr/lib64/lua/5.1/?.so;/usr/local/lib/lua/5.1/?.so"
print = function() end
io.write = function(...) end
io.stdout = function() return nil end
io.stderr = function() return nil end
io.read = function(...) return nil end
---@type table<string, any>
Status = {
ok = "ok",
error = "error",
invalid = "invalid",
}