mirror of
https://github.com/akyaiy/GoSally-mvp.git
synced 2026-01-03 20:12:25 +00:00
Compare commits
28 Commits
bed0471cc4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d4413c433f | |||
| d9a4bb7871 | |||
| 8e017af3ed | |||
| ef6023330d | |||
| 5474b22fc8 | |||
| 6cd678d9f1 | |||
| 856d3b418c | |||
| 5734ca7a67 | |||
| 608c5aed4a | |||
|
|
d4d04115f3 | ||
|
|
4b916f4fc9 | ||
| 54cc496c39 | |||
| f7b0014a37 | |||
| 54eb5eec6a | |||
| 6cc24a1e7f | |||
| ea41c435dd | |||
| d24e1a94ae | |||
| 846dc06601 | |||
| 740fbbff78 | |||
| 40be3c8d09 | |||
| 9c140abc6d | |||
| e90233aec4 | |||
| df1ef57769 | |||
| 4c840c40bb | |||
| 57f35e8f33 | |||
| f0c591f325 | |||
| 36ee320c45 | |||
| ee6fd205d5 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -12,6 +12,8 @@ com/_config.lua
|
||||
Taskfile.yml
|
||||
config.yaml
|
||||
|
||||
wiki
|
||||
|
||||
# Garbage
|
||||
com/_Access/GetMasterAccess.lua
|
||||
com/_Zones/GetZoneInfo.lua
|
||||
com/_*
|
||||
com/test.lua
|
||||
47
Makefile
47
Makefile
@@ -4,7 +4,10 @@ GOPATH := $(shell go env GOPATH)
|
||||
export CONFIG_PATH := ./config.yaml
|
||||
export NODE_PATH := $(shell pwd)
|
||||
|
||||
LDFLAGS := -X 'github.com/akyaiy/GoSally-mvp/internal/engine/config.NodeVersion=v0.0.1-dev'
|
||||
NODE_VERSION := v0.0.1-dev
|
||||
SV1_VERSION := v0.0.1-dev
|
||||
|
||||
LDFLAGS := -X 'github.com/akyaiy/GoSally-mvp/src/internal/engine/config.NodeVersion=$(NODE_VERSION)' -X 'github.com/akyaiy/GoSally-mvp/src/internal/server/sv1.SV1Version=$(SV1_VERSION)'
|
||||
CGO_CFLAGS := -I/usr/local/include
|
||||
CGO_LDFLAGS := -L/usr/local/lib -llua5.1 -lm -ldl
|
||||
.PHONY: all build run runq test fmt vet lint check clean
|
||||
@@ -30,14 +33,14 @@ build:
|
||||
@# @echo "CGO_CFLAGS is: '$(CGO_CFLAGS)'"
|
||||
@# @echo "CGO_LDFLAGS is: '$(CGO_LDFLAGS)'"
|
||||
@# CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)"
|
||||
@go build -trimpath -ldflags "-w -s $(LDFLAGS)" -o $(BIN_DIR)/$(APP_NAME) ./
|
||||
@if ! command -v upx >/dev/null 2>&1; then \
|
||||
echo "upx not found, skipping compression."; \
|
||||
elif upx -t $(BIN_DIR)/$(APP_NAME) >/dev/null 2>&1; then \
|
||||
echo "$(BIN_DIR)/$(APP_NAME) already compressed, skipping."; \
|
||||
else \
|
||||
upx $(BIN_DIR)/$(APP_NAME) >/dev/null 2>&1 || true; \
|
||||
fi
|
||||
cd src && go build -trimpath -ldflags "-w -s $(LDFLAGS)" -o ../$(BIN_DIR)/$(APP_NAME) ./
|
||||
# @if ! command -v upx >/dev/null 2>&1; then \
|
||||
# echo "upx not found, skipping compression."; \
|
||||
# elif upx -t $(BIN_DIR)/$(APP_NAME) >/dev/null 2>&1; then \
|
||||
# echo "$(BIN_DIR)/$(APP_NAME) already compressed, skipping."; \
|
||||
# else \
|
||||
# upx $(BIN_DIR)/$(APP_NAME) >/dev/null 2>&1 || true; \
|
||||
# fi
|
||||
|
||||
run: build
|
||||
@echo "Running!"
|
||||
@@ -52,30 +55,22 @@ pure-run:
|
||||
exec ./$(BIN_DIR)/$(APP_NAME)
|
||||
|
||||
test:
|
||||
@go test ./... | grep -v '^?' || true
|
||||
@cd src && go test ./... | grep -v '^?' || true
|
||||
|
||||
fmt:
|
||||
@go fmt ./internal/./...
|
||||
@go fmt ./cmd/./...
|
||||
@go fmt ./hooks/./...
|
||||
@$(GOPATH)/bin/goimports -w ./internal/
|
||||
@$(GOPATH)/bin/goimports -w ./cmd/
|
||||
@$(GOPATH)/bin/goimports -w ./hooks/
|
||||
@cd src && go fmt .
|
||||
@cd src && $(GOPATH)/bin/goimports -w .
|
||||
|
||||
vet:
|
||||
@go vet ./...
|
||||
|
||||
lint:
|
||||
@$(GOPATH)/bin/golangci-lint run
|
||||
|
||||
@cd src && go vet ./...
|
||||
check: fmt vet lint test
|
||||
|
||||
licenses:
|
||||
lint:
|
||||
@cd src && $(GOPATH)/bin/golangci-lint run ./...
|
||||
@$(GOPATH)/bin/go-licenses save ./... --save_path=third_party/licenses --force
|
||||
@echo "Licenses have been exported to third_party/licenses"
|
||||
|
||||
clean:
|
||||
@rm -rf bin
|
||||
|
||||
licenses:
|
||||
@cd src && $(GOPATH)/bin/go-licenses save ./... --save_path=../third_party/licenses --force
|
||||
@echo "Licenses have been exported to third_party/licenses"
|
||||
help:
|
||||
@echo "Available commands: $$(cat Makefile | grep -E '^[a-zA-Z_-]+:.*?' | grep -v -- '-setup:' | sed 's/:.*//g' | sort | uniq | tr '\n' ' ')"
|
||||
|
||||
147
README.md
147
README.md
@@ -1,51 +1,132 @@
|
||||
# Go Sally MVP (Minimum/Minimal Viable Product)
|
||||
[]()
|
||||
[](https://go.dev/)
|
||||
[](https://www.lua.org/manual/5.1/)
|
||||
[](https://pkg.go.dev/github.com/akyaiy/GoSally-mvp)
|
||||
[](LICENSE)
|
||||
|
||||
### What is this?
|
||||
System that allows you to build your own infrastructure based on identical nodes and various scripts written using built-in Lua 5.1, shebang scripts (scripts that start with the `#!` symbols), compiled binaries.
|
||||
[]()
|
||||
[]()
|
||||
[](https://github.com/akyaiy/GoSally-mvp/wiki)
|
||||
|
||||
### Features
|
||||
Go Sally is not viable at the moment, but it already has the ability to run embedded scripts, log slog events to stdout, handle RPC like requests, and independent automatic update from the repository (my pride, to be honest).
|
||||
|
||||
### Example of use
|
||||
The basic directory tree looks something like this
|
||||
```
|
||||
.
|
||||
├── bin
|
||||
│ └── node Node core binary file
|
||||
├── com
|
||||
│ ├── echo.lua
|
||||
│ ├── _globals.lua Declaring global variables and functions for all internal scripts (also required for luarc to work correctly)
|
||||
│ └── _prepare.lua Script that is executed before each script launch
|
||||
└── config.yaml
|
||||
> ⚡ **What, Why, Why Care?**
|
||||
|
||||
3 directories, 5 files
|
||||
> **What:** Go Sally is a lightweight decentralized node system with Lua scripting and JSON-RPC2.0.
|
||||
|
||||
```
|
||||
Launch by command
|
||||
> **Why:** Large admin tools are too heavy, and Raspberry Pi and small servers require a lightweight, modular architecture.
|
||||
|
||||
> **Why Care:** Create, automate, and expand your infrastructure quickly, without unnecessary software or dependencies.
|
||||
|
||||
## Navigation
|
||||
* [Core features](#core-features)
|
||||
* [Quick start](#quick-start)
|
||||
* [Test it](#test-it)
|
||||
* [Concept](#concept)
|
||||
* [API](#api)
|
||||
* [License](#license)
|
||||
* [Wiki →](https://github.com/akyaiy/GoSally-mvp/wiki)
|
||||
|
||||
> [!NOTE]
|
||||
> If you see "💡" in the text, it means the information below is about plans for the future of the project.
|
||||
|
||||
## Core features
|
||||
- **Decentralized nodes**<details>this means that *multiple GS[^1] nodes can be located on a single machine*, provided no attempt is made to disrupt, sabotage, or bypass the built-in protection mechanism against running a node under the same identifier as one already running in the system. Identification plays a role in node communication. 💡 In the future, we plan to create tools for conveniently building distributed systems using node identification.
|
||||
**Why Care?** Multiple nodes on one machine allow testing, experimentation, and scaling small infrastructures without extra hardware or complex setup.</details>
|
||||
- **RPC request processing**<details>the GS operates *using HTTP/https and the JSONRPC2.0 protocol.* Unlike gRPC, jsonrpc is extremely simple, allows for easy sending of requests from the browser, and does not require any additional code compilation. **Why Care?** Easy-to-use API means you can control nodes from anywhere, including lightweight web clients, without compiling extra code.</details>
|
||||
- **Lua script-based methods**<details>*The gopher-lua library is used, providing full support for Lua 5.1.* scripts implement libraries for interacting with sessions (receiving parameters and sending responses), hashing, logging, and more. This allows you to quickly write business logic on the fly without touching the lower layers of abstraction, which also eliminates unnecessary compilation and the risk of breaking the codebase.
|
||||
Example of the "echo" method:
|
||||
```lua
|
||||
local session = require("internal.session")
|
||||
-- import the internal library for interacting with sessions
|
||||
|
||||
session.response.send(session.request.params.get())
|
||||
-- send everything passed in the parameters in response.
|
||||
```
|
||||
**Why Care?** You can extend node behavior dynamically, write custom logic fast, and iterate without recompiling — perfect for experiments or automation.
|
||||
</details>
|
||||
- **Relatively flexible configuration** <details>
|
||||
you can configure the server port, address, name, node settings, and more. 💡 More settings are planned in the future. **Why Care?** Configure nodes for any environment, from Raspberry Pi to VPS, without touching the source code. obviously :)</details>
|
||||
- ***And more in the future***
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This is the beginning of the project's development, and some aspects of it may be unstable, unfinished, and the text about it may be overly ambitious. It's just a matter of time.
|
||||
|
||||
## Quick start
|
||||
```bash
|
||||
git clone https://github.com/akyaiy/GoSally-mvp.git && \
|
||||
cd GoSally-mvp && \
|
||||
make build && \
|
||||
echo -e "node:\n com_dir: \"%path%/com\"" > config.yaml && \
|
||||
mkdir -p com && \
|
||||
echo -e 'local session = require("internal.session")\n\nsession.response.send(session.request.params.get())' > com/echo.lua && \
|
||||
./bin/node run
|
||||
```
|
||||
or for structured logs
|
||||
```bash
|
||||
./bin/node run | jq
|
||||
```
|
||||
|
||||
Example of GET request to server
|
||||
If you have problems, make sure you have all [dependencies](https://github.com/akyaiy/GoSally-mvp/wiki/Getting-started#installing-dependencies) installed, otherwise [file an issue report](https://github.com/akyaiy/GoSally-mvp/issues)
|
||||
|
||||
### Test it
|
||||
```bash
|
||||
curl -s http://localhost:8080/api/v1/com/echo?msg=Hello
|
||||
curl -X POST http://localhost:8080/com \
|
||||
-d '{"jsonrpc":"2.0","context-version": "v1","method":"echo","params":["Hi!!"],"id":1}'
|
||||
```
|
||||
Then the response from the server
|
||||
Expected response:
|
||||
```json
|
||||
{
|
||||
"ResponsibleAgentUUID": "4593a87000bbe088f4e79c477e9c90d3",
|
||||
"RequestedCommand": "echo",
|
||||
"Response": {
|
||||
"answer": "Hello",
|
||||
"status": "ok"
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": [
|
||||
"Hi!!"
|
||||
],
|
||||
"data": {
|
||||
"responsible-node": "a0e1c440473ffd4d87e32cff2717f5b3",
|
||||
"salt": "f26df732-a3be-4400-8e71-b8dc3ba705fc",
|
||||
"checksum-md5": "cd8bec6a365d1b8ee90773567cb3ad0a"
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### How to install
|
||||
**You don't need it now, but you can figure it out with the Makefile**
|
||||
## Concept
|
||||
The project was originally conceived as a tool for building infrastructure using relatively *small nodes with limited functionality*. 💡 In the future, we plan to create a *web interface for interacting with nodes, administration, and configuration*. The concept is simple: suppose we have a node that manages Bind9. It has all the necessary methods for interacting with the service: creating new zones, viewing zone status, changing configuration, and server operation status. All of this works only through manual configuration, with the exception of larger solutions like Webmin and the BIND DNS Server module. The big problem is that while we only needed web configuration for Bind9, we have to pull in a massive amount of software just to implement one module. What if the service is hosted on a low-power Raspberry Pi? That's where GS nodes come in. By default, GS nodes communicate only through API calls, so 💡 in the future, we plan to create a dedicated, also programmable, web node that will provide convenient access to node management.
|
||||
|
||||
There's an obvious advantage here: transparency. The project is *completely open source and aims to support community-driven node functionality*. 💡 In the future, we plan to create a "store" similar to Docker Hub, which will contain scripts for configuring bind9, openvpn, and even custom projects.
|
||||
|
||||
## API
|
||||
As mentioned earlier, *the server handles [jsonrpc2.0](https://www.jsonrpc.org/specification) requests*
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"context-version": "v1",
|
||||
"method": "test",
|
||||
"params": [
|
||||
"Hi!!"
|
||||
],
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
This is a typical example of a request using the jsonrpc2.0 protocol.
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": [
|
||||
"Hi!!"
|
||||
],
|
||||
"data": {
|
||||
"responsible-node": "2ad6ebeaf579a7c52801fb6c9dd1b83d",
|
||||
"salt": "e7a81115-01c1-45b1-9618-0eae0ff26451",
|
||||
"checksum-md5": "cd8bec6a365d1b8ee90773567cb3ad0a"
|
||||
}
|
||||
}
|
||||
```
|
||||
In the result field, we see the echo method's response. Those familiar with the jsonrpc2.0 specification will notice that the data structure here is unclear. This is my extension, which has three functions:
|
||||
| Field | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `responsible-node` | string | ID of the node that executed the task |
|
||||
| `salt` | string | Random value for each request — can be used to check that the response is unique |
|
||||
| `checksum-md5` | string | MD5 hash of the result field — can be used to avoid processing identical results separately |
|
||||
|
||||
## License
|
||||
Distributed under the BSD 3-Clause License. See [`LICENSE`](./LICENSE) for more information.
|
||||
|
||||
[^1]: Go Sally
|
||||
|
||||
22
com/Access/_common.lua
Normal file
22
com/Access/_common.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
-- File com/Access/_common.lua
|
||||
--
|
||||
-- Created at 2025-21-10
|
||||
--
|
||||
-- Description:
|
||||
--- Common functions for Unit module
|
||||
|
||||
local common = {}
|
||||
|
||||
function common.CheckMissingElement(arr, cmp)
|
||||
local is_missing = {}
|
||||
local ok = true
|
||||
for _, key in ipairs(arr) do
|
||||
if cmp[key] == nil then
|
||||
table.insert(is_missing, key)
|
||||
ok = false
|
||||
end
|
||||
end
|
||||
return ok, is_missing
|
||||
end
|
||||
|
||||
return common
|
||||
30
com/Access/_errors.lua
Normal file
30
com/Access/_errors.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
-- File com/Access/_errors.lua
|
||||
--
|
||||
-- Created at 2025-21-10
|
||||
-- Description:
|
||||
--- Centralized error definitions for Access operations
|
||||
--- to keep API responses consistent and clean.
|
||||
|
||||
local errors = {
|
||||
-- Common validation
|
||||
MISSING_PARAMS = { code = -32602, message = "Missing params" },
|
||||
INVALID_FIELD_TYPE = { code = -32602, message = "'fields' must be a non-empty table" },
|
||||
INVALID_BY_PARAM = { code = -32602, message = "Invalid 'by' param" },
|
||||
NO_VALID_FIELDS = { code = -32604, message = "No valid fields to update" },
|
||||
|
||||
-- Existence / duplication
|
||||
UNIT_NOT_FOUND = { code = -32102, message = "Unit is not exists" },
|
||||
UNIT_EXISTS = { code = -32101, message = "Unit is already exists" },
|
||||
|
||||
-- Database & constraint
|
||||
UNIQUE_CONSTRAINT = { code = -32602, message = "Unique constraint failed" },
|
||||
DB_QUERY_FAILED = { code = -32001, message = "Database query failed" },
|
||||
DB_EXEC_FAILED = { code = -32002, message = "Database execution failed" },
|
||||
DB_INSERT_FAILED = { code = -32003, message = "Failed to create unit" },
|
||||
DB_DELETE_FAILED = { code = -32004, message = "Failed to delete unit" },
|
||||
|
||||
-- Generic fallback
|
||||
UNKNOWN = { code = -32099, message = "Unexpected internal error" },
|
||||
}
|
||||
|
||||
return errors
|
||||
@@ -1,119 +0,0 @@
|
||||
-- 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()
|
||||
@@ -1,76 +0,0 @@
|
||||
-- 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()
|
||||
@@ -1,109 +0,0 @@
|
||||
-- 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()
|
||||
@@ -1,66 +0,0 @@
|
||||
---@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()
|
||||
@@ -1,29 +0,0 @@
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
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"
|
||||
}
|
||||
44
com/test.lua
44
com/test.lua
@@ -1,44 +0,0 @@
|
||||
local sha256 = require("internal.crypt.sha256")
|
||||
local log = require("internal.log")
|
||||
local session = require("internal.session")
|
||||
|
||||
-- local secret = require("_config").token()
|
||||
|
||||
-- local token = jwt.encode({
|
||||
-- secret = secret,
|
||||
-- payload = { session_uuid = session.id },
|
||||
-- expires_in = 3600
|
||||
-- })
|
||||
|
||||
-- local err, data = jwt.decode(token, { secret = secret })
|
||||
|
||||
-- if not err then
|
||||
-- session.response.result = {
|
||||
-- token = token
|
||||
-- }
|
||||
-- return
|
||||
-- end
|
||||
|
||||
-- session.response.error = {
|
||||
-- message = "not sigma"
|
||||
-- }
|
||||
-- local array = session.request.params.get("array", "oops")
|
||||
-- function s()
|
||||
-- session.throw_error("dqdqwdqwdqiwhodiwqohdq", 10)
|
||||
-- end
|
||||
-- s()
|
||||
|
||||
-- session.response.__script_data.result = {
|
||||
-- data = {
|
||||
-- sewf = 1
|
||||
-- },
|
||||
-- 2
|
||||
-- }
|
||||
session.response.set_error()
|
||||
--session.response.send_error({1})
|
||||
-- session.response.set()
|
||||
-- session.response.__script_data.result = {
|
||||
-- status = "ok"
|
||||
-- }
|
||||
session.response.set(1)
|
||||
log.event("popi")
|
||||
@@ -1,30 +0,0 @@
|
||||
node:
|
||||
mode: dev
|
||||
name: "My gosally node"
|
||||
show_config: true
|
||||
com_dir: "%path%/com"
|
||||
|
||||
http_server:
|
||||
address: "0.0.0.0"
|
||||
port: "8080"
|
||||
session_ttl: 5s
|
||||
timeout: 3s
|
||||
idle_timeout: 30s
|
||||
|
||||
tls:
|
||||
enabled: true
|
||||
cert_file: "%path%/cert/fullchain.pem"
|
||||
key_file: "%path%/cert/privkey.pem"
|
||||
|
||||
updates:
|
||||
enabled: false
|
||||
check-interval: 1h
|
||||
repository_url: "https://repo.serve.lv/raw/go-sally"
|
||||
|
||||
log:
|
||||
json_format: false
|
||||
level: "debug"
|
||||
|
||||
disable_warnings:
|
||||
- --WNonStdTmpDir
|
||||
- --WUndefLogLevel
|
||||
Binary file not shown.
Binary file not shown.
BIN
db/root.db
BIN
db/root.db
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,9 +7,9 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/hooks"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/hooks"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/akyaiy/GoSally-mvp/hooks"
|
||||
"github.com/akyaiy/GoSally-mvp/src/hooks"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,8 @@ import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/sv1"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -13,7 +14,8 @@ var verCmd = &cobra.Command{
|
||||
Aliases: []string{"ver", "v"},
|
||||
Short: "Return node version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Printf("GoSally node: %s\n", config.NodeVersion)
|
||||
fmt.Printf("Go Sally version: %s\n", config.NodeVersion)
|
||||
fmt.Printf("sv1 version: %s\n", sv1.SV1Version)
|
||||
fmt.Printf("Go version: %s\n", runtime.Version())
|
||||
fmt.Printf("Go OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH)
|
||||
},
|
||||
@@ -1,4 +1,4 @@
|
||||
module github.com/akyaiy/GoSally-mvp
|
||||
module github.com/akyaiy/GoSally-mvp/src
|
||||
|
||||
go 1.24.4
|
||||
|
||||
@@ -13,8 +13,6 @@ github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
|
||||
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
@@ -18,13 +18,13 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/run_manager"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/logs"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/run_manager"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/logs"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
@@ -234,7 +234,11 @@ func InitConfigPrintHook(ctx context.Context, cs *corestate.CoreState, x *app.Ap
|
||||
}
|
||||
}
|
||||
|
||||
if *x.Config.Conf.Node.Name == "noname" {
|
||||
x.Log.Printf("Starting node")
|
||||
} else {
|
||||
x.Log.Printf("Starting \"%s\" node", *x.Config.Conf.Node.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func InitSLogHook(_ context.Context, cs *corestate.CoreState, x *app.AppX) {
|
||||
@@ -11,17 +11,18 @@ import (
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/run_manager"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/update"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/logs"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/gateway"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/session"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/sv1"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/run_manager"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/update"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/logs"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/gateway"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/session"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/sv1"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/sv2"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/cors"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -65,13 +66,20 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
|
||||
Ver: "v1",
|
||||
})
|
||||
|
||||
sv2 := sv2.InitServer(&sv2.HandlerInitStruct{
|
||||
X: x,
|
||||
CS: cs,
|
||||
AllowedCmd: regexp.MustCompile(AllowedCmdPattern),
|
||||
Ver: "v2",
|
||||
})
|
||||
|
||||
session_manager := session.New(*x.Config.Conf.HTTPServer.SessionTTL)
|
||||
|
||||
s := gateway.InitGateway(&gateway.GatewayServerInit{
|
||||
SM: session_manager,
|
||||
CS: cs,
|
||||
X: x,
|
||||
}, serverv1)
|
||||
}, serverv1, sv2)
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Use(cors.Handler(cors.Options{
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/config"
|
||||
)
|
||||
|
||||
// GetNodeUUID outputs the correct uuid from the file at the path specified in the arguments.
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/utils"
|
||||
)
|
||||
|
||||
type RunManagerContract interface {
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/run_manager"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/run_manager"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/config"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/config"
|
||||
)
|
||||
|
||||
func NewUUIDRaw(length int) ([]byte, error) {
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/config"
|
||||
)
|
||||
|
||||
type AppContract interface {
|
||||
@@ -61,6 +61,7 @@ func (c *Compositor) LoadConf(path string) error {
|
||||
v.SetDefault("log.json_format", "false")
|
||||
v.SetDefault("log.level", "info")
|
||||
v.SetDefault("log.output", "%2%")
|
||||
v.SetDefault("disable_warnings", []string{})
|
||||
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/colors"
|
||||
)
|
||||
|
||||
func (c *Compositor) Print(v any) {
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/config"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
@@ -3,9 +3,9 @@ package lua
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/rpc"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/rpc"
|
||||
)
|
||||
|
||||
type LuaEngineDeps struct {
|
||||
@@ -17,7 +17,6 @@ type LuaEngineDeps struct {
|
||||
|
||||
type LuaEngineContract interface {
|
||||
Handle(deps *LuaEngineDeps) *rpc.RPCResponse
|
||||
|
||||
}
|
||||
|
||||
type LuaEngine struct {
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/rpc"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/session"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/rpc"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/session"
|
||||
)
|
||||
|
||||
// serversApiVer is a type alias for string, used to represent API version strings in the GeneralServer.
|
||||
@@ -3,9 +3,9 @@ package gateway
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/session"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/session"
|
||||
)
|
||||
|
||||
// GeneralServerInit structure only for initialization general server.
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/rpc"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/utils"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/rpc"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@@ -37,7 +37,9 @@ func NewError(code int, message string, data any, id *json.RawMessage) *RPCRespo
|
||||
Error = map[string]any{
|
||||
"code": code,
|
||||
"message": message,
|
||||
"data": data,
|
||||
}
|
||||
if data != nil {
|
||||
Error["data"] = data
|
||||
}
|
||||
|
||||
return &RPCResponse{
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/rpc"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/rpc"
|
||||
)
|
||||
|
||||
func (h *HandlerV1) Handle(_ context.Context, sid string, r *http.Request, req *rpc.RPCRequest) *rpc.RPCResponse {
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/rpc"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/colors"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/rpc"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
@@ -186,11 +186,6 @@ func (h *HandlerV1) handleLUA(sid string, r *http.Request, req *rpc.RPCRequest,
|
||||
L.SetField(scriptDataTable, "result", resTable)
|
||||
L.SetField(outTable, "send", L.NewFunction(func(L *lua.LState) int {
|
||||
res := L.Get(1)
|
||||
if res == lua.LNil {
|
||||
__exit = 0
|
||||
L.RaiseError("__successfull")
|
||||
return 0
|
||||
}
|
||||
|
||||
resFTable := scriptDataTable.RawGetString("result")
|
||||
if resPTable, ok := res.(*lua.LTable); ok {
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/server/rpc"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/rpc"
|
||||
)
|
||||
|
||||
var RPCMethodSeparator = "."
|
||||
@@ -5,10 +5,12 @@ package sv1
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/internal/engine/app"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/app"
|
||||
)
|
||||
|
||||
var SV1Version = "v1"
|
||||
|
||||
// HandlerV1InitStruct structure is only for initialization
|
||||
type HandlerV1InitStruct struct {
|
||||
Ver string
|
||||
12
src/internal/server/sv2/handle.go
Normal file
12
src/internal/server/sv2/handle.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package sv2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/server/rpc"
|
||||
)
|
||||
|
||||
func (h *Handler) Handle(_ context.Context, sid string, r *http.Request, req *rpc.RPCRequest) *rpc.RPCResponse {
|
||||
return nil
|
||||
}
|
||||
43
src/internal/server/sv2/server.go
Normal file
43
src/internal/server/sv2/server.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// SV2 works with binaries, scripts, and anything else that has access to stdin/stdout.
|
||||
// Modules run in a separate process and communicate via I/O.
|
||||
package sv2
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/core/corestate"
|
||||
"github.com/akyaiy/GoSally-mvp/src/internal/engine/app"
|
||||
)
|
||||
|
||||
// HandlerV2InitStruct structure is only for initialization
|
||||
type HandlerInitStruct struct {
|
||||
Ver string
|
||||
CS *corestate.CoreState
|
||||
X *app.AppX
|
||||
AllowedCmd *regexp.Regexp
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
cs *corestate.CoreState
|
||||
x *app.AppX
|
||||
|
||||
// allowedCmd and listAllowedCmd are regular expressions used to validate command names.
|
||||
allowedCmd *regexp.Regexp
|
||||
|
||||
ver string
|
||||
}
|
||||
|
||||
func InitServer(o *HandlerInitStruct) *Handler {
|
||||
return &Handler{
|
||||
cs: o.CS,
|
||||
x: o.X,
|
||||
allowedCmd: o.AllowedCmd,
|
||||
ver: o.Ver,
|
||||
}
|
||||
}
|
||||
|
||||
// GetVersion returns the API version of the HandlerV1, which is set during initialization.
|
||||
// This version is used to identify the API version in the request routing.
|
||||
func (h *Handler) GetVersion() string {
|
||||
return h.ver
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/akyaiy/GoSally-mvp/cmd"
|
||||
"github.com/akyaiy/GoSally-mvp/src/cmd"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user