initial commit
This commit is contained in:
160
lua/gitea/auth.lua
Normal file
160
lua/gitea/auth.lua
Normal file
@@ -0,0 +1,160 @@
|
||||
local config = require("gitea.config")
|
||||
local uv = vim.loop
|
||||
|
||||
local M = {}
|
||||
local token_cached = nil
|
||||
|
||||
-- Attempt to read the token file from disk
|
||||
local function read_token_file(path)
|
||||
local fd = uv.fs_open(path, "r", 438) -- 0666 in decimal
|
||||
if not fd then return nil end
|
||||
local stat = uv.fs_fstat(fd)
|
||||
local data = uv.fs_read(fd, stat.size, 0)
|
||||
uv.fs_close(fd)
|
||||
return data
|
||||
end
|
||||
|
||||
-- Write token file
|
||||
local function write_token_file(path, token)
|
||||
local fd = uv.fs_open(path, "w", 384) -- 0600 in decimal
|
||||
if not fd then
|
||||
error("[gitea.nvim] Failed to open token file for writing: " .. path)
|
||||
end
|
||||
uv.fs_write(fd, token, -1)
|
||||
uv.fs_close(fd)
|
||||
end
|
||||
|
||||
-- Checks if the token file is in .gitignore, if not ask user
|
||||
local function ensure_ignored(token_file, ignore_file)
|
||||
-- Read .gitignore lines if present
|
||||
local file = io.open(ignore_file, "r")
|
||||
local lines = {}
|
||||
if file then
|
||||
for line in file:lines() do
|
||||
table.insert(lines, line)
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
-- Check if token_file is in .gitignore
|
||||
for _, l in ipairs(lines) do
|
||||
if l == token_file then
|
||||
return
|
||||
end
|
||||
end
|
||||
-- Not in ignore, ask user
|
||||
vim.schedule(function()
|
||||
vim.cmd([[echohl WarningMsg]])
|
||||
vim.cmd([[echo "gitea.nvim: We recommend adding ']]..token_file..[[' to ']]..ignore_file..[['. Add now? (y/N)"]])
|
||||
vim.cmd([[echohl None]])
|
||||
|
||||
local ans = vim.fn.getchar()
|
||||
ans = vim.fn.nr2char(ans)
|
||||
|
||||
if ans == "y" or ans == "Y" then
|
||||
local f = io.open(ignore_file, "a")
|
||||
if f then
|
||||
f:write("\n" .. token_file .. "\n")
|
||||
f:close()
|
||||
vim.notify("Added '"..token_file.."' to '"..ignore_file.."'", vim.log.levels.INFO)
|
||||
else
|
||||
vim.notify("Failed to open '"..ignore_file.."' for appending.", vim.log.levels.ERROR)
|
||||
end
|
||||
else
|
||||
vim.notify("Ok, not adding token file to '"..ignore_file.."'. Be mindful of security!", vim.log.levels.WARN)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Parse .git/config or `git remote get-url origin` to guess the Gitea server
|
||||
local function detect_gitea_server()
|
||||
-- Attempt: use `git config remote.origin.url`
|
||||
local cmd = "git config remote.origin.url"
|
||||
local url = vim.fn.systemlist(cmd)[1]
|
||||
if vim.v.shell_error ~= 0 or not url or url == "" then
|
||||
return nil
|
||||
end
|
||||
-- Example: https://gitea.myserver.com/owner/repo.git
|
||||
-- Strip `.git` suffix if present
|
||||
url = url:gsub("%.git$", "")
|
||||
-- Attempt to extract domain, e.g. "https://gitea.myserver.com"
|
||||
-- We'll do a naive pattern match
|
||||
local protocol, domain_and_path = url:match("^(https?://)(.*)$")
|
||||
if not protocol or not domain_and_path then
|
||||
-- Could be SSH or something else
|
||||
-- For instance: git@gitea.myserver.com:owner/repo.git
|
||||
-- Try a different parse
|
||||
local user_host, path = url:match("^(.-):(.*)$")
|
||||
if user_host and path and user_host:match(".*@") then
|
||||
-- user_host could be "git@gitea.myserver.com"
|
||||
local host = user_host:match("@(.*)")
|
||||
if host then
|
||||
return "https://"..host
|
||||
end
|
||||
end
|
||||
-- Fallback
|
||||
return nil
|
||||
end
|
||||
|
||||
-- domain_and_path might be "gitea.myserver.com/owner/repo"
|
||||
-- just extract "gitea.myserver.com"
|
||||
local server = domain_and_path:match("^([^/]+)")
|
||||
if not server then
|
||||
return nil
|
||||
end
|
||||
return protocol .. server
|
||||
end
|
||||
|
||||
-- Called during plugin setup or first command usage
|
||||
function M.ensure_token()
|
||||
if token_cached then
|
||||
return token_cached
|
||||
end
|
||||
|
||||
local cfg = config.values
|
||||
local token_file = cfg.config_file
|
||||
local ignore_file = cfg.ignore_file
|
||||
|
||||
-- Attempt to detect the Gitea server if not provided
|
||||
if not cfg.server_url or cfg.server_url == "" then
|
||||
cfg.server_url = detect_gitea_server()
|
||||
end
|
||||
if not cfg.server_url then
|
||||
vim.notify("[gitea.nvim] Could not detect Gitea server from .git/config. Please configure manually.", vim.log.levels.WARN)
|
||||
end
|
||||
|
||||
local token_data = read_token_file(token_file)
|
||||
if token_data and token_data ~= "" then
|
||||
token_cached = token_data
|
||||
return token_cached
|
||||
end
|
||||
|
||||
-- If we reach here, no token was found
|
||||
vim.schedule(function()
|
||||
vim.cmd([[echohl WarningMsg]])
|
||||
vim.cmd([[echo "gitea.nvim: No Gitea token found. Please enter your Gitea Personal Access Token:"]])
|
||||
vim.cmd([[echohl None]])
|
||||
|
||||
local user_token = vim.fn.input("Token: ")
|
||||
vim.cmd("redraw")
|
||||
|
||||
if user_token == nil or user_token == "" then
|
||||
vim.notify("[gitea.nvim] No token provided, plugin may not work properly.", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
write_token_file(token_file, user_token)
|
||||
token_cached = user_token
|
||||
vim.notify("Token saved to " .. token_file .. ".", vim.log.levels.INFO)
|
||||
|
||||
-- Offer to add token_file to .gitignore
|
||||
ensure_ignored(token_file, ignore_file)
|
||||
end)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function M.get_token()
|
||||
return token_cached
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user