feat(credentials): guard login/submit/logout on credential helper
Problem: if no git credential helper is configured, login and submit silently fail to persist credentials. Solution: add `has_helper()` to `git_credential.lua` that checks `git config credential.helper`. Guard the top of `login()`, `logout()`, and `submit()` with an early-return error. Add a healthcheck warning when no helper is configured. Add LuaCATS annotations to all `git_credential` functions.
This commit is contained in:
parent
8348b6195e
commit
5aa2c024e0
4 changed files with 57 additions and 0 deletions
|
|
@ -71,6 +71,14 @@ function M.login(platform)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not git_credential.has_helper() then
|
||||||
|
logger.log(
|
||||||
|
'No git credential helper configured. See :help cp-credentials',
|
||||||
|
{ level = vim.log.levels.ERROR }
|
||||||
|
)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local display = constants.PLATFORM_DISPLAY_NAMES[platform] or platform
|
local display = constants.PLATFORM_DISPLAY_NAMES[platform] or platform
|
||||||
|
|
||||||
local existing = git_credential.get(platform) or {}
|
local existing = git_credential.get(platform) or {}
|
||||||
|
|
@ -111,6 +119,14 @@ function M.logout(platform)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if not git_credential.has_helper() then
|
||||||
|
logger.log(
|
||||||
|
'No git credential helper configured. See :help cp-credentials',
|
||||||
|
{ level = vim.log.levels.ERROR }
|
||||||
|
)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local display = constants.PLATFORM_DISPLAY_NAMES[platform] or platform
|
local display = constants.PLATFORM_DISPLAY_NAMES[platform] or platform
|
||||||
local existing = git_credential.get(platform)
|
local existing = git_credential.get(platform)
|
||||||
if existing then
|
if existing then
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,24 @@ local HOSTS = {
|
||||||
usaco = 'usaco.org',
|
usaco = 'usaco.org',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local _helper_checked = false
|
||||||
|
local _helper_ok = false
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
|
function M.has_helper()
|
||||||
|
if not _helper_checked then
|
||||||
|
local r = vim
|
||||||
|
.system({ 'git', 'config', 'credential.helper' }, { text = true, timeout = 5000 })
|
||||||
|
:wait()
|
||||||
|
_helper_ok = r.code == 0 and r.stdout ~= nil and vim.trim(r.stdout) ~= ''
|
||||||
|
_helper_checked = true
|
||||||
|
end
|
||||||
|
return _helper_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param host string
|
||||||
|
---@param extra? table<string, string>
|
||||||
|
---@return string
|
||||||
local function _build_input(host, extra)
|
local function _build_input(host, extra)
|
||||||
local lines = { 'protocol=https', 'host=' .. host }
|
local lines = { 'protocol=https', 'host=' .. host }
|
||||||
if extra then
|
if extra then
|
||||||
|
|
@ -21,6 +39,8 @@ local function _build_input(host, extra)
|
||||||
return table.concat(lines, '\n')
|
return table.concat(lines, '\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param stdout string
|
||||||
|
---@return table<string, string>
|
||||||
local function _parse_output(stdout)
|
local function _parse_output(stdout)
|
||||||
local result = {}
|
local result = {}
|
||||||
for line in stdout:gmatch('[^\n]+') do
|
for line in stdout:gmatch('[^\n]+') do
|
||||||
|
|
@ -32,6 +52,8 @@ local function _parse_output(stdout)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param platform string
|
||||||
|
---@return { username: string, password: string, token?: string }?
|
||||||
function M.get(platform)
|
function M.get(platform)
|
||||||
local host = HOSTS[platform]
|
local host = HOSTS[platform]
|
||||||
if not host then
|
if not host then
|
||||||
|
|
@ -69,6 +91,8 @@ function M.get(platform)
|
||||||
return creds
|
return creds
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param platform string
|
||||||
|
---@param creds { username: string, password: string, token?: string }
|
||||||
function M.store(platform, creds)
|
function M.store(platform, creds)
|
||||||
local host = HOSTS[platform]
|
local host = HOSTS[platform]
|
||||||
if not host then
|
if not host then
|
||||||
|
|
@ -85,6 +109,8 @@ function M.store(platform, creds)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param platform string
|
||||||
|
---@param creds { username: string, password: string, token?: string }
|
||||||
function M.reject(platform, creds)
|
function M.reject(platform, creds)
|
||||||
local host = HOSTS[platform]
|
local host = HOSTS[platform]
|
||||||
if not host or not creds then
|
if not host or not creds then
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,13 @@ local function check()
|
||||||
vim.health.warn('git >= 1.7.9 required for credential storage, found ' .. ver_str)
|
vim.health.warn('git >= 1.7.9 required for credential storage, found ' .. ver_str)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local helper = vim.system({ 'git', 'config', 'credential.helper' }, { text = true }):wait()
|
||||||
|
if helper.code == 0 and helper.stdout and vim.trim(helper.stdout) ~= '' then
|
||||||
|
vim.health.ok('git credential helper: ' .. vim.trim(helper.stdout))
|
||||||
|
else
|
||||||
|
vim.health.warn('no git credential helper configured (required for login/submit)')
|
||||||
|
end
|
||||||
else
|
else
|
||||||
vim.health.warn('git not found (required for credential storage)')
|
vim.health.warn('git not found (required for credential storage)')
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,14 @@ end
|
||||||
|
|
||||||
---@param opts { language?: string }?
|
---@param opts { language?: string }?
|
||||||
function M.submit(opts)
|
function M.submit(opts)
|
||||||
|
if not git_credential.has_helper() then
|
||||||
|
logger.log(
|
||||||
|
'No git credential helper configured. See :help cp-credentials',
|
||||||
|
{ level = vim.log.levels.ERROR }
|
||||||
|
)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local platform = state.get_platform()
|
local platform = state.get_platform()
|
||||||
local contest_id = state.get_contest_id()
|
local contest_id = state.get_contest_id()
|
||||||
local problem_id = state.get_problem_id()
|
local problem_id = state.get_problem_id()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue