fix(credentials): pack CSES token into single credential entry
Problem: the CSES API token was stored as a separate git credential entry using `path=api-token`, but many credential helpers (e.g. `cache`) ignore the `path` field, so the token was lost on retrieval. The scraper `on_event` callback also called `git_credential.store` from a `uv.spawn` fast event context, causing `vim.wait` errors. Solution: encode the CSES token into the password field as `password<TAB>token` and decode on retrieval. One credential entry per platform, no `path` dependency. Wrap `store` calls in `scraper.lua` with `vim.schedule` to avoid fast event context.
This commit is contained in:
parent
0d06d5cb89
commit
a255fa47a0
2 changed files with 40 additions and 29 deletions
|
|
@ -57,6 +57,32 @@ local function _parse_output(stdout)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local CSES_TOKEN_SEP = '\t'
|
||||||
|
|
||||||
|
---@param platform string
|
||||||
|
---@param password string
|
||||||
|
---@return string, string?
|
||||||
|
local function _decode_password(platform, password)
|
||||||
|
if platform ~= 'cses' then
|
||||||
|
return password, nil
|
||||||
|
end
|
||||||
|
local pw, token = password:match('^(.-)' .. CSES_TOKEN_SEP .. '(.+)$')
|
||||||
|
if pw then
|
||||||
|
return pw, token
|
||||||
|
end
|
||||||
|
return password, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param password string
|
||||||
|
---@param token? string
|
||||||
|
---@return string
|
||||||
|
local function _encode_password(password, token)
|
||||||
|
if token then
|
||||||
|
return password .. CSES_TOKEN_SEP .. token
|
||||||
|
end
|
||||||
|
return password
|
||||||
|
end
|
||||||
|
|
||||||
---@param platform string
|
---@param platform string
|
||||||
---@return cp.Credentials?
|
---@return cp.Credentials?
|
||||||
function M.get(platform)
|
function M.get(platform)
|
||||||
|
|
@ -78,19 +104,10 @@ function M.get(platform)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local creds = { username = parsed.username, password = parsed.password }
|
local password, token = _decode_password(platform, parsed.password)
|
||||||
|
local creds = { username = parsed.username, password = password }
|
||||||
if platform == 'cses' then
|
if token then
|
||||||
local token_input = _build_input(host, { path = 'api-token' })
|
creds.token = token
|
||||||
local token_obj = vim
|
|
||||||
.system({ 'git', 'credential', 'fill' }, { stdin = token_input, text = true, timeout = 5000 })
|
|
||||||
:wait()
|
|
||||||
if token_obj.code == 0 then
|
|
||||||
local token_parsed = _parse_output(token_obj.stdout or '')
|
|
||||||
if token_parsed.password then
|
|
||||||
creds.token = token_parsed.password
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return creds
|
return creds
|
||||||
|
|
@ -104,14 +121,9 @@ function M.store(platform, creds)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local input = _build_input(host, { username = creds.username, password = creds.password })
|
local stored_password = _encode_password(creds.password, creds.token)
|
||||||
|
local input = _build_input(host, { username = creds.username, password = stored_password })
|
||||||
vim.system({ 'git', 'credential', 'approve' }, { stdin = input, text = true }):wait()
|
vim.system({ 'git', 'credential', 'approve' }, { stdin = input, text = true }):wait()
|
||||||
|
|
||||||
if platform == 'cses' and creds.token then
|
|
||||||
local token_input =
|
|
||||||
_build_input(host, { path = 'api-token', username = creds.username, password = creds.token })
|
|
||||||
vim.system({ 'git', 'credential', 'approve' }, { stdin = token_input, text = true }):wait()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param platform string
|
---@param platform string
|
||||||
|
|
@ -122,14 +134,9 @@ function M.reject(platform, creds)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local input = _build_input(host, { username = creds.username, password = creds.password })
|
local stored_password = _encode_password(creds.password, creds.token)
|
||||||
|
local input = _build_input(host, { username = creds.username, password = stored_password })
|
||||||
vim.system({ 'git', 'credential', 'reject' }, { stdin = input, text = true }):wait()
|
vim.system({ 'git', 'credential', 'reject' }, { stdin = input, text = true }):wait()
|
||||||
|
|
||||||
if platform == 'cses' and creds.token then
|
|
||||||
local token_input =
|
|
||||||
_build_input(host, { path = 'api-token', username = creds.username, password = creds.token })
|
|
||||||
vim.system({ 'git', 'credential', 'reject' }, { stdin = token_input, text = true }):wait()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,9 @@ function M.login(platform, credentials, on_status, callback)
|
||||||
stdin = vim.json.encode(credentials),
|
stdin = vim.json.encode(credentials),
|
||||||
on_event = function(ev)
|
on_event = function(ev)
|
||||||
if ev.credentials ~= nil and next(ev.credentials) ~= nil then
|
if ev.credentials ~= nil and next(ev.credentials) ~= nil then
|
||||||
|
vim.schedule(function()
|
||||||
require('cp.git_credential').store(platform, ev.credentials)
|
require('cp.git_credential').store(platform, ev.credentials)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
if ev.status ~= nil then
|
if ev.status ~= nil then
|
||||||
if type(on_status) == 'function' then
|
if type(on_status) == 'function' then
|
||||||
|
|
@ -395,7 +397,9 @@ function M.submit(
|
||||||
stdin = vim.json.encode(credentials),
|
stdin = vim.json.encode(credentials),
|
||||||
on_event = function(ev)
|
on_event = function(ev)
|
||||||
if ev.credentials ~= nil and next(ev.credentials) ~= nil then
|
if ev.credentials ~= nil and next(ev.credentials) ~= nil then
|
||||||
|
vim.schedule(function()
|
||||||
require('cp.git_credential').store(platform, ev.credentials)
|
require('cp.git_credential').store(platform, ev.credentials)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
if ev.status ~= nil then
|
if ev.status ~= nil then
|
||||||
if type(on_status) == 'function' then
|
if type(on_status) == 'function' then
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue