gitlab-mcp-agent-server 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -5,7 +5,10 @@ MCP server for GitLab integration (TypeScript + Node.js).
|
|
|
5
5
|
Полный пользовательский сценарий подключения к ИИ-агенту:
|
|
6
6
|
- `docs/USER_GUIDE.md`
|
|
7
7
|
|
|
8
|
-
Основной сценарий:
|
|
8
|
+
Основной сценарий: модель `multi-instance`.
|
|
9
|
+
- Один MCP-блок в `~/.codex/config.toml` на один GitLab instance.
|
|
10
|
+
- Для `gitlab.com` и каждого self-hosted GitLab добавляется отдельный блок.
|
|
11
|
+
- Готовые блоки есть в `docs/USER_GUIDE.md`.
|
|
9
12
|
|
|
10
13
|
Для конечного пользователя обычно достаточно:
|
|
11
14
|
1. Зарегистрировать GitLab OAuth application.
|
|
@@ -13,9 +16,9 @@ MCP server for GitLab integration (TypeScript + Node.js).
|
|
|
13
16
|
|
|
14
17
|
Остальное работает по дефолту:
|
|
15
18
|
- OAuth auto-login при отсутствии токена.
|
|
16
|
-
- token store в `~/.config/gitlab-mcp
|
|
19
|
+
- instance-aware token store в `~/.config/gitlab-mcp/<gitlab-host>/token.json`.
|
|
17
20
|
- auto-refresh access token.
|
|
18
|
-
-
|
|
21
|
+
- поддержка явного `project` в tool input и fallback-резолва проекта.
|
|
19
22
|
|
|
20
23
|
## Local setup (development)
|
|
21
24
|
|
|
@@ -12,7 +12,6 @@ const health_check_1 = require("../../application/use-cases/health-check");
|
|
|
12
12
|
const list_labels_1 = require("../../application/use-cases/list-labels");
|
|
13
13
|
const list_issues_1 = require("../../application/use-cases/list-issues");
|
|
14
14
|
const update_issue_labels_1 = require("../../application/use-cases/update-issue-labels");
|
|
15
|
-
const group_oauth_token_provider_1 = require("../../infrastructure/auth/group-oauth-token-provider");
|
|
16
15
|
const gitlab_oauth_manager_1 = require("../../infrastructure/auth/gitlab-oauth-manager");
|
|
17
16
|
const token_provider_1 = require("../../infrastructure/auth/token-provider");
|
|
18
17
|
const gitlab_api_client_1 = require("../../infrastructure/gitlab/gitlab-api-client");
|
|
@@ -21,20 +20,16 @@ const register_tools_1 = require("./register-tools");
|
|
|
21
20
|
function createMcpServer() {
|
|
22
21
|
const config = (0, config_1.loadConfig)();
|
|
23
22
|
const tokenProvider = config.gitlab.authMode === 'oauth'
|
|
24
|
-
? new
|
|
23
|
+
? new gitlab_oauth_manager_1.GitLabOAuthManager({
|
|
25
24
|
apiUrl: config.gitlab.apiUrl,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
autoLogin: config.gitlab.oauth.autoLogin,
|
|
35
|
-
openBrowser: config.gitlab.oauth.openBrowser
|
|
36
|
-
}),
|
|
37
|
-
groupConfigs: config.gitlab.groupOAuthConfigs
|
|
25
|
+
clientId: config.gitlab.oauth.clientId,
|
|
26
|
+
clientSecret: config.gitlab.oauth.clientSecret,
|
|
27
|
+
redirectUri: config.gitlab.oauth.redirectUri,
|
|
28
|
+
scopes: config.gitlab.oauth.scopes,
|
|
29
|
+
bootstrapAccessToken: config.gitlab.accessToken,
|
|
30
|
+
tokenStorePath: config.gitlab.oauth.tokenStorePath,
|
|
31
|
+
autoLogin: config.gitlab.oauth.autoLogin,
|
|
32
|
+
openBrowser: config.gitlab.oauth.openBrowser
|
|
38
33
|
})
|
|
39
34
|
: new token_provider_1.StaticTokenProvider(config.gitlab.accessToken);
|
|
40
35
|
const gitlabApiClient = new gitlab_api_client_1.GitLabApiClient({
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.loadConfig = loadConfig;
|
|
4
|
+
exports.resolveDefaultTokenStorePath = resolveDefaultTokenStorePath;
|
|
4
5
|
const node_child_process_1 = require("node:child_process");
|
|
5
6
|
const node_os_1 = require("node:os");
|
|
6
7
|
const node_path_1 = require("node:path");
|
|
7
8
|
const zod_1 = require("zod");
|
|
8
|
-
const DEFAULT_TOKEN_STORE_PATH = (0, node_path_1.join)((0, node_os_1.homedir)(), '.config', 'gitlab-mcp', 'token.json');
|
|
9
9
|
const EnvSchema = zod_1.z.object({
|
|
10
10
|
GITLAB_API_URL: zod_1.z.string().url().default('https://gitlab.com/api/v4'),
|
|
11
11
|
GITLAB_AUTH_MODE: zod_1.z.enum(['oauth', 'pat']).default('oauth'),
|
|
@@ -14,7 +14,7 @@ const EnvSchema = zod_1.z.object({
|
|
|
14
14
|
GITLAB_OAUTH_CLIENT_SECRET: zod_1.z.string().optional(),
|
|
15
15
|
GITLAB_OAUTH_REDIRECT_URI: zod_1.z.string().optional(),
|
|
16
16
|
GITLAB_OAUTH_SCOPES: zod_1.z.string().default('api'),
|
|
17
|
-
GITLAB_OAUTH_TOKEN_STORE_PATH: zod_1.z.string().
|
|
17
|
+
GITLAB_OAUTH_TOKEN_STORE_PATH: zod_1.z.string().optional(),
|
|
18
18
|
GITLAB_OAUTH_AUTO_LOGIN: zod_1.z
|
|
19
19
|
.enum(['true', 'false'])
|
|
20
20
|
.optional()
|
|
@@ -23,7 +23,6 @@ const EnvSchema = zod_1.z.object({
|
|
|
23
23
|
.enum(['true', 'false'])
|
|
24
24
|
.optional()
|
|
25
25
|
.transform((value) => value !== 'false'),
|
|
26
|
-
GITLAB_GROUP_OAUTH_CONFIG_JSON: zod_1.z.string().optional(),
|
|
27
26
|
GITLAB_PAT: zod_1.z.string().optional(),
|
|
28
27
|
GITLAB_DEFAULT_PROJECT: zod_1.z.string().optional(),
|
|
29
28
|
GITLAB_AUTO_RESOLVE_PROJECT_FROM_GIT: zod_1.z
|
|
@@ -57,6 +56,7 @@ function loadConfig() {
|
|
|
57
56
|
const autoDetectedProject = env.GITLAB_AUTO_RESOLVE_PROJECT_FROM_GIT
|
|
58
57
|
? detectProjectFromGitRemote()
|
|
59
58
|
: undefined;
|
|
59
|
+
const defaultTokenStorePath = env.GITLAB_OAUTH_TOKEN_STORE_PATH ?? resolveDefaultTokenStorePath(env.GITLAB_API_URL);
|
|
60
60
|
return {
|
|
61
61
|
gitlab: {
|
|
62
62
|
apiUrl: env.GITLAB_API_URL,
|
|
@@ -67,16 +67,10 @@ function loadConfig() {
|
|
|
67
67
|
clientSecret: env.GITLAB_OAUTH_CLIENT_SECRET,
|
|
68
68
|
redirectUri: env.GITLAB_OAUTH_REDIRECT_URI,
|
|
69
69
|
scopes: splitCsv(env.GITLAB_OAUTH_SCOPES),
|
|
70
|
-
tokenStorePath:
|
|
70
|
+
tokenStorePath: defaultTokenStorePath,
|
|
71
71
|
autoLogin: env.GITLAB_OAUTH_AUTO_LOGIN,
|
|
72
72
|
openBrowser: env.GITLAB_OAUTH_OPEN_BROWSER
|
|
73
73
|
},
|
|
74
|
-
groupOAuthConfigs: parseGroupOAuthConfigJson(env.GITLAB_GROUP_OAUTH_CONFIG_JSON, {
|
|
75
|
-
redirectUri: env.GITLAB_OAUTH_REDIRECT_URI,
|
|
76
|
-
scopes: splitCsv(env.GITLAB_OAUTH_SCOPES),
|
|
77
|
-
autoLogin: env.GITLAB_OAUTH_AUTO_LOGIN,
|
|
78
|
-
openBrowser: env.GITLAB_OAUTH_OPEN_BROWSER
|
|
79
|
-
}),
|
|
80
74
|
defaultProject: env.GITLAB_DEFAULT_PROJECT,
|
|
81
75
|
autoResolveProjectFromGit: env.GITLAB_AUTO_RESOLVE_PROJECT_FROM_GIT,
|
|
82
76
|
autoDetectedProject
|
|
@@ -91,62 +85,9 @@ function loadConfig() {
|
|
|
91
85
|
}
|
|
92
86
|
};
|
|
93
87
|
}
|
|
94
|
-
function
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
let parsed;
|
|
99
|
-
try {
|
|
100
|
-
parsed = JSON.parse(raw);
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
throw new Error('GITLAB_GROUP_OAUTH_CONFIG_JSON must be valid JSON.');
|
|
104
|
-
}
|
|
105
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
106
|
-
throw new Error('GITLAB_GROUP_OAUTH_CONFIG_JSON must be an object map.');
|
|
107
|
-
}
|
|
108
|
-
const result = {};
|
|
109
|
-
for (const [groupKey, value] of Object.entries(parsed)) {
|
|
110
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
const rec = value;
|
|
114
|
-
result[groupKey] = {
|
|
115
|
-
clientId: toStringOrUndefined(rec.clientId ?? rec.client_id),
|
|
116
|
-
clientSecret: toStringOrUndefined(rec.clientSecret ?? rec.client_secret),
|
|
117
|
-
redirectUri: toStringOrUndefined(rec.redirectUri ?? rec.redirect_uri ?? defaults.redirectUri),
|
|
118
|
-
scopes: parseScopes(rec.scopes, defaults.scopes),
|
|
119
|
-
tokenStorePath: toStringOrUndefined(rec.tokenStorePath ?? rec.token_store_path) ??
|
|
120
|
-
(0, node_path_1.join)((0, node_os_1.homedir)(), '.config', 'gitlab-mcp', `${sanitizeForFilename(groupKey)}-token.json`),
|
|
121
|
-
autoLogin: toBooleanOrDefault(rec.autoLogin ?? rec.auto_login, defaults.autoLogin),
|
|
122
|
-
openBrowser: toBooleanOrDefault(rec.openBrowser ?? rec.open_browser, defaults.openBrowser),
|
|
123
|
-
bootstrapAccessToken: toStringOrUndefined(rec.bootstrapAccessToken ?? rec.bootstrap_access_token)
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
return result;
|
|
127
|
-
}
|
|
128
|
-
function parseScopes(value, fallback) {
|
|
129
|
-
if (typeof value === 'string') {
|
|
130
|
-
return splitCsv(value);
|
|
131
|
-
}
|
|
132
|
-
if (Array.isArray(value)) {
|
|
133
|
-
return value
|
|
134
|
-
.map((item) => (typeof item === 'string' ? item.trim() : ''))
|
|
135
|
-
.filter((item) => item.length > 0);
|
|
136
|
-
}
|
|
137
|
-
return fallback;
|
|
138
|
-
}
|
|
139
|
-
function toStringOrUndefined(value) {
|
|
140
|
-
return typeof value === 'string' && value.trim() !== '' ? value : undefined;
|
|
141
|
-
}
|
|
142
|
-
function toBooleanOrDefault(value, fallback) {
|
|
143
|
-
if (typeof value === 'boolean') {
|
|
144
|
-
return value;
|
|
145
|
-
}
|
|
146
|
-
if (typeof value === 'string') {
|
|
147
|
-
return value !== 'false';
|
|
148
|
-
}
|
|
149
|
-
return fallback;
|
|
88
|
+
function resolveDefaultTokenStorePath(apiUrl, filePrefix = 'token') {
|
|
89
|
+
const hostKey = sanitizeForFilename(new URL(apiUrl).host.toLowerCase());
|
|
90
|
+
return (0, node_path_1.join)((0, node_os_1.homedir)(), '.config', 'gitlab-mcp', hostKey, `${filePrefix}.json`);
|
|
150
91
|
}
|
|
151
92
|
function sanitizeForFilename(value) {
|
|
152
93
|
return value.replace(/[^a-zA-Z0-9._-]+/g, '_');
|
package/docs/USER_GUIDE.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# User Guide
|
|
2
2
|
|
|
3
|
-
Этот гайд для конечного пользователя: как подключить `gitlab-mcp-agent-server` в **Codex
|
|
3
|
+
Этот гайд для конечного пользователя: как подключить `gitlab-mcp-agent-server` в **Codex**.
|
|
4
|
+
|
|
5
|
+
Основная модель: **multi-instance**.
|
|
6
|
+
- Один блок MCP в `config.toml` = один GitLab instance.
|
|
7
|
+
- Для `gitlab.com` и каждого self-hosted GitLab создаётся отдельный MCP-блок.
|
|
4
8
|
|
|
5
9
|
## 1. Подготовка GitLab OAuth Application
|
|
6
10
|
|
|
@@ -25,15 +29,16 @@
|
|
|
25
29
|
|
|
26
30
|
## 3. Конфиг Codex (`~/.codex/config.toml`)
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
### 3.1 Один instance (минимально)
|
|
29
33
|
|
|
30
34
|
```toml
|
|
31
|
-
[mcp_servers.
|
|
35
|
+
[mcp_servers.gitlab_com]
|
|
32
36
|
command = "bash"
|
|
33
37
|
args = ["-lc", """
|
|
34
38
|
export NVM_DIR="$HOME/.nvm";
|
|
35
39
|
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh";
|
|
36
40
|
|
|
41
|
+
export GITLAB_API_URL="https://gitlab.com/api/v4";
|
|
37
42
|
export GITLAB_OAUTH_CLIENT_ID="<APPLICATION_ID>";
|
|
38
43
|
export GITLAB_OAUTH_CLIENT_SECRET="<SECRET>";
|
|
39
44
|
|
|
@@ -41,10 +46,10 @@ npx -y gitlab-mcp-agent-server
|
|
|
41
46
|
"""]
|
|
42
47
|
```
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
### 3.2 Несколько instances (рекомендуемая модель)
|
|
45
50
|
|
|
46
51
|
```toml
|
|
47
|
-
[mcp_servers.
|
|
52
|
+
[mcp_servers.gitlab_com]
|
|
48
53
|
command = "bash"
|
|
49
54
|
args = ["-lc", """
|
|
50
55
|
export NVM_DIR="$HOME/.nvm";
|
|
@@ -52,18 +57,28 @@ export NVM_DIR="$HOME/.nvm";
|
|
|
52
57
|
|
|
53
58
|
export GITLAB_API_URL="https://gitlab.com/api/v4";
|
|
54
59
|
export GITLAB_AUTH_MODE="oauth";
|
|
55
|
-
export GITLAB_OAUTH_CLIENT_ID="<
|
|
56
|
-
export GITLAB_OAUTH_CLIENT_SECRET="<
|
|
60
|
+
export GITLAB_OAUTH_CLIENT_ID="<GITLAB_COM_APP_ID>";
|
|
61
|
+
export GITLAB_OAUTH_CLIENT_SECRET="<GITLAB_COM_APP_SECRET>";
|
|
57
62
|
export GITLAB_OAUTH_REDIRECT_URI="http://127.0.0.1:8787/oauth/callback";
|
|
58
|
-
export GITLAB_OAUTH_SCOPES="api";
|
|
59
|
-
export GITLAB_OAUTH_TOKEN_STORE_PATH="$HOME/.config/gitlab-mcp/token.json";
|
|
60
63
|
export GITLAB_OAUTH_AUTO_LOGIN="true";
|
|
61
|
-
export GITLAB_OAUTH_OPEN_BROWSER="
|
|
62
|
-
|
|
64
|
+
export GITLAB_OAUTH_OPEN_BROWSER="true";
|
|
65
|
+
|
|
66
|
+
npx -y gitlab-mcp-agent-server
|
|
67
|
+
"""]
|
|
68
|
+
|
|
69
|
+
[mcp_servers.gitlab_work]
|
|
70
|
+
command = "bash"
|
|
71
|
+
args = ["-lc", """
|
|
72
|
+
export NVM_DIR="$HOME/.nvm";
|
|
73
|
+
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh";
|
|
63
74
|
|
|
64
|
-
|
|
65
|
-
export
|
|
66
|
-
export
|
|
75
|
+
export GITLAB_API_URL="https://gitlab.work.local/api/v4";
|
|
76
|
+
export GITLAB_AUTH_MODE="oauth";
|
|
77
|
+
export GITLAB_OAUTH_CLIENT_ID="<WORK_APP_ID>";
|
|
78
|
+
export GITLAB_OAUTH_CLIENT_SECRET="<WORK_APP_SECRET>";
|
|
79
|
+
export GITLAB_OAUTH_REDIRECT_URI="http://127.0.0.1:8788/oauth/callback";
|
|
80
|
+
export GITLAB_OAUTH_AUTO_LOGIN="true";
|
|
81
|
+
export GITLAB_OAUTH_OPEN_BROWSER="true";
|
|
67
82
|
|
|
68
83
|
npx -y gitlab-mcp-agent-server
|
|
69
84
|
"""]
|
|
@@ -71,10 +86,9 @@ npx -y gitlab-mcp-agent-server
|
|
|
71
86
|
|
|
72
87
|
После изменения `config.toml` перезапусти Codex.
|
|
73
88
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
3. Использует соответствующие `clientId/clientSecret/redirectUri/tokenStorePath`.
|
|
89
|
+
По умолчанию token store instance-aware:
|
|
90
|
+
- `~/.config/gitlab-mcp/gitlab.com/token.json`
|
|
91
|
+
- `~/.config/gitlab-mcp/gitlab.work.local/token.json`
|
|
78
92
|
|
|
79
93
|
## 4. Что происходит при первом запуске
|
|
80
94
|
|
|
@@ -83,11 +97,7 @@ npx -y gitlab-mcp-agent-server
|
|
|
83
97
|
3. Если `GITLAB_OAUTH_OPEN_BROWSER=true` и окружение GUI доступно, браузер откроется автоматически.
|
|
84
98
|
4. Локальный URL `http://127.0.0.1:8787/` автоматически редиректит на GitLab OAuth.
|
|
85
99
|
5. Если браузер не может быть открыт, сервер печатает URL авторизации в лог.
|
|
86
|
-
6. После подтверждения в GitLab и callback на `http://127.0.0.1:8787/oauth/callback` токены сохраняются в
|
|
87
|
-
|
|
88
|
-
Если `GITLAB_DEFAULT_PROJECT` не указан:
|
|
89
|
-
1. сервер пытается автоматически определить проект из `git remote origin` в `cwd`;
|
|
90
|
-
2. если не удалось, tool запросит `project` явно.
|
|
100
|
+
6. После подтверждения в GitLab и callback на `http://127.0.0.1:8787/oauth/callback` токены сохраняются в token store для конкретного instance.
|
|
91
101
|
|
|
92
102
|
## 5. Автообновление токена
|
|
93
103
|
|
|
@@ -99,13 +109,27 @@ npx -y gitlab-mcp-agent-server
|
|
|
99
109
|
## 6. Рекомендованные настройки для production
|
|
100
110
|
|
|
101
111
|
1. Держи token store вне репозитория:
|
|
102
|
-
- пример: `/home/<user>/.config/gitlab-mcp/token.json`
|
|
112
|
+
- пример: `/home/<user>/.config/gitlab-mcp/gitlab.com/token.json`
|
|
103
113
|
2. Ограничь права файла:
|
|
104
|
-
- `chmod 600 /home/<user>/.config/gitlab-mcp/token.json`
|
|
105
|
-
3.
|
|
106
|
-
4. Для multi-repo режима лучше не задавать `GITLAB_DEFAULT_PROJECT`, чтобы проект брался из `git remote` текущего `cwd`.
|
|
114
|
+
- `chmod 600 /home/<user>/.config/gitlab-mcp/gitlab.com/token.json`
|
|
115
|
+
3. Для headless окружений ставь `GITLAB_OAUTH_OPEN_BROWSER=false`.
|
|
107
116
|
|
|
108
|
-
## 7.
|
|
117
|
+
## 7. Сценарий пользовательского запроса
|
|
118
|
+
|
|
119
|
+
Пример запроса: `Покажи мне все задачи, которые сейчас есть в проекте?`
|
|
120
|
+
|
|
121
|
+
1. Пользователь добавляет MCP-блок в `~/.codex/config.toml`.
|
|
122
|
+
2. Codex поднимает сервер командой `npx -y gitlab-mcp-agent-server`.
|
|
123
|
+
3. Codex вызывает tool `gitlab_list_issues`.
|
|
124
|
+
4. Сервер резолвит проект в порядке:
|
|
125
|
+
- `project` из входа tool,
|
|
126
|
+
- `git remote origin` текущего `cwd`,
|
|
127
|
+
- `GITLAB_DEFAULT_PROJECT`.
|
|
128
|
+
5. Если токена для этого instance нет, запускается OAuth flow.
|
|
129
|
+
6. После callback токен сохраняется в token store этого instance.
|
|
130
|
+
7. Сервер возвращает список issues.
|
|
131
|
+
|
|
132
|
+
## 8. Быстрая проверка работоспособности
|
|
109
133
|
|
|
110
134
|
1. Вызови `gitlab_list_labels`.
|
|
111
135
|
2. Создай issue: `gitlab_create_issue`.
|
|
@@ -113,7 +137,7 @@ npx -y gitlab-mcp-agent-server
|
|
|
113
137
|
4. Обнови labels: `gitlab_update_issue_labels`.
|
|
114
138
|
5. Закрой issue: `gitlab_close_issue`.
|
|
115
139
|
|
|
116
|
-
##
|
|
140
|
+
## 9. Troubleshooting
|
|
117
141
|
|
|
118
142
|
`The redirect URI included is not valid`:
|
|
119
143
|
1. Проверь, что URI совпадает 1-в-1:
|
|
@@ -125,3 +149,10 @@ npx -y gitlab-mcp-agent-server
|
|
|
125
149
|
1. Проверь scope `api`.
|
|
126
150
|
2. Убедись, что `client_id`/`client_secret` от того же приложения.
|
|
127
151
|
3. Удали token store файл и пройди OAuth заново.
|
|
152
|
+
|
|
153
|
+
## 10. Advanced (необязательно)
|
|
154
|
+
|
|
155
|
+
Если нужен тонкий контроль, можно использовать:
|
|
156
|
+
1. `GITLAB_DEFAULT_PROJECT` для явного fallback проекта.
|
|
157
|
+
2. `GITLAB_AUTO_RESOLVE_PROJECT_FROM_GIT` для автоопределения проекта из `git remote`.
|
|
158
|
+
3. `GITLAB_OAUTH_TOKEN_STORE_PATH` для ручного override пути токена.
|
package/package.json
CHANGED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GroupOAuthTokenProvider = void 0;
|
|
4
|
-
exports.resolveOAuthGroupKey = resolveOAuthGroupKey;
|
|
5
|
-
const errors_1 = require("../../shared/errors");
|
|
6
|
-
const gitlab_oauth_manager_1 = require("./gitlab-oauth-manager");
|
|
7
|
-
class GroupOAuthTokenProvider {
|
|
8
|
-
options;
|
|
9
|
-
groupProviders;
|
|
10
|
-
constructor(options) {
|
|
11
|
-
this.options = options;
|
|
12
|
-
this.groupProviders = Object.fromEntries(Object.entries(options.groupConfigs).map(([groupKey, cfg]) => {
|
|
13
|
-
return [
|
|
14
|
-
groupKey,
|
|
15
|
-
new gitlab_oauth_manager_1.GitLabOAuthManager({
|
|
16
|
-
apiUrl: options.apiUrl,
|
|
17
|
-
clientId: cfg.clientId,
|
|
18
|
-
clientSecret: cfg.clientSecret,
|
|
19
|
-
redirectUri: cfg.redirectUri,
|
|
20
|
-
scopes: cfg.scopes,
|
|
21
|
-
bootstrapAccessToken: cfg.bootstrapAccessToken,
|
|
22
|
-
tokenStorePath: cfg.tokenStorePath,
|
|
23
|
-
autoLogin: cfg.autoLogin,
|
|
24
|
-
openBrowser: cfg.openBrowser
|
|
25
|
-
})
|
|
26
|
-
];
|
|
27
|
-
}));
|
|
28
|
-
}
|
|
29
|
-
async getAccessToken(projectRef) {
|
|
30
|
-
const groupKey = resolveOAuthGroupKey(projectRef, Object.keys(this.groupProviders));
|
|
31
|
-
if (groupKey) {
|
|
32
|
-
const provider = this.groupProviders[groupKey];
|
|
33
|
-
if (provider) {
|
|
34
|
-
return provider.getAccessToken(projectRef);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
if (this.options.defaultProvider) {
|
|
38
|
-
return this.options.defaultProvider.getAccessToken(projectRef);
|
|
39
|
-
}
|
|
40
|
-
throw new errors_1.ConfigurationError('No OAuth config matched this project and default OAuth config is not available.');
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
exports.GroupOAuthTokenProvider = GroupOAuthTokenProvider;
|
|
44
|
-
function resolveOAuthGroupKey(projectRef, configuredGroups) {
|
|
45
|
-
if (typeof projectRef !== 'string' || projectRef.trim() === '') {
|
|
46
|
-
return undefined;
|
|
47
|
-
}
|
|
48
|
-
const normalized = projectRef.trim().replace(/^\/+/, '');
|
|
49
|
-
const sorted = [...configuredGroups].sort((a, b) => b.length - a.length);
|
|
50
|
-
return sorted.find((group) => normalized === group || normalized.startsWith(`${group}/`));
|
|
51
|
-
}
|